diff options
-rw-r--r-- | doc/classes/AnimationNodeOneShot.xml | 15 | ||||
-rw-r--r-- | doc/classes/GPUParticles2D.xml | 29 | ||||
-rw-r--r-- | doc/classes/GPUParticles3D.xml | 6 | ||||
-rw-r--r-- | doc/classes/Tree.xml | 8 | ||||
-rw-r--r-- | editor/plugins/canvas_item_editor_plugin.cpp | 1 | ||||
-rw-r--r-- | modules/gltf/gltf_document.cpp | 1 | ||||
-rw-r--r-- | scene/2d/gpu_particles_2d.cpp | 58 | ||||
-rw-r--r-- | scene/2d/gpu_particles_2d.h | 16 | ||||
-rw-r--r-- | scene/2d/node_2d.cpp | 2 | ||||
-rw-r--r-- | scene/3d/node_3d.cpp | 2 | ||||
-rw-r--r-- | scene/animation/animation_blend_tree.cpp | 2 | ||||
-rw-r--r-- | scene/gui/code_edit.cpp | 6 | ||||
-rw-r--r-- | scene/gui/text_edit.cpp | 1 | ||||
-rw-r--r-- | scene/gui/view_panner.cpp | 11 | ||||
-rw-r--r-- | scene/gui/view_panner.h | 3 | ||||
-rw-r--r-- | tests/scene/test_code_edit.h | 49 |
16 files changed, 189 insertions, 21 deletions
diff --git a/doc/classes/AnimationNodeOneShot.xml b/doc/classes/AnimationNodeOneShot.xml index 116b54e39e..71ed82cf46 100644 --- a/doc/classes/AnimationNodeOneShot.xml +++ b/doc/classes/AnimationNodeOneShot.xml @@ -10,19 +10,6 @@ <link title="AnimationTree">$DOCS_URL/tutorials/animation/animation_tree.html</link> <link title="Third Person Shooter Demo">https://godotengine.org/asset-library/asset/678</link> </tutorials> - <methods> - <method name="get_mix_mode" qualifiers="const"> - <return type="int" enum="AnimationNodeOneShot.MixMode" /> - <description> - </description> - </method> - <method name="set_mix_mode"> - <return type="void" /> - <argument index="0" name="mode" type="int" enum="AnimationNodeOneShot.MixMode" /> - <description> - </description> - </method> - </methods> <members> <member name="autorestart" type="bool" setter="set_autorestart" getter="has_autorestart" default="false"> If [code]true[/code], the sub-animation will restart automatically after finishing. @@ -37,6 +24,8 @@ </member> <member name="fadeout_time" type="float" setter="set_fadeout_time" getter="get_fadeout_time" default="0.1"> </member> + <member name="mix_mode" type="int" setter="set_mix_mode" getter="get_mix_mode" enum="AnimationNodeOneShot.MixMode" default="0"> + </member> <member name="sync" type="bool" setter="set_use_sync" getter="is_using_sync" default="false"> </member> </members> diff --git a/doc/classes/GPUParticles2D.xml b/doc/classes/GPUParticles2D.xml index 72adc49742..f97198658e 100644 --- a/doc/classes/GPUParticles2D.xml +++ b/doc/classes/GPUParticles2D.xml @@ -18,6 +18,17 @@ Returns a rectangle containing the positions of all existing particles. </description> </method> + <method name="emit_particle"> + <return type="void" /> + <argument index="0" name="xform" type="Transform2D" /> + <argument index="1" name="velocity" type="Vector2" /> + <argument index="2" name="color" type="Color" /> + <argument index="3" name="custom" type="Color" /> + <argument index="4" name="flags" type="int" /> + <description> + Emits a single particle. Whether [code]xform[/code], [code]velocity[/code], [code]color[/code] and [code]custom[/code] are applied depends on the value of [code]flags[/code]. See [enum EmitFlags]. + </description> + </method> <method name="restart"> <return type="void" /> <description> @@ -67,6 +78,9 @@ <member name="speed_scale" type="float" setter="set_speed_scale" getter="get_speed_scale" default="1.0"> Particle system's running speed scaling ratio. A value of [code]0[/code] can be used to pause the particles. </member> + <member name="sub_emitter" type="NodePath" setter="set_sub_emitter" getter="get_sub_emitter" default="NodePath("")"> + The [NodePath] to the [GPUParticles2D] used for sub-emissions. + </member> <member name="texture" type="Texture2D" setter="set_texture" getter="get_texture"> Particle texture. If [code]null[/code], particles will be squares. </member> @@ -92,5 +106,20 @@ </constant> <constant name="DRAW_ORDER_REVERSE_LIFETIME" value="2" enum="DrawOrder"> </constant> + <constant name="EMIT_FLAG_POSITION" value="1" enum="EmitFlags"> + Particle starts at the specified position. + </constant> + <constant name="EMIT_FLAG_ROTATION_SCALE" value="2" enum="EmitFlags"> + Particle starts with specified rotation and scale. + </constant> + <constant name="EMIT_FLAG_VELOCITY" value="4" enum="EmitFlags"> + Particle starts with the specified velocity vector, which defines the emission direction and speed. + </constant> + <constant name="EMIT_FLAG_COLOR" value="8" enum="EmitFlags"> + Particle starts with specified color. + </constant> + <constant name="EMIT_FLAG_CUSTOM" value="16" enum="EmitFlags"> + Particle starts with specificed [code]CUSTOM[/code] data. + </constant> </constants> </class> diff --git a/doc/classes/GPUParticles3D.xml b/doc/classes/GPUParticles3D.xml index 771056cb93..62ac846077 100644 --- a/doc/classes/GPUParticles3D.xml +++ b/doc/classes/GPUParticles3D.xml @@ -26,6 +26,7 @@ <argument index="3" name="custom" type="Color" /> <argument index="4" name="flags" type="int" /> <description> + Emits a single particle. Whether [code]xform[/code], [code]velocity[/code], [code]color[/code] and [code]custom[/code] are applied depends on the value of [code]flags[/code]. See [enum EmitFlags]. </description> </method> <method name="get_draw_pass_mesh" qualifiers="const"> @@ -137,14 +138,19 @@ Particles are drawn in order of depth. </constant> <constant name="EMIT_FLAG_POSITION" value="1" enum="EmitFlags"> + Particle starts at the specified position. </constant> <constant name="EMIT_FLAG_ROTATION_SCALE" value="2" enum="EmitFlags"> + Particle starts with specified rotation and scale. </constant> <constant name="EMIT_FLAG_VELOCITY" value="4" enum="EmitFlags"> + Particle starts with the specified velocity vector, which defines the emission direction and speed. </constant> <constant name="EMIT_FLAG_COLOR" value="8" enum="EmitFlags"> + Particle starts with specified color. </constant> <constant name="EMIT_FLAG_CUSTOM" value="16" enum="EmitFlags"> + Particle starts with specificed [code]CUSTOM[/code] data. </constant> <constant name="MAX_DRAW_PASSES" value="4"> Maximum number of draw passes supported. diff --git a/doc/classes/Tree.xml b/doc/classes/Tree.xml index 106bcf9d37..6392d0853f 100644 --- a/doc/classes/Tree.xml +++ b/doc/classes/Tree.xml @@ -53,7 +53,7 @@ <argument index="0" name="parent" type="Object" default="null" /> <argument index="1" name="idx" type="int" default="-1" /> <description> - Creates an item in the tree and adds it as a child of [code]parent[/code]. + Creates an item in the tree and adds it as a child of [code]parent[/code], which can be either a valid [TreeItem] or [code]null[/code]. If [code]parent[/code] is [code]null[/code], the root item will be the parent, or the new item will be the root itself if the tree is empty. The new item will be the [code]idx[/code]th child of parent, or it will be the last child if there are not enough siblings. </description> @@ -173,7 +173,7 @@ <argument index="0" name="item" type="Object" /> <argument index="1" name="column" type="int" default="-1" /> <description> - Returns the rectangle area for the specified item. If [code]column[/code] is specified, only get the position and size of that column, otherwise get the rectangle containing all columns. + Returns the rectangle area for the specified [TreeItem]. If [code]column[/code] is specified, only get the position and size of that column, otherwise get the rectangle containing all columns. </description> </method> <method name="get_item_at_position" qualifiers="const"> @@ -187,7 +187,7 @@ <return type="TreeItem" /> <argument index="0" name="from" type="Object" /> <description> - Returns the next selected item after the given one, or [code]null[/code] if the end is reached. + Returns the next selected [TreeItem] after the given one, or [code]null[/code] if the end is reached. If [code]from[/code] is [code]null[/code], this returns the first selected item. </description> </method> @@ -241,7 +241,7 @@ <return type="void" /> <argument index="0" name="item" type="Object" /> <description> - Causes the [Tree] to jump to the specified item. + Causes the [Tree] to jump to the specified [TreeItem]. </description> </method> <method name="set_column_clip_content"> diff --git a/editor/plugins/canvas_item_editor_plugin.cpp b/editor/plugins/canvas_item_editor_plugin.cpp index 4093c70c47..1aae82f66f 100644 --- a/editor/plugins/canvas_item_editor_plugin.cpp +++ b/editor/plugins/canvas_item_editor_plugin.cpp @@ -1117,6 +1117,7 @@ bool CanvasItemEditor::_gui_input_rulers_and_guides(const Ref<InputEvent> &p_eve } bool CanvasItemEditor::_gui_input_zoom_or_pan(const Ref<InputEvent> &p_event, bool p_already_accepted) { + panner->set_force_drag(tool == TOOL_PAN); bool panner_active = panner->gui_input(p_event, warped_panning ? viewport->get_global_rect() : Rect2()); if (panner->is_panning() != pan_pressed) { pan_pressed = panner->is_panning(); diff --git a/modules/gltf/gltf_document.cpp b/modules/gltf/gltf_document.cpp index 5a931ed839..51608273a1 100644 --- a/modules/gltf/gltf_document.cpp +++ b/modules/gltf/gltf_document.cpp @@ -6843,6 +6843,7 @@ Error GLTFDocument::write_to_filesystem(Ref<GLTFState> state, const String &p_pa } Node *GLTFDocument::generate_scene(Ref<GLTFState> state, int32_t p_bake_fps) { + ERR_FAIL_NULL_V(state, nullptr); ERR_FAIL_INDEX_V(0, state->root_nodes.size(), nullptr); GLTFNodeIndex gltf_root = state->root_nodes.write[0]; Node *gltf_root_node = state->get_scene_node(gltf_root); diff --git a/scene/2d/gpu_particles_2d.cpp b/scene/2d/gpu_particles_2d.cpp index b6d1e5c934..11c036ac9c 100644 --- a/scene/2d/gpu_particles_2d.cpp +++ b/scene/2d/gpu_particles_2d.cpp @@ -335,6 +335,42 @@ Ref<Texture2D> GPUParticles2D::get_texture() const { void GPUParticles2D::_validate_property(PropertyInfo &property) const { } +void GPUParticles2D::emit_particle(const Transform2D &p_transform2d, const Vector2 &p_velocity2d, const Color &p_color, const Color &p_custom, uint32_t p_emit_flags) { + Transform3D transform; + transform.basis.set_axis(0, Vector3(p_transform2d.get_axis(0).x, p_transform2d.get_axis(0).y, 0)); + transform.basis.set_axis(1, Vector3(p_transform2d.get_axis(1).x, p_transform2d.get_axis(1).y, 0)); + transform.set_origin(Vector3(p_transform2d.get_origin().x, p_transform2d.get_origin().y, 0)); + Vector3 velocity = Vector3(p_velocity2d.x, p_velocity2d.y, 0); + + RS::get_singleton()->particles_emit(particles, transform, velocity, p_color, p_custom, p_emit_flags); +} + +void GPUParticles2D::_attach_sub_emitter() { + Node *n = get_node_or_null(sub_emitter); + if (n) { + GPUParticles2D *sen = Object::cast_to<GPUParticles2D>(n); + if (sen && sen != this) { + RS::get_singleton()->particles_set_subemitter(particles, sen->particles); + } + } +} + +void GPUParticles2D::set_sub_emitter(const NodePath &p_path) { + if (is_inside_tree()) { + RS::get_singleton()->particles_set_subemitter(particles, RID()); + } + + sub_emitter = p_path; + + if (is_inside_tree() && sub_emitter != NodePath()) { + _attach_sub_emitter(); + } +} + +NodePath GPUParticles2D::get_sub_emitter() const { + return sub_emitter; +} + void GPUParticles2D::restart() { RS::get_singleton()->particles_restart(particles); RS::get_singleton()->particles_set_emitting(particles, true); @@ -462,6 +498,16 @@ void GPUParticles2D::_notification(int p_what) { #endif } + if (p_what == NOTIFICATION_ENTER_TREE) { + if (sub_emitter != NodePath()) { + _attach_sub_emitter(); + } + } + + if (p_what == NOTIFICATION_EXIT_TREE) { + RS::get_singleton()->particles_set_subemitter(particles, RID()); + } + if (p_what == NOTIFICATION_PAUSED || p_what == NOTIFICATION_UNPAUSED) { if (can_process()) { RS::get_singleton()->particles_set_speed_scale(particles, speed_scale); @@ -523,6 +569,11 @@ void GPUParticles2D::_bind_methods() { ClassDB::bind_method(D_METHOD("restart"), &GPUParticles2D::restart); + ClassDB::bind_method(D_METHOD("set_sub_emitter", "path"), &GPUParticles2D::set_sub_emitter); + ClassDB::bind_method(D_METHOD("get_sub_emitter"), &GPUParticles2D::get_sub_emitter); + + ClassDB::bind_method(D_METHOD("emit_particle", "xform", "velocity", "color", "custom", "flags"), &GPUParticles2D::emit_particle); + ClassDB::bind_method(D_METHOD("set_trail_enabled", "enabled"), &GPUParticles2D::set_trail_enabled); ClassDB::bind_method(D_METHOD("set_trail_length", "secs"), &GPUParticles2D::set_trail_length); @@ -538,6 +589,7 @@ void GPUParticles2D::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::BOOL, "emitting"), "set_emitting", "is_emitting"); ADD_PROPERTY_DEFAULT("emitting", true); // Workaround for doctool in headless mode, as dummy rasterizer always returns false. ADD_PROPERTY(PropertyInfo(Variant::INT, "amount", PROPERTY_HINT_RANGE, "1,1000000,1,exp"), "set_amount", "get_amount"); + ADD_PROPERTY(PropertyInfo(Variant::NODE_PATH, "sub_emitter", PROPERTY_HINT_NODE_PATH_VALID_TYPES, "GPUParticles2D"), "set_sub_emitter", "get_sub_emitter"); ADD_GROUP("Time", ""); ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "lifetime", PROPERTY_HINT_RANGE, "0.01,600.0,0.01,or_greater"), "set_lifetime", "get_lifetime"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "one_shot"), "set_one_shot", "get_one_shot"); @@ -566,6 +618,12 @@ void GPUParticles2D::_bind_methods() { BIND_ENUM_CONSTANT(DRAW_ORDER_INDEX); BIND_ENUM_CONSTANT(DRAW_ORDER_LIFETIME); BIND_ENUM_CONSTANT(DRAW_ORDER_REVERSE_LIFETIME); + + BIND_ENUM_CONSTANT(EMIT_FLAG_POSITION); + BIND_ENUM_CONSTANT(EMIT_FLAG_ROTATION_SCALE); + BIND_ENUM_CONSTANT(EMIT_FLAG_VELOCITY); + BIND_ENUM_CONSTANT(EMIT_FLAG_COLOR); + BIND_ENUM_CONSTANT(EMIT_FLAG_CUSTOM); } GPUParticles2D::GPUParticles2D() { diff --git a/scene/2d/gpu_particles_2d.h b/scene/2d/gpu_particles_2d.h index aa9a8da129..fc95ae27b2 100644 --- a/scene/2d/gpu_particles_2d.h +++ b/scene/2d/gpu_particles_2d.h @@ -79,6 +79,8 @@ private: RID mesh; + void _attach_sub_emitter(); + protected: static void _bind_methods(); virtual void _validate_property(PropertyInfo &property) const override; @@ -139,6 +141,19 @@ public: TypedArray<String> get_configuration_warnings() const override; + void set_sub_emitter(const NodePath &p_path); + NodePath get_sub_emitter() const; + + enum EmitFlags { + EMIT_FLAG_POSITION = RS::PARTICLES_EMIT_FLAG_POSITION, + EMIT_FLAG_ROTATION_SCALE = RS::PARTICLES_EMIT_FLAG_ROTATION_SCALE, + EMIT_FLAG_VELOCITY = RS::PARTICLES_EMIT_FLAG_VELOCITY, + EMIT_FLAG_COLOR = RS::PARTICLES_EMIT_FLAG_COLOR, + EMIT_FLAG_CUSTOM = RS::PARTICLES_EMIT_FLAG_CUSTOM + }; + + void emit_particle(const Transform2D &p_transform, const Vector2 &p_velocity, const Color &p_color, const Color &p_custom, uint32_t p_emit_flags); + void restart(); Rect2 capture_rect() const; GPUParticles2D(); @@ -146,5 +161,6 @@ public: }; VARIANT_ENUM_CAST(GPUParticles2D::DrawOrder) +VARIANT_ENUM_CAST(GPUParticles2D::EmitFlags) #endif // PARTICLES_2D_H diff --git a/scene/2d/node_2d.cpp b/scene/2d/node_2d.cpp index 9331340e1b..9d26543243 100644 --- a/scene/2d/node_2d.cpp +++ b/scene/2d/node_2d.cpp @@ -413,7 +413,7 @@ void Node2D::_bind_methods() { ClassDB::bind_method(D_METHOD("get_relative_transform_to_parent", "parent"), &Node2D::get_relative_transform_to_parent); ADD_GROUP("Transform", ""); - ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "position", PROPERTY_HINT_RANGE, "-99999,99999,0,or_lesser,or_greater,noslider,suffix:px"), "set_position", "get_position"); + ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "position", PROPERTY_HINT_RANGE, "-99999,99999,0.001,or_lesser,or_greater,noslider,suffix:px"), "set_position", "get_position"); ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "rotation", PROPERTY_HINT_RANGE, "-360,360,0.1,or_lesser,or_greater,radians"), "set_rotation", "get_rotation"); ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "scale"), "set_scale", "get_scale"); ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "skew", PROPERTY_HINT_RANGE, "-89.9,89.9,0.1,radians"), "set_skew", "get_skew"); diff --git a/scene/3d/node_3d.cpp b/scene/3d/node_3d.cpp index a992d2aaf2..515d2cfdc7 100644 --- a/scene/3d/node_3d.cpp +++ b/scene/3d/node_3d.cpp @@ -990,7 +990,7 @@ void Node3D::_bind_methods() { ADD_GROUP("Transform", ""); ADD_PROPERTY(PropertyInfo(Variant::TRANSFORM3D, "transform", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR), "set_transform", "get_transform"); ADD_PROPERTY(PropertyInfo(Variant::TRANSFORM3D, "global_transform", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NONE), "set_global_transform", "get_global_transform"); - ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "position", PROPERTY_HINT_RANGE, "-99999,99999,0,or_greater,or_lesser,noslider,suffix:m", PROPERTY_USAGE_EDITOR), "set_position", "get_position"); + ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "position", PROPERTY_HINT_RANGE, "-99999,99999,0.001,or_greater,or_lesser,noslider,suffix:m", PROPERTY_USAGE_EDITOR), "set_position", "get_position"); ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "rotation", PROPERTY_HINT_RANGE, "-360,360,0.1,or_lesser,or_greater,radians", PROPERTY_USAGE_EDITOR), "set_rotation", "get_rotation"); ADD_PROPERTY(PropertyInfo(Variant::QUATERNION, "quaternion", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_EDITOR), "set_quaternion", "get_quaternion"); ADD_PROPERTY(PropertyInfo(Variant::BASIS, "basis", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_EDITOR), "set_basis", "get_basis"); diff --git a/scene/animation/animation_blend_tree.cpp b/scene/animation/animation_blend_tree.cpp index 2740103a4a..9d37b2d6ac 100644 --- a/scene/animation/animation_blend_tree.cpp +++ b/scene/animation/animation_blend_tree.cpp @@ -371,6 +371,8 @@ void AnimationNodeOneShot::_bind_methods() { ClassDB::bind_method(D_METHOD("set_use_sync", "enable"), &AnimationNodeOneShot::set_use_sync); ClassDB::bind_method(D_METHOD("is_using_sync"), &AnimationNodeOneShot::is_using_sync); + ADD_PROPERTY(PropertyInfo(Variant::INT, "mix_mode", PROPERTY_HINT_ENUM, "Blend,Add"), "set_mix_mode", "get_mix_mode"); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "fadein_time", PROPERTY_HINT_RANGE, "0,60,0.01,or_greater"), "set_fadein_time", "get_fadein_time"); ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "fadeout_time", PROPERTY_HINT_RANGE, "0,60,0.01,or_greater"), "set_fadeout_time", "get_fadeout_time"); diff --git a/scene/gui/code_edit.cpp b/scene/gui/code_edit.cpp index 8da7264b02..8924c37c50 100644 --- a/scene/gui/code_edit.cpp +++ b/scene/gui/code_edit.cpp @@ -937,8 +937,10 @@ void CodeEdit::_new_line(bool p_split_current_line, bool p_above) { return; } - const int cc = get_caret_column(); + /* When not splitting the line, we need to factor in indentation from the end of the current line. */ + const int cc = p_split_current_line ? get_caret_column() : get_line(get_caret_line()).length(); const int cl = get_caret_line(); + const String line = get_line(cl); String ins = "\n"; @@ -1012,6 +1014,8 @@ void CodeEdit::_new_line(bool p_split_current_line, bool p_above) { bool first_line = false; if (!p_split_current_line) { + deselect(); + if (p_above) { if (cl > 0) { set_caret_line(cl - 1, false); diff --git a/scene/gui/text_edit.cpp b/scene/gui/text_edit.cpp index 9b7a5b90d4..fe1aaab557 100644 --- a/scene/gui/text_edit.cpp +++ b/scene/gui/text_edit.cpp @@ -2058,6 +2058,7 @@ void TextEdit::_new_line(bool p_split_current_line, bool p_above) { bool first_line = false; if (!p_split_current_line) { + deselect(); if (p_above) { if (caret.line > 0) { set_caret_line(caret.line - 1, false); diff --git a/scene/gui/view_panner.cpp b/scene/gui/view_panner.cpp index 7476887877..71865b4864 100644 --- a/scene/gui/view_panner.cpp +++ b/scene/gui/view_panner.cpp @@ -81,7 +81,12 @@ bool ViewPanner::gui_input(const Ref<InputEvent> &p_event, Rect2 p_canvas_rect) return false; } - if (mb->get_button_index() == MouseButton::MIDDLE || (enable_rmb && mb->get_button_index() == MouseButton::RIGHT) || (!simple_panning_enabled && mb->get_button_index() == MouseButton::LEFT && is_panning())) { + bool is_drag_event = mb->get_button_index() == MouseButton::MIDDLE || + (enable_rmb && mb->get_button_index() == MouseButton::RIGHT) || + (!simple_panning_enabled && mb->get_button_index() == MouseButton::LEFT && is_panning()) || + (force_drag && mb->get_button_index() == MouseButton::LEFT); + + if (is_drag_event) { if (mb->is_pressed()) { is_dragging = true; } else { @@ -166,6 +171,10 @@ bool ViewPanner::is_panning() const { return is_dragging || pan_key_pressed; } +void ViewPanner::set_force_drag(bool p_force) { + force_drag = p_force; +} + ViewPanner::ViewPanner() { Array inputs; inputs.append(InputEventKey::create_reference(Key::SPACE)); diff --git a/scene/gui/view_panner.h b/scene/gui/view_panner.h index 8423c2a1c0..5b820c5f8f 100644 --- a/scene/gui/view_panner.h +++ b/scene/gui/view_panner.h @@ -48,6 +48,8 @@ public: private: bool is_dragging = false; bool pan_key_pressed = false; + bool force_drag = false; + bool enable_rmb = false; bool simple_panning_enabled = false; @@ -70,6 +72,7 @@ public: void setup(ControlScheme p_scheme, Ref<Shortcut> p_shortcut, bool p_simple_panning); bool is_panning() const; + void set_force_drag(bool p_force); bool gui_input(const Ref<InputEvent> &p_ev, Rect2 p_canvas_rect = Rect2()); void release_pan_key(); diff --git a/tests/scene/test_code_edit.h b/tests/scene/test_code_edit.h index 95c3e456ca..84e71150c7 100644 --- a/tests/scene/test_code_edit.h +++ b/tests/scene/test_code_edit.h @@ -3248,6 +3248,55 @@ TEST_CASE("[SceneTree][CodeEdit] Backspace delete") { memdelete(code_edit); } +TEST_CASE("[SceneTree][CodeEdit] New Line") { + CodeEdit *code_edit = memnew(CodeEdit); + SceneTree::get_singleton()->get_root()->add_child(code_edit); + + /* Add a new line. */ + code_edit->set_text(""); + code_edit->insert_text_at_caret("test new line"); + code_edit->set_caret_line(0); + code_edit->set_caret_column(13); + SEND_GUI_ACTION(code_edit, "ui_text_newline"); + CHECK(code_edit->get_line(0) == "test new line"); + CHECK(code_edit->get_line(1) == ""); + + /* Split line with new line. */ + code_edit->set_text(""); + code_edit->insert_text_at_caret("test new line"); + code_edit->set_caret_line(0); + code_edit->set_caret_column(5); + SEND_GUI_ACTION(code_edit, "ui_text_newline"); + CHECK(code_edit->get_line(0) == "test "); + CHECK(code_edit->get_line(1) == "new line"); + + /* Delete selection and split with new line. */ + code_edit->set_text(""); + code_edit->insert_text_at_caret("test new line"); + code_edit->select(0, 0, 0, 5); + SEND_GUI_ACTION(code_edit, "ui_text_newline"); + CHECK(code_edit->get_line(0) == ""); + CHECK(code_edit->get_line(1) == "new line"); + + /* Blank new line below with selection should not split. */ + code_edit->set_text(""); + code_edit->insert_text_at_caret("test new line"); + code_edit->select(0, 0, 0, 5); + SEND_GUI_ACTION(code_edit, "ui_text_newline_blank"); + CHECK(code_edit->get_line(0) == "test new line"); + CHECK(code_edit->get_line(1) == ""); + + /* Blank new line above with selection should not split. */ + code_edit->set_text(""); + code_edit->insert_text_at_caret("test new line"); + code_edit->select(0, 0, 0, 5); + SEND_GUI_ACTION(code_edit, "ui_text_newline_above"); + CHECK(code_edit->get_line(0) == ""); + CHECK(code_edit->get_line(1) == "test new line"); + + memdelete(code_edit); +} + } // namespace TestCodeEdit #endif // TEST_CODE_EDIT_H |