diff options
Diffstat (limited to 'scene')
62 files changed, 810 insertions, 332 deletions
diff --git a/scene/2d/audio_stream_player_2d.cpp b/scene/2d/audio_stream_player_2d.cpp index 24da2ce9ce..8bf95e6965 100644 --- a/scene/2d/audio_stream_player_2d.cpp +++ b/scene/2d/audio_stream_player_2d.cpp @@ -97,7 +97,7 @@ void AudioStreamPlayer2D::_notification(int p_what) { while (stream_playbacks.size() > max_polyphony) { AudioServer::get_singleton()->stop_playback_stream(stream_playbacks[0]); - stream_playbacks.remove(0); + stream_playbacks.remove_at(0); } } } diff --git a/scene/2d/collision_object_2d.cpp b/scene/2d/collision_object_2d.cpp index 4b348f12e6..bd13d96b01 100644 --- a/scene/2d/collision_object_2d.cpp +++ b/scene/2d/collision_object_2d.cpp @@ -434,7 +434,7 @@ void CollisionObject2D::shape_owner_remove_shape(uint32_t p_owner, int p_shape) PhysicsServer2D::get_singleton()->body_remove_shape(rid, index_to_remove); } - shapes[p_owner].shapes.remove(p_shape); + shapes[p_owner].shapes.remove_at(p_shape); for (KeyValue<uint32_t, ShapeData> &E : shapes) { for (int i = 0; i < E.value.shapes.size(); i++) { diff --git a/scene/2d/gpu_particles_2d.cpp b/scene/2d/gpu_particles_2d.cpp index f1f4d1b769..4384ec8141 100644 --- a/scene/2d/gpu_particles_2d.cpp +++ b/scene/2d/gpu_particles_2d.cpp @@ -170,6 +170,13 @@ void GPUParticles2D::set_trail_section_subdivisions(int p_subdivisions) { update(); } +#ifdef TOOLS_ENABLED +void GPUParticles2D::set_show_visibility_rect(bool p_show_visibility_rect) { + show_visibility_rect = p_show_visibility_rect; + update(); +} +#endif + bool GPUParticles2D::is_trail_enabled() const { return trail_enabled; } @@ -452,7 +459,7 @@ void GPUParticles2D::_notification(int p_what) { RS::get_singleton()->canvas_item_add_particles(get_canvas_item(), particles, texture_rid); #ifdef TOOLS_ENABLED - if (Engine::get_singleton()->is_editor_hint() && (this == get_tree()->get_edited_scene_root() || get_tree()->get_edited_scene_root()->is_ancestor_of(this))) { + if (show_visibility_rect) { draw_rect(visibility_rect, Color(0, 0.7, 0.9, 0.4), false); } #endif @@ -588,6 +595,9 @@ GPUParticles2D::GPUParticles2D() { set_speed_scale(1); set_fixed_fps(30); set_collision_base_size(collision_base_size); +#ifdef TOOLS_ENABLED + show_visibility_rect = false; +#endif } GPUParticles2D::~GPUParticles2D() { diff --git a/scene/2d/gpu_particles_2d.h b/scene/2d/gpu_particles_2d.h index d7eee461b4..a9e66b3051 100644 --- a/scene/2d/gpu_particles_2d.h +++ b/scene/2d/gpu_particles_2d.h @@ -58,7 +58,9 @@ private: bool local_coords; int fixed_fps; bool fractional_delta; - +#ifdef TOOLS_ENABLED + bool show_visibility_rect; +#endif Ref<Material> process_material; DrawOrder draw_order; @@ -81,7 +83,6 @@ protected: static void _bind_methods(); virtual void _validate_property(PropertyInfo &property) const override; void _notification(int p_what); - void _update_collision_size(); public: @@ -102,6 +103,10 @@ public: void set_trail_sections(int p_sections); void set_trail_section_subdivisions(int p_subdivisions); +#ifdef TOOLS_ENABLED + void set_show_visibility_rect(bool p_show_visibility_rect); +#endif + bool is_emitting() const; int get_amount() const; double get_lifetime() const; diff --git a/scene/2d/line_2d.cpp b/scene/2d/line_2d.cpp index 37eb45c21d..00767ec22c 100644 --- a/scene/2d/line_2d.cpp +++ b/scene/2d/line_2d.cpp @@ -148,7 +148,7 @@ void Line2D::add_point(Vector2 p_pos, int p_atpos) { } void Line2D::remove_point(int i) { - _points.remove(i); + _points.remove_at(i); update(); } diff --git a/scene/2d/navigation_region_2d.cpp b/scene/2d/navigation_region_2d.cpp index 204ed72878..ecd79c23a7 100644 --- a/scene/2d/navigation_region_2d.cpp +++ b/scene/2d/navigation_region_2d.cpp @@ -207,7 +207,7 @@ void NavigationPolygon::set_outline(int p_idx, const Vector<Vector2> &p_outline) void NavigationPolygon::remove_outline(int p_idx) { ERR_FAIL_INDEX(p_idx, outlines.size()); - outlines.remove(p_idx); + outlines.remove_at(p_idx); rect_cache_dirty = true; } diff --git a/scene/2d/physics_body_2d.cpp b/scene/2d/physics_body_2d.cpp index 5ec2a81108..f0e51097db 100644 --- a/scene/2d/physics_body_2d.cpp +++ b/scene/2d/physics_body_2d.cpp @@ -1317,6 +1317,17 @@ void CharacterBody2D::_move_and_slide_grounded(double p_delta, bool p_was_on_flo _snap_on_floor(p_was_on_floor, vel_dir_facing_up); + // Scales the horizontal velocity according to the wall slope. + if (is_on_wall_only() && motion_slide_up.dot(motion_results.get(0).collision_normal) < 0) { + Vector2 slide_motion = motion_velocity.slide(motion_results.get(0).collision_normal); + if (motion_slide_up.dot(slide_motion) < 0) { + motion_velocity = up_direction * up_direction.dot(motion_velocity); + } else { + // Keeps the vertical motion from motion_velocity and add the horizontal motion of the projection. + motion_velocity = up_direction * up_direction.dot(motion_velocity) + slide_motion.slide(up_direction); + } + } + // Reset the gravity accumulation when touching the ground. if (on_floor && !vel_dir_facing_up) { motion_velocity = motion_velocity.slide(up_direction); diff --git a/scene/2d/polygon_2d.cpp b/scene/2d/polygon_2d.cpp index f00959bbb6..7a237bf557 100644 --- a/scene/2d/polygon_2d.cpp +++ b/scene/2d/polygon_2d.cpp @@ -532,7 +532,7 @@ Vector<float> Polygon2D::get_bone_weights(int p_index) const { void Polygon2D::erase_bone(int p_idx) { ERR_FAIL_INDEX(p_idx, bone_weights.size()); - bone_weights.remove(p_idx); + bone_weights.remove_at(p_idx); } void Polygon2D::clear_bones() { diff --git a/scene/2d/skeleton_2d.cpp b/scene/2d/skeleton_2d.cpp index 63a0fb9b89..b558f0aa21 100644 --- a/scene/2d/skeleton_2d.cpp +++ b/scene/2d/skeleton_2d.cpp @@ -165,7 +165,7 @@ void Bone2D::_notification(int p_what) { if (skeleton) { for (int i = 0; i < skeleton->bones.size(); i++) { if (skeleton->bones[i].bone == this) { - skeleton->bones.remove(i); + skeleton->bones.remove_at(i); break; } } diff --git a/scene/2d/tile_map.cpp b/scene/2d/tile_map.cpp index 96c4164721..084a5a520d 100644 --- a/scene/2d/tile_map.cpp +++ b/scene/2d/tile_map.cpp @@ -576,7 +576,7 @@ void TileMap::move_layer(int p_layer, int p_to_pos) { TileMapLayer tl = layers[p_layer]; layers.insert(p_to_pos, tl); - layers.remove(p_to_pos < p_layer ? p_layer + 1 : p_layer); + layers.remove_at(p_to_pos < p_layer ? p_layer + 1 : p_layer); _recreate_internals(); notify_property_list_changed(); @@ -595,7 +595,7 @@ void TileMap::remove_layer(int p_layer) { // Clear before removing the layer. _clear_internals(); - layers.remove(p_layer); + layers.remove_at(p_layer); _recreate_internals(); notify_property_list_changed(); @@ -1928,7 +1928,7 @@ void TileMap::set_cell(int p_layer, const Vector2i &p_coords, int p_source_id, c if ((source_id == TileSet::INVALID_SOURCE || atlas_coords == TileSetSource::INVALID_ATLAS_COORDS || alternative_tile == TileSetSource::INVALID_TILE_ALTERNATIVE) && (source_id != TileSet::INVALID_SOURCE || atlas_coords != TileSetSource::INVALID_ATLAS_COORDS || alternative_tile != TileSetSource::INVALID_TILE_ALTERNATIVE)) { - WARN_PRINT("Setting a cell a cell as empty requires both source_id, atlas_coord and alternative_tile to be set to their respective \"invalid\" values. Values were thus changes accordingly."); + WARN_PRINT("Setting a cell as empty requires both source_id, atlas_coord and alternative_tile to be set to their respective \"invalid\" values. Values were thus changes accordingly."); source_id = TileSet::INVALID_SOURCE; atlas_coords = TileSetSource::INVALID_ATLAS_COORDS; alternative_tile = TileSetSource::INVALID_TILE_ALTERNATIVE; diff --git a/scene/3d/audio_stream_player_3d.cpp b/scene/3d/audio_stream_player_3d.cpp index 34f748b197..efe23c6102 100644 --- a/scene/3d/audio_stream_player_3d.cpp +++ b/scene/3d/audio_stream_player_3d.cpp @@ -311,7 +311,7 @@ void AudioStreamPlayer3D::_notification(int p_what) { while (stream_playbacks.size() > max_polyphony) { AudioServer::get_singleton()->stop_playback_stream(stream_playbacks[0]); - stream_playbacks.remove(0); + stream_playbacks.remove_at(0); } } } diff --git a/scene/3d/collision_object_3d.cpp b/scene/3d/collision_object_3d.cpp index a166a05c71..085f1ade66 100644 --- a/scene/3d/collision_object_3d.cpp +++ b/scene/3d/collision_object_3d.cpp @@ -628,7 +628,7 @@ void CollisionObject3D::shape_owner_remove_shape(uint32_t p_owner, int p_shape) --debug_shapes_count; } - shapes[p_owner].shapes.remove(p_shape); + shapes[p_owner].shapes.remove_at(p_shape); for (KeyValue<uint32_t, ShapeData> &E : shapes) { for (int i = 0; i < E.value.shapes.size(); i++) { diff --git a/scene/3d/decal.cpp b/scene/3d/decal.cpp index c9f634a5e5..500bf4d8f5 100644 --- a/scene/3d/decal.cpp +++ b/scene/3d/decal.cpp @@ -175,9 +175,6 @@ TypedArray<String> Decal::get_configuration_warnings() const { } if (cull_mask == 0) { - // NOTE: This warning will not be emitted if none of the 20 checkboxes - // exposed in the editor are checked. This is because there are - // currently 12 unexposed layers in the editor inspector. warnings.push_back(TTR("The decal's Cull Mask has no bits enabled, which means the decal will not paint objects on any layer.\nTo resolve this, enable at least one bit in the Cull Mask property.")); } diff --git a/scene/3d/node_3d.cpp b/scene/3d/node_3d.cpp index b7b88c7135..ddd9d2da8a 100644 --- a/scene/3d/node_3d.cpp +++ b/scene/3d/node_3d.cpp @@ -478,7 +478,7 @@ void Node3D::remove_gizmo(Ref<Node3DGizmo> p_gizmo) { int idx = data.gizmos.find(p_gizmo); if (idx != -1) { p_gizmo->free(); - data.gizmos.remove(idx); + data.gizmos.remove_at(idx); } #endif } diff --git a/scene/3d/occluder_instance_3d.cpp b/scene/3d/occluder_instance_3d.cpp index 6c548edc74..aeac430cd9 100644 --- a/scene/3d/occluder_instance_3d.cpp +++ b/scene/3d/occluder_instance_3d.cpp @@ -329,9 +329,6 @@ TypedArray<String> OccluderInstance3D::get_configuration_warnings() const { } if (bake_mask == 0) { - // NOTE: This warning will not be emitted if none of the 20 checkboxes - // exposed in the editor are checked. This is because there are - // currently 12 unexposed layers in the editor inspector. warnings.push_back(TTR("The Bake Mask has no bits enabled, which means baking will not produce any occluder meshes for this OccluderInstance3D.\nTo resolve this, enable at least one bit in the Bake Mask property.")); } diff --git a/scene/3d/physics_body_3d.cpp b/scene/3d/physics_body_3d.cpp index 5cb7f431e3..393e29e398 100644 --- a/scene/3d/physics_body_3d.cpp +++ b/scene/3d/physics_body_3d.cpp @@ -1299,7 +1299,6 @@ void CharacterBody3D::_move_and_slide_grounded(double p_delta, bool p_was_on_flo // in order to avoid blocking lateral motion along a wall. if (motion_angle < .5 * Math_PI) { apply_default_sliding = false; - if (p_was_on_floor && !vel_dir_facing_up) { // Cancel the motion. Transform3D gt = get_global_transform(); @@ -1307,14 +1306,18 @@ void CharacterBody3D::_move_and_slide_grounded(double p_delta, bool p_was_on_flo real_t cancel_dist_max = MIN(0.1, margin * 20); if (travel_total <= margin + CMP_EPSILON) { gt.origin -= result.travel; + result.travel = Vector3(); // Cancel for constant speed computation. } else if (travel_total < cancel_dist_max) { // If the movement is large the body can be prevented from reaching the walls. gt.origin -= result.travel.slide(up_direction); // Keep remaining motion in sync with amount canceled. motion = motion.slide(up_direction); + result.travel = Vector3(); + } else { + // Travel is too high to be safely cancelled, we take it into account. + result.travel = result.travel.slide(up_direction); + motion = motion.normalized() * result.travel.length(); } set_global_transform(gt); - result.travel = Vector3(); // Cancel for constant speed computation. - // Determines if you are on the ground, and limits the possibility of climbing on the walls because of the approximations. _snap_on_floor(true, false); } else { @@ -1325,8 +1328,15 @@ void CharacterBody3D::_move_and_slide_grounded(double p_delta, bool p_was_on_flo // Apply slide on forward in order to allow only lateral motion on next step. Vector3 forward = wall_normal.slide(up_direction).normalized(); motion = motion.slide(forward); - // Avoid accelerating when you jump on the wall and smooth falling. - motion_velocity = motion_velocity.slide(forward); + + // Scales the horizontal velocity according to the wall slope. + if (vel_dir_facing_up) { + Vector3 slide_motion = motion_velocity.slide(result.collisions[0].normal); + // Keeps the vertical motion from motion_velocity and add the horizontal motion of the projection. + motion_velocity = up_direction * up_direction.dot(motion_velocity) + slide_motion.slide(up_direction); + } else { + motion_velocity = motion_velocity.slide(forward); + } // Allow only lateral motion along previous floor when already on floor. // Fixes slowing down when moving in diagonal against an inclined wall. @@ -1584,6 +1594,7 @@ void CharacterBody3D::_set_collision_direction(const PhysicsServer3D::MotionResu Vector3 prev_wall_normal = wall_normal; int wall_collision_count = 0; Vector3 combined_wall_normal; + Vector3 tmp_wall_col; // Avoid duplicate on average calculation. for (int i = p_result.collision_count - 1; i >= 0; i--) { const PhysicsServer3D::MotionCollision &collision = p_result.collisions[i]; @@ -1630,8 +1641,11 @@ void CharacterBody3D::_set_collision_direction(const PhysicsServer3D::MotionResu } // Collect normal for calculating average. - combined_wall_normal += collision.normal; - wall_collision_count++; + if (!collision.normal.is_equal_approx(tmp_wall_col)) { + tmp_wall_col = collision.normal; + combined_wall_normal += collision.normal; + wall_collision_count++; + } } if (r_state.wall) { diff --git a/scene/3d/skeleton_3d.cpp b/scene/3d/skeleton_3d.cpp index d4d3c0ebe1..04b5b88ef8 100644 --- a/scene/3d/skeleton_3d.cpp +++ b/scene/3d/skeleton_3d.cpp @@ -633,7 +633,7 @@ void Skeleton3D::remove_bone_child(int p_bone, int p_child) { int child_idx = bones[p_bone].child_bones.find(p_child); if (child_idx >= 0) { - bones.write[p_bone].child_bones.remove(child_idx); + bones.write[p_bone].child_bones.remove_at(child_idx); } else { WARN_PRINT("Cannot remove child bone: Child bone not found."); } diff --git a/scene/3d/soft_dynamic_body_3d.cpp b/scene/3d/soft_dynamic_body_3d.cpp index 903eedb58b..5546b88fb1 100644 --- a/scene/3d/soft_dynamic_body_3d.cpp +++ b/scene/3d/soft_dynamic_body_3d.cpp @@ -773,7 +773,7 @@ void SoftDynamicBody3D::_reset_points_offsets() { void SoftDynamicBody3D::_remove_pinned_point(int p_point_index) { const int id(_has_pinned_point(p_point_index)); if (-1 != id) { - pinned_points.remove(id); + pinned_points.remove_at(id); } } diff --git a/scene/animation/animation_blend_space_2d.cpp b/scene/animation/animation_blend_space_2d.cpp index e621f06ce9..8b5203961f 100644 --- a/scene/animation/animation_blend_space_2d.cpp +++ b/scene/animation/animation_blend_space_2d.cpp @@ -134,7 +134,7 @@ void AnimationNodeBlendSpace2D::remove_blend_point(int p_point) { } } if (erase) { - triangles.remove(i); + triangles.remove_at(i); i--; } @@ -224,7 +224,7 @@ int AnimationNodeBlendSpace2D::get_triangle_point(int p_triangle, int p_point) { void AnimationNodeBlendSpace2D::remove_triangle(int p_triangle) { ERR_FAIL_INDEX(p_triangle, triangles.size()); - triangles.remove(p_triangle); + triangles.remove_at(p_triangle); } int AnimationNodeBlendSpace2D::get_triangle_count() const { diff --git a/scene/animation/animation_node_state_machine.cpp b/scene/animation/animation_node_state_machine.cpp index b5d7a0555e..c8fa8bf395 100644 --- a/scene/animation/animation_node_state_machine.cpp +++ b/scene/animation/animation_node_state_machine.cpp @@ -464,7 +464,7 @@ double AnimationNodeStateMachinePlayback::process(AnimationNodeStateMachine *p_s } if (path.size()) { //if it came from path, remove path - path.remove(0); + path.remove_at(0); } current = next; if (switch_mode == AnimationNodeStateMachineTransition::SWITCH_MODE_SYNC) { @@ -624,7 +624,7 @@ void AnimationNodeStateMachine::remove_node(const StringName &p_name) { for (int i = 0; i < transitions.size(); i++) { if (transitions[i].from == p_name || transitions[i].to == p_name) { transitions.write[i].transition->disconnect("advance_condition_changed", callable_mp(this, &AnimationNodeStateMachine::_tree_changed)); - transitions.remove(i); + transitions.remove_at(i); i--; } } @@ -751,7 +751,7 @@ void AnimationNodeStateMachine::remove_transition(const StringName &p_from, cons for (int i = 0; i < transitions.size(); i++) { if (transitions[i].from == p_from && transitions[i].to == p_to) { transitions.write[i].transition->disconnect("advance_condition_changed", callable_mp(this, &AnimationNodeStateMachine::_tree_changed)); - transitions.remove(i); + transitions.remove_at(i); return; } } @@ -764,7 +764,7 @@ void AnimationNodeStateMachine::remove_transition(const StringName &p_from, cons void AnimationNodeStateMachine::remove_transition_by_index(int p_transition) { ERR_FAIL_INDEX(p_transition, transitions.size()); transitions.write[p_transition].transition->disconnect("advance_condition_changed", callable_mp(this, &AnimationNodeStateMachine::_tree_changed)); - transitions.remove(p_transition); + transitions.remove_at(p_transition); /*if (playing) { path.clear(); }*/ diff --git a/scene/animation/animation_player.h b/scene/animation/animation_player.h index ea04918988..1b07c086c0 100644 --- a/scene/animation/animation_player.h +++ b/scene/animation/animation_player.h @@ -198,7 +198,7 @@ private: struct PlaybackData { AnimationData *from = nullptr; - float pos = 0.0; + double pos = 0.0; float speed_scale = 1.0; }; diff --git a/scene/animation/animation_tree.cpp b/scene/animation/animation_tree.cpp index 37e754148c..57c615a6ab 100644 --- a/scene/animation/animation_tree.cpp +++ b/scene/animation/animation_tree.cpp @@ -329,7 +329,7 @@ void AnimationNode::set_input_name(int p_input, const String &p_name) { void AnimationNode::remove_input(int p_index) { ERR_FAIL_INDEX(p_index, inputs.size()); - inputs.remove(p_index); + inputs.remove_at(p_index); emit_changed(); } diff --git a/scene/audio/audio_stream_player.cpp b/scene/audio/audio_stream_player.cpp index 43c4ce4c82..3da4f23a08 100644 --- a/scene/audio/audio_stream_player.cpp +++ b/scene/audio/audio_stream_player.cpp @@ -143,7 +143,7 @@ void AudioStreamPlayer::play(float p_from_pos) { set_process_internal(true); while (stream_playbacks.size() > max_polyphony) { AudioServer::get_singleton()->stop_playback_stream(stream_playbacks[0]); - stream_playbacks.remove(0); + stream_playbacks.remove_at(0); } } diff --git a/scene/debugger/scene_debugger.cpp b/scene/debugger/scene_debugger.cpp index 3c8949ddfb..56c04b32e3 100644 --- a/scene/debugger/scene_debugger.cpp +++ b/scene/debugger/scene_debugger.cpp @@ -367,7 +367,7 @@ void SceneDebuggerObject::serialize(Array &r_arr, int p_max_size) { PropertyHint hint = pi.hint; String hint_string = pi.hint_string; - if (!res.is_null()) { + if (!res.is_null() && !res->get_path().is_empty()) { var = res->get_path(); } else { //only send information that can be sent.. int len = 0; //test how big is this to encode diff --git a/scene/gui/code_edit.cpp b/scene/gui/code_edit.cpp index 324b21c6d0..a8c5966569 100644 --- a/scene/gui/code_edit.cpp +++ b/scene/gui/code_edit.cpp @@ -296,11 +296,11 @@ void CodeEdit::gui_input(const Ref<InputEvent> &p_gui_input) { mpos.x = get_size().x - mpos.x; } - Point2i pos = get_line_column_at_pos(mpos); + Point2i pos = get_line_column_at_pos(mpos, false); int line = pos.y; int col = pos.x; - if (mb->get_button_index() == MouseButton::LEFT) { + if (line != -1 && mb->get_button_index() == MouseButton::LEFT) { if (is_line_folded(line)) { int wrap_index = get_line_wrap_index_at_column(line, col); if (wrap_index == get_line_wrap_count(line)) { @@ -321,11 +321,13 @@ void CodeEdit::gui_input(const Ref<InputEvent> &p_gui_input) { mpos.x = get_size().x - mpos.x; } - Point2i pos = get_line_column_at_pos(mpos); + Point2i pos = get_line_column_at_pos(mpos, false); int line = pos.y; int col = pos.x; - emit_signal(SNAME("symbol_lookup"), symbol_lookup_word, line, col); + if (line != -1) { + emit_signal(SNAME("symbol_lookup"), symbol_lookup_word, line, col); + } return; } } @@ -536,11 +538,11 @@ Control::CursorShape CodeEdit::get_cursor_shape(const Point2 &p_pos) const { return CURSOR_ARROW; } - Point2i pos = get_line_column_at_pos(p_pos); + Point2i pos = get_line_column_at_pos(p_pos, false); int line = pos.y; int col = pos.x; - if (is_line_folded(line)) { + if (line != -1 && is_line_folded(line)) { int wrap_index = get_line_wrap_index_at_column(line, col); if (wrap_index == get_line_wrap_count(line)) { int eol_icon_width = folded_eol_icon->get_width(); @@ -1417,40 +1419,23 @@ void CodeEdit::fold_line(int p_line) { /* End line is the same therefore we have a block of single line delimiters. */ if (end_line == p_line) { for (int i = p_line + 1; i <= line_count; i++) { - if (i == line_count) { - end_line = line_count; - break; - } - if ((in_string != -1 && is_in_string(i) == -1) || (in_comment != -1 && is_in_comment(i) == -1)) { - end_line = i - 1; break; } + end_line = i; } } } else { int start_indent = get_indent_level(p_line); for (int i = p_line + 1; i <= line_count; i++) { - if (get_line(p_line).strip_edges().size() == 0 || is_in_string(i) != -1 || is_in_comment(i) != -1) { - end_line = i; + if (get_line(i).strip_edges().size() == 0) { continue; } - - if (i == line_count) { - /* Do not fold empty last line of script if any */ + if (get_indent_level(i) > start_indent) { end_line = i; - if (get_line(i).strip_edges().size() == 0) { - end_line--; - } - break; + continue; } - - if ((get_indent_level(i) <= start_indent && get_line(i).strip_edges().size() != 0)) { - /* Keep an empty line unfolded if any */ - end_line = i - 1; - if (get_line(i - 1).strip_edges().size() == 0 && i - 2 > p_line) { - end_line = i - 2; - } + if (is_in_string(i) == -1 && is_in_comment(i) == -1) { break; } } @@ -2016,10 +2001,14 @@ bool CodeEdit::is_symbol_lookup_on_click_enabled() const { String CodeEdit::get_text_for_symbol_lookup() { Point2i mp = get_local_mouse_pos(); - Point2i pos = get_line_column_at_pos(mp); + Point2i pos = get_line_column_at_pos(mp, false); int line = pos.y; int col = pos.x; + if (line == -1) { + return String(); + } + StringBuilder lookup_text; const int text_size = get_line_count(); for (int i = 0; i < text_size; i++) { @@ -2389,7 +2378,7 @@ void CodeEdit::_update_delimiter_cache(int p_from_line, int p_to_line) { if (start_line != end_line) { if (p_to_line < p_from_line) { for (int i = end_line; i > start_line; i--) { - delimiter_cache.remove(i); + delimiter_cache.remove_at(i); } } else { for (int i = start_line; i < end_line; i++) { @@ -2626,7 +2615,7 @@ void CodeEdit::_remove_delimiter(const String &p_start_key, DelimiterType p_type break; } - delimiters.remove(i); + delimiters.remove_at(i); if (!setting_delimiters) { delimiter_cache.clear(); _update_delimiter_cache(); @@ -2667,7 +2656,7 @@ void CodeEdit::_set_delimiters(const TypedArray<String> &p_delimiters, Delimiter void CodeEdit::_clear_delimiters(DelimiterType p_type) { for (int i = delimiters.size() - 1; i >= 0; i--) { if (delimiters[i].type == p_type) { - delimiters.remove(i); + delimiters.remove_at(i); } } delimiter_cache.clear(); diff --git a/scene/gui/control.cpp b/scene/gui/control.cpp index 582c8e5860..9f715be155 100644 --- a/scene/gui/control.cpp +++ b/scene/gui/control.cpp @@ -810,6 +810,10 @@ void Control::set_drag_preview(Control *p_control) { get_viewport()->_gui_set_drag_preview(this, p_control); } +bool Control::is_drag_successful() const { + return is_inside_tree() && get_viewport()->gui_is_drag_successful(); +} + void Control::_call_gui_input(const Ref<InputEvent> &p_event) { emit_signal(SceneStringNames::get_singleton()->gui_input, p_event); //signal should be first, so it's possible to override an event (and then accept it) if (!is_inside_tree() || get_viewport()->is_input_handled()) { @@ -1821,6 +1825,10 @@ Size2 Control::get_size() const { return data.size_cache; } +void Control::reset_size() { + set_size(Size2()); +} + Rect2 Control::get_global_rect() const { return Rect2(get_global_position(), get_size()); } @@ -2841,6 +2849,7 @@ void Control::_bind_methods() { ClassDB::bind_method(D_METHOD("set_position", "position", "keep_offsets"), &Control::set_position, DEFVAL(false)); ClassDB::bind_method(D_METHOD("_set_position", "position"), &Control::_set_position); ClassDB::bind_method(D_METHOD("set_size", "size", "keep_offsets"), &Control::set_size, DEFVAL(false)); + ClassDB::bind_method(D_METHOD("reset_size"), &Control::reset_size); ClassDB::bind_method(D_METHOD("_set_size", "size"), &Control::_set_size); ClassDB::bind_method(D_METHOD("set_custom_minimum_size", "size"), &Control::set_custom_minimum_size); ClassDB::bind_method(D_METHOD("set_global_position", "position", "keep_offsets"), &Control::set_global_position, DEFVAL(false)); @@ -2964,6 +2973,7 @@ void Control::_bind_methods() { ClassDB::bind_method(D_METHOD("set_drag_forwarding", "target"), &Control::set_drag_forwarding); ClassDB::bind_method(D_METHOD("set_drag_preview", "control"), &Control::set_drag_preview); + ClassDB::bind_method(D_METHOD("is_drag_successful"), &Control::is_drag_successful); ClassDB::bind_method(D_METHOD("warp_mouse", "to_position"), &Control::warp_mouse); diff --git a/scene/gui/control.h b/scene/gui/control.h index 02ab336ef0..1a94cc68a6 100644 --- a/scene/gui/control.h +++ b/scene/gui/control.h @@ -357,6 +357,7 @@ public: virtual void drop_data(const Point2 &p_point, const Variant &p_data); void set_drag_preview(Control *p_control); void force_drag(const Variant &p_data, Control *p_control); + bool is_drag_successful() const; void set_custom_minimum_size(const Size2 &p_custom); Size2 get_custom_minimum_size() const; @@ -400,6 +401,7 @@ public: void set_size(const Size2 &p_size, bool p_keep_offsets = false); Size2 get_size() const; + void reset_size(); Rect2 get_rect() const; Rect2 get_global_rect() const; diff --git a/scene/gui/gradient_edit.cpp b/scene/gui/gradient_edit.cpp index ae15b021a5..1210be15ce 100644 --- a/scene/gui/gradient_edit.cpp +++ b/scene/gui/gradient_edit.cpp @@ -89,7 +89,7 @@ void GradientEdit::gui_input(const Ref<InputEvent> &p_event) { Ref<InputEventKey> k = p_event; if (k.is_valid() && k->is_pressed() && k->get_keycode() == Key::KEY_DELETE && grabbed != -1) { - points.remove(grabbed); + points.remove_at(grabbed); grabbed = -1; grabbing = false; update(); @@ -109,7 +109,7 @@ void GradientEdit::gui_input(const Ref<InputEvent> &p_event) { if (mb.is_valid() && mb->get_button_index() == MouseButton::RIGHT && mb->is_pressed()) { grabbed = _get_point_from_pos(mb->get_position().x); if (grabbed != -1) { - points.remove(grabbed); + points.remove_at(grabbed); grabbed = -1; grabbing = false; update(); diff --git a/scene/gui/item_list.cpp b/scene/gui/item_list.cpp index c0f2cdbef1..408ef53e89 100644 --- a/scene/gui/item_list.cpp +++ b/scene/gui/item_list.cpp @@ -381,7 +381,7 @@ void ItemList::move_item(int p_from_idx, int p_to_idx) { } Item item = items[p_from_idx]; - items.remove(p_from_idx); + items.remove_at(p_from_idx); items.insert(p_to_idx, item); update(); @@ -404,7 +404,7 @@ int ItemList::get_item_count() const { void ItemList::remove_item(int p_idx) { ERR_FAIL_INDEX(p_idx, items.size()); - items.remove(p_idx); + items.remove_at(p_idx); if (current == p_idx) { current = -1; } diff --git a/scene/gui/line_edit.cpp b/scene/gui/line_edit.cpp index 124d5c7821..69b08fda3c 100644 --- a/scene/gui/line_edit.cpp +++ b/scene/gui/line_edit.cpp @@ -228,7 +228,7 @@ void LineEdit::gui_input(const Ref<InputEvent> &p_event) { if (b->is_pressed() && b->get_button_index() == MouseButton::RIGHT && context_menu_enabled) { _ensure_menu(); menu->set_position(get_screen_transform().xform(get_local_mouse_position())); - menu->set_size(Vector2(1, 1)); + menu->reset_size(); menu->popup(); grab_focus(); accept_event(); @@ -268,7 +268,9 @@ void LineEdit::gui_input(const Ref<InputEvent> &p_event) { return; } - shift_selection_check_pre(b->is_shift_pressed()); + if (b->is_shift_pressed()) { + shift_selection_check_pre(true); + } set_caret_at_pixel_pos(b->get_position().x); @@ -345,6 +347,9 @@ void LineEdit::gui_input(const Ref<InputEvent> &p_event) { } selection.creating = false; selection.double_click = false; + if (!drag_action) { + selection.drag_attempt = false; + } show_virtual_keyboard(); } @@ -369,6 +374,11 @@ void LineEdit::gui_input(const Ref<InputEvent> &p_event) { selection_fill_at_caret(); } } + + if (drag_action && can_drop_data(m->get_position(), get_viewport()->gui_get_drag_data())) { + drag_caret_force_displayed = true; + set_caret_at_pixel_pos(m->get_position().x); + } } Ref<InputEventKey> k = p_event; @@ -383,7 +393,7 @@ void LineEdit::gui_input(const Ref<InputEvent> &p_event) { _ensure_menu(); Point2 pos = Point2(get_caret_pixel_pos().x, (get_size().y + get_theme_font(SNAME("font"))->get_height(get_theme_font_size(SNAME("font_size")))) / 2); menu->set_position(get_global_transform().xform(pos)); - menu->set_size(Vector2(1, 1)); + menu->reset_size(); menu->popup(); menu->grab_focus(); } @@ -569,21 +579,44 @@ bool LineEdit::can_drop_data(const Point2 &p_point, const Variant &p_data) const return drop_override; } - return p_data.get_type() == Variant::STRING; + return is_editable() && p_data.get_type() == Variant::STRING; } void LineEdit::drop_data(const Point2 &p_point, const Variant &p_data) { Control::drop_data(p_point, p_data); - if (p_data.get_type() == Variant::STRING) { + if (p_data.get_type() == Variant::STRING && is_editable()) { set_caret_at_pixel_pos(p_point.x); + int caret_column_tmp = caret_column; + if (selection.drag_attempt) { + selection.drag_attempt = false; + if (caret_column < selection.begin || caret_column > selection.end) { + if (caret_column_tmp > selection.end) { + caret_column_tmp = caret_column_tmp - (selection.end - selection.begin); + } + selection_delete(); - text = text.left(selection.begin) + text.substr(selection.end); - _shape(); - - insert_text_at_caret(p_data); - selection.begin = caret_column - (selection.end - selection.begin); - selection.end = caret_column; + set_caret_column(caret_column_tmp); + insert_text_at_caret(p_data); + } + } else if (selection.enabled && caret_column >= selection.begin && caret_column <= selection.end) { + caret_column_tmp = selection.begin; + selection_delete(); + set_caret_column(caret_column_tmp); + insert_text_at_caret(p_data); + grab_focus(); + } else { + insert_text_at_caret(p_data); + grab_focus(); + } + select(caret_column_tmp, caret_column); + if (!text_changed_dirty) { + if (is_inside_tree()) { + MessageQueue::get_singleton()->push_call(this, "_text_changed"); + } + text_changed_dirty = true; + } + update(); } } @@ -803,7 +836,7 @@ void LineEdit::_notification(int p_what) { // Draw carets. ofs.x = x_ofs + scroll_offset; - if (draw_caret) { + if (draw_caret || drag_caret_force_displayed) { if (ime_text.length() == 0) { // Normal caret. CaretInfo caret = TS->shaped_text_get_carets(text_rid, caret_column); @@ -921,7 +954,7 @@ void LineEdit::_notification(int p_what) { DisplayServer::get_singleton()->virtual_keyboard_hide(); } - if (deselect_on_focus_loss_enabled) { + if (deselect_on_focus_loss_enabled && !selection.drag_attempt) { deselect(); } } break; @@ -935,6 +968,25 @@ void LineEdit::_notification(int p_what) { update(); } } break; + case Control::NOTIFICATION_DRAG_BEGIN: { + drag_action = true; + } break; + case Control::NOTIFICATION_DRAG_END: { + if (is_drag_successful()) { + if (selection.drag_attempt) { + selection.drag_attempt = false; + if (is_editable()) { + selection_delete(); + } else if (deselect_on_focus_loss_enabled) { + deselect(); + } + } + } else { + selection.drag_attempt = false; + } + drag_action = false; + drag_caret_force_displayed = false; + } break; } } @@ -999,6 +1051,9 @@ void LineEdit::undo() { } else if (undo_stack_pos == undo_stack.front()) { return; } + + deselect(); + undo_stack_pos = undo_stack_pos->prev(); TextOperation op = undo_stack_pos->get(); text = op.text; @@ -1020,6 +1075,9 @@ void LineEdit::redo() { if (undo_stack_pos == undo_stack.back()) { return; } + + deselect(); + undo_stack_pos = undo_stack_pos->next(); TextOperation op = undo_stack_pos->get(); text = op.text; diff --git a/scene/gui/line_edit.h b/scene/gui/line_edit.h index 134d5f8f76..221dd9eb2e 100644 --- a/scene/gui/line_edit.h +++ b/scene/gui/line_edit.h @@ -129,6 +129,9 @@ private: bool middle_mouse_paste_enabled = true; + bool drag_action = false; + bool drag_caret_force_displayed = false; + Ref<Texture2D> right_icon; bool flat = false; diff --git a/scene/gui/popup_menu.cpp b/scene/gui/popup_menu.cpp index 7e9b545776..2e854abb76 100644 --- a/scene/gui/popup_menu.cpp +++ b/scene/gui/popup_menu.cpp @@ -1403,7 +1403,7 @@ void PopupMenu::remove_item(int p_idx) { _unref_shortcut(items[p_idx].shortcut); } - items.remove(p_idx); + items.remove_at(p_idx); control->update(); child_controls_changed(); } diff --git a/scene/gui/range.cpp b/scene/gui/range.cpp index 92d4261d8d..c4f05a7975 100644 --- a/scene/gui/range.cpp +++ b/scene/gui/range.cpp @@ -61,6 +61,11 @@ void Range::_changed_notify(const char *p_what) { update(); } +void Range::_validate_values() { + shared->max = MAX(shared->max, shared->min); + shared->page = CLAMP(shared->page, 0, shared->max - shared->min); +} + void Range::Shared::emit_changed(const char *p_what) { for (Set<Range *>::Element *E = owners.front(); E; E = E->next()) { Range *r = E->get(); @@ -100,6 +105,7 @@ void Range::set_value(double p_val) { void Range::set_min(double p_min) { shared->min = p_min; set_value(shared->val); + _validate_values(); shared->emit_changed("min"); @@ -109,6 +115,7 @@ void Range::set_min(double p_min) { void Range::set_max(double p_max) { shared->max = p_max; set_value(shared->val); + _validate_values(); shared->emit_changed("max"); } @@ -121,6 +128,7 @@ void Range::set_step(double p_step) { void Range::set_page(double p_page) { shared->page = p_page; set_value(shared->val); + _validate_values(); shared->emit_changed("page"); } @@ -270,6 +278,12 @@ void Range::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::BOOL, "rounded"), "set_use_rounded_values", "is_using_rounded_values"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "allow_greater"), "set_allow_greater", "is_greater_allowed"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "allow_lesser"), "set_allow_lesser", "is_lesser_allowed"); + + ADD_LINKED_PROPERTY("min_value", "value"); + ADD_LINKED_PROPERTY("min_value", "max_value"); + ADD_LINKED_PROPERTY("min_value", "page"); + ADD_LINKED_PROPERTY("max_value", "value"); + ADD_LINKED_PROPERTY("max_value", "page"); } void Range::set_use_rounded_values(bool p_enable) { diff --git a/scene/gui/range.h b/scene/gui/range.h index 7a129e88d6..0dc702b19c 100644 --- a/scene/gui/range.h +++ b/scene/gui/range.h @@ -59,6 +59,7 @@ class Range : public Control { void _value_changed_notify(); void _changed_notify(const char *p_what = ""); + void _validate_values(); protected: virtual void _value_changed(double) {} diff --git a/scene/gui/rich_text_label.cpp b/scene/gui/rich_text_label.cpp index f191dfecb4..fd19fad667 100644 --- a/scene/gui/rich_text_label.cpp +++ b/scene/gui/rich_text_label.cpp @@ -2334,7 +2334,7 @@ void RichTextLabel::_remove_item(Item *p_item, const int p_line, const int p_sub p_item->parent->subitems.erase(p_item); // If a newline was erased, all lines AFTER the newline need to be decremented. if (p_item->type == ITEM_NEWLINE) { - current_frame->lines.remove(p_line); + current_frame->lines.remove_at(p_line); for (int i = 0; i < current->subitems.size(); i++) { if (current->subitems[i]->line > p_subitem_line) { current->subitems[i]->line--; @@ -2423,7 +2423,7 @@ bool RichTextLabel::remove_line(const int p_line) { } if (!had_newline) { - current_frame->lines.remove(p_line); + current_frame->lines.remove_at(p_line); if (current_frame->lines.size() == 0) { current_frame->lines.resize(1); } @@ -3527,7 +3527,7 @@ void RichTextLabel::append_text(const String &p_bbcode) { pos = brk_pos + 1; } else { String identifier = expr[0]; - expr.remove(0); + expr.remove_at(0); Dictionary properties = parse_expressions_for_values(expr); Ref<RichTextEffect> effect = _get_custom_effect_by_code(identifier); diff --git a/scene/gui/tab_bar.cpp b/scene/gui/tab_bar.cpp index 1dda29f668..57ee7fd494 100644 --- a/scene/gui/tab_bar.cpp +++ b/scene/gui/tab_bar.cpp @@ -790,7 +790,7 @@ void TabBar::clear_tabs() { void TabBar::remove_tab(int p_idx) { ERR_FAIL_INDEX(p_idx, tabs.size()); - tabs.remove(p_idx); + tabs.remove_at(p_idx); if (current >= p_idx) { current--; } @@ -961,7 +961,7 @@ void TabBar::move_tab(int from, int to) { ERR_FAIL_INDEX(to, tabs.size()); Tab tab_from = tabs[from]; - tabs.remove(from); + tabs.remove_at(from); tabs.insert(to, tab_from); _update_cache(); diff --git a/scene/gui/text_edit.cpp b/scene/gui/text_edit.cpp index fbfeea5722..2cb9d10fca 100644 --- a/scene/gui/text_edit.cpp +++ b/scene/gui/text_edit.cpp @@ -300,11 +300,11 @@ void TextEdit::Text::insert(int p_at, const String &p_text, const Array &p_bidi_ invalidate_cache(p_at); } -void TextEdit::Text::remove(int p_at) { - int height = text[p_at].height; - int width = text[p_at].width; +void TextEdit::Text::remove_at(int p_index) { + int height = text[p_index].height; + int width = text[p_index].width; - text.remove(p_at); + text.remove_at(p_index); // If this is the tallest line, we need to get the next tallest. if (height == line_height) { @@ -330,7 +330,7 @@ void TextEdit::Text::add_gutter(int p_at) { void TextEdit::Text::remove_gutter(int p_gutter) { for (int i = 0; i < text.size(); i++) { - text.write[i].gutters.remove(p_gutter); + text.write[i].gutters.remove_at(p_gutter); } gutter_count--; } @@ -608,7 +608,7 @@ void TextEdit::_notification(int p_what) { int draw_amount = visible_rows + (smooth_scroll_enabled ? 1 : 0); draw_amount += get_line_wrap_count(first_visible_line + 1); - // minimap + // Draw minimap. if (draw_minimap) { int minimap_visible_lines = get_minimap_visible_lines(); int minimap_line_height = (minimap_char_size.y + minimap_line_spacing); @@ -788,8 +788,9 @@ void TextEdit::_notification(int p_what) { bottom_limit_y -= style_normal->get_margin(SIDE_BOTTOM); } - // draw main text + // Draw main text. caret.visible = false; + line_drawing_cache.clear(); int row_height = get_line_height(); int line = first_visible_line; for (int i = 0; i < draw_amount; i++) { @@ -810,6 +811,8 @@ void TextEdit::_notification(int p_what) { continue; } + LineDrawingCache cache_entry; + Dictionary color_map = _get_line_syntax_highlighting(line); // Ensure we at least use the font color. @@ -899,6 +902,8 @@ void TextEdit::_notification(int p_what) { if (line_wrap_index == 0) { // Only do these if we are on the first wrapped part of a line. + cache_entry.y_offset = ofs_y; + int gutter_offset = style_normal->get_margin(SIDE_LEFT); for (int g = 0; g < gutters.size(); g++) { const GutterInfo gutter = gutters[g]; @@ -1076,6 +1081,10 @@ void TextEdit::_notification(int p_what) { int gl_size = TS->shaped_text_get_glyph_count(rid); ofs_y += ldata->get_line_ascent(line_wrap_index); + + int first_visible_char = TS->shaped_text_get_range(rid).y; + int last_visible_char = TS->shaped_text_get_range(rid).x; + int char_ofs = 0; if (outline_size > 0 && outline_color.a > 0) { for (int j = 0; j < gl_size; j++) { @@ -1143,21 +1152,36 @@ void TextEdit::_notification(int p_what) { } } + bool had_glyphs_drawn = false; for (int k = 0; k < glyphs[j].repeat; k++) { if (!clipped && (char_ofs + char_margin) >= xmargin_beg && (char_ofs + glyphs[j].advance + char_margin) <= xmargin_end) { if (glyphs[j].font_rid != RID()) { TS->font_draw_glyph(glyphs[j].font_rid, ci, glyphs[j].font_size, Vector2(char_margin + char_ofs + ofs_x + glyphs[j].x_off, ofs_y + glyphs[j].y_off), glyphs[j].index, current_color); + had_glyphs_drawn = true; } else if ((glyphs[j].flags & TextServer::GRAPHEME_IS_VIRTUAL) != TextServer::GRAPHEME_IS_VIRTUAL) { TS->draw_hex_code_box(ci, glyphs[j].font_size, Vector2(char_margin + char_ofs + ofs_x + glyphs[j].x_off, ofs_y + glyphs[j].y_off), glyphs[j].index, current_color); + had_glyphs_drawn = true; } } char_ofs += glyphs[j].advance; } + + if (had_glyphs_drawn) { + if (first_visible_char > glyphs[j].start) { + first_visible_char = glyphs[j].start; + } else if (last_visible_char < glyphs[j].end) { + last_visible_char = glyphs[j].end; + } + } + if ((char_ofs + char_margin) >= xmargin_end) { break; } } + cache_entry.first_visible_chars.push_back(first_visible_char); + cache_entry.last_visible_chars.push_back(last_visible_char); + // is_line_folded if (line_wrap_index == line_wrap_amount && line < text.size() - 1 && _is_line_hidden(line + 1)) { int xofs = char_ofs + char_margin + ofs_x + (folded_eol_icon->get_width() / 2); @@ -1308,6 +1332,8 @@ void TextEdit::_notification(int p_what) { } } } + + line_drawing_cache[line] = cache_entry; } if (has_focus()) { @@ -1569,7 +1595,7 @@ void TextEdit::gui_input(const Ref<InputEvent> &p_gui_input) { _generate_context_menu(); menu->set_position(get_screen_transform().xform(mpos)); - menu->set_size(Vector2(1, 1)); + menu->reset_size(); menu->popup(); grab_focus(); } @@ -1802,7 +1828,7 @@ void TextEdit::gui_input(const Ref<InputEvent> &p_gui_input) { _generate_context_menu(); adjust_viewport_to_caret(); menu->set_position(get_screen_transform().xform(get_caret_draw_pos())); - menu->set_size(Vector2(1, 1)); + menu->reset_size(); menu->popup(); menu->grab_focus(); } @@ -2878,6 +2904,16 @@ Point2i TextEdit::get_next_visible_line_index_offset_from(int p_line_from, int p } } wrap_index = get_line_wrap_count(MIN(i, text.size() - 1)) - MAX(0, num_visible - p_visible_amount); + + // If we are a hidden line, then we are the last line as we cannot reach "p_visible_amount". + // This means we need to backtrack to get last visible line. + // Currently, line 0 cannot be hidden so this should always be valid. + int line = (p_line_from + num_total) - 1; + if (_is_line_hidden(line)) { + Point2i backtrack = get_next_visible_line_index_offset_from(line, 0, -1); + num_total = num_total - (backtrack.x - 1); + wrap_index = backtrack.y; + } } else { p_visible_amount = ABS(p_visible_amount); int i; @@ -3386,7 +3422,7 @@ String TextEdit::get_word_at_pos(const Vector2 &p_pos) const { return String(); } -Point2i TextEdit::get_line_column_at_pos(const Point2i &p_pos) const { +Point2i TextEdit::get_line_column_at_pos(const Point2i &p_pos, bool p_allow_out_of_bounds) const { float rows = p_pos.y; rows -= style_normal->get_margin(SIDE_TOP); rows /= get_line_height(); @@ -3398,6 +3434,7 @@ Point2i TextEdit::get_line_column_at_pos(const Point2i &p_pos) const { if (get_line_wrapping_mode() != LineWrappingMode::LINE_WRAPPING_NONE || _is_hiding_enabled()) { Point2i f_ofs = get_next_visible_line_index_offset_from(first_vis_line, caret.wrap_ofs, rows + (1 * SIGN(rows))); wrap_index = f_ofs.y; + if (rows < 0) { row = first_vis_line - (f_ofs.x - 1); } else { @@ -3409,37 +3446,86 @@ Point2i TextEdit::get_line_column_at_pos(const Point2i &p_pos) const { row = 0; } - int col = 0; - if (row >= text.size()) { row = text.size() - 1; - col = text[row].size(); - } else { - int colx = p_pos.x - (style_normal->get_margin(SIDE_LEFT) + gutters_width + gutter_padding); - colx += caret.x_ofs; - col = _get_char_pos_for_line(colx, row, wrap_index); - if (get_line_wrapping_mode() != LineWrappingMode::LINE_WRAPPING_NONE && wrap_index < get_line_wrap_count(row)) { - // Move back one if we are at the end of the row. - Vector<String> rows2 = get_line_wrapped_text(row); - int row_end_col = 0; - for (int i = 0; i < wrap_index + 1; i++) { - row_end_col += rows2[i].length(); - } - if (col >= row_end_col) { - col -= 1; - } + } + + int visible_lines = get_visible_line_count_in_range(first_vis_line, row); + if (rows > visible_lines) { + if (!p_allow_out_of_bounds) { + return Point2i(-1, -1); } + return Point2i(text[row].size(), row); + } - RID text_rid = text.get_line_data(row)->get_line_rid(wrap_index); - if (is_layout_rtl()) { - colx = TS->shaped_text_get_size(text_rid).x - colx; + int col = 0; + int colx = p_pos.x - (style_normal->get_margin(SIDE_LEFT) + gutters_width + gutter_padding); + colx += caret.x_ofs; + col = _get_char_pos_for_line(colx, row, wrap_index); + if (get_line_wrapping_mode() != LineWrappingMode::LINE_WRAPPING_NONE && wrap_index < get_line_wrap_count(row)) { + // Move back one if we are at the end of the row. + Vector<String> rows2 = get_line_wrapped_text(row); + int row_end_col = 0; + for (int i = 0; i < wrap_index + 1; i++) { + row_end_col += rows2[i].length(); + } + if (col >= row_end_col) { + col -= 1; } - col = TS->shaped_text_hit_test_position(text_rid, colx); } + RID text_rid = text.get_line_data(row)->get_line_rid(wrap_index); + if (is_layout_rtl()) { + colx = TS->shaped_text_get_size(text_rid).x - colx; + } + col = TS->shaped_text_hit_test_position(text_rid, colx); + return Point2i(col, row); } +Point2i TextEdit::get_pos_at_line_column(int p_line, int p_column) const { + Rect2i rect = get_rect_at_line_column(p_line, p_column); + return rect.position + Vector2i(0, get_line_height()); +} + +Rect2i TextEdit::get_rect_at_line_column(int p_line, int p_column) const { + ERR_FAIL_INDEX_V(p_line, text.size(), Rect2i(-1, -1, 0, 0)); + ERR_FAIL_COND_V(p_column < 0, Rect2i(-1, -1, 0, 0)); + ERR_FAIL_COND_V(p_column > text[p_line].length(), Rect2i(-1, -1, 0, 0)); + + if (line_drawing_cache.size() == 0 || !line_drawing_cache.has(p_line)) { + // Line is not in the cache, which means it's outside of the viewing area. + return Rect2i(-1, -1, 0, 0); + } + LineDrawingCache cache_entry = line_drawing_cache[p_line]; + + int wrap_index = get_line_wrap_index_at_column(p_line, p_column); + if (wrap_index >= cache_entry.first_visible_chars.size()) { + // Line seems to be wrapped beyond the viewable area. + return Rect2i(-1, -1, 0, 0); + } + + int first_visible_char = cache_entry.first_visible_chars[wrap_index]; + int last_visible_char = cache_entry.last_visible_chars[wrap_index]; + if (p_column < first_visible_char || p_column > last_visible_char) { + // Character is outside of the viewing area, no point calculating its position. + return Rect2i(-1, -1, 0, 0); + } + + Point2i pos, size; + pos.y = cache_entry.y_offset + get_line_height() * wrap_index; + pos.x = get_total_gutter_width() + style_normal->get_margin(SIDE_LEFT) - get_h_scroll(); + + RID text_rid = text.get_line_data(p_line)->get_line_rid(wrap_index); + Vector2 col_bounds = TS->shaped_text_get_grapheme_bounds(text_rid, p_column); + pos.x += col_bounds.x; + size.x = col_bounds.y - col_bounds.x; + + size.y = get_line_height(); + + return Rect2i(pos, size); +} + int TextEdit::get_minimap_line_at_pos(const Point2i &p_pos) const { float rows = p_pos.y; rows -= style_normal->get_margin(SIDE_TOP); @@ -3880,7 +3966,7 @@ void TextEdit::delete_selection() { update(); } -/* line wrapping. */ +/* Line wrapping. */ void TextEdit::set_line_wrapping_mode(LineWrappingMode p_wrapping_mode) { if (line_wrapping_mode != p_wrapping_mode) { line_wrapping_mode = p_wrapping_mode; @@ -4012,15 +4098,7 @@ double TextEdit::get_scroll_pos_for_line(int p_line, int p_wrap_index) const { return p_line; } - // Count the number of visible lines up to this line. - double new_line_scroll_pos = 0.0; - int to = CLAMP(p_line, 0, text.size() - 1); - for (int i = 0; i < to; i++) { - if (!text.is_hidden(i)) { - new_line_scroll_pos++; - new_line_scroll_pos += get_line_wrap_count(i); - } - } + double new_line_scroll_pos = get_visible_line_count_in_range(0, CLAMP(p_line, 0, text.size() - 1)); new_line_scroll_pos += p_wrap_index; return new_line_scroll_pos; } @@ -4077,14 +4155,18 @@ int TextEdit::get_visible_line_count() const { return _get_control_height() / get_line_height(); } -int TextEdit::get_total_visible_line_count() const { +int TextEdit::get_visible_line_count_in_range(int p_from_line, int p_to_line) const { + ERR_FAIL_INDEX_V(p_from_line, text.size(), 0); + ERR_FAIL_INDEX_V(p_to_line, text.size(), 0); + ERR_FAIL_COND_V(p_from_line > p_to_line, 0); + /* Returns the total number of (lines + wrapped - hidden). */ if (!_is_hiding_enabled() && get_line_wrapping_mode() == LineWrappingMode::LINE_WRAPPING_NONE) { - return text.size(); + return p_to_line - p_from_line; } int total_rows = 0; - for (int i = 0; i < text.size(); i++) { + for (int i = p_from_line; i <= p_to_line; i++) { if (!text.is_hidden(i)) { total_rows++; total_rows += get_line_wrap_count(i); @@ -4093,6 +4175,10 @@ int TextEdit::get_total_visible_line_count() const { return total_rows; } +int TextEdit::get_total_visible_line_count() const { + return get_visible_line_count_in_range(0, text.size() - 1); +} + // Auto adjust void TextEdit::adjust_viewport_to_caret() { // Make sure Caret is visible on the screen. @@ -4261,7 +4347,7 @@ void TextEdit::add_gutter(int p_at) { void TextEdit::remove_gutter(int p_gutter) { ERR_FAIL_INDEX(p_gutter, gutters.size()); - gutters.remove(p_gutter); + gutters.remove_at(p_gutter); for (int i = 0; i < text.size() + 1; i++) { text.remove_gutter(p_gutter); @@ -4683,7 +4769,10 @@ void TextEdit::_bind_methods() { ClassDB::bind_method(D_METHOD("get_word_at_pos", "position"), &TextEdit::get_word_at_pos); - ClassDB::bind_method(D_METHOD("get_line_column_at_pos", "position"), &TextEdit::get_line_column_at_pos); + ClassDB::bind_method(D_METHOD("get_line_column_at_pos", "position", "allow_out_of_bounds"), &TextEdit::get_line_column_at_pos, DEFVAL(true)); + ClassDB::bind_method(D_METHOD("get_pos_at_line_column", "line", "column"), &TextEdit::get_pos_at_line_column); + ClassDB::bind_method(D_METHOD("get_rect_at_line_column", "line", "column"), &TextEdit::get_rect_at_line_column); + ClassDB::bind_method(D_METHOD("get_minimap_line_at_pos", "position"), &TextEdit::get_minimap_line_at_pos); ClassDB::bind_method(D_METHOD("is_dragging_cursor"), &TextEdit::is_dragging_cursor); @@ -4761,7 +4850,7 @@ void TextEdit::_bind_methods() { ClassDB::bind_method(D_METHOD("deselect"), &TextEdit::deselect); ClassDB::bind_method(D_METHOD("delete_selection"), &TextEdit::delete_selection); - /* line wrapping. */ + /* Line wrapping. */ BIND_ENUM_CONSTANT(LINE_WRAPPING_NONE); BIND_ENUM_CONSTANT(LINE_WRAPPING_BOUNDARY); @@ -4807,6 +4896,7 @@ void TextEdit::_bind_methods() { ClassDB::bind_method(D_METHOD("get_last_full_visible_line_wrap_index"), &TextEdit::get_last_full_visible_line_wrap_index); ClassDB::bind_method(D_METHOD("get_visible_line_count"), &TextEdit::get_visible_line_count); + ClassDB::bind_method(D_METHOD("get_visible_line_count_in_range", "from_line", "to_line"), &TextEdit::get_visible_line_count_in_range); ClassDB::bind_method(D_METHOD("get_total_visible_line_count"), &TextEdit::get_total_visible_line_count); // Auto adjust @@ -6159,7 +6249,7 @@ void TextEdit::_base_remove_text(int p_from_line, int p_from_column, int p_to_li String post_text = text[p_to_line].substr(p_to_column, text[p_to_line].length()); for (int i = p_from_line; i < p_to_line; i++) { - text.remove(p_from_line + 1); + text.remove_at(p_from_line + 1); } text.set(p_from_line, pre_text + post_text, structured_text_parser(st_parser, st_args, pre_text + post_text)); diff --git a/scene/gui/text_edit.h b/scene/gui/text_edit.h index 1a7dc851b5..42b21cbe9c 100644 --- a/scene/gui/text_edit.h +++ b/scene/gui/text_edit.h @@ -205,7 +205,7 @@ private: } bool is_hidden(int p_line) const { return text[p_line].hidden; } void insert(int p_at, const String &p_text, const Array &p_bidi_override); - void remove(int p_at); + void remove_at(int p_index); int size() const { return text.size(); } void clear(); @@ -271,7 +271,7 @@ private: bool virtual_keyboard_enabled = true; bool middle_mouse_paste_enabled = true; - // Overridable actions + // Overridable actions. String cut_copy_line = ""; // Context menu. @@ -336,6 +336,14 @@ private: Variant tooltip_ud; /* Mouse */ + struct LineDrawingCache { + int y_offset = 0; + Vector<int> first_visible_chars; + Vector<int> last_visible_chars; + }; + + Map<int, LineDrawingCache> line_drawing_cache; + int _get_char_pos_for_line(int p_px, int p_line, int p_wrap_index = 0) const; /* Caret. */ @@ -415,7 +423,7 @@ private: void _pre_shift_selection(); void _post_shift_selection(); - /* line wrapping. */ + /* Line wrapping. */ LineWrappingMode line_wrapping_mode = LineWrappingMode::LINE_WRAPPING_NONE; int wrap_at_column = 0; @@ -455,14 +463,14 @@ private: void _scroll_lines_up(); void _scroll_lines_down(); - // Minimap + // Minimap. bool draw_minimap = false; int minimap_width = 80; Point2 minimap_char_size = Point2(1, 2); int minimap_line_spacing = 1; - // minimap scroll + // Minimap scroll. bool minimap_clicked = false; bool hovering_minimap = false; bool dragging_minimap = false; @@ -716,7 +724,10 @@ public: String get_word_at_pos(const Vector2 &p_pos) const; - Point2i get_line_column_at_pos(const Point2i &p_pos) const; + Point2i get_line_column_at_pos(const Point2i &p_pos, bool p_allow_out_of_bounds = true) const; + Point2i get_pos_at_line_column(int p_line, int p_column) const; + Rect2i get_rect_at_line_column(int p_line, int p_column) const; + int get_minimap_line_at_pos(const Point2i &p_pos) const; bool is_dragging_cursor() const; @@ -782,7 +793,7 @@ public: void deselect(); void delete_selection(); - /* line wrapping. */ + /* Line wrapping. */ void set_line_wrapping_mode(LineWrappingMode p_wrapping_mode); LineWrappingMode get_line_wrapping_mode() const; @@ -822,6 +833,7 @@ public: int get_last_full_visible_line_wrap_index() const; int get_visible_line_count() const; + int get_visible_line_count_in_range(int p_from, int p_to) const; int get_total_visible_line_count() const; // Auto Adjust diff --git a/scene/gui/texture_progress_bar.cpp b/scene/gui/texture_progress_bar.cpp index fe11de128a..facbe06d4d 100644 --- a/scene/gui/texture_progress_bar.cpp +++ b/scene/gui/texture_progress_bar.cpp @@ -387,7 +387,6 @@ void TextureProgressBar::draw_nine_patch_stretched(const Ref<Texture2D> &p_textu } void TextureProgressBar::_notification(int p_what) { - const float corners[12] = { -0.125, -0.375, -0.625, -0.875, 0.125, 0.375, 0.625, 0.875, 1.125, 1.375, 1.625, 1.875 }; switch (p_what) { case NOTIFICATION_DRAW: { if (nine_patch_stretch && (mode == FILL_LEFT_TO_RIGHT || mode == FILL_RIGHT_TO_LEFT || mode == FILL_TOP_TO_BOTTOM || mode == FILL_BOTTOM_TO_TOP || mode == FILL_BILINEAR_LEFT_AND_RIGHT || mode == FILL_BILINEAR_TOP_AND_BOTTOM)) { @@ -452,7 +451,7 @@ void TextureProgressBar::_notification(int p_what) { float val = get_as_ratio() * rad_max_degrees / 360; if (val == 1) { Rect2 region = Rect2(progress_offset, s); - Rect2 source = Rect2(Point2(), s); + Rect2 source = Rect2(Point2(), progress->get_size()); draw_texture_rect_region(progress, region, source, tint_progress); } else if (val != 0) { Array pts; @@ -466,16 +465,14 @@ void TextureProgressBar::_notification(int p_what) { } float end = start + direction * val; - pts.append(start); - pts.append(end); float from = MIN(start, end); float to = MAX(start, end); - for (int i = 0; i < 12; i++) { - if (corners[i] > from && corners[i] < to) { - pts.append(corners[i]); - } + pts.append(from); + for (float corner = Math::floor(from * 4 + 0.5) * 0.25 + 0.125; corner < to; corner += 0.25) { + pts.append(corner); } - pts.sort(); + pts.append(to); + Vector<Point2> uvs; Vector<Point2> points; uvs.push_back(get_relative_center()); @@ -492,6 +489,8 @@ void TextureProgressBar::_notification(int p_what) { colors.push_back(tint_progress); draw_polygon(points, colors, uvs, progress); } + + // Draw a reference cross. if (Engine::get_singleton()->is_editor_hint()) { Point2 p; diff --git a/scene/gui/tree.cpp b/scene/gui/tree.cpp index 27e617bdd0..89caaaafd0 100644 --- a/scene/gui/tree.cpp +++ b/scene/gui/tree.cpp @@ -848,7 +848,7 @@ String TreeItem::get_button_tooltip(int p_column, int p_idx) const { void TreeItem::erase_button(int p_column, int p_idx) { ERR_FAIL_INDEX(p_column, cells.size()); ERR_FAIL_INDEX(p_idx, cells[p_column].buttons.size()); - cells.write[p_column].buttons.remove(p_idx); + cells.write[p_column].buttons.remove_at(p_idx); _changed_notify(p_column); } diff --git a/scene/gui/tree.h b/scene/gui/tree.h index 2e4e1bd364..d4caec614a 100644 --- a/scene/gui/tree.h +++ b/scene/gui/tree.h @@ -171,7 +171,7 @@ private: } if (parent) { if (!parent->children_cache.is_empty()) { - parent->children_cache.remove(get_index()); + parent->children_cache.remove_at(get_index()); } if (parent->first_child == this) { parent->first_child = next; diff --git a/scene/main/node.cpp b/scene/main/node.cpp index 44420fcc31..0d646ff2a9 100644 --- a/scene/main/node.cpp +++ b/scene/main/node.cpp @@ -114,7 +114,7 @@ void Node::_notification(int p_notification) { get_multiplayer()->scene_enter_exit_notify(data.scene_file_path, this, false); } } break; - case NOTIFICATION_PATH_CHANGED: { + case NOTIFICATION_PATH_RENAMED: { if (data.path_cache) { memdelete(data.path_cache); data.path_cache = nullptr; @@ -332,7 +332,7 @@ void Node::_move_child(Node *p_child, int p_pos, bool p_ignore_end) { int motion_from = MIN(p_pos, p_child->data.pos); int motion_to = MAX(p_pos, p_child->data.pos); - data.children.remove(p_child->data.pos); + data.children.remove_at(p_child->data.pos); data.children.insert(p_pos, p_child); if (data.tree) { @@ -899,7 +899,7 @@ void Node::set_name(const String &p_name) { data.parent->_validate_child_name(this); } - propagate_notification(NOTIFICATION_PATH_CHANGED); + propagate_notification(NOTIFICATION_PATH_RENAMED); if (is_inside_tree()) { emit_signal(SNAME("renamed")); @@ -1208,7 +1208,7 @@ void Node::remove_child(Node *p_child) { remove_child_notify(p_child); p_child->notification(NOTIFICATION_UNPARENTED); - data.children.remove(idx); + data.children.remove_at(idx); //update pointer and size child_count = data.children.size(); @@ -2829,7 +2829,7 @@ void Node::_bind_methods() { BIND_CONSTANT(NOTIFICATION_INSTANCED); BIND_CONSTANT(NOTIFICATION_DRAG_BEGIN); BIND_CONSTANT(NOTIFICATION_DRAG_END); - BIND_CONSTANT(NOTIFICATION_PATH_CHANGED); + BIND_CONSTANT(NOTIFICATION_PATH_RENAMED); BIND_CONSTANT(NOTIFICATION_INTERNAL_PROCESS); BIND_CONSTANT(NOTIFICATION_INTERNAL_PHYSICS_PROCESS); BIND_CONSTANT(NOTIFICATION_POST_ENTER_TREE); diff --git a/scene/main/node.h b/scene/main/node.h index 2dd32a2e1d..dc74a33580 100644 --- a/scene/main/node.h +++ b/scene/main/node.h @@ -256,7 +256,7 @@ public: NOTIFICATION_INSTANCED = 20, NOTIFICATION_DRAG_BEGIN = 21, NOTIFICATION_DRAG_END = 22, - NOTIFICATION_PATH_CHANGED = 23, + NOTIFICATION_PATH_RENAMED = 23, //NOTIFICATION_TRANSLATION_CHANGED = 24, moved below NOTIFICATION_INTERNAL_PROCESS = 25, NOTIFICATION_INTERNAL_PHYSICS_PROCESS = 26, diff --git a/scene/main/viewport.cpp b/scene/main/viewport.cpp index 1ecc3c762a..f9e96a0784 100644 --- a/scene/main/viewport.cpp +++ b/scene/main/viewport.cpp @@ -55,6 +55,7 @@ #include "scene/resources/world_2d.h" #include "scene/scene_string_names.h" #include "servers/audio_server.h" +#include "servers/rendering/rendering_server_globals.h" void ViewportTexture::setup_local_to_scene() { Node *local_scene = get_local_scene(); @@ -290,7 +291,7 @@ void Viewport::_sub_window_grab_focus(Window *p_window) { if (p_window->get_flag(Window::FLAG_NO_FOCUS)) { // Can only move to foreground, but no focus granted. SubWindow sw = gui.sub_windows[index]; - gui.sub_windows.remove(index); + gui.sub_windows.remove_at(index); gui.sub_windows.push_back(sw); index = gui.sub_windows.size() - 1; _sub_window_update_order(); @@ -318,7 +319,7 @@ void Viewport::_sub_window_grab_focus(Window *p_window) { { // Move to foreground. SubWindow sw = gui.sub_windows[index]; - gui.sub_windows.remove(index); + gui.sub_windows.remove_at(index); gui.sub_windows.push_back(sw); index = gui.sub_windows.size() - 1; _sub_window_update_order(); @@ -335,7 +336,7 @@ void Viewport::_sub_window_remove(Window *p_window) { for (int i = 0; i < gui.sub_windows.size(); i++) { if (gui.sub_windows[i].window == p_window) { RS::get_singleton()->free(gui.sub_windows[i].canvas_item); - gui.sub_windows.remove(i); + gui.sub_windows.remove_at(i); break; } } @@ -1515,8 +1516,9 @@ void Viewport::_gui_input_event(Ref<InputEvent> p_event) { if (gui.drag_data.get_type() != Variant::NIL && mb->get_button_index() == MouseButton::LEFT) { // Alternate drop use (when using force_drag(), as proposed by #5342). + gui.drag_successful = false; if (gui.mouse_focus) { - _gui_drop(gui.mouse_focus, pos, false); + gui.drag_successful = _gui_drop(gui.mouse_focus, pos, false); } gui.drag_data = Variant(); @@ -1534,8 +1536,9 @@ void Viewport::_gui_input_event(Ref<InputEvent> p_event) { _gui_cancel_tooltip(); } else { if (gui.drag_data.get_type() != Variant::NIL && mb->get_button_index() == MouseButton::LEFT) { + gui.drag_successful = false; if (gui.drag_mouse_over) { - _gui_drop(gui.drag_mouse_over, gui.drag_mouse_over_pos, false); + gui.drag_successful = _gui_drop(gui.drag_mouse_over, gui.drag_mouse_over_pos, false); } Control *drag_preview = _gui_get_drag_preview(); @@ -2895,6 +2898,10 @@ bool Viewport::gui_is_dragging() const { return gui.dragging; } +bool Viewport::gui_is_drag_successful() const { + return gui.drag_successful; +} + void Viewport::set_input_as_handled() { _drop_physics_mouseover(); @@ -3467,17 +3474,60 @@ bool Viewport::is_using_xr() { return use_xr; } -void Viewport::set_scale_3d(float p_scale_3d) { +void Viewport::set_scaling_3d_mode(Scaling3DMode p_scaling_3d_mode) { + if (scaling_3d_mode == p_scaling_3d_mode) { + return; + } + + scaling_3d_mode = p_scaling_3d_mode; + RS::get_singleton()->viewport_set_scaling_3d_mode(viewport, (RS::ViewportScaling3DMode)(int)p_scaling_3d_mode); +} + +Viewport::Scaling3DMode Viewport::get_scaling_3d_mode() const { + return scaling_3d_mode; +} + +void Viewport::set_scaling_3d_scale(float p_scaling_3d_scale) { // Clamp to reasonable values that are actually useful. // Values above 2.0 don't serve a practical purpose since the viewport // isn't displayed with mipmaps. - scale_3d = CLAMP(p_scale_3d, 0.1, 2.0); + scaling_3d_scale = CLAMP(p_scaling_3d_scale, 0.1, 2.0); + + RS::get_singleton()->viewport_set_scaling_3d_scale(viewport, scaling_3d_scale); +} + +float Viewport::get_scaling_3d_scale() const { + return scaling_3d_scale; +} + +void Viewport::set_fsr_sharpness(float p_fsr_sharpness) { + if (fsr_sharpness == p_fsr_sharpness) { + return; + } + + if (p_fsr_sharpness < 0.0f) { + p_fsr_sharpness = 0.0f; + } - RS::get_singleton()->viewport_set_scale_3d(viewport, scale_3d); + fsr_sharpness = p_fsr_sharpness; + RS::get_singleton()->viewport_set_fsr_sharpness(viewport, p_fsr_sharpness); } -float Viewport::get_scale_3d() const { - return scale_3d; +float Viewport::get_fsr_sharpness() const { + return fsr_sharpness; +} + +void Viewport::set_fsr_mipmap_bias(float p_fsr_mipmap_bias) { + if (fsr_mipmap_bias == p_fsr_mipmap_bias) { + return; + } + + fsr_mipmap_bias = p_fsr_mipmap_bias; + RS::get_singleton()->viewport_set_fsr_mipmap_bias(viewport, p_fsr_mipmap_bias); +} + +float Viewport::get_fsr_mipmap_bias() const { + return fsr_mipmap_bias; } #endif // _3D_DISABLED @@ -3534,6 +3584,7 @@ void Viewport::_bind_methods() { ClassDB::bind_method(D_METHOD("gui_get_drag_data"), &Viewport::gui_get_drag_data); ClassDB::bind_method(D_METHOD("gui_is_dragging"), &Viewport::gui_is_dragging); + ClassDB::bind_method(D_METHOD("gui_is_drag_successful"), &Viewport::gui_is_drag_successful); ClassDB::bind_method(D_METHOD("set_disable_input", "disable"), &Viewport::set_disable_input); ClassDB::bind_method(D_METHOD("is_input_disabled"), &Viewport::is_input_disabled); @@ -3604,12 +3655,20 @@ void Viewport::_bind_methods() { ClassDB::bind_method(D_METHOD("set_use_xr", "use"), &Viewport::set_use_xr); ClassDB::bind_method(D_METHOD("is_using_xr"), &Viewport::is_using_xr); - ClassDB::bind_method(D_METHOD("set_scale_3d", "scale"), &Viewport::set_scale_3d); - ClassDB::bind_method(D_METHOD("get_scale_3d"), &Viewport::get_scale_3d); + ClassDB::bind_method(D_METHOD("set_scaling_3d_mode", "scaling_3d_mode"), &Viewport::set_scaling_3d_mode); + ClassDB::bind_method(D_METHOD("get_scaling_3d_mode"), &Viewport::get_scaling_3d_mode); + + ClassDB::bind_method(D_METHOD("set_scaling_3d_scale", "scale"), &Viewport::set_scaling_3d_scale); + ClassDB::bind_method(D_METHOD("get_scaling_3d_scale"), &Viewport::get_scaling_3d_scale); + + ClassDB::bind_method(D_METHOD("set_fsr_sharpness", "fsr_sharpness"), &Viewport::set_fsr_sharpness); + ClassDB::bind_method(D_METHOD("get_fsr_sharpness"), &Viewport::get_fsr_sharpness); + + ClassDB::bind_method(D_METHOD("set_fsr_mipmap_bias", "fsr_mipmap_bias"), &Viewport::set_fsr_mipmap_bias); + ClassDB::bind_method(D_METHOD("get_fsr_mipmap_bias"), &Viewport::get_fsr_mipmap_bias); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "disable_3d"), "set_disable_3d", "is_3d_disabled"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "use_xr"), "set_use_xr", "is_using_xr"); - ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "scale_3d", PROPERTY_HINT_RANGE, "0.25,2.0,0.01"), "set_scale_3d", "get_scale_3d"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "audio_listener_enable_3d"), "set_as_audio_listener_3d", "is_audio_listener_3d"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "own_world_3d"), "set_use_own_world_3d", "is_using_own_world_3d"); ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "world_3d", PROPERTY_HINT_RESOURCE_TYPE, "World3D"), "set_world_3d", "get_world_3d"); @@ -3626,6 +3685,13 @@ void Viewport::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::BOOL, "use_occlusion_culling"), "set_use_occlusion_culling", "is_using_occlusion_culling"); ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "lod_threshold", PROPERTY_HINT_RANGE, "0,1024,0.1"), "set_lod_threshold", "get_lod_threshold"); ADD_PROPERTY(PropertyInfo(Variant::INT, "debug_draw", PROPERTY_HINT_ENUM, "Disabled,Unshaded,Overdraw,Wireframe"), "set_debug_draw", "get_debug_draw"); +#ifndef _3D_DISABLED + ADD_GROUP("Scaling 3D", ""); + ADD_PROPERTY(PropertyInfo(Variant::INT, "scaling_3d_mode", PROPERTY_HINT_ENUM, "Disabled (Slowest),Bilinear (Fastest),FSR (Fast)"), "set_scaling_3d_mode", "get_scaling_3d_mode"); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "scaling_3d_scale", PROPERTY_HINT_RANGE, "0.25,2.0,0.01"), "set_scaling_3d_scale", "get_scaling_3d_scale"); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "fsr_mipmap_bias", PROPERTY_HINT_RANGE, "-2,2,0.1"), "set_fsr_mipmap_bias", "get_fsr_mipmap_bias"); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "fsr_sharpness", PROPERTY_HINT_RANGE, "0,2,0.1"), "set_fsr_sharpness", "get_fsr_sharpness"); +#endif ADD_GROUP("Canvas Items", "canvas_item_"); ADD_PROPERTY(PropertyInfo(Variant::INT, "canvas_item_default_texture_filter", PROPERTY_HINT_ENUM, "Nearest,Linear,Linear Mipmap,Nearest Mipmap"), "set_default_canvas_item_texture_filter", "get_default_canvas_item_texture_filter"); ADD_PROPERTY(PropertyInfo(Variant::INT, "canvas_item_default_texture_repeat", PROPERTY_HINT_ENUM, "Disabled,Enabled,Mirror"), "set_default_canvas_item_texture_repeat", "get_default_canvas_item_texture_repeat"); @@ -3662,6 +3728,10 @@ void Viewport::_bind_methods() { BIND_ENUM_CONSTANT(SHADOW_ATLAS_QUADRANT_SUBDIV_1024); BIND_ENUM_CONSTANT(SHADOW_ATLAS_QUADRANT_SUBDIV_MAX); + BIND_ENUM_CONSTANT(SCALING_3D_MODE_BILINEAR); + BIND_ENUM_CONSTANT(SCALING_3D_MODE_FSR); + BIND_ENUM_CONSTANT(SCALING_3D_MODE_MAX); + BIND_ENUM_CONSTANT(MSAA_DISABLED); BIND_ENUM_CONSTANT(MSAA_2X); BIND_ENUM_CONSTANT(MSAA_4X); @@ -3765,7 +3835,16 @@ Viewport::Viewport() { ProjectSettings::get_singleton()->set_custom_property_info("gui/timers/tooltip_delay_sec", PropertyInfo(Variant::FLOAT, "gui/timers/tooltip_delay_sec", PROPERTY_HINT_RANGE, "0,5,0.01,or_greater")); // No negative numbers #ifndef _3D_DISABLED - set_scale_3d(GLOBAL_GET("rendering/3d/viewport/scale")); + Viewport::Scaling3DMode scaling_3d_mode = (Viewport::Scaling3DMode)(int)GLOBAL_GET("rendering/scaling_3d/mode"); + set_scaling_3d_mode(scaling_3d_mode); + + set_scaling_3d_scale(GLOBAL_GET("rendering/scaling_3d/scale")); + + float fsr_sharpness = GLOBAL_GET("rendering/scaling_3d/fsr_sharpness"); + set_fsr_sharpness(fsr_sharpness); + + float fsr_mipmap_bias = GLOBAL_GET("rendering/scaling_3d/fsr_mipmap_bias"); + set_fsr_mipmap_bias(fsr_mipmap_bias); #endif // _3D_DISABLED set_sdf_oversize(sdf_oversize); // Set to server. diff --git a/scene/main/viewport.h b/scene/main/viewport.h index 5320aea02a..38d43e1e59 100644 --- a/scene/main/viewport.h +++ b/scene/main/viewport.h @@ -89,6 +89,12 @@ class Viewport : public Node { GDCLASS(Viewport, Node); public: + enum Scaling3DMode { + SCALING_3D_MODE_BILINEAR, + SCALING_3D_MODE_FSR, + SCALING_3D_MODE_MAX + }; + enum ShadowAtlasQuadrantSubdiv { SHADOW_ATLAS_QUADRANT_SUBDIV_DISABLED, SHADOW_ATLAS_QUADRANT_SUBDIV_1, @@ -284,6 +290,11 @@ private: MSAA msaa = MSAA_DISABLED; ScreenSpaceAA screen_space_aa = SCREEN_SPACE_AA_DISABLED; + + Scaling3DMode scaling_3d_mode = SCALING_3D_MODE_BILINEAR; + float scaling_3d_scale = 1.0; + float fsr_sharpness = 0.2f; + float fsr_mipmap_bias = 0.0f; bool use_debanding = false; float lod_threshold = 1.0; bool use_occlusion_culling = false; @@ -348,6 +359,7 @@ private: List<Control *> roots; int canvas_sort_index = 0; //for sorting items with canvas as root bool dragging = false; + bool drag_successful = false; bool embed_subwindows_hint = false; bool embedding_subwindows = false; @@ -503,6 +515,18 @@ public: void set_screen_space_aa(ScreenSpaceAA p_screen_space_aa); ScreenSpaceAA get_screen_space_aa() const; + void set_scaling_3d_mode(Scaling3DMode p_scaling_3d_mode); + Scaling3DMode get_scaling_3d_mode() const; + + void set_scaling_3d_scale(float p_scaling_3d_scale); + float get_scaling_3d_scale() const; + + void set_fsr_sharpness(float p_fsr_sharpness); + float get_fsr_sharpness() const; + + void set_fsr_mipmap_bias(float p_fsr_mipmap_bias); + float get_fsr_mipmap_bias() const; + void set_use_debanding(bool p_use_debanding); bool is_using_debanding() const; @@ -556,6 +580,7 @@ public: bool is_handling_input_locally() const; bool gui_is_dragging() const; + bool gui_is_drag_successful() const; Control *gui_find_control(const Point2 &p_global); @@ -584,7 +609,6 @@ public: #ifndef _3D_DISABLED bool use_xr = false; - float scale_3d = 1.0; friend class AudioListener3D; AudioListener3D *audio_listener_3d = nullptr; Set<AudioListener3D *> audio_listener_3d_set; @@ -655,9 +679,6 @@ public: void set_use_xr(bool p_use_xr); bool is_using_xr(); - - void set_scale_3d(float p_scale_3d); - float get_scale_3d() const; #endif // _3D_DISABLED Viewport(); @@ -712,6 +733,7 @@ public: SubViewport(); ~SubViewport(); }; +VARIANT_ENUM_CAST(Viewport::Scaling3DMode); VARIANT_ENUM_CAST(SubViewport::UpdateMode); VARIANT_ENUM_CAST(Viewport::ShadowAtlasQuadrantSubdiv); VARIANT_ENUM_CAST(Viewport::MSAA); diff --git a/scene/main/window.cpp b/scene/main/window.cpp index 5da5a183f7..20f8b30dc6 100644 --- a/scene/main/window.cpp +++ b/scene/main/window.cpp @@ -88,6 +88,10 @@ Size2i Window::get_size() const { return size; } +void Window::reset_size() { + set_size(Size2i()); +} + Size2i Window::get_real_size() const { if (window_id != DisplayServer::INVALID_WINDOW_ID) { return DisplayServer::get_singleton()->window_get_real_size(window_id); @@ -1410,6 +1414,7 @@ void Window::_bind_methods() { ClassDB::bind_method(D_METHOD("set_size", "size"), &Window::set_size); ClassDB::bind_method(D_METHOD("get_size"), &Window::get_size); + ClassDB::bind_method(D_METHOD("reset_size"), &Window::reset_size); ClassDB::bind_method(D_METHOD("get_real_size"), &Window::get_real_size); diff --git a/scene/main/window.h b/scene/main/window.h index def6eab7b8..0b1075ff76 100644 --- a/scene/main/window.h +++ b/scene/main/window.h @@ -178,6 +178,7 @@ public: void set_size(const Size2i &p_size); Size2i get_size() const; + void reset_size(); Size2i get_real_size() const; diff --git a/scene/resources/animation.cpp b/scene/resources/animation.cpp index 29aca6b321..e3cf9183a0 100644 --- a/scene/resources/animation.cpp +++ b/scene/resources/animation.cpp @@ -335,7 +335,7 @@ bool Animation::_set(const StringName &p_name, const Variant &p_value) { bt->values.write[i].value.in_handle.y = rv[i * 6 + 2]; bt->values.write[i].value.out_handle.x = rv[i * 6 + 3]; bt->values.write[i].value.out_handle.y = rv[i * 6 + 4]; - bt->values.write[i].value.handle_mode = (HandleMode)rv[i * 6 + 5]; + bt->values.write[i].value.handle_mode = static_cast<HandleMode>((int)rv[i * 6 + 5]); } } @@ -930,7 +930,7 @@ void Animation::remove_track(int p_track) { } memdelete(t); - tracks.remove(p_track); + tracks.remove_at(p_track); emit_changed(); emit_signal(SceneStringNames::get_singleton()->tracks_changed); } @@ -1320,7 +1320,7 @@ void Animation::track_remove_key(int p_track, int p_idx) { ERR_FAIL_COND(tt->compressed_track >= 0); ERR_FAIL_INDEX(p_idx, tt->positions.size()); - tt->positions.remove(p_idx); + tt->positions.remove_at(p_idx); } break; case TYPE_ROTATION_3D: { @@ -1329,7 +1329,7 @@ void Animation::track_remove_key(int p_track, int p_idx) { ERR_FAIL_COND(rt->compressed_track >= 0); ERR_FAIL_INDEX(p_idx, rt->rotations.size()); - rt->rotations.remove(p_idx); + rt->rotations.remove_at(p_idx); } break; case TYPE_SCALE_3D: { @@ -1338,7 +1338,7 @@ void Animation::track_remove_key(int p_track, int p_idx) { ERR_FAIL_COND(st->compressed_track >= 0); ERR_FAIL_INDEX(p_idx, st->scales.size()); - st->scales.remove(p_idx); + st->scales.remove_at(p_idx); } break; case TYPE_BLEND_SHAPE: { @@ -1347,37 +1347,37 @@ void Animation::track_remove_key(int p_track, int p_idx) { ERR_FAIL_COND(bst->compressed_track >= 0); ERR_FAIL_INDEX(p_idx, bst->blend_shapes.size()); - bst->blend_shapes.remove(p_idx); + bst->blend_shapes.remove_at(p_idx); } break; case TYPE_VALUE: { ValueTrack *vt = static_cast<ValueTrack *>(t); ERR_FAIL_INDEX(p_idx, vt->values.size()); - vt->values.remove(p_idx); + vt->values.remove_at(p_idx); } break; case TYPE_METHOD: { MethodTrack *mt = static_cast<MethodTrack *>(t); ERR_FAIL_INDEX(p_idx, mt->methods.size()); - mt->methods.remove(p_idx); + mt->methods.remove_at(p_idx); } break; case TYPE_BEZIER: { BezierTrack *bz = static_cast<BezierTrack *>(t); ERR_FAIL_INDEX(p_idx, bz->values.size()); - bz->values.remove(p_idx); + bz->values.remove_at(p_idx); } break; case TYPE_AUDIO: { AudioTrack *ad = static_cast<AudioTrack *>(t); ERR_FAIL_INDEX(p_idx, ad->values.size()); - ad->values.remove(p_idx); + ad->values.remove_at(p_idx); } break; case TYPE_ANIMATION: { AnimationTrack *an = static_cast<AnimationTrack *>(t); ERR_FAIL_INDEX(p_idx, an->values.size()); - an->values.remove(p_idx); + an->values.remove_at(p_idx); } break; } @@ -1634,7 +1634,7 @@ void Animation::track_insert_key(int p_track, double p_time, const Variant &p_ke k.value.in_handle.y = arr[2]; k.value.out_handle.x = arr[3]; k.value.out_handle.y = arr[4]; - k.value.handle_mode = (HandleMode) int(arr[5]); + k.value.handle_mode = static_cast<HandleMode>((int)arr[5]); _insert(p_time, bt->values, k); } break; @@ -1905,7 +1905,7 @@ void Animation::track_set_key_time(int p_track, int p_key_idx, double p_time) { ERR_FAIL_INDEX(p_key_idx, tt->positions.size()); TKey<Vector3> key = tt->positions[p_key_idx]; key.time = p_time; - tt->positions.remove(p_key_idx); + tt->positions.remove_at(p_key_idx); _insert(p_time, tt->positions, key); return; } @@ -1915,7 +1915,7 @@ void Animation::track_set_key_time(int p_track, int p_key_idx, double p_time) { ERR_FAIL_INDEX(p_key_idx, tt->rotations.size()); TKey<Quaternion> key = tt->rotations[p_key_idx]; key.time = p_time; - tt->rotations.remove(p_key_idx); + tt->rotations.remove_at(p_key_idx); _insert(p_time, tt->rotations, key); return; } @@ -1925,7 +1925,7 @@ void Animation::track_set_key_time(int p_track, int p_key_idx, double p_time) { ERR_FAIL_INDEX(p_key_idx, tt->scales.size()); TKey<Vector3> key = tt->scales[p_key_idx]; key.time = p_time; - tt->scales.remove(p_key_idx); + tt->scales.remove_at(p_key_idx); _insert(p_time, tt->scales, key); return; } @@ -1935,7 +1935,7 @@ void Animation::track_set_key_time(int p_track, int p_key_idx, double p_time) { ERR_FAIL_INDEX(p_key_idx, tt->blend_shapes.size()); TKey<float> key = tt->blend_shapes[p_key_idx]; key.time = p_time; - tt->blend_shapes.remove(p_key_idx); + tt->blend_shapes.remove_at(p_key_idx); _insert(p_time, tt->blend_shapes, key); return; } @@ -1944,7 +1944,7 @@ void Animation::track_set_key_time(int p_track, int p_key_idx, double p_time) { ERR_FAIL_INDEX(p_key_idx, vt->values.size()); TKey<Variant> key = vt->values[p_key_idx]; key.time = p_time; - vt->values.remove(p_key_idx); + vt->values.remove_at(p_key_idx); _insert(p_time, vt->values, key); return; } @@ -1953,7 +1953,7 @@ void Animation::track_set_key_time(int p_track, int p_key_idx, double p_time) { ERR_FAIL_INDEX(p_key_idx, mt->methods.size()); MethodKey key = mt->methods[p_key_idx]; key.time = p_time; - mt->methods.remove(p_key_idx); + mt->methods.remove_at(p_key_idx); _insert(p_time, mt->methods, key); return; } @@ -1962,7 +1962,7 @@ void Animation::track_set_key_time(int p_track, int p_key_idx, double p_time) { ERR_FAIL_INDEX(p_key_idx, bt->values.size()); TKey<BezierKey> key = bt->values[p_key_idx]; key.time = p_time; - bt->values.remove(p_key_idx); + bt->values.remove_at(p_key_idx); _insert(p_time, bt->values, key); return; } @@ -1971,7 +1971,7 @@ void Animation::track_set_key_time(int p_track, int p_key_idx, double p_time) { ERR_FAIL_INDEX(p_key_idx, at->values.size()); TKey<AudioKey> key = at->values[p_key_idx]; key.time = p_time; - at->values.remove(p_key_idx); + at->values.remove_at(p_key_idx); _insert(p_time, at->values, key); return; } @@ -1980,7 +1980,7 @@ void Animation::track_set_key_time(int p_track, int p_key_idx, double p_time) { ERR_FAIL_INDEX(p_key_idx, at->values.size()); TKey<StringName> key = at->values[p_key_idx]; key.time = p_time; - at->values.remove(p_key_idx); + at->values.remove_at(p_key_idx); _insert(p_time, at->values, key); return; } @@ -2155,7 +2155,7 @@ void Animation::track_set_key_value(int p_track, int p_key_idx, const Variant &p bt->values.write[p_key_idx].value.in_handle.y = arr[2]; bt->values.write[p_key_idx].value.out_handle.x = arr[3]; bt->values.write[p_key_idx].value.out_handle.y = arr[4]; - bt->values.write[p_key_idx].value.handle_mode = (HandleMode) int(arr[5]); + bt->values.write[p_key_idx].value.handle_mode = static_cast<HandleMode>((int)arr[5]); } break; case TYPE_AUDIO: { @@ -3679,7 +3679,7 @@ void Animation::track_move_to(int p_track, int p_to_index) { } Track *track = tracks.get(p_track); - tracks.remove(p_track); + tracks.remove_at(p_track); // Take into account that the position of the tracks that come after the one removed will change. tracks.insert(p_to_index > p_track ? p_to_index - 1 : p_to_index, track); @@ -4058,7 +4058,7 @@ void Animation::_position_track_optimize(int p_idx, real_t p_allowed_linear_err, prev_erased = true; } - tt->positions.remove(i); + tt->positions.remove_at(i); i--; } else { @@ -4093,7 +4093,7 @@ void Animation::_rotation_track_optimize(int p_idx, real_t p_allowed_angular_err prev_erased = true; } - tt->rotations.remove(i); + tt->rotations.remove_at(i); i--; } else { @@ -4127,7 +4127,7 @@ void Animation::_scale_track_optimize(int p_idx, real_t p_allowed_linear_err) { prev_erased = true; } - tt->scales.remove(i); + tt->scales.remove_at(i); i--; } else { @@ -4162,7 +4162,7 @@ void Animation::_blend_shape_track_optimize(int p_idx, real_t p_allowed_linear_e prev_erased = true; } - tt->blend_shapes.remove(i); + tt->blend_shapes.remove_at(i); i--; } else { diff --git a/scene/resources/curve.cpp b/scene/resources/curve.cpp index b530a72033..b87639de6a 100644 --- a/scene/resources/curve.cpp +++ b/scene/resources/curve.cpp @@ -136,7 +136,7 @@ void Curve::clean_dupes() { for (int i = 1; i < _points.size(); ++i) { real_t diff = _points[i - 1].pos.x - _points[i].pos.x; if (diff <= CMP_EPSILON) { - _points.remove(i); + _points.remove_at(i); --i; dirty = true; } @@ -207,7 +207,7 @@ Curve::TangentMode Curve::get_point_right_mode(int i) const { void Curve::remove_point(int p_index) { ERR_FAIL_INDEX(p_index, _points.size()); - _points.remove(p_index); + _points.remove_at(p_index); mark_dirty(); } @@ -591,7 +591,7 @@ Vector2 Curve2D::get_point_out(int p_index) const { void Curve2D::remove_point(int p_index) { ERR_FAIL_INDEX(p_index, points.size()); - points.remove(p_index); + points.remove_at(p_index); baked_cache_dirty = true; emit_signal(CoreStringNames::get_singleton()->changed); } @@ -1095,7 +1095,7 @@ Vector3 Curve3D::get_point_out(int p_index) const { void Curve3D::remove_point(int p_index) { ERR_FAIL_INDEX(p_index, points.size()); - points.remove(p_index); + points.remove_at(p_index); baked_cache_dirty = true; emit_signal(CoreStringNames::get_singleton()->changed); } diff --git a/scene/resources/font.cpp b/scene/resources/font.cpp index d9de47afc7..d88a2c557b 100644 --- a/scene/resources/font.cpp +++ b/scene/resources/font.cpp @@ -88,6 +88,9 @@ void FontData::_bind_methods() { ClassDB::bind_method(D_METHOD("set_msdf_size", "msdf_size"), &FontData::set_msdf_size); ClassDB::bind_method(D_METHOD("get_msdf_size"), &FontData::get_msdf_size); + ClassDB::bind_method(D_METHOD("set_fixed_size", "fixed_size"), &FontData::set_fixed_size); + ClassDB::bind_method(D_METHOD("get_fixed_size"), &FontData::get_fixed_size); + ClassDB::bind_method(D_METHOD("set_force_autohinter", "force_autohinter"), &FontData::set_force_autohinter); ClassDB::bind_method(D_METHOD("is_force_autohinter"), &FontData::is_force_autohinter); @@ -749,7 +752,7 @@ void FontData::remove_cache(int p_cache_index) { if (cache[p_cache_index].is_valid()) { TS->free(cache.write[p_cache_index]); } - cache.remove(p_cache_index); + cache.remove_at(p_cache_index); emit_changed(); } @@ -1353,8 +1356,8 @@ void Font::remove_data(int p_idx) { data.write[p_idx]->disconnect(SNAME("changed"), callable_mp(this, &Font::_data_changed)); } - data.remove(p_idx); - rids.remove(p_idx); + data.remove_at(p_idx); + rids.remove_at(p_idx); cache.clear(); cache_wrap.clear(); diff --git a/scene/resources/gradient.cpp b/scene/resources/gradient.cpp index 4559b4ce0a..95ec141df6 100644 --- a/scene/resources/gradient.cpp +++ b/scene/resources/gradient.cpp @@ -144,7 +144,7 @@ void Gradient::add_point(float p_offset, const Color &p_color) { void Gradient::remove_point(int p_index) { ERR_FAIL_INDEX(p_index, points.size()); ERR_FAIL_COND(points.size() <= 1); - points.remove(p_index); + points.remove_at(p_index); emit_signal(CoreStringNames::get_singleton()->changed); } diff --git a/scene/resources/packed_scene.cpp b/scene/resources/packed_scene.cpp index 3f4765d20f..c39f59d535 100644 --- a/scene/resources/packed_scene.cpp +++ b/scene/resources/packed_scene.cpp @@ -62,7 +62,7 @@ static Array _sanitize_node_pinned_properties(Node *p_node) { if (storable_properties.has(pinned[i])) { i++; } else { - pinned.remove(i); + pinned.remove_at(i); } } while (i < pinned.size()); if (pinned.is_empty()) { diff --git a/scene/resources/resource_format_text.cpp b/scene/resources/resource_format_text.cpp index ea3b72af1b..cead42b4e2 100644 --- a/scene/resources/resource_format_text.cpp +++ b/scene/resources/resource_format_text.cpp @@ -350,7 +350,7 @@ Ref<PackedScene> ResourceLoaderText::_parse_node_tag(VariantParser::ResourcePars } else if (next_tag.name == "editable") { if (!next_tag.fields.has("path")) { error = ERR_FILE_CORRUPT; - error_text = "missing 'path' field from connection tag"; + error_text = "missing 'path' field from editable tag"; _printerr(); return Ref<PackedScene>(); } diff --git a/scene/resources/skeleton_modification_stack_2d.cpp b/scene/resources/skeleton_modification_stack_2d.cpp index 25c3e9d2ef..e596390f78 100644 --- a/scene/resources/skeleton_modification_stack_2d.cpp +++ b/scene/resources/skeleton_modification_stack_2d.cpp @@ -172,7 +172,7 @@ void SkeletonModificationStack2D::add_modification(Ref<SkeletonModification2D> p void SkeletonModificationStack2D::delete_modification(int p_mod_idx) { ERR_FAIL_INDEX(p_mod_idx, modifications.size()); - modifications.remove(p_mod_idx); + modifications.remove_at(p_mod_idx); #ifdef TOOLS_ENABLED set_editor_gizmos_dirty(true); diff --git a/scene/resources/skeleton_modification_stack_3d.cpp b/scene/resources/skeleton_modification_stack_3d.cpp index 301811f0b6..e5b7771251 100644 --- a/scene/resources/skeleton_modification_stack_3d.cpp +++ b/scene/resources/skeleton_modification_stack_3d.cpp @@ -133,7 +133,7 @@ void SkeletonModificationStack3D::add_modification(Ref<SkeletonModification3D> p void SkeletonModificationStack3D::delete_modification(int p_mod_idx) { const int modifications_size = modifications.size(); ERR_FAIL_INDEX(p_mod_idx, modifications_size); - modifications.remove(p_mod_idx); + modifications.remove_at(p_mod_idx); } void SkeletonModificationStack3D::set_modification(int p_mod_idx, Ref<SkeletonModification3D> p_mod) { @@ -141,7 +141,7 @@ void SkeletonModificationStack3D::set_modification(int p_mod_idx, Ref<SkeletonMo ERR_FAIL_INDEX(p_mod_idx, modifications_size); if (p_mod == nullptr) { - modifications.remove(p_mod_idx); + modifications.remove_at(p_mod_idx); } else { p_mod->_setup_modification(this); modifications[p_mod_idx] = p_mod; diff --git a/scene/resources/sky_material.cpp b/scene/resources/sky_material.cpp index de94c92cac..ff388e288c 100644 --- a/scene/resources/sky_material.cpp +++ b/scene/resources/sky_material.cpp @@ -37,7 +37,7 @@ RID ProceduralSkyMaterial::shader; void ProceduralSkyMaterial::set_sky_top_color(const Color &p_sky_top) { sky_top_color = p_sky_top; - RS::get_singleton()->material_set_param(_get_material(), "sky_top_color", sky_top_color.to_linear()); + RS::get_singleton()->material_set_param(_get_material(), "sky_top_color", sky_top_color); } Color ProceduralSkyMaterial::get_sky_top_color() const { @@ -46,7 +46,7 @@ Color ProceduralSkyMaterial::get_sky_top_color() const { void ProceduralSkyMaterial::set_sky_horizon_color(const Color &p_sky_horizon) { sky_horizon_color = p_sky_horizon; - RS::get_singleton()->material_set_param(_get_material(), "sky_horizon_color", sky_horizon_color.to_linear()); + RS::get_singleton()->material_set_param(_get_material(), "sky_horizon_color", sky_horizon_color); } Color ProceduralSkyMaterial::get_sky_horizon_color() const { @@ -73,7 +73,7 @@ float ProceduralSkyMaterial::get_sky_energy() const { void ProceduralSkyMaterial::set_ground_bottom_color(const Color &p_ground_bottom) { ground_bottom_color = p_ground_bottom; - RS::get_singleton()->material_set_param(_get_material(), "ground_bottom_color", ground_bottom_color.to_linear()); + RS::get_singleton()->material_set_param(_get_material(), "ground_bottom_color", ground_bottom_color); } Color ProceduralSkyMaterial::get_ground_bottom_color() const { @@ -82,7 +82,7 @@ Color ProceduralSkyMaterial::get_ground_bottom_color() const { void ProceduralSkyMaterial::set_ground_horizon_color(const Color &p_ground_horizon) { ground_horizon_color = p_ground_horizon; - RS::get_singleton()->material_set_param(_get_material(), "ground_horizon_color", ground_horizon_color.to_linear()); + RS::get_singleton()->material_set_param(_get_material(), "ground_horizon_color", ground_horizon_color); } Color ProceduralSkyMaterial::get_ground_horizon_color() const { @@ -564,10 +564,10 @@ void PhysicalSkyMaterial::_update_shader() { shader_type sky; uniform float rayleigh : hint_range(0, 64) = 2.0; -uniform vec4 rayleigh_color : hint_color = vec4(0.056, 0.14, 0.3, 1.0); +uniform vec4 rayleigh_color : hint_color = vec4(0.26, 0.41, 0.58, 1.0); uniform float mie : hint_range(0, 1) = 0.005; uniform float mie_eccentricity : hint_range(-1, 1) = 0.8; -uniform vec4 mie_color : hint_color = vec4(0.36, 0.56, 0.82, 1.0); +uniform vec4 mie_color : hint_color = vec4(0.63, 0.77, 0.92, 1.0); uniform float turbidity : hint_range(0, 1000) = 10.0; uniform float sun_disk_scale : hint_range(0, 360) = 1.0; @@ -661,10 +661,10 @@ void sky() { PhysicalSkyMaterial::PhysicalSkyMaterial() { set_rayleigh_coefficient(2.0); - set_rayleigh_color(Color(0.056, 0.14, 0.3)); + set_rayleigh_color(Color(0.26, 0.41, 0.58)); set_mie_coefficient(0.005); set_mie_eccentricity(0.8); - set_mie_color(Color(0.36, 0.56, 0.82)); + set_mie_color(Color(0.63, 0.77, 0.92)); set_turbidity(10.0); set_sun_disk_scale(1.0); set_ground_color(Color(1.0, 1.0, 1.0)); diff --git a/scene/resources/sprite_frames.cpp b/scene/resources/sprite_frames.cpp index 5524d59dc7..71ed96cf15 100644 --- a/scene/resources/sprite_frames.cpp +++ b/scene/resources/sprite_frames.cpp @@ -56,7 +56,7 @@ void SpriteFrames::remove_frame(const StringName &p_anim, int p_idx) { Map<StringName, Anim>::Element *E = animations.find(p_anim); ERR_FAIL_COND_MSG(!E, "Animation '" + String(p_anim) + "' doesn't exist."); - E->get().frames.remove(p_idx); + E->get().frames.remove_at(p_idx); emit_changed(); } diff --git a/scene/resources/syntax_highlighter.cpp b/scene/resources/syntax_highlighter.cpp index 52a3abf74d..cfb5ac2ca6 100644 --- a/scene/resources/syntax_highlighter.cpp +++ b/scene/resources/syntax_highlighter.cpp @@ -501,7 +501,7 @@ void CodeHighlighter::add_color_region(const String &p_start_key, const String & void CodeHighlighter::remove_color_region(const String &p_start_key) { for (int i = 0; i < color_regions.size(); i++) { if (color_regions[i].start_key == p_start_key) { - color_regions.remove(i); + color_regions.remove_at(i); break; } } diff --git a/scene/resources/tile_set.cpp b/scene/resources/tile_set.cpp index 8c92445338..34fe7c0b87 100644 --- a/scene/resources/tile_set.cpp +++ b/scene/resources/tile_set.cpp @@ -560,7 +560,7 @@ void TileSet::move_occlusion_layer(int p_from_index, int p_to_pos) { ERR_FAIL_INDEX(p_from_index, occlusion_layers.size()); ERR_FAIL_INDEX(p_to_pos, occlusion_layers.size() + 1); occlusion_layers.insert(p_to_pos, occlusion_layers[p_from_index]); - occlusion_layers.remove(p_to_pos < p_from_index ? p_from_index + 1 : p_from_index); + occlusion_layers.remove_at(p_to_pos < p_from_index ? p_from_index + 1 : p_from_index); for (KeyValue<int, Ref<TileSetSource>> source : sources) { source.value->move_occlusion_layer(p_from_index, p_to_pos); } @@ -570,7 +570,7 @@ void TileSet::move_occlusion_layer(int p_from_index, int p_to_pos) { void TileSet::remove_occlusion_layer(int p_index) { ERR_FAIL_INDEX(p_index, occlusion_layers.size()); - occlusion_layers.remove(p_index); + occlusion_layers.remove_at(p_index); for (KeyValue<int, Ref<TileSetSource>> source : sources) { source.value->remove_occlusion_layer(p_index); } @@ -623,7 +623,7 @@ void TileSet::move_physics_layer(int p_from_index, int p_to_pos) { ERR_FAIL_INDEX(p_from_index, physics_layers.size()); ERR_FAIL_INDEX(p_to_pos, physics_layers.size() + 1); physics_layers.insert(p_to_pos, physics_layers[p_from_index]); - physics_layers.remove(p_to_pos < p_from_index ? p_from_index + 1 : p_from_index); + physics_layers.remove_at(p_to_pos < p_from_index ? p_from_index + 1 : p_from_index); for (KeyValue<int, Ref<TileSetSource>> source : sources) { source.value->move_physics_layer(p_from_index, p_to_pos); } @@ -633,7 +633,7 @@ void TileSet::move_physics_layer(int p_from_index, int p_to_pos) { void TileSet::remove_physics_layer(int p_index) { ERR_FAIL_INDEX(p_index, physics_layers.size()); - physics_layers.remove(p_index); + physics_layers.remove_at(p_index); for (KeyValue<int, Ref<TileSetSource>> source : sources) { source.value->remove_physics_layer(p_index); } @@ -698,7 +698,7 @@ void TileSet::move_terrain_set(int p_from_index, int p_to_pos) { ERR_FAIL_INDEX(p_from_index, terrain_sets.size()); ERR_FAIL_INDEX(p_to_pos, terrain_sets.size() + 1); terrain_sets.insert(p_to_pos, terrain_sets[p_from_index]); - terrain_sets.remove(p_to_pos < p_from_index ? p_from_index + 1 : p_from_index); + terrain_sets.remove_at(p_to_pos < p_from_index ? p_from_index + 1 : p_from_index); for (KeyValue<int, Ref<TileSetSource>> source : sources) { source.value->move_terrain_set(p_from_index, p_to_pos); } @@ -709,7 +709,7 @@ void TileSet::move_terrain_set(int p_from_index, int p_to_pos) { void TileSet::remove_terrain_set(int p_index) { ERR_FAIL_INDEX(p_index, terrain_sets.size()); - terrain_sets.remove(p_index); + terrain_sets.remove_at(p_index); for (KeyValue<int, Ref<TileSetSource>> source : sources) { source.value->remove_terrain_set(p_index); } @@ -772,7 +772,7 @@ void TileSet::move_terrain(int p_terrain_set, int p_from_index, int p_to_pos) { ERR_FAIL_INDEX(p_from_index, terrains.size()); ERR_FAIL_INDEX(p_to_pos, terrains.size() + 1); terrains.insert(p_to_pos, terrains[p_from_index]); - terrains.remove(p_to_pos < p_from_index ? p_from_index + 1 : p_from_index); + terrains.remove_at(p_to_pos < p_from_index ? p_from_index + 1 : p_from_index); for (KeyValue<int, Ref<TileSetSource>> source : sources) { source.value->move_terrain(p_terrain_set, p_from_index, p_to_pos); } @@ -786,7 +786,7 @@ void TileSet::remove_terrain(int p_terrain_set, int p_index) { Vector<Terrain> &terrains = terrain_sets.write[p_terrain_set].terrains; ERR_FAIL_INDEX(p_index, terrains.size()); - terrains.remove(p_index); + terrains.remove_at(p_index); for (KeyValue<int, Ref<TileSetSource>> source : sources) { source.value->remove_terrain(p_terrain_set, p_index); } @@ -941,7 +941,7 @@ void TileSet::move_navigation_layer(int p_from_index, int p_to_pos) { ERR_FAIL_INDEX(p_from_index, navigation_layers.size()); ERR_FAIL_INDEX(p_to_pos, navigation_layers.size() + 1); navigation_layers.insert(p_to_pos, navigation_layers[p_from_index]); - navigation_layers.remove(p_to_pos < p_from_index ? p_from_index + 1 : p_from_index); + navigation_layers.remove_at(p_to_pos < p_from_index ? p_from_index + 1 : p_from_index); for (KeyValue<int, Ref<TileSetSource>> source : sources) { source.value->move_navigation_layer(p_from_index, p_to_pos); } @@ -951,7 +951,7 @@ void TileSet::move_navigation_layer(int p_from_index, int p_to_pos) { void TileSet::remove_navigation_layer(int p_index) { ERR_FAIL_INDEX(p_index, navigation_layers.size()); - navigation_layers.remove(p_index); + navigation_layers.remove_at(p_index); for (KeyValue<int, Ref<TileSetSource>> source : sources) { source.value->remove_navigation_layer(p_index); } @@ -994,7 +994,7 @@ void TileSet::move_custom_data_layer(int p_from_index, int p_to_pos) { ERR_FAIL_INDEX(p_from_index, custom_data_layers.size()); ERR_FAIL_INDEX(p_to_pos, custom_data_layers.size() + 1); custom_data_layers.insert(p_to_pos, custom_data_layers[p_from_index]); - custom_data_layers.remove(p_to_pos < p_from_index ? p_from_index + 1 : p_from_index); + custom_data_layers.remove_at(p_to_pos < p_from_index ? p_from_index + 1 : p_from_index); for (KeyValue<int, Ref<TileSetSource>> source : sources) { source.value->move_custom_data_layer(p_from_index, p_to_pos); } @@ -1004,7 +1004,7 @@ void TileSet::move_custom_data_layer(int p_from_index, int p_to_pos) { void TileSet::remove_custom_data_layer(int p_index) { ERR_FAIL_INDEX(p_index, custom_data_layers.size()); - custom_data_layers.remove(p_index); + custom_data_layers.remove_at(p_index); for (KeyValue<String, int> E : custom_data_layers_by_name) { if (E.value == p_index) { custom_data_layers_by_name.erase(E.key); @@ -1340,7 +1340,7 @@ Ref<TileMapPattern> TileSet::get_pattern(int p_index) { void TileSet::remove_pattern(int p_index) { ERR_FAIL_INDEX(p_index, (int)patterns.size()); - patterns.remove(p_index); + patterns.remove_at(p_index); emit_changed(); } @@ -4707,12 +4707,12 @@ void TileData::move_occlusion_layer(int p_from_index, int p_to_pos) { ERR_FAIL_INDEX(p_from_index, occluders.size()); ERR_FAIL_INDEX(p_to_pos, occluders.size() + 1); occluders.insert(p_to_pos, occluders[p_from_index]); - occluders.remove(p_to_pos < p_from_index ? p_from_index + 1 : p_from_index); + occluders.remove_at(p_to_pos < p_from_index ? p_from_index + 1 : p_from_index); } void TileData::remove_occlusion_layer(int p_index) { ERR_FAIL_INDEX(p_index, occluders.size()); - occluders.remove(p_index); + occluders.remove_at(p_index); } void TileData::add_physics_layer(int p_to_pos) { @@ -4727,12 +4727,12 @@ void TileData::move_physics_layer(int p_from_index, int p_to_pos) { ERR_FAIL_INDEX(p_from_index, physics.size()); ERR_FAIL_INDEX(p_to_pos, physics.size() + 1); physics.insert(p_to_pos, physics[p_from_index]); - physics.remove(p_to_pos < p_from_index ? p_from_index + 1 : p_from_index); + physics.remove_at(p_to_pos < p_from_index ? p_from_index + 1 : p_from_index); } void TileData::remove_physics_layer(int p_index) { ERR_FAIL_INDEX(p_index, physics.size()); - physics.remove(p_index); + physics.remove_at(p_index); } void TileData::add_terrain_set(int p_to_pos) { @@ -4816,12 +4816,12 @@ void TileData::move_navigation_layer(int p_from_index, int p_to_pos) { ERR_FAIL_INDEX(p_from_index, navigation.size()); ERR_FAIL_INDEX(p_to_pos, navigation.size() + 1); navigation.insert(p_to_pos, navigation[p_from_index]); - navigation.remove(p_to_pos < p_from_index ? p_from_index + 1 : p_from_index); + navigation.remove_at(p_to_pos < p_from_index ? p_from_index + 1 : p_from_index); } void TileData::remove_navigation_layer(int p_index) { ERR_FAIL_INDEX(p_index, navigation.size()); - navigation.remove(p_index); + navigation.remove_at(p_index); } void TileData::add_custom_data_layer(int p_to_pos) { @@ -4836,12 +4836,12 @@ void TileData::move_custom_data_layer(int p_from_index, int p_to_pos) { ERR_FAIL_INDEX(p_from_index, custom_data.size()); ERR_FAIL_INDEX(p_to_pos, custom_data.size() + 1); custom_data.insert(p_to_pos, navigation[p_from_index]); - custom_data.remove(p_to_pos < p_from_index ? p_from_index + 1 : p_from_index); + custom_data.remove_at(p_to_pos < p_from_index ? p_from_index + 1 : p_from_index); } void TileData::remove_custom_data_layer(int p_index) { ERR_FAIL_INDEX(p_index, custom_data.size()); - custom_data.remove(p_index); + custom_data.remove_at(p_index); } void TileData::reset_state() { @@ -5019,7 +5019,7 @@ void TileData::add_collision_polygon(int p_layer_id) { void TileData::remove_collision_polygon(int p_layer_id, int p_polygon_index) { ERR_FAIL_INDEX(p_layer_id, physics.size()); ERR_FAIL_INDEX(p_polygon_index, physics[p_layer_id].polygons.size()); - physics.write[p_layer_id].polygons.remove(p_polygon_index); + physics.write[p_layer_id].polygons.remove_at(p_polygon_index); emit_signal(SNAME("changed")); } diff --git a/scene/resources/visual_shader.cpp b/scene/resources/visual_shader.cpp index 0bdc81330e..41e78e0bc8 100644 --- a/scene/resources/visual_shader.cpp +++ b/scene/resources/visual_shader.cpp @@ -367,7 +367,7 @@ String VisualShaderNodeCustom::generate_code(Shader::Mode p_mode, VisualShader:: if (!nend) { code += "\n }"; } else { - code.remove(code.size() - 1); + code.remove_at(code.size() - 1); code += "}"; } code += "\n"; @@ -1835,6 +1835,7 @@ void VisualShader::_update_shader() const { code += " float __scalar_buff1;\n"; code += " float __scalar_buff2;\n"; code += " int __scalar_ibuff;\n"; + code += " vec4 __vec4_buff;\n"; code += " vec3 __ndiff = normalize(__diff);\n\n"; } if (has_start) { diff --git a/scene/resources/visual_shader_particle_nodes.cpp b/scene/resources/visual_shader_particle_nodes.cpp index 7dd4eed15b..1a829968e3 100644 --- a/scene/resources/visual_shader_particle_nodes.cpp +++ b/scene/resources/visual_shader_particle_nodes.cpp @@ -264,7 +264,7 @@ String VisualShaderNodeParticleMeshEmitter::get_caption() const { } int VisualShaderNodeParticleMeshEmitter::get_output_port_count() const { - return 2; + return 6; } VisualShaderNodeParticleBoxEmitter::PortType VisualShaderNodeParticleMeshEmitter::get_output_port_type(int p_port) const { @@ -273,6 +273,14 @@ VisualShaderNodeParticleBoxEmitter::PortType VisualShaderNodeParticleMeshEmitter return PORT_TYPE_VECTOR; // position case 1: return PORT_TYPE_VECTOR; // normal + case 2: + return PORT_TYPE_VECTOR; // color + case 3: + return PORT_TYPE_SCALAR; // alpha + case 4: + return PORT_TYPE_VECTOR; // uv + case 5: + return PORT_TYPE_VECTOR; // uv2 } return PORT_TYPE_SCALAR; } @@ -283,6 +291,14 @@ String VisualShaderNodeParticleMeshEmitter::get_output_port_name(int p_port) con return "position"; case 1: return "normal"; + case 2: + return "color"; + case 3: + return "alpha"; + case 4: + return "uv"; + case 5: + return "uv2"; } return String(); } @@ -299,135 +315,263 @@ String VisualShaderNodeParticleMeshEmitter::get_input_port_name(int p_port) cons return String(); } -String VisualShaderNodeParticleMeshEmitter::generate_global_per_node(Shader::Mode p_mode, VisualShader::Type p_type, int p_id) const { +String VisualShaderNodeParticleMeshEmitter::generate_global(Shader::Mode p_mode, VisualShader::Type p_type, int p_id) const { String code; if (mesh.is_valid()) { - code += "uniform sampler2D " + make_unique_id(p_type, p_id, "mesh_vx") + ";\n"; - code += "uniform sampler2D " + make_unique_id(p_type, p_id, "mesh_nm") + ";\n"; + if (is_output_port_connected(0)) { // position + code += "uniform sampler2D " + make_unique_id(p_type, p_id, "mesh_vx") + ";\n"; + } + + if (is_output_port_connected(1)) { // normal + code += "uniform sampler2D " + make_unique_id(p_type, p_id, "mesh_nm") + ";\n"; + } + + if (is_output_port_connected(2) || is_output_port_connected(3)) { // color & alpha + code += "uniform sampler2D " + make_unique_id(p_type, p_id, "mesh_col") + ";\n"; + } + + if (is_output_port_connected(4)) { // uv + code += "uniform sampler2D " + make_unique_id(p_type, p_id, "mesh_uv") + ";\n"; + } + + if (is_output_port_connected(5)) { // uv2 + code += "uniform sampler2D " + make_unique_id(p_type, p_id, "mesh_uv2") + ";\n"; + } } return code; } -String VisualShaderNodeParticleMeshEmitter::generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview) const { +String VisualShaderNodeParticleMeshEmitter::_generate_code(VisualShader::Type p_type, int p_id, const String *p_output_vars, int p_index, const String &p_texture_name, bool p_ignore_mode2d) const { String code; - - code += " __scalar_ibuff = int(__rand_from_seed(__seed) * 65535.0) % " + itos(position_texture->get_width()) + ";\n"; - - if (position_texture->get_width() == 0) { - code += " " + p_output_vars[0] + " = vec3(0.0);\n"; - } else { - if (mode_2d) { - code += " " + p_output_vars[0] + " = vec3("; + if (is_output_port_connected(p_index)) { + if (mode_2d && !p_ignore_mode2d) { + code += " " + p_output_vars[p_index] + " = vec3("; code += "texelFetch("; - code += make_unique_id(p_type, p_id, "mesh_vx") + ", "; + code += make_unique_id(p_type, p_id, p_texture_name) + ", "; code += "ivec2(__scalar_ibuff, 0), 0).xy, 0.0);\n"; } else { - code += " " + p_output_vars[0] + " = texelFetch("; - code += make_unique_id(p_type, p_id, "mesh_vx") + ", "; + code += " " + p_output_vars[p_index] + " = texelFetch("; + code += make_unique_id(p_type, p_id, p_texture_name) + ", "; code += "ivec2(__scalar_ibuff, 0), 0).xyz;\n"; } } + return code; +} - if (normal_texture->get_width() == 0) { - code += " " + p_output_vars[1] + " = vec3(0.0);\n"; - } else { - if (mode_2d) { - code += " " + p_output_vars[1] + " = vec3("; - code += "texelFetch("; - code += make_unique_id(p_type, p_id, "mesh_nm") + ", "; - code += "ivec2(__scalar_ibuff, 0), 0).xy, 0.0);\n"; +String VisualShaderNodeParticleMeshEmitter::generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview) const { + String code; + code += " __scalar_ibuff = int(__rand_from_seed(__seed) * 65535.0) % " + itos(position_texture->get_width()) + ";\n"; + + code += _generate_code(p_type, p_id, p_output_vars, 0, "mesh_vx"); + code += _generate_code(p_type, p_id, p_output_vars, 1, "mesh_nm"); + + if (is_output_port_connected(2) || is_output_port_connected(3)) { + code += " __vec4_buff = texelFetch("; + code += make_unique_id(p_type, p_id, "mesh_col") + ", "; + code += "ivec2(__scalar_ibuff, 0), 0);\n"; + if (is_output_port_connected(2)) { + code += " " + p_output_vars[2] + " = __vec4_buff.rgb;\n"; } else { - code += " " + p_output_vars[1] + " = texelFetch("; - code += make_unique_id(p_type, p_id, "mesh_nm") + ", "; - code += "ivec2(__scalar_ibuff, 0), 0).xyz;\n"; + code += " " + p_output_vars[2] + " = vec3(0.0);\n"; + } + if (is_output_port_connected(3)) { + code += " " + p_output_vars[3] + " = __vec4_buff.a;\n"; + } else { + code += " " + p_output_vars[3] + " = 0.0;\n"; } } + code += _generate_code(p_type, p_id, p_output_vars, 4, "mesh_uv", true); + code += _generate_code(p_type, p_id, p_output_vars, 5, "mesh_uv2", true); + return code; } Vector<VisualShader::DefaultTextureParam> VisualShaderNodeParticleMeshEmitter::get_default_texture_parameters(VisualShader::Type p_type, int p_id) const { - VisualShader::DefaultTextureParam dtp_vx; - dtp_vx.name = make_unique_id(p_type, p_id, "mesh_vx"); - dtp_vx.params.push_back(position_texture); + Vector<VisualShader::DefaultTextureParam> ret; - VisualShader::DefaultTextureParam dtp_nm; - dtp_nm.name = make_unique_id(p_type, p_id, "mesh_nm"); - dtp_nm.params.push_back(normal_texture); + if (is_output_port_connected(0)) { + VisualShader::DefaultTextureParam dtp; + dtp.name = make_unique_id(p_type, p_id, "mesh_vx"); + dtp.params.push_back(position_texture); + ret.push_back(dtp); + } + + if (is_output_port_connected(1)) { + VisualShader::DefaultTextureParam dtp; + dtp.name = make_unique_id(p_type, p_id, "mesh_nm"); + dtp.params.push_back(normal_texture); + ret.push_back(dtp); + } + + if (is_output_port_connected(2) || is_output_port_connected(3)) { + VisualShader::DefaultTextureParam dtp; + dtp.name = make_unique_id(p_type, p_id, "mesh_col"); + dtp.params.push_back(color_texture); + ret.push_back(dtp); + } + + if (is_output_port_connected(4)) { + VisualShader::DefaultTextureParam dtp; + dtp.name = make_unique_id(p_type, p_id, "mesh_uv"); + dtp.params.push_back(uv_texture); + ret.push_back(dtp); + } + + if (is_output_port_connected(5)) { + VisualShader::DefaultTextureParam dtp; + dtp.name = make_unique_id(p_type, p_id, "mesh_uv2"); + dtp.params.push_back(uv2_texture); + ret.push_back(dtp); + } - Vector<VisualShader::DefaultTextureParam> ret; - ret.push_back(dtp_vx); - ret.push_back(dtp_nm); return ret; } -void VisualShaderNodeParticleMeshEmitter::update_texture() { +void VisualShaderNodeParticleMeshEmitter::_update_texture(const Vector<Vector2> &p_array, Ref<ImageTexture> &r_texture) { + Ref<Image> image; + image.instantiate(); + + if (p_array.size() == 0) { + image->create(1, 1, false, Image::Format::FORMAT_RGBF); + } else { + image->create(p_array.size(), 1, false, Image::Format::FORMAT_RGBF); + } + + for (int i = 0; i < p_array.size(); i++) { + Vector2 v = p_array[i]; + image->set_pixel(i, 0, Color(v.x, v.y, 0)); + } + if (r_texture->get_width() != p_array.size() || p_array.size() == 0) { + r_texture->create_from_image(image); + } else { + r_texture->update(image); + } +} + +void VisualShaderNodeParticleMeshEmitter::_update_texture(const Vector<Vector3> &p_array, Ref<ImageTexture> &r_texture) { + Ref<Image> image; + image.instantiate(); + + if (p_array.size() == 0) { + image->create(1, 1, false, Image::Format::FORMAT_RGBF); + } else { + image->create(p_array.size(), 1, false, Image::Format::FORMAT_RGBF); + } + + for (int i = 0; i < p_array.size(); i++) { + Vector3 v = p_array[i]; + image->set_pixel(i, 0, Color(v.x, v.y, v.z)); + } + if (r_texture->get_width() != p_array.size() || p_array.size() == 0) { + r_texture->create_from_image(image); + } else { + r_texture->update(image); + } +} + +void VisualShaderNodeParticleMeshEmitter::_update_texture(const Vector<Color> &p_array, Ref<ImageTexture> &r_texture) { + Ref<Image> image; + image.instantiate(); + + if (p_array.size() == 0) { + image->create(1, 1, false, Image::Format::FORMAT_RGBA8); + } else { + image->create(p_array.size(), 1, false, Image::Format::FORMAT_RGBA8); + } + + for (int i = 0; i < p_array.size(); i++) { + image->set_pixel(i, 0, p_array[i]); + } + if (r_texture->get_width() != p_array.size() || p_array.size() == 0) { + r_texture->create_from_image(image); + } else { + r_texture->update(image); + } +} + +void VisualShaderNodeParticleMeshEmitter::_update_textures() { if (!mesh.is_valid()) { return; } Vector<Vector3> vertices; Vector<Vector3> normals; + Vector<Color> colors; + Vector<Vector2> uvs; + Vector<Vector2> uvs2; if (use_all_surfaces) { for (int i = 0; i < max_surface_index; i++) { + // position Array vertex_array = mesh->surface_get_arrays(i)[Mesh::ARRAY_VERTEX]; for (int j = 0; j < vertex_array.size(); j++) { vertices.push_back((Vector3)vertex_array[j]); } + // normal Array normal_array = mesh->surface_get_arrays(i)[Mesh::ARRAY_NORMAL]; - for (int j = 0; j < vertex_array.size(); j++) { - normals.push_back((Vector3)vertex_array[j]); + for (int j = 0; j < normal_array.size(); j++) { + normals.push_back((Vector3)normal_array[j]); + } + + // color + Array color_array = mesh->surface_get_arrays(i)[Mesh::ARRAY_COLOR]; + for (int j = 0; j < color_array.size(); j++) { + colors.push_back((Color)color_array[j]); + } + + // uv + Array uv_array = mesh->surface_get_arrays(i)[Mesh::ARRAY_TEX_UV]; + for (int j = 0; j < uv_array.size(); j++) { + uvs.push_back((Vector2)uv_array[j]); + } + + // uv2 + Array uv2_array = mesh->surface_get_arrays(i)[Mesh::ARRAY_TEX_UV2]; + for (int j = 0; j < uv2_array.size(); j++) { + uvs2.push_back((Vector2)uv2_array[j]); } } } else { + // position Array vertex_array = mesh->surface_get_arrays(surface_index)[Mesh::ARRAY_VERTEX]; for (int i = 0; i < vertex_array.size(); i++) { vertices.push_back((Vector3)vertex_array[i]); } + // normal Array normal_array = mesh->surface_get_arrays(surface_index)[Mesh::ARRAY_NORMAL]; for (int i = 0; i < normal_array.size(); i++) { normals.push_back((Vector3)normal_array[i]); } - } - // vertices - { - Ref<Image> image; - image.instantiate(); - image->create(vertices.size(), 1, false, Image::Format::FORMAT_RGBF); - - for (int i = 0; i < vertices.size(); i++) { - Vector3 v = vertices[i]; - image->set_pixel(i, 0, Color(v.x, v.y, v.z)); - } - if (position_texture->get_width() != vertices.size()) { - position_texture->create_from_image(image); - } else { - position_texture->update(image); + // color + Array color_array = mesh->surface_get_arrays(surface_index)[Mesh::ARRAY_COLOR]; + for (int i = 0; i < color_array.size(); i++) { + colors.push_back((Color)color_array[i]); } - } - - // normals - { - Ref<Image> image; - image.instantiate(); - image->create(normals.size(), 1, false, Image::Format::FORMAT_RGBF); - for (int i = 0; i < normals.size(); i++) { - Vector3 v = normals[i]; - image->set_pixel(i, 0, Color(v.x, v.y, v.z)); + // uv + Array uv_array = mesh->surface_get_arrays(surface_index)[Mesh::ARRAY_TEX_UV]; + for (int j = 0; j < uv_array.size(); j++) { + uvs.push_back((Vector2)uv_array[j]); } - if (normal_texture->get_width() != normals.size()) { - normal_texture->create_from_image(image); - } else { - normal_texture->update(image); + + // uv2 + Array uv2_array = mesh->surface_get_arrays(surface_index)[Mesh::ARRAY_TEX_UV2]; + for (int j = 0; j < uv2_array.size(); j++) { + uvs2.push_back((Vector2)uv2_array[j]); } } + + _update_texture(vertices, position_texture); + _update_texture(normals, normal_texture); + _update_texture(colors, color_texture); + _update_texture(uvs, uv_texture); + _update_texture(uvs2, uv2_texture); } void VisualShaderNodeParticleMeshEmitter::set_mesh(Ref<Mesh> p_mesh) { @@ -442,7 +586,7 @@ void VisualShaderNodeParticleMeshEmitter::set_mesh(Ref<Mesh> p_mesh) { } if (mesh.is_valid()) { - Callable callable = callable_mp(this, &VisualShaderNodeParticleMeshEmitter::update_texture); + Callable callable = callable_mp(this, &VisualShaderNodeParticleMeshEmitter::_update_textures); if (mesh->is_connected(CoreStringNames::get_singleton()->changed, callable)) { mesh->disconnect(CoreStringNames::get_singleton()->changed, callable); @@ -452,7 +596,7 @@ void VisualShaderNodeParticleMeshEmitter::set_mesh(Ref<Mesh> p_mesh) { mesh = p_mesh; if (mesh.is_valid()) { - Callable callable = callable_mp(this, &VisualShaderNodeParticleMeshEmitter::update_texture); + Callable callable = callable_mp(this, &VisualShaderNodeParticleMeshEmitter::_update_textures); if (!mesh->is_connected(CoreStringNames::get_singleton()->changed, callable)) { mesh->connect(CoreStringNames::get_singleton()->changed, callable); @@ -528,10 +672,13 @@ void VisualShaderNodeParticleMeshEmitter::_bind_methods() { } VisualShaderNodeParticleMeshEmitter::VisualShaderNodeParticleMeshEmitter() { - connect(CoreStringNames::get_singleton()->changed, callable_mp(this, &VisualShaderNodeParticleMeshEmitter::update_texture)); + connect(CoreStringNames::get_singleton()->changed, callable_mp(this, &VisualShaderNodeParticleMeshEmitter::_update_textures)); position_texture.instantiate(); normal_texture.instantiate(); + color_texture.instantiate(); + uv_texture.instantiate(); + uv2_texture.instantiate(); } // VisualShaderNodeParticleMultiplyByAxisAngle diff --git a/scene/resources/visual_shader_particle_nodes.h b/scene/resources/visual_shader_particle_nodes.h index 0d0f21e4bf..79459432f1 100644 --- a/scene/resources/visual_shader_particle_nodes.h +++ b/scene/resources/visual_shader_particle_nodes.h @@ -115,6 +115,16 @@ class VisualShaderNodeParticleMeshEmitter : public VisualShaderNodeParticleEmitt Ref<ImageTexture> position_texture; Ref<ImageTexture> normal_texture; + Ref<ImageTexture> color_texture; + Ref<ImageTexture> uv_texture; + Ref<ImageTexture> uv2_texture; + + String _generate_code(VisualShader::Type p_type, int p_id, const String *p_output_vars, int p_index, const String &p_texture_name, bool p_ignore_mode2d = false) const; + + void _update_texture(const Vector<Vector2> &p_array, Ref<ImageTexture> &r_texture); + void _update_texture(const Vector<Vector3> &p_array, Ref<ImageTexture> &r_texture); + void _update_texture(const Vector<Color> &p_array, Ref<ImageTexture> &r_texture); + void _update_textures(); protected: static void _bind_methods(); @@ -130,11 +140,9 @@ public: virtual PortType get_input_port_type(int p_port) const override; virtual String get_input_port_name(int p_port) const override; - virtual String generate_global_per_node(Shader::Mode p_mode, VisualShader::Type p_type, int p_id) const override; + virtual String generate_global(Shader::Mode p_mode, VisualShader::Type p_type, int p_id) const override; virtual String generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview = false) const override; - void update_texture(); - void set_mesh(Ref<Mesh> p_mesh); Ref<Mesh> get_mesh() const; |