diff options
49 files changed, 746 insertions, 390 deletions
diff --git a/doc/classes/Animation.xml b/doc/classes/Animation.xml index bc64cfbb19..97da8c9980 100644 --- a/doc/classes/Animation.xml +++ b/doc/classes/Animation.xml @@ -34,7 +34,7 @@ <method name="animation_track_get_key_animation" qualifiers="const"> <return type="String"> </return> - <argument index="0" name="idx" type="int"> + <argument index="0" name="track_idx" type="int"> </argument> <argument index="1" name="key_idx" type="int"> </argument> @@ -44,7 +44,7 @@ <method name="animation_track_insert_key"> <return type="int"> </return> - <argument index="0" name="track" type="int"> + <argument index="0" name="track_idx" type="int"> </argument> <argument index="1" name="time" type="float"> </argument> @@ -56,7 +56,7 @@ <method name="animation_track_set_key_animation"> <return type="void"> </return> - <argument index="0" name="idx" type="int"> + <argument index="0" name="track_idx" type="int"> </argument> <argument index="1" name="key_idx" type="int"> </argument> @@ -68,7 +68,7 @@ <method name="audio_track_get_key_end_offset" qualifiers="const"> <return type="float"> </return> - <argument index="0" name="idx" type="int"> + <argument index="0" name="track_idx" type="int"> </argument> <argument index="1" name="key_idx" type="int"> </argument> @@ -78,7 +78,7 @@ <method name="audio_track_get_key_start_offset" qualifiers="const"> <return type="float"> </return> - <argument index="0" name="idx" type="int"> + <argument index="0" name="track_idx" type="int"> </argument> <argument index="1" name="key_idx" type="int"> </argument> @@ -88,7 +88,7 @@ <method name="audio_track_get_key_stream" qualifiers="const"> <return type="Resource"> </return> - <argument index="0" name="idx" type="int"> + <argument index="0" name="track_idx" type="int"> </argument> <argument index="1" name="key_idx" type="int"> </argument> @@ -98,7 +98,7 @@ <method name="audio_track_insert_key"> <return type="int"> </return> - <argument index="0" name="track" type="int"> + <argument index="0" name="track_idx" type="int"> </argument> <argument index="1" name="time" type="float"> </argument> @@ -114,7 +114,7 @@ <method name="audio_track_set_key_end_offset"> <return type="void"> </return> - <argument index="0" name="idx" type="int"> + <argument index="0" name="track_idx" type="int"> </argument> <argument index="1" name="key_idx" type="int"> </argument> @@ -126,7 +126,7 @@ <method name="audio_track_set_key_start_offset"> <return type="void"> </return> - <argument index="0" name="idx" type="int"> + <argument index="0" name="track_idx" type="int"> </argument> <argument index="1" name="key_idx" type="int"> </argument> @@ -138,7 +138,7 @@ <method name="audio_track_set_key_stream"> <return type="void"> </return> - <argument index="0" name="idx" type="int"> + <argument index="0" name="track_idx" type="int"> </argument> <argument index="1" name="key_idx" type="int"> </argument> @@ -150,7 +150,7 @@ <method name="bezier_track_get_key_in_handle" qualifiers="const"> <return type="Vector2"> </return> - <argument index="0" name="idx" type="int"> + <argument index="0" name="track_idx" type="int"> </argument> <argument index="1" name="key_idx" type="int"> </argument> @@ -160,7 +160,7 @@ <method name="bezier_track_get_key_out_handle" qualifiers="const"> <return type="Vector2"> </return> - <argument index="0" name="idx" type="int"> + <argument index="0" name="track_idx" type="int"> </argument> <argument index="1" name="key_idx" type="int"> </argument> @@ -170,7 +170,7 @@ <method name="bezier_track_get_key_value" qualifiers="const"> <return type="float"> </return> - <argument index="0" name="idx" type="int"> + <argument index="0" name="track_idx" type="int"> </argument> <argument index="1" name="key_idx" type="int"> </argument> @@ -180,7 +180,7 @@ <method name="bezier_track_insert_key"> <return type="int"> </return> - <argument index="0" name="track" type="int"> + <argument index="0" name="track_idx" type="int"> </argument> <argument index="1" name="time" type="float"> </argument> @@ -196,7 +196,7 @@ <method name="bezier_track_interpolate" qualifiers="const"> <return type="float"> </return> - <argument index="0" name="track" type="int"> + <argument index="0" name="track_idx" type="int"> </argument> <argument index="1" name="time" type="float"> </argument> @@ -206,7 +206,7 @@ <method name="bezier_track_set_key_in_handle"> <return type="void"> </return> - <argument index="0" name="idx" type="int"> + <argument index="0" name="track_idx" type="int"> </argument> <argument index="1" name="key_idx" type="int"> </argument> @@ -218,7 +218,7 @@ <method name="bezier_track_set_key_out_handle"> <return type="void"> </return> - <argument index="0" name="idx" type="int"> + <argument index="0" name="track_idx" type="int"> </argument> <argument index="1" name="key_idx" type="int"> </argument> @@ -230,7 +230,7 @@ <method name="bezier_track_set_key_value"> <return type="void"> </return> - <argument index="0" name="idx" type="int"> + <argument index="0" name="track_idx" type="int"> </argument> <argument index="1" name="key_idx" type="int"> </argument> @@ -249,7 +249,7 @@ <method name="copy_track"> <return type="void"> </return> - <argument index="0" name="track" type="int"> + <argument index="0" name="track_idx" type="int"> </argument> <argument index="1" name="to_animation" type="Animation"> </argument> @@ -276,7 +276,7 @@ <method name="method_track_get_key_indices" qualifiers="const"> <return type="PoolIntArray"> </return> - <argument index="0" name="idx" type="int"> + <argument index="0" name="track_idx" type="int"> </argument> <argument index="1" name="time_sec" type="float"> </argument> @@ -289,7 +289,7 @@ <method name="method_track_get_name" qualifiers="const"> <return type="String"> </return> - <argument index="0" name="idx" type="int"> + <argument index="0" name="track_idx" type="int"> </argument> <argument index="1" name="key_idx" type="int"> </argument> @@ -300,7 +300,7 @@ <method name="method_track_get_params" qualifiers="const"> <return type="Array"> </return> - <argument index="0" name="idx" type="int"> + <argument index="0" name="track_idx" type="int"> </argument> <argument index="1" name="key_idx" type="int"> </argument> @@ -311,7 +311,7 @@ <method name="remove_track"> <return type="void"> </return> - <argument index="0" name="idx" type="int"> + <argument index="0" name="track_idx" type="int"> </argument> <description> Removes a track by specifying the track index. @@ -320,7 +320,7 @@ <method name="track_find_key" qualifiers="const"> <return type="int"> </return> - <argument index="0" name="idx" type="int"> + <argument index="0" name="track_idx" type="int"> </argument> <argument index="1" name="time" type="float"> </argument> @@ -333,7 +333,7 @@ <method name="track_get_interpolation_loop_wrap" qualifiers="const"> <return type="bool"> </return> - <argument index="0" name="idx" type="int"> + <argument index="0" name="track_idx" type="int"> </argument> <description> Returns [code]true[/code] if the track at [code]idx[/code] wraps the interpolation loop. New tracks wrap the interpolation loop by default. @@ -342,7 +342,7 @@ <method name="track_get_interpolation_type" qualifiers="const"> <return type="int" enum="Animation.InterpolationType"> </return> - <argument index="0" name="idx" type="int"> + <argument index="0" name="track_idx" type="int"> </argument> <description> Returns the interpolation type of a given track. @@ -351,7 +351,7 @@ <method name="track_get_key_count" qualifiers="const"> <return type="int"> </return> - <argument index="0" name="idx" type="int"> + <argument index="0" name="track_idx" type="int"> </argument> <description> Returns the amount of keys in a given track. @@ -360,7 +360,7 @@ <method name="track_get_key_time" qualifiers="const"> <return type="float"> </return> - <argument index="0" name="idx" type="int"> + <argument index="0" name="track_idx" type="int"> </argument> <argument index="1" name="key_idx" type="int"> </argument> @@ -371,7 +371,7 @@ <method name="track_get_key_transition" qualifiers="const"> <return type="float"> </return> - <argument index="0" name="idx" type="int"> + <argument index="0" name="track_idx" type="int"> </argument> <argument index="1" name="key_idx" type="int"> </argument> @@ -382,7 +382,7 @@ <method name="track_get_key_value" qualifiers="const"> <return type="Variant"> </return> - <argument index="0" name="idx" type="int"> + <argument index="0" name="track_idx" type="int"> </argument> <argument index="1" name="key_idx" type="int"> </argument> @@ -393,7 +393,7 @@ <method name="track_get_path" qualifiers="const"> <return type="NodePath"> </return> - <argument index="0" name="idx" type="int"> + <argument index="0" name="track_idx" type="int"> </argument> <description> Gets the path of a track. For more information on the path format, see [method track_set_path]. @@ -402,7 +402,7 @@ <method name="track_get_type" qualifiers="const"> <return type="int" enum="Animation.TrackType"> </return> - <argument index="0" name="idx" type="int"> + <argument index="0" name="track_idx" type="int"> </argument> <description> Gets the type of a track. @@ -411,7 +411,7 @@ <method name="track_insert_key"> <return type="void"> </return> - <argument index="0" name="idx" type="int"> + <argument index="0" name="track_idx" type="int"> </argument> <argument index="1" name="time" type="float"> </argument> @@ -426,7 +426,7 @@ <method name="track_is_enabled" qualifiers="const"> <return type="bool"> </return> - <argument index="0" name="idx" type="int"> + <argument index="0" name="track_idx" type="int"> </argument> <description> Returns [code]true[/code] if the track at index [code]idx[/code] is enabled. @@ -435,7 +435,7 @@ <method name="track_is_imported" qualifiers="const"> <return type="bool"> </return> - <argument index="0" name="idx" type="int"> + <argument index="0" name="track_idx" type="int"> </argument> <description> Returns [code]true[/code] if the given track is imported. Else, return [code]false[/code]. @@ -444,7 +444,7 @@ <method name="track_move_down"> <return type="void"> </return> - <argument index="0" name="idx" type="int"> + <argument index="0" name="track_idx" type="int"> </argument> <description> Moves a track down. @@ -453,7 +453,7 @@ <method name="track_move_to"> <return type="void"> </return> - <argument index="0" name="idx" type="int"> + <argument index="0" name="track_idx" type="int"> </argument> <argument index="1" name="to_idx" type="int"> </argument> @@ -464,7 +464,7 @@ <method name="track_move_up"> <return type="void"> </return> - <argument index="0" name="idx" type="int"> + <argument index="0" name="track_idx" type="int"> </argument> <description> Moves a track up. @@ -473,7 +473,7 @@ <method name="track_remove_key"> <return type="void"> </return> - <argument index="0" name="idx" type="int"> + <argument index="0" name="track_idx" type="int"> </argument> <argument index="1" name="key_idx" type="int"> </argument> @@ -484,7 +484,7 @@ <method name="track_remove_key_at_position"> <return type="void"> </return> - <argument index="0" name="idx" type="int"> + <argument index="0" name="track_idx" type="int"> </argument> <argument index="1" name="position" type="float"> </argument> @@ -495,7 +495,7 @@ <method name="track_set_enabled"> <return type="void"> </return> - <argument index="0" name="idx" type="int"> + <argument index="0" name="track_idx" type="int"> </argument> <argument index="1" name="enabled" type="bool"> </argument> @@ -506,7 +506,7 @@ <method name="track_set_imported"> <return type="void"> </return> - <argument index="0" name="idx" type="int"> + <argument index="0" name="track_idx" type="int"> </argument> <argument index="1" name="imported" type="bool"> </argument> @@ -517,7 +517,7 @@ <method name="track_set_interpolation_loop_wrap"> <return type="void"> </return> - <argument index="0" name="idx" type="int"> + <argument index="0" name="track_idx" type="int"> </argument> <argument index="1" name="interpolation" type="bool"> </argument> @@ -528,7 +528,7 @@ <method name="track_set_interpolation_type"> <return type="void"> </return> - <argument index="0" name="idx" type="int"> + <argument index="0" name="track_idx" type="int"> </argument> <argument index="1" name="interpolation" type="int" enum="Animation.InterpolationType"> </argument> @@ -539,7 +539,7 @@ <method name="track_set_key_time"> <return type="void"> </return> - <argument index="0" name="idx" type="int"> + <argument index="0" name="track_idx" type="int"> </argument> <argument index="1" name="key_idx" type="int"> </argument> @@ -552,7 +552,7 @@ <method name="track_set_key_transition"> <return type="void"> </return> - <argument index="0" name="idx" type="int"> + <argument index="0" name="track_idx" type="int"> </argument> <argument index="1" name="key_idx" type="int"> </argument> @@ -565,7 +565,7 @@ <method name="track_set_key_value"> <return type="void"> </return> - <argument index="0" name="idx" type="int"> + <argument index="0" name="track_idx" type="int"> </argument> <argument index="1" name="key" type="int"> </argument> @@ -578,7 +578,7 @@ <method name="track_set_path"> <return type="void"> </return> - <argument index="0" name="idx" type="int"> + <argument index="0" name="track_idx" type="int"> </argument> <argument index="1" name="path" type="NodePath"> </argument> @@ -590,7 +590,7 @@ <method name="track_swap"> <return type="void"> </return> - <argument index="0" name="idx" type="int"> + <argument index="0" name="track_idx" type="int"> </argument> <argument index="1" name="with_idx" type="int"> </argument> @@ -601,7 +601,7 @@ <method name="transform_track_insert_key"> <return type="int"> </return> - <argument index="0" name="idx" type="int"> + <argument index="0" name="track_idx" type="int"> </argument> <argument index="1" name="time" type="float"> </argument> @@ -618,7 +618,7 @@ <method name="transform_track_interpolate" qualifiers="const"> <return type="Array"> </return> - <argument index="0" name="idx" type="int"> + <argument index="0" name="track_idx" type="int"> </argument> <argument index="1" name="time_sec" type="float"> </argument> @@ -629,7 +629,7 @@ <method name="value_track_get_key_indices" qualifiers="const"> <return type="PoolIntArray"> </return> - <argument index="0" name="idx" type="int"> + <argument index="0" name="track_idx" type="int"> </argument> <argument index="1" name="time_sec" type="float"> </argument> @@ -642,7 +642,7 @@ <method name="value_track_get_update_mode" qualifiers="const"> <return type="int" enum="Animation.UpdateMode"> </return> - <argument index="0" name="idx" type="int"> + <argument index="0" name="track_idx" type="int"> </argument> <description> Returns the update mode of a value track. @@ -651,7 +651,7 @@ <method name="value_track_set_update_mode"> <return type="void"> </return> - <argument index="0" name="idx" type="int"> + <argument index="0" name="track_idx" type="int"> </argument> <argument index="1" name="mode" type="int" enum="Animation.UpdateMode"> </argument> diff --git a/doc/classes/HTTPClient.xml b/doc/classes/HTTPClient.xml index 1a2d5cab81..52e4b94051 100644 --- a/doc/classes/HTTPClient.xml +++ b/doc/classes/HTTPClient.xml @@ -44,6 +44,7 @@ </return> <description> Returns the response's body length. + [b]Note:[/b] Some Web servers may not send a body length. In this case, the value returned will be [code]-1[/code]. If using chunked transfer encoding, the body length will also be [code]-1[/code]. </description> </method> <method name="get_response_code" qualifiers="const"> @@ -175,7 +176,7 @@ <argument index="0" name="bytes" type="int"> </argument> <description> - Sets the size of the buffer used and maximum bytes to read per iteration. see [method read_response_body_chunk] + Sets the size of the buffer used and maximum bytes to read per iteration. See [method read_response_body_chunk]. </description> </method> </methods> diff --git a/doc/classes/HTTPRequest.xml b/doc/classes/HTTPRequest.xml index 53ee0b6132..3a73d44a01 100644 --- a/doc/classes/HTTPRequest.xml +++ b/doc/classes/HTTPRequest.xml @@ -23,6 +23,7 @@ </return> <description> Returns the response body length. + [b]Note:[/b] Some Web servers may not send a body length. In this case, the value returned will be [code]-1[/code]. If using chunked transfer encoding, the body length will also be [code]-1[/code]. </description> </method> <method name="get_downloaded_bytes" qualifiers="const"> diff --git a/doc/classes/Node.xml b/doc/classes/Node.xml index b206d4a4d2..1f685aab81 100644 --- a/doc/classes/Node.xml +++ b/doc/classes/Node.xml @@ -40,8 +40,9 @@ <return type="String"> </return> <description> - The string returned from this method is displayed as a warning in the "Scene Dock" if the script that overrides it is a [code]tool[/code] script. + The string returned from this method is displayed as a warning in the Scene Dock if the script that overrides it is a [code]tool[/code] script. Returning an empty string produces no warning. + Call [method update_configuration_warning] when the warning needs to be updated for this node. </description> </method> <method name="_input" qualifiers="virtual"> @@ -818,6 +819,14 @@ Sets whether this is an instance load placeholder. See [InstancePlaceholder]. </description> </method> + <method name="update_configuration_warning"> + <return type="void"> + </return> + <description> + Updates the warning displayed for this node in the Scene Dock. + Use [method _get_configuration_warning] to setup the warning message to display. + </description> + </method> </methods> <members> <member name="custom_multiplayer" type="MultiplayerAPI" setter="set_custom_multiplayer" getter="get_custom_multiplayer"> diff --git a/doc/classes/RichTextLabel.xml b/doc/classes/RichTextLabel.xml index faf2ac1ff9..01c8ee4779 100644 --- a/doc/classes/RichTextLabel.xml +++ b/doc/classes/RichTextLabel.xml @@ -16,8 +16,13 @@ </return> <argument index="0" name="image" type="Texture"> </argument> + <argument index="1" name="width" type="int" default="0"> + </argument> + <argument index="2" name="height" type="int" default="0"> + </argument> <description> - Adds an image's opening and closing tags to the tag stack. + Adds an image's opening and closing tags to the tag stack, optionally providing a [code]width[/code] and [code]height[/code] to resize the image. + If [code]width[/code] or [code]height[/code] is set to 0, the image size will be adjusted in order to keep the original aspect ratio. </description> </method> <method name="add_text"> diff --git a/doc/classes/TextEdit.xml b/doc/classes/TextEdit.xml index 8a114efd34..27eab85301 100644 --- a/doc/classes/TextEdit.xml +++ b/doc/classes/TextEdit.xml @@ -54,7 +54,7 @@ <return type="void"> </return> <description> - Clears all the syntax coloring information. + Clears all custom syntax coloring information previously added with [method add_color_region] or [method add_keyword_color]. </description> </method> <method name="clear_undo_history"> diff --git a/editor/animation_track_editor_plugins.cpp b/editor/animation_track_editor_plugins.cpp index 226eef9c1e..3e0b644b20 100644 --- a/editor/animation_track_editor_plugins.cpp +++ b/editor/animation_track_editor_plugins.cpp @@ -337,7 +337,7 @@ AnimationTrackEditAudio::AnimationTrackEditAudio() { AudioStreamPreviewGenerator::get_singleton()->connect("preview_updated", this, "_preview_changed"); } -/// SPRITE FRAME /// +/// SPRITE FRAME / FRAME_COORDS /// int AnimationTrackEditSpriteFrame::get_key_height() const { @@ -439,14 +439,24 @@ void AnimationTrackEditSpriteFrame::draw_key(int p_index, float p_pixels_sec, in if (Object::cast_to<Sprite>(object) || Object::cast_to<Sprite3D>(object)) { - int frame = get_animation()->track_get_key_value(get_track(), p_index); - texture = object->call("get_texture"); if (!texture.is_valid()) { AnimationTrackEdit::draw_key(p_index, p_pixels_sec, p_x, p_selected, p_clip_left, p_clip_right); return; } + int hframes = object->call("get_hframes"); + int vframes = object->call("get_vframes"); + + Vector2 coords; + if (is_coords) { + coords = get_animation()->track_get_key_value(get_track(), p_index); + } else { + int frame = get_animation()->track_get_key_value(get_track(), p_index); + coords.x = frame % hframes; + coords.y = frame / hframes; + } + region.size = texture->get_size(); if (bool(object->call("is_region"))) { @@ -454,9 +464,6 @@ void AnimationTrackEditSpriteFrame::draw_key(int p_index, float p_pixels_sec, in region = Rect2(object->call("get_region_rect")); } - int hframes = object->call("get_hframes"); - int vframes = object->call("get_vframes"); - if (hframes > 1) { region.size.x /= hframes; } @@ -464,8 +471,8 @@ void AnimationTrackEditSpriteFrame::draw_key(int p_index, float p_pixels_sec, in region.size.y /= vframes; } - region.position.x += region.size.x * (frame % hframes); - region.position.y += region.size.y * (frame / hframes); + region.position.x += region.size.x * coords.x; + region.position.y += region.size.y * coords.y; } else if (Object::cast_to<AnimatedSprite>(object) || Object::cast_to<AnimatedSprite3D>(object)) { @@ -532,6 +539,11 @@ void AnimationTrackEditSpriteFrame::set_node(Object *p_object) { id = p_object->get_instance_id(); } +void AnimationTrackEditSpriteFrame::set_as_coords() { + + is_coords = true; +} + /// SUB ANIMATION /// int AnimationTrackEditSubAnim::get_key_height() const { @@ -1297,6 +1309,14 @@ AnimationTrackEdit *AnimationTrackEditDefaultPlugin::create_value_track_edit(Obj return sprite; } + if (p_property == "frame_coords" && (p_object->is_class("Sprite") || p_object->is_class("Sprite3D"))) { + + AnimationTrackEditSpriteFrame *sprite = memnew(AnimationTrackEditSpriteFrame); + sprite->set_as_coords(); + sprite->set_node(p_object); + return sprite; + } + if (p_property == "current_animation" && (p_object->is_class("AnimationPlayer"))) { AnimationTrackEditSubAnim *player = memnew(AnimationTrackEditSubAnim); diff --git a/editor/animation_track_editor_plugins.h b/editor/animation_track_editor_plugins.h index 5f0ea6196c..1013cccf72 100644 --- a/editor/animation_track_editor_plugins.h +++ b/editor/animation_track_editor_plugins.h @@ -81,6 +81,7 @@ class AnimationTrackEditSpriteFrame : public AnimationTrackEdit { GDCLASS(AnimationTrackEditSpriteFrame, AnimationTrackEdit); ObjectID id; + bool is_coords; public: virtual int get_key_height() const; @@ -89,6 +90,9 @@ public: virtual void draw_key(int p_index, float p_pixels_sec, int p_x, bool p_selected, int p_clip_left, int p_clip_right); void set_node(Object *p_object); + void set_as_coords(); + + AnimationTrackEditSpriteFrame() { is_coords = false; } }; class AnimationTrackEditSubAnim : public AnimationTrackEdit { diff --git a/editor/editor_help.cpp b/editor/editor_help.cpp index 4a1e93eaad..690538f44c 100644 --- a/editor/editor_help.cpp +++ b/editor/editor_help.cpp @@ -1467,6 +1467,11 @@ void EditorHelp::_notification(int p_what) { _update_doc(); } break; + case NOTIFICATION_THEME_CHANGED: { + if (is_visible_in_tree()) { + _class_desc_resized(); + } + } break; default: break; } } diff --git a/editor/editor_inspector.cpp b/editor/editor_inspector.cpp index 78e058eeaa..96b6a32914 100644 --- a/editor/editor_inspector.cpp +++ b/editor/editor_inspector.cpp @@ -644,7 +644,19 @@ void EditorProperty::_gui_input(const Ref<InputEvent> &p_event) { emit_signal("property_keyed", property, use_keying_next()); if (use_keying_next()) { - call_deferred("emit_changed", property, object->get(property).operator int64_t() + 1, "", false); + if (property == "frame_coords" && (object->is_class("Sprite") || object->is_class("Sprite3D"))) { + Vector2 new_coords = object->get(property); + new_coords.x++; + if (new_coords.x >= object->get("hframes").operator int64_t()) { + new_coords.x = 0; + new_coords.y++; + } + + call_deferred("emit_changed", property, new_coords, "", false); + } else { + call_deferred("emit_changed", property, object->get(property).operator int64_t() + 1, "", false); + } + call_deferred("update_property"); } } diff --git a/editor/editor_node.cpp b/editor/editor_node.cpp index 2c3a84857a..6e2a4810cd 100644 --- a/editor/editor_node.cpp +++ b/editor/editor_node.cpp @@ -56,6 +56,7 @@ #include "editor/editor_help.h" #include "editor/editor_properties.h" #include "editor/editor_settings.h" +#include "editor/editor_spin_slider.h" #include "editor/editor_themes.h" #include "editor/import/editor_import_collada.h" #include "editor/import/editor_scene_importer_gltf.h" @@ -3558,6 +3559,7 @@ void EditorNode::register_editor_types() { ClassDB::register_class<AnimationTrackEditPlugin>(); ClassDB::register_class<ScriptCreateDialog>(); ClassDB::register_class<EditorFeatureProfile>(); + ClassDB::register_class<EditorSpinSlider>(); // FIXME: Is this stuff obsolete, or should it be ported to new APIs? ClassDB::register_class<EditorScenePostImport>(); diff --git a/editor/editor_properties.cpp b/editor/editor_properties.cpp index fbb66744a7..d3d91e6e0d 100644 --- a/editor/editor_properties.cpp +++ b/editor/editor_properties.cpp @@ -2205,7 +2205,14 @@ void EditorPropertyResource::_menu_option(int p_which) { case OBJ_MENU_NEW_SCRIPT: { if (Object::cast_to<Node>(get_edited_object())) { - EditorNode::get_singleton()->get_scene_tree_dock()->open_script_dialog(Object::cast_to<Node>(get_edited_object())); + EditorNode::get_singleton()->get_scene_tree_dock()->open_script_dialog(Object::cast_to<Node>(get_edited_object()), false); + } + + } break; + case OBJ_MENU_EXTEND_SCRIPT: { + + if (Object::cast_to<Node>(get_edited_object())) { + EditorNode::get_singleton()->get_scene_tree_dock()->open_script_dialog(Object::cast_to<Node>(get_edited_object()), true); } } break; @@ -2338,7 +2345,8 @@ void EditorPropertyResource::_update_menu_items() { menu->clear(); if (get_edited_property() == "script" && base_type == "Script" && Object::cast_to<Node>(get_edited_object())) { - menu->add_icon_item(get_icon("Script", "EditorIcons"), TTR("New Script"), OBJ_MENU_NEW_SCRIPT); + menu->add_icon_item(get_icon("ScriptCreate", "EditorIcons"), TTR("New Script"), OBJ_MENU_NEW_SCRIPT); + menu->add_icon_item(get_icon("ScriptExtend", "EditorIcons"), TTR("Extend Script"), OBJ_MENU_EXTEND_SCRIPT); menu->add_separator(); } else if (base_type != "") { int idx = 0; @@ -2633,7 +2641,6 @@ void EditorPropertyResource::update_property() { if (res == RES()) { assign->set_icon(Ref<Texture>()); assign->set_text(TTR("[empty]")); - assign->set_tooltip(""); } else { assign->set_icon(EditorNode::get_singleton()->get_object_icon(res.operator->(), "Object")); @@ -2909,7 +2916,7 @@ void EditorInspectorDefaultPlugin::parse_begin(Object *p_object) { bool EditorInspectorDefaultPlugin::parse_property(Object *p_object, Variant::Type p_type, const String &p_path, PropertyHint p_hint, const String &p_hint_text, int p_usage) { - double default_float_step = EDITOR_GET("interface/inspector/default_float_step"); + float default_float_step = EDITOR_GET("interface/inspector/default_float_step"); switch (p_type) { diff --git a/editor/editor_properties.h b/editor/editor_properties.h index b8d6aa00c2..952b0447e2 100644 --- a/editor/editor_properties.h +++ b/editor/editor_properties.h @@ -550,7 +550,8 @@ class EditorPropertyResource : public EditorProperty { OBJ_MENU_COPY = 5, OBJ_MENU_PASTE = 6, OBJ_MENU_NEW_SCRIPT = 7, - OBJ_MENU_SHOW_IN_FILE_SYSTEM = 8, + OBJ_MENU_EXTEND_SCRIPT = 8, + OBJ_MENU_SHOW_IN_FILE_SYSTEM = 9, TYPE_BASE_ID = 100, CONVERT_BASE_ID = 1000 diff --git a/editor/icons/icon_crypto_key.svg b/editor/icons/icon_crypto_key.svg new file mode 100644 index 0000000000..45b53c815d --- /dev/null +++ b/editor/icons/icon_crypto_key.svg @@ -0,0 +1 @@ +<svg height="16" viewBox="0 0 4.233 4.233" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m2.397.34-.374.373-.375.374v.375l.188.187-1.497 1.496v.375l.374.374h.374l.187-.188.282-.092.092-.282.282-.093.093-.28.094-.28.28-.095.187-.187.187.187h.374l.375-.375.373-.373.001-.374-1.122-1.122zm.374.858a.264.264 0 1 1 .002.528.264.264 0 0 1 -.002-.528z" fill="#e0e0e0"/></svg>
\ No newline at end of file diff --git a/editor/icons/icon_x509_certificate.svg b/editor/icons/icon_x509_certificate.svg new file mode 100644 index 0000000000..e175fa3234 --- /dev/null +++ b/editor/icons/icon_x509_certificate.svg @@ -0,0 +1 @@ +<svg height="16" viewBox="0 0 4.233 4.233" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m3.967.263-3.704.001v2.646h1.427a.993.993 0 0 1 -.022-.096.993.993 0 0 1 -.012-.099.993.993 0 0 1 -.002-.07.993.993 0 0 1 .005-.1.993.993 0 0 1 .014-.097.993.993 0 0 1 .025-.096.993.993 0 0 1 .034-.093.993.993 0 0 1 .043-.09.993.993 0 0 1 .052-.085.993.993 0 0 1 .06-.079.993.993 0 0 1 .068-.072.993.993 0 0 1 .074-.066.993.993 0 0 1 .08-.057.993.993 0 0 1 .087-.05.993.993 0 0 1 .09-.04.993.993 0 0 1 .095-.031.993.993 0 0 1 .096-.022.993.993 0 0 1 .099-.012.993.993 0 0 1 .07-.003.993.993 0 0 1 .099.006.993.993 0 0 1 .098.014.993.993 0 0 1 .096.025.993.993 0 0 1 .094.034.993.993 0 0 1 .089.043.993.993 0 0 1 .084.052.993.993 0 0 1 .08.06.993.993 0 0 1 .072.068.993.993 0 0 1 .065.074.993.993 0 0 1 .058.08.993.993 0 0 1 .05.087.993.993 0 0 1 .04.09.993.993 0 0 1 .031.095.993.993 0 0 1 .022.096.993.993 0 0 1 .012.099.993.993 0 0 1 .002.07.993.993 0 0 1 -.004.1.993.993 0 0 1 -.015.097.993.993 0 0 1 -.017.068h.365z" fill="#e0e0e0"/><g fill="#ff8484"><path d="m2.116 3.175v.793l.53-.253.529.253v-.793z"/><circle cx="2.646" cy="2.645" r=".794"/></g></svg>
\ No newline at end of file diff --git a/editor/node_dock.cpp b/editor/node_dock.cpp index d6df3bd369..7ba1796600 100644 --- a/editor/node_dock.cpp +++ b/editor/node_dock.cpp @@ -129,6 +129,7 @@ NodeDock::NodeDock() { select_a_node = memnew(Label); select_a_node->set_text(TTR("Select a single node to edit its signals and groups.")); + select_a_node->set_custom_minimum_size(Size2(100 * EDSCALE, 0)); select_a_node->set_v_size_flags(SIZE_EXPAND_FILL); select_a_node->set_valign(Label::VALIGN_CENTER); select_a_node->set_align(Label::ALIGN_CENTER); diff --git a/editor/plugins/canvas_item_editor_plugin.cpp b/editor/plugins/canvas_item_editor_plugin.cpp index 2a31d53a7e..f9a7b7caf1 100644 --- a/editor/plugins/canvas_item_editor_plugin.cpp +++ b/editor/plugins/canvas_item_editor_plugin.cpp @@ -2721,8 +2721,10 @@ void CanvasItemEditor::_draw_ruler_tool() { viewport->draw_string(font, text_pos, vformat("%.2f px", length_vector.length()), font_color); if (draw_secondary_lines) { - int horizontal_axis_angle = round(180 * atan2(length_vector.y, length_vector.x) / Math_PI); - int vertictal_axis_angle = 90 - horizontal_axis_angle; + const float horizontal_angle_rad = atan2(length_vector.y, length_vector.x); + const float vertical_angle_rad = Math_PI / 2.0 - horizontal_angle_rad; + const int horizontal_angle = round(180 * horizontal_angle_rad / Math_PI); + const int vertical_angle = round(180 * vertical_angle_rad / Math_PI); Point2 text_pos2 = text_pos; text_pos2.x = begin.x < text_pos.x ? MIN(text_pos.x - text_width, begin.x - text_width / 2) : MAX(text_pos.x + text_width, begin.x - text_width / 2); @@ -2731,7 +2733,7 @@ void CanvasItemEditor::_draw_ruler_tool() { Point2 v_angle_text_pos = Point2(); v_angle_text_pos.x = CLAMP(begin.x - angle_text_width / 2, angle_text_width / 2, viewport->get_rect().size.x - angle_text_width); v_angle_text_pos.y = begin.y < end.y ? MIN(text_pos2.y - 2 * text_height, begin.y - text_height * 0.5) : MAX(text_pos2.y + text_height * 3, begin.y + text_height * 1.5); - viewport->draw_string(font, v_angle_text_pos, vformat("%d deg", vertictal_axis_angle), font_secondary_color); + viewport->draw_string(font, v_angle_text_pos, vformat("%d deg", vertical_angle), font_secondary_color); text_pos2 = text_pos; text_pos2.y = end.y < text_pos.y ? MIN(text_pos.y - text_height * 2, end.y - text_height / 2) : MAX(text_pos.y + text_height * 2, end.y - text_height / 2); @@ -2752,7 +2754,35 @@ void CanvasItemEditor::_draw_ruler_tool() { h_angle_text_pos.y = MIN(text_pos.y - height_multiplier * text_height, MIN(end.y - text_height * 0.5, text_pos2.y - height_multiplier * text_height)); } } - viewport->draw_string(font, h_angle_text_pos, vformat("%d deg", horizontal_axis_angle), font_secondary_color); + viewport->draw_string(font, h_angle_text_pos, vformat("%d deg", horizontal_angle), font_secondary_color); + + // Angle arcs + int arc_point_count = 8; + float arc_radius_max_length_percent = 0.1; + float ruler_length = length_vector.length() * zoom; + float arc_max_radius = 50.0; + float arc_line_width = 2.0; + + const Vector2 end_to_begin = (end - begin); + + float arc_1_start_angle = + end_to_begin.x < 0 ? + (end_to_begin.y < 0 ? 3.0 * Math_PI / 2.0 - vertical_angle_rad : Math_PI / 2.0) : + (end_to_begin.y < 0 ? 3.0 * Math_PI / 2.0 : Math_PI / 2.0 - vertical_angle_rad); + float arc_1_end_angle = arc_1_start_angle + vertical_angle_rad; + // Constrain arc to triangle height & max size + float arc_1_radius = MIN(MIN(arc_radius_max_length_percent * ruler_length, ABS(end_to_begin.y)), arc_max_radius); + + float arc_2_start_angle = + end_to_begin.x < 0 ? + (end_to_begin.y < 0 ? 0.0 : -horizontal_angle_rad) : + (end_to_begin.y < 0 ? Math_PI - horizontal_angle_rad : Math_PI); + float arc_2_end_angle = arc_2_start_angle + horizontal_angle_rad; + // Constrain arc to triangle width & max size + float arc_2_radius = MIN(MIN(arc_radius_max_length_percent * ruler_length, ABS(end_to_begin.x)), arc_max_radius); + + viewport->draw_arc(begin, arc_1_radius, arc_1_start_angle, arc_1_end_angle, arc_point_count, ruler_primary_color, Math::round(EDSCALE * arc_line_width)); + viewport->draw_arc(end, arc_2_radius, arc_2_start_angle, arc_2_end_angle, arc_point_count, ruler_primary_color, Math::round(EDSCALE * arc_line_width)); } if (is_snap_active) { diff --git a/editor/plugins/script_text_editor.cpp b/editor/plugins/script_text_editor.cpp index ecb2354aa1..5bccb36252 100644 --- a/editor/plugins/script_text_editor.cpp +++ b/editor/plugins/script_text_editor.cpp @@ -1186,7 +1186,7 @@ void ScriptTextEditor::_edit_option(int p_op) { if (expression.parse(line) == OK) { Variant result = expression.execute(Array(), Variant(), false); if (expression.get_error_text() == "") { - results.append(whitespace + (String)result); + results.append(whitespace + result.get_construct_string()); } else { results.append(line); } diff --git a/editor/property_editor.cpp b/editor/property_editor.cpp index ecb272876d..ce82d44164 100644 --- a/editor/property_editor.cpp +++ b/editor/property_editor.cpp @@ -246,7 +246,13 @@ void CustomPropertyEditor::_menu_option(int p_which) { case OBJ_MENU_NEW_SCRIPT: { if (Object::cast_to<Node>(owner)) - EditorNode::get_singleton()->get_scene_tree_dock()->open_script_dialog(Object::cast_to<Node>(owner)); + EditorNode::get_singleton()->get_scene_tree_dock()->open_script_dialog(Object::cast_to<Node>(owner), false); + + } break; + case OBJ_MENU_EXTEND_SCRIPT: { + + if (Object::cast_to<Node>(owner)) + EditorNode::get_singleton()->get_scene_tree_dock()->open_script_dialog(Object::cast_to<Node>(owner), true); } break; case OBJ_MENU_SHOW_IN_FILE_SYSTEM: { diff --git a/editor/property_editor.h b/editor/property_editor.h index 029c2211d5..b1c61c5e25 100644 --- a/editor/property_editor.h +++ b/editor/property_editor.h @@ -77,7 +77,8 @@ class CustomPropertyEditor : public Popup { OBJ_MENU_COPY = 4, OBJ_MENU_PASTE = 5, OBJ_MENU_NEW_SCRIPT = 6, - OBJ_MENU_SHOW_IN_FILE_SYSTEM = 7, + OBJ_MENU_EXTEND_SCRIPT = 7, + OBJ_MENU_SHOW_IN_FILE_SYSTEM = 8, TYPE_BASE_ID = 100, CONVERT_BASE_ID = 1000 }; diff --git a/editor/scene_tree_dock.cpp b/editor/scene_tree_dock.cpp index 98ab1bfb54..0884620e5d 100644 --- a/editor/scene_tree_dock.cpp +++ b/editor/scene_tree_dock.cpp @@ -421,53 +421,11 @@ void SceneTreeDock::_tool_selected(int p_tool, bool p_confirm_override) { create_dialog->popup_create(false, true, selected->get_class()); } break; + case TOOL_EXTEND_SCRIPT: { + attach_script_to_selected(true); + } break; case TOOL_ATTACH_SCRIPT: { - - if (!profile_allow_script_editing) { - break; - } - - List<Node *> selection = editor_selection->get_selected_node_list(); - if (selection.empty()) - break; - - Node *selected = scene_tree->get_selected(); - if (!selected) - selected = selection.front()->get(); - - Ref<Script> existing = selected->get_script(); - - String path = selected->get_filename(); - if (path == "") { - String root_path = editor_data->get_edited_scene_root()->get_filename(); - if (root_path == "") { - path = String("res://").plus_file(selected->get_name()); - } else { - path = root_path.get_base_dir().plus_file(selected->get_name()); - } - } - - String inherits = selected->get_class(); - if (existing.is_valid()) { - for (int i = 0; i < ScriptServer::get_language_count(); i++) { - ScriptLanguage *l = ScriptServer::get_language(i); - if (l->get_type() == existing->get_class()) { - String name = l->get_global_class_name(existing->get_path()); - if (ScriptServer::is_global_class(name) && EDITOR_GET("interface/editors/derive_script_globals_by_name").operator bool()) { - inherits = name; - } else if (l->can_inherit_from_file()) { - inherits = "\"" + existing->get_path() + "\""; - } - break; - } - } - } - script_create_dialog->connect("script_created", this, "_script_created"); - script_create_dialog->connect("popup_hide", this, "_script_creation_closed"); - script_create_dialog->set_inheritance_base_type("Node"); - script_create_dialog->config(inherits, path); - script_create_dialog->popup_centered(); - + attach_script_to_selected(false); } break; case TOOL_CLEAR_SCRIPT: { @@ -2482,10 +2440,9 @@ void SceneTreeDock::_tree_rmb(const Vector2 &p_menu_pos) { if (profile_allow_script_editing) { if (selection.size() == 1) { - if (!existing_script.is_valid()) { - menu->add_icon_shortcut(get_icon("ScriptCreate", "EditorIcons"), ED_GET_SHORTCUT("scene_tree/attach_script"), TOOL_ATTACH_SCRIPT); - } else { - menu->add_icon_shortcut(get_icon("ScriptExtend", "EditorIcons"), ED_GET_SHORTCUT("scene_tree/extend_script"), TOOL_ATTACH_SCRIPT); + menu->add_icon_shortcut(get_icon("ScriptCreate", "EditorIcons"), ED_GET_SHORTCUT("scene_tree/attach_script"), TOOL_ATTACH_SCRIPT); + if (existing_script.is_valid()) { + menu->add_icon_shortcut(get_icon("ScriptExtend", "EditorIcons"), ED_GET_SHORTCUT("scene_tree/extend_script"), TOOL_EXTEND_SCRIPT); } } if (selection.size() > 1 || (existing_script.is_valid() && exisiting_script_removable)) { @@ -2595,10 +2552,64 @@ void SceneTreeDock::_focus_node() { } } -void SceneTreeDock::open_script_dialog(Node *p_for_node) { +void SceneTreeDock::attach_script_to_selected(bool p_extend) { + if (!profile_allow_script_editing) { + return; + } + + List<Node *> selection = editor_selection->get_selected_node_list(); + if (selection.empty()) + return; + + Node *selected = scene_tree->get_selected(); + if (!selected) + selected = selection.front()->get(); + + Ref<Script> existing = selected->get_script(); + + String path = selected->get_filename(); + if (path == "") { + String root_path = editor_data->get_edited_scene_root()->get_filename(); + if (root_path == "") { + path = String("res://").plus_file(selected->get_name()); + } else { + path = root_path.get_base_dir().plus_file(selected->get_name()); + } + } + + String inherits = selected->get_class(); + + if (p_extend && existing.is_valid()) { + for (int i = 0; i < ScriptServer::get_language_count(); i++) { + ScriptLanguage *l = ScriptServer::get_language(i); + if (l->get_type() == existing->get_class()) { + String name = l->get_global_class_name(existing->get_path()); + if (ScriptServer::is_global_class(name) && EDITOR_GET("interface/editors/derive_script_globals_by_name").operator bool()) { + inherits = name; + } else if (l->can_inherit_from_file()) { + inherits = "\"" + existing->get_path() + "\""; + } + break; + } + } + } + + script_create_dialog->connect("script_created", this, "_script_created"); + script_create_dialog->connect("popup_hide", this, "_script_creation_closed"); + script_create_dialog->set_inheritance_base_type("Node"); + script_create_dialog->config(inherits, path); + script_create_dialog->popup_centered(); +} + +void SceneTreeDock::open_script_dialog(Node *p_for_node, bool p_extend) { scene_tree->set_selected(p_for_node, false); - _tool_selected(TOOL_ATTACH_SCRIPT); + + if (p_extend) { + _tool_selected(TOOL_EXTEND_SCRIPT); + } else { + _tool_selected(TOOL_ATTACH_SCRIPT); + } } void SceneTreeDock::add_remote_tree_editor(Control *p_remote) { diff --git a/editor/scene_tree_dock.h b/editor/scene_tree_dock.h index 014ce58e88..4e78b84c53 100644 --- a/editor/scene_tree_dock.h +++ b/editor/scene_tree_dock.h @@ -64,6 +64,7 @@ class SceneTreeDock : public VBoxContainer { TOOL_RENAME, TOOL_BATCH_RENAME, TOOL_REPLACE, + TOOL_EXTEND_SCRIPT, TOOL_ATTACH_SCRIPT, TOOL_CLEAR_SCRIPT, TOOL_MOVE_UP, @@ -259,7 +260,8 @@ public: void replace_node(Node *p_node, Node *p_by_node, bool p_keep_properties = true, bool p_remove_old = true); - void open_script_dialog(Node *p_for_node); + void attach_script_to_selected(bool p_extend); + void open_script_dialog(Node *p_for_node, bool p_extend); ScriptCreateDialog *get_script_create_dialog() { return script_create_dialog; } diff --git a/modules/gdscript/gdscript_editor.cpp b/modules/gdscript/gdscript_editor.cpp index 9b3bf8ad5b..1d82735328 100644 --- a/modules/gdscript/gdscript_editor.cpp +++ b/modules/gdscript/gdscript_editor.cpp @@ -1944,11 +1944,10 @@ static void _find_identifiers_in_base(const GDScriptCompletionContext &p_context ScriptCodeCompletionOption option(E->get().name, ScriptCodeCompletionOption::KIND_MEMBER); r_result.insert(option.display, option); } - } else { - for (const Set<StringName>::Element *E = script->get_members().front(); E; E = E->next()) { - ScriptCodeCompletionOption option(E->get().operator String(), ScriptCodeCompletionOption::KIND_MEMBER); - r_result.insert(option.display, option); - } + } + for (const Set<StringName>::Element *E = script->get_members().front(); E; E = E->next()) { + ScriptCodeCompletionOption option(E->get().operator String(), ScriptCodeCompletionOption::KIND_MEMBER); + r_result.insert(option.display, option); } } if (!p_only_functions) { diff --git a/modules/gdscript/gdscript_parser.cpp b/modules/gdscript/gdscript_parser.cpp index 282bb45c3f..da6a52ff0d 100644 --- a/modules/gdscript/gdscript_parser.cpp +++ b/modules/gdscript/gdscript_parser.cpp @@ -858,11 +858,23 @@ GDScriptParser::Node *GDScriptParser::_parse_expression(Node *p_parent, bool p_s if (current_function) { int arg_idx = current_function->arguments.find(identifier); if (arg_idx != -1) { - if (tokenizer->get_token() == GDScriptTokenizer::TK_OP_ASSIGN) { - // Assignment is not really usage - current_function->arguments_usage.write[arg_idx] = current_function->arguments_usage[arg_idx] - 1; - } else { - current_function->arguments_usage.write[arg_idx] = current_function->arguments_usage[arg_idx] + 1; + switch (tokenizer->get_token()) { + case GDScriptTokenizer::TK_OP_ASSIGN_ADD: + case GDScriptTokenizer::TK_OP_ASSIGN_BIT_AND: + case GDScriptTokenizer::TK_OP_ASSIGN_BIT_OR: + case GDScriptTokenizer::TK_OP_ASSIGN_BIT_XOR: + case GDScriptTokenizer::TK_OP_ASSIGN_DIV: + case GDScriptTokenizer::TK_OP_ASSIGN_MOD: + case GDScriptTokenizer::TK_OP_ASSIGN_MUL: + case GDScriptTokenizer::TK_OP_ASSIGN_SHIFT_LEFT: + case GDScriptTokenizer::TK_OP_ASSIGN_SHIFT_RIGHT: + case GDScriptTokenizer::TK_OP_ASSIGN_SUB: + case GDScriptTokenizer::TK_OP_ASSIGN: { + // Assignment is not really usage + } break; + default: { + current_function->arguments_usage.write[arg_idx] = current_function->arguments_usage[arg_idx] + 1; + } } } } diff --git a/modules/gdscript/gdscript_tokenizer.cpp b/modules/gdscript/gdscript_tokenizer.cpp index 8b20b0ff48..4730e9b6bc 100644 --- a/modules/gdscript/gdscript_tokenizer.cpp +++ b/modules/gdscript/gdscript_tokenizer.cpp @@ -849,12 +849,8 @@ void GDScriptTokenizerText::_advance() { _make_error("Unterminated String"); return; } - if (!((c >= '0' && c <= '9') || (c >= 'a' && c <= 'f') || (c >= 'A' && c <= 'F'))) { - _make_error("Malformed hex constant in string"); - return; - } - CharType v; + CharType v = 0; if (c >= '0' && c <= '9') { v = c - '0'; } else if (c >= 'a' && c <= 'f') { @@ -864,8 +860,8 @@ void GDScriptTokenizerText::_advance() { v = c - 'A'; v += 10; } else { - ERR_PRINT("BUG"); - v = 0; + _make_error("Malformed hex constant in string"); + return; } res <<= 4; diff --git a/modules/gridmap/grid_map_editor_plugin.cpp b/modules/gridmap/grid_map_editor_plugin.cpp index c97524a54d..804c57fc6e 100644 --- a/modules/gridmap/grid_map_editor_plugin.cpp +++ b/modules/gridmap/grid_map_editor_plugin.cpp @@ -40,11 +40,8 @@ void GridMapEditor::_node_removed(Node *p_node) { - if (p_node == node) { + if (p_node == node) node = NULL; - hide(); - mesh_library_palette->hide(); - } } void GridMapEditor::_configure() { @@ -353,7 +350,14 @@ void GridMapEditor::_set_selection(bool p_active, const Vector3 &p_begin, const selection.click = p_begin; selection.current = p_end; - _update_selection_transform(); + if (is_visible_in_tree()) { + _update_selection_transform(); + } + + options->get_popup()->set_item_disabled(options->get_popup()->get_item_index(MENU_OPTION_SELECTION_CLEAR), !selection.active); + options->get_popup()->set_item_disabled(options->get_popup()->get_item_index(MENU_OPTION_SELECTION_CUT), !selection.active); + options->get_popup()->set_item_disabled(options->get_popup()->get_item_index(MENU_OPTION_SELECTION_DUPLICATE), !selection.active); + options->get_popup()->set_item_disabled(options->get_popup()->get_item_index(MENU_OPTION_SELECTION_FILL), !selection.active); } bool GridMapEditor::do_input_action(Camera *p_camera, const Point2 &p_point, bool p_click) { @@ -1465,7 +1469,7 @@ GridMapEditor::GridMapEditor(EditorNode *p_editor) { } } - selection.active = false; + _set_selection(false); updating = false; accumulated_floor_delta = 0.0; } diff --git a/platform/android/java/lib/src/org/godotengine/godot/Godot.java b/platform/android/java/lib/src/org/godotengine/godot/Godot.java index 739aa285bf..247f006a69 100644 --- a/platform/android/java/lib/src/org/godotengine/godot/Godot.java +++ b/platform/android/java/lib/src/org/godotengine/godot/Godot.java @@ -56,11 +56,14 @@ import android.hardware.SensorManager; import android.os.Build; import android.os.Bundle; import android.os.Environment; +import android.os.Handler; +import android.os.Looper; import android.os.Messenger; import android.os.VibrationEffect; import android.os.Vibrator; import android.provider.Settings.Secure; import android.support.annotation.Keep; +import android.support.annotation.Nullable; import android.support.v4.content.ContextCompat; import android.view.Display; import android.view.KeyEvent; @@ -126,6 +129,9 @@ public abstract class Godot extends Activity implements SensorEventListener, IDo private boolean activityResumed; private int mState; + // Used to dispatch events to the main thread. + private final Handler mainThreadHandler = new Handler(Looper.getMainLooper()); + static private Intent mCurrentIntent; @Override @@ -187,6 +193,20 @@ public abstract class Godot extends Activity implements SensorEventListener, IDo Godot.singletons[Godot.singleton_count++] = this; } + /** + * Invoked once during the Godot Android initialization process after creation of the + * {@link GodotView} view. + * <p> + * This method should be overridden by descendants of this class that would like to add + * their view/layout to the Godot view hierarchy. + * + * @return the view to be included; null if no views should be included. + */ + @Nullable + protected View onMainCreateView(Activity activity) { + return null; + } + protected void onMainActivityResult(int requestCode, int resultCode, Intent data) { } @@ -306,6 +326,20 @@ public abstract class Godot extends Activity implements SensorEventListener, IDo public void run() { GodotLib.setup(current_command_line); setKeepScreenOn("True".equals(GodotLib.getGlobal("display/window/energy_saving/keep_screen_on"))); + + // The Godot Android plugins are setup on completion of GodotLib.setup + mainThreadHandler.post(new Runnable() { + @Override + public void run() { + // Include the non-null views returned in the Godot view hierarchy. + for (int i = 0; i < singleton_count; i++) { + View view = singletons[i].onMainCreateView(Godot.this); + if (view != null) { + layout.addView(view); + } + } + } + }); } }); } diff --git a/platform/osx/dir_access_osx.mm b/platform/osx/dir_access_osx.mm index ada142005b..75f50aaa28 100644 --- a/platform/osx/dir_access_osx.mm +++ b/platform/osx/dir_access_osx.mm @@ -48,18 +48,25 @@ String DirAccessOSX::fix_unicode_name(const char *p_name) const { } int DirAccessOSX::get_drive_count() { - NSArray *vols = [[NSWorkspace sharedWorkspace] mountedLocalVolumePaths]; + NSArray *res_keys = [NSArray arrayWithObjects:NSURLVolumeURLKey, NSURLIsSystemImmutableKey, nil]; + NSArray *vols = [[NSFileManager defaultManager] mountedVolumeURLsIncludingResourceValuesForKeys:res_keys options:NSVolumeEnumerationSkipHiddenVolumes]; + return [vols count]; } String DirAccessOSX::get_drive(int p_drive) { - NSArray *vols = [[NSWorkspace sharedWorkspace] mountedLocalVolumePaths]; + NSArray *res_keys = [NSArray arrayWithObjects:NSURLVolumeURLKey, NSURLIsSystemImmutableKey, nil]; + NSArray *vols = [[NSFileManager defaultManager] mountedVolumeURLsIncludingResourceValuesForKeys:res_keys options:NSVolumeEnumerationSkipHiddenVolumes]; int count = [vols count]; ERR_FAIL_INDEX_V(p_drive, count, ""); - NSString *path = vols[p_drive]; - return String([path UTF8String]); + String volname; + NSString *path = [vols[p_drive] path]; + + volname.parse_utf8([path UTF8String]); + + return volname; } #endif //posix_enabled diff --git a/platform/windows/detect.py b/platform/windows/detect.py index cc9ba720a8..f4390a9882 100644 --- a/platform/windows/detect.py +++ b/platform/windows/detect.py @@ -65,6 +65,8 @@ def get_opts(): BoolVariable('separate_debug_symbols', 'Create a separate file containing debugging symbols', False), ('msvc_version', 'MSVC version to use. Ignored if VCINSTALLDIR is set in shell env.', None), BoolVariable('use_mingw', 'Use the Mingw compiler, even if MSVC is installed. Only used on Windows.', False), + BoolVariable('use_llvm', 'Use the LLVM compiler', False), + BoolVariable('use_thinlto', 'Use ThinLTO', False), ] @@ -312,17 +314,33 @@ def configure_mingw(env): env.Append(LINKFLAGS=['-static']) mingw_prefix = env["mingw_prefix_64"] - env["CC"] = mingw_prefix + "gcc" - env['AS'] = mingw_prefix + "as" - env['CXX'] = mingw_prefix + "g++" - env['AR'] = mingw_prefix + "gcc-ar" - env['RANLIB'] = mingw_prefix + "gcc-ranlib" - env['LINK'] = mingw_prefix + "g++" + if env['use_llvm']: + env["CC"] = mingw_prefix + "clang" + env['AS'] = mingw_prefix + "as" + env["CXX"] = mingw_prefix + "clang++" + env['AR'] = mingw_prefix + "ar" + env['RANLIB'] = mingw_prefix + "ranlib" + env["LINK"] = mingw_prefix + "clang++" + else: + env["CC"] = mingw_prefix + "gcc" + env['AS'] = mingw_prefix + "as" + env['CXX'] = mingw_prefix + "g++" + env['AR'] = mingw_prefix + "gcc-ar" + env['RANLIB'] = mingw_prefix + "gcc-ranlib" + env['LINK'] = mingw_prefix + "g++" env["x86_libtheora_opt_gcc"] = True if env['use_lto']: - env.Append(CCFLAGS=['-flto']) - env.Append(LINKFLAGS=['-flto=' + str(env.GetOption("num_jobs"))]) + if not env['use_llvm'] and env.GetOption("num_jobs") > 1: + env.Append(CCFLAGS=['-flto']) + env.Append(LINKFLAGS=['-flto=' + str(env.GetOption("num_jobs"))]) + else: + if env['use_thinlto']: + env.Append(CCFLAGS=['-flto=thin']) + env.Append(LINKFLAGS=['-flto=thin']) + else: + env.Append(CCFLAGS=['-flto']) + env.Append(LINKFLAGS=['-flto']) ## Compile flags diff --git a/scene/2d/canvas_item.cpp b/scene/2d/canvas_item.cpp index b38fbfe981..d584492737 100644 --- a/scene/2d/canvas_item.cpp +++ b/scene/2d/canvas_item.cpp @@ -735,6 +735,19 @@ void CanvasItem::draw_polyline_colors(const Vector<Point2> &p_points, const Vect VisualServer::get_singleton()->canvas_item_add_polyline(canvas_item, p_points, p_colors, p_width, p_antialiased); } +void CanvasItem::draw_arc(const Vector2 &p_center, float p_radius, float p_start_angle, float p_end_angle, int p_point_count, const Color &p_color, float p_width, bool p_antialiased) { + + Vector<Point2> points; + points.resize(p_point_count); + const float delta_angle = p_end_angle - p_start_angle; + for (int i = 0; i < p_point_count; i++) { + float theta = (i / (p_point_count - 1.0f)) * delta_angle + p_start_angle; + points.set(i, p_center + Vector2(Math::cos(theta), Math::sin(theta)) * p_radius); + } + + draw_polyline(points, p_color, p_width, p_antialiased); +} + void CanvasItem::draw_multiline(const Vector<Point2> &p_points, const Color &p_color, float p_width, bool p_antialiased) { ERR_FAIL_COND_MSG(!drawing, "Drawing is only allowed inside NOTIFICATION_DRAW, _draw() function or 'draw' signal."); @@ -1152,6 +1165,7 @@ void CanvasItem::_bind_methods() { ClassDB::bind_method(D_METHOD("draw_line", "from", "to", "color", "width", "antialiased"), &CanvasItem::draw_line, DEFVAL(1.0), DEFVAL(false)); ClassDB::bind_method(D_METHOD("draw_polyline", "points", "color", "width", "antialiased"), &CanvasItem::draw_polyline, DEFVAL(1.0), DEFVAL(false)); ClassDB::bind_method(D_METHOD("draw_polyline_colors", "points", "colors", "width", "antialiased"), &CanvasItem::draw_polyline_colors, DEFVAL(1.0), DEFVAL(false)); + ClassDB::bind_method(D_METHOD("draw_arc", "center", "radius", "start_angle", "end_angle", "point_count", "color", "width", "antialiased"), &CanvasItem::draw_arc, DEFVAL(1.0), DEFVAL(false)); ClassDB::bind_method(D_METHOD("draw_multiline", "points", "color", "width", "antialiased"), &CanvasItem::draw_multiline, DEFVAL(1.0), DEFVAL(false)); ClassDB::bind_method(D_METHOD("draw_multiline_colors", "points", "colors", "width", "antialiased"), &CanvasItem::draw_multiline_colors, DEFVAL(1.0), DEFVAL(false)); ClassDB::bind_method(D_METHOD("draw_rect", "rect", "color", "filled", "width", "antialiased"), &CanvasItem::draw_rect, DEFVAL(true), DEFVAL(1.0), DEFVAL(false)); diff --git a/scene/2d/canvas_item.h b/scene/2d/canvas_item.h index 9c6799a441..581adf1396 100644 --- a/scene/2d/canvas_item.h +++ b/scene/2d/canvas_item.h @@ -305,6 +305,7 @@ public: void draw_line(const Point2 &p_from, const Point2 &p_to, const Color &p_color, float p_width = 1.0, bool p_antialiased = false); void draw_polyline(const Vector<Point2> &p_points, const Color &p_color, float p_width = 1.0, bool p_antialiased = false); void draw_polyline_colors(const Vector<Point2> &p_points, const Vector<Color> &p_colors, float p_width = 1.0, bool p_antialiased = false); + void draw_arc(const Vector2 &p_center, float p_radius, float p_start_angle, float p_end_angle, int p_point_count, const Color &p_color, float p_width = 1.0, bool p_antialiased = false); void draw_multiline(const Vector<Point2> &p_points, const Color &p_color, float p_width = 1.0, bool p_antialiased = false); void draw_multiline_colors(const Vector<Point2> &p_points, const Vector<Color> &p_colors, float p_width = 1.0, bool p_antialiased = false); void draw_rect(const Rect2 &p_rect, const Color &p_color, bool p_filled = true, float p_width = 1.0, bool p_antialiased = false); diff --git a/scene/2d/cpu_particles_2d.cpp b/scene/2d/cpu_particles_2d.cpp index 85c423964b..9da41914d7 100644 --- a/scene/2d/cpu_particles_2d.cpp +++ b/scene/2d/cpu_particles_2d.cpp @@ -37,6 +37,9 @@ void CPUParticles2D::set_emitting(bool p_emitting) { + if (emitting == p_emitting) + return; + emitting = p_emitting; if (emitting) set_process_internal(true); @@ -535,6 +538,74 @@ static float rand_from_seed(uint32_t &seed) { return float(seed % uint32_t(65536)) / 65535.0; } +void CPUParticles2D::_update_internal() { + + if (particles.size() == 0 || !is_visible_in_tree()) { + _set_redraw(false); + return; + } + + float delta = get_process_delta_time(); + if (emitting) { + inactive_time = 0; + } else { + inactive_time += delta; + if (inactive_time > lifetime * 1.2) { + set_process_internal(false); + _set_redraw(false); + + //reset variables + time = 0; + inactive_time = 0; + frame_remainder = 0; + cycle = 0; + return; + } + } + _set_redraw(true); + + if (time == 0 && pre_process_time > 0.0) { + + float frame_time; + if (fixed_fps > 0) + frame_time = 1.0 / fixed_fps; + else + frame_time = 1.0 / 30.0; + + float todo = pre_process_time; + + while (todo >= 0) { + _particles_process(frame_time); + todo -= frame_time; + } + } + + if (fixed_fps > 0) { + float frame_time = 1.0 / fixed_fps; + float decr = frame_time; + + float ldelta = delta; + if (ldelta > 0.1) { //avoid recursive stalls if fps goes below 10 + ldelta = 0.1; + } else if (ldelta <= 0.0) { //unlikely but.. + ldelta = 0.001; + } + float todo = frame_remainder + ldelta; + + while (todo >= frame_time) { + _particles_process(frame_time); + todo -= decr; + } + + frame_remainder = todo; + + } else { + _particles_process(delta); + } + + _update_particle_data_buffer(); +} + void CPUParticles2D::_particles_process(float p_delta) { p_delta *= speed_scale; @@ -1000,6 +1071,10 @@ void CPUParticles2D::_notification(int p_what) { } if (p_what == NOTIFICATION_DRAW) { + // first update before rendering to avoid one frame delay after emitting starts + if (emitting && (time == 0)) + _update_internal(); + if (!redraw) return; // don't add to render list @@ -1017,71 +1092,7 @@ void CPUParticles2D::_notification(int p_what) { } if (p_what == NOTIFICATION_INTERNAL_PROCESS) { - - if (particles.size() == 0 || !is_visible_in_tree()) { - _set_redraw(false); - return; - } - - float delta = get_process_delta_time(); - if (emitting) { - inactive_time = 0; - } else { - inactive_time += delta; - if (inactive_time > lifetime * 1.2) { - set_process_internal(false); - _set_redraw(false); - - //reset variables - time = 0; - inactive_time = 0; - frame_remainder = 0; - cycle = 0; - return; - } - } - _set_redraw(true); - - if (time == 0 && pre_process_time > 0.0) { - - float frame_time; - if (fixed_fps > 0) - frame_time = 1.0 / fixed_fps; - else - frame_time = 1.0 / 30.0; - - float todo = pre_process_time; - - while (todo >= 0) { - _particles_process(frame_time); - todo -= frame_time; - } - } - - if (fixed_fps > 0) { - float frame_time = 1.0 / fixed_fps; - float decr = frame_time; - - float ldelta = delta; - if (ldelta > 0.1) { //avoid recursive stalls if fps goes below 10 - ldelta = 0.1; - } else if (ldelta <= 0.0) { //unlikely but.. - ldelta = 0.001; - } - float todo = frame_remainder + ldelta; - - while (todo >= frame_time) { - _particles_process(frame_time); - todo -= decr; - } - - frame_remainder = todo; - - } else { - _particles_process(delta); - } - - _update_particle_data_buffer(); + _update_internal(); } if (p_what == NOTIFICATION_TRANSFORM_CHANGED) { diff --git a/scene/2d/cpu_particles_2d.h b/scene/2d/cpu_particles_2d.h index da668664b9..47b4568dd4 100644 --- a/scene/2d/cpu_particles_2d.h +++ b/scene/2d/cpu_particles_2d.h @@ -174,6 +174,7 @@ private: Vector2 gravity; + void _update_internal(); void _particles_process(float p_delta); void _update_particle_data_buffer(); diff --git a/scene/2d/joints_2d.cpp b/scene/2d/joints_2d.cpp index 12fb18cedc..847d08b025 100644 --- a/scene/2d/joints_2d.cpp +++ b/scene/2d/joints_2d.cpp @@ -37,8 +37,8 @@ void Joint2D::_update_joint(bool p_only_free) { if (joint.is_valid()) { - if (ba.is_valid() && bb.is_valid()) - Physics2DServer::get_singleton()->body_remove_collision_exception(ba, bb); + if (ba.is_valid() && bb.is_valid() && exclude_from_collision) + Physics2DServer::get_singleton()->joint_disable_collisions_between_bodies(joint, false); Physics2DServer::get_singleton()->free(joint); joint = RID(); @@ -131,6 +131,8 @@ void Joint2D::set_exclude_nodes_from_collision(bool p_enable) { if (exclude_from_collision == p_enable) return; + + _update_joint(true); exclude_from_collision = p_enable; _update_joint(); } diff --git a/scene/2d/sprite.cpp b/scene/2d/sprite.cpp index d2e1e494e3..8cdfceea52 100644 --- a/scene/2d/sprite.cpp +++ b/scene/2d/sprite.cpp @@ -387,6 +387,10 @@ void Sprite::_validate_property(PropertyInfo &property) const { property.hint_string = "0," + itos(vframes * hframes - 1) + ",1"; property.usage |= PROPERTY_USAGE_KEYING_INCREMENTS; } + + if (property.name == "frame_coords") { + property.usage |= PROPERTY_USAGE_KEYING_INCREMENTS; + } } void Sprite::_texture_changed() { diff --git a/scene/2d/touch_screen_button.cpp b/scene/2d/touch_screen_button.cpp index 9a1a759e72..cf68528388 100644 --- a/scene/2d/touch_screen_button.cpp +++ b/scene/2d/touch_screen_button.cpp @@ -325,8 +325,12 @@ void TouchScreenButton::_release(bool p_exiting_tree) { } Rect2 TouchScreenButton::_edit_get_rect() const { - if (texture.is_null()) - return CanvasItem::_edit_get_rect(); + if (texture.is_null()) { + if (shape.is_valid()) + return shape->get_rect(); + else + return CanvasItem::_edit_get_rect(); + } return Rect2(Size2(), texture->get_size()); } diff --git a/scene/3d/cpu_particles.cpp b/scene/3d/cpu_particles.cpp index 93ff60bc4e..5c895ecf22 100644 --- a/scene/3d/cpu_particles.cpp +++ b/scene/3d/cpu_particles.cpp @@ -46,9 +46,17 @@ PoolVector<Face3> CPUParticles::get_faces(uint32_t p_usage_flags) const { void CPUParticles::set_emitting(bool p_emitting) { + if (emitting == p_emitting) + return; + emitting = p_emitting; - if (emitting) + if (emitting) { set_process_internal(true); + + // first update before rendering to avoid one frame delay after emitting starts + if (time == 0) + _update_internal(); + } } void CPUParticles::set_amount(int p_amount) { @@ -508,6 +516,81 @@ static float rand_from_seed(uint32_t &seed) { return float(seed % uint32_t(65536)) / 65535.0; } +void CPUParticles::_update_internal() { + + if (particles.size() == 0 || !is_visible_in_tree()) { + _set_redraw(false); + return; + } + + float delta = get_process_delta_time(); + if (emitting) { + inactive_time = 0; + } else { + inactive_time += delta; + if (inactive_time > lifetime * 1.2) { + set_process_internal(false); + _set_redraw(false); + + //reset variables + time = 0; + inactive_time = 0; + frame_remainder = 0; + cycle = 0; + return; + } + } + _set_redraw(true); + + bool processed = false; + + if (time == 0 && pre_process_time > 0.0) { + + float frame_time; + if (fixed_fps > 0) + frame_time = 1.0 / fixed_fps; + else + frame_time = 1.0 / 30.0; + + float todo = pre_process_time; + + while (todo >= 0) { + _particles_process(frame_time); + processed = true; + todo -= frame_time; + } + } + + if (fixed_fps > 0) { + float frame_time = 1.0 / fixed_fps; + float decr = frame_time; + + float ldelta = delta; + if (ldelta > 0.1) { //avoid recursive stalls if fps goes below 10 + ldelta = 0.1; + } else if (ldelta <= 0.0) { //unlikely but.. + ldelta = 0.001; + } + float todo = frame_remainder + ldelta; + + while (todo >= frame_time) { + _particles_process(frame_time); + processed = true; + todo -= decr; + } + + frame_remainder = todo; + + } else { + _particles_process(delta); + processed = true; + } + + if (processed) { + _update_particle_data_buffer(); + } +} + void CPUParticles::_particles_process(float p_delta) { p_delta *= speed_scale; @@ -1068,85 +1151,24 @@ void CPUParticles::_notification(int p_what) { if (p_what == NOTIFICATION_ENTER_TREE) { set_process_internal(emitting); + + // first update before rendering to avoid one frame delay after emitting starts + if (emitting && (time == 0)) + _update_internal(); } if (p_what == NOTIFICATION_EXIT_TREE) { _set_redraw(false); } - if (p_what == NOTIFICATION_INTERNAL_PROCESS) { - - if (particles.size() == 0 || !is_visible_in_tree()) { - _set_redraw(false); - return; - } - - float delta = get_process_delta_time(); - if (emitting) { - inactive_time = 0; - } else { - inactive_time += delta; - if (inactive_time > lifetime * 1.2) { - set_process_internal(false); - _set_redraw(false); - - //reset variables - time = 0; - inactive_time = 0; - frame_remainder = 0; - cycle = 0; - return; - } - } - _set_redraw(true); - - bool processed = false; - - if (time == 0 && pre_process_time > 0.0) { - - float frame_time; - if (fixed_fps > 0) - frame_time = 1.0 / fixed_fps; - else - frame_time = 1.0 / 30.0; - - float todo = pre_process_time; - - while (todo >= 0) { - _particles_process(frame_time); - processed = true; - todo -= frame_time; - } - } - - if (fixed_fps > 0) { - float frame_time = 1.0 / fixed_fps; - float decr = frame_time; - - float ldelta = delta; - if (ldelta > 0.1) { //avoid recursive stalls if fps goes below 10 - ldelta = 0.1; - } else if (ldelta <= 0.0) { //unlikely but.. - ldelta = 0.001; - } - float todo = frame_remainder + ldelta; - - while (todo >= frame_time) { - _particles_process(frame_time); - processed = true; - todo -= decr; - } - - frame_remainder = todo; - - } else { - _particles_process(delta); - processed = true; - } + if (p_what == NOTIFICATION_VISIBILITY_CHANGED) { + // first update before rendering to avoid one frame delay after emitting starts + if (emitting && (time == 0)) + _update_internal(); + } - if (processed) { - _update_particle_data_buffer(); - } + if (p_what == NOTIFICATION_INTERNAL_PROCESS) { + _update_internal(); } if (p_what == NOTIFICATION_TRANSFORM_CHANGED) { diff --git a/scene/3d/cpu_particles.h b/scene/3d/cpu_particles.h index 66b37f359a..635265be7f 100644 --- a/scene/3d/cpu_particles.h +++ b/scene/3d/cpu_particles.h @@ -173,6 +173,7 @@ private: Vector3 gravity; + void _update_internal(); void _particles_process(float p_delta); void _update_particle_data_buffer(); diff --git a/scene/3d/sprite_3d.cpp b/scene/3d/sprite_3d.cpp index a8d2f4d415..adcd80b0ab 100644 --- a/scene/3d/sprite_3d.cpp +++ b/scene/3d/sprite_3d.cpp @@ -662,6 +662,10 @@ void Sprite3D::_validate_property(PropertyInfo &property) const { property.hint_string = "0," + itos(vframes * hframes - 1) + ",1"; property.usage |= PROPERTY_USAGE_KEYING_INCREMENTS; } + + if (property.name == "frame_coords") { + property.usage |= PROPERTY_USAGE_KEYING_INCREMENTS; + } } void Sprite3D::_bind_methods() { diff --git a/scene/gui/control.cpp b/scene/gui/control.cpp index fafbcf0c55..8b4d5d4980 100644 --- a/scene/gui/control.cpp +++ b/scene/gui/control.cpp @@ -2221,9 +2221,11 @@ void Control::_modal_stack_remove() { if (!data.MI) return; - get_viewport()->_gui_remove_from_modal_stack(data.MI, data.modal_prev_focus_owner); - + List<Control *>::Element *element = data.MI; data.MI = NULL; + + get_viewport()->_gui_remove_from_modal_stack(element, data.modal_prev_focus_owner); + data.modal_prev_focus_owner = 0; } diff --git a/scene/gui/label.cpp b/scene/gui/label.cpp index 510f1b18ad..4edd4b8530 100644 --- a/scene/gui/label.cpp +++ b/scene/gui/label.cpp @@ -452,6 +452,11 @@ void Label::regenerate_word_cache() { current_word_size += char_width; line_width += char_width; total_char_cache++; + + // allow autowrap to cut words when they exceed line width + if (autowrap && (current_word_size > width)) { + separatable = true; + } } if ((autowrap && (line_width >= width) && ((last && last->char_pos >= 0) || separatable)) || insert_newline) { diff --git a/scene/gui/rich_text_label.cpp b/scene/gui/rich_text_label.cpp index 42cb89b2d6..8c19255fd0 100644 --- a/scene/gui/rich_text_label.cpp +++ b/scene/gui/rich_text_label.cpp @@ -555,12 +555,12 @@ int RichTextLabel::_process_line(ItemFrame *p_frame, const Vector2 &p_ofs, int & if (p_font_color_shadow.a > 0) { float x_ofs_shadow = align_ofs + pofs; float y_ofs_shadow = y + lh - line_descent; - font->draw_char(ci, Point2(x_ofs_shadow, y_ofs_shadow) + shadow_ofs, fx_char, c[i + 1], p_font_color_shadow); + font->draw_char(ci, Point2(x_ofs_shadow, y_ofs_shadow) + shadow_ofs + fx_offset, fx_char, c[i + 1], p_font_color_shadow); if (p_shadow_as_outline) { - font->draw_char(ci, Point2(x_ofs_shadow, y_ofs_shadow) + Vector2(-shadow_ofs.x, shadow_ofs.y), fx_char, c[i + 1], p_font_color_shadow); - font->draw_char(ci, Point2(x_ofs_shadow, y_ofs_shadow) + Vector2(shadow_ofs.x, -shadow_ofs.y), fx_char, c[i + 1], p_font_color_shadow); - font->draw_char(ci, Point2(x_ofs_shadow, y_ofs_shadow) + Vector2(-shadow_ofs.x, -shadow_ofs.y), fx_char, c[i + 1], p_font_color_shadow); + font->draw_char(ci, Point2(x_ofs_shadow, y_ofs_shadow) + Vector2(-shadow_ofs.x, shadow_ofs.y) + fx_offset, fx_char, c[i + 1], p_font_color_shadow); + font->draw_char(ci, Point2(x_ofs_shadow, y_ofs_shadow) + Vector2(shadow_ofs.x, -shadow_ofs.y) + fx_offset, fx_char, c[i + 1], p_font_color_shadow); + font->draw_char(ci, Point2(x_ofs_shadow, y_ofs_shadow) + Vector2(-shadow_ofs.x, -shadow_ofs.y) + fx_offset, fx_char, c[i + 1], p_font_color_shadow); } } @@ -624,19 +624,19 @@ int RichTextLabel::_process_line(ItemFrame *p_frame, const Vector2 &p_ofs, int & if (p_mode == PROCESS_POINTER && r_click_char) *r_click_char = 0; - ENSURE_WIDTH(img->image->get_width()); + ENSURE_WIDTH(img->size.width); - bool visible = visible_characters < 0 || (p_char_count < visible_characters && YRANGE_VISIBLE(y + lh - font->get_descent() - img->image->get_height(), img->image->get_height())); + bool visible = visible_characters < 0 || (p_char_count < visible_characters && YRANGE_VISIBLE(y + lh - font->get_descent() - img->size.height, img->size.height)); if (visible) line_is_blank = false; if (p_mode == PROCESS_DRAW && visible) { - img->image->draw(ci, p_ofs + Point2(align_ofs + wofs, y + lh - font->get_descent() - img->image->get_height())); + img->image->draw_rect(ci, Rect2(p_ofs + Point2(align_ofs + wofs, y + lh - font->get_descent() - img->size.height), img->size)); } p_char_count++; - ADVANCE(img->image->get_width()); - CHECK_HEIGHT((img->image->get_height() + font->get_descent())); + ADVANCE(img->size.width); + CHECK_HEIGHT((img->size.height + font->get_descent())); } break; case ITEM_NEWLINE: { @@ -859,7 +859,7 @@ int RichTextLabel::_process_line(ItemFrame *p_frame, const Vector2 &p_ofs, int & void RichTextLabel::_scroll_changed(double) { - if (updating_scroll) + if (updating_scroll || !scroll_active) return; if (scroll_follow && vscroll->get_value() >= (vscroll->get_max() - vscroll->get_page())) @@ -1634,7 +1634,7 @@ void RichTextLabel::_remove_item(Item *p_item, const int p_line, const int p_sub } } -void RichTextLabel::add_image(const Ref<Texture> &p_image) { +void RichTextLabel::add_image(const Ref<Texture> &p_image, const int p_width, const int p_height) { if (current->type == ITEM_TABLE) return; @@ -1643,6 +1643,30 @@ void RichTextLabel::add_image(const Ref<Texture> &p_image) { ItemImage *item = memnew(ItemImage); item->image = p_image; + + if (p_width > 0) { + // custom width + item->size.width = p_width; + if (p_height > 0) { + // custom height + item->size.height = p_height; + } else { + // calculate height to keep aspect ratio + item->size.height = p_image->get_height() * p_width / p_image->get_width(); + } + } else { + if (p_height > 0) { + // custom height + item->size.height = p_height; + // calculate width to keep aspect ratio + item->size.width = p_image->get_width() * p_height / p_image->get_height(); + } else { + // keep original width and height + item->size.height = p_image->get_height(); + item->size.width = p_image->get_width(); + } + } + _add_item(item, false); } @@ -2125,6 +2149,7 @@ Error RichTextLabel::append_bbcode(const String &p_bbcode) { int end = p_bbcode.find("[", brk_end); if (end == -1) end = p_bbcode.length(); + String image = p_bbcode.substr(brk_end + 1, end - brk_end - 1); Ref<Texture> texture = ResourceLoader::load(image, "Texture"); @@ -2133,6 +2158,32 @@ Error RichTextLabel::append_bbcode(const String &p_bbcode) { pos = end; tag_stack.push_front(tag); + } else if (tag.begins_with("img=")) { + + int width = 0; + int height = 0; + + String params = tag.substr(4, tag.length()); + int sep = params.find("x"); + if (sep == -1) { + width = params.to_int(); + } else { + width = params.substr(0, sep).to_int(); + height = params.substr(sep + 1, params.length()).to_int(); + } + + int end = p_bbcode.find("[", brk_end); + if (end == -1) + end = p_bbcode.length(); + + String image = p_bbcode.substr(brk_end + 1, end - brk_end - 1); + + Ref<Texture> texture = ResourceLoader::load(image, "Texture"); + if (texture.is_valid()) + add_image(texture, width, height); + + pos = end; + tag_stack.push_front("img"); } else if (tag.begins_with("color=")) { String col = tag.substr(6, tag.length()); @@ -2581,7 +2632,7 @@ void RichTextLabel::_bind_methods() { ClassDB::bind_method(D_METHOD("get_text"), &RichTextLabel::get_text); ClassDB::bind_method(D_METHOD("add_text", "text"), &RichTextLabel::add_text); ClassDB::bind_method(D_METHOD("set_text", "text"), &RichTextLabel::set_text); - ClassDB::bind_method(D_METHOD("add_image", "image"), &RichTextLabel::add_image); + ClassDB::bind_method(D_METHOD("add_image", "image", "width", "height"), &RichTextLabel::add_image, DEFVAL(0), DEFVAL(0)); ClassDB::bind_method(D_METHOD("newline"), &RichTextLabel::add_newline); ClassDB::bind_method(D_METHOD("remove_line", "line"), &RichTextLabel::remove_line); ClassDB::bind_method(D_METHOD("push_font", "font"), &RichTextLabel::push_font); diff --git a/scene/gui/rich_text_label.h b/scene/gui/rich_text_label.h index 1c90d974e4..6cd69b9187 100644 --- a/scene/gui/rich_text_label.h +++ b/scene/gui/rich_text_label.h @@ -148,6 +148,7 @@ private: struct ItemImage : public Item { Ref<Texture> image; + Size2 size; ItemImage() { type = ITEM_IMAGE; } }; @@ -406,7 +407,7 @@ protected: public: String get_text(); void add_text(const String &p_text); - void add_image(const Ref<Texture> &p_image); + void add_image(const Ref<Texture> &p_image, const int p_width = 0, const int p_height = 0); void add_newline(); bool remove_line(const int p_line); void push_font(const Ref<Font> &p_font); diff --git a/scene/gui/text_edit.cpp b/scene/gui/text_edit.cpp index 69d076c41b..5e548b7715 100644 --- a/scene/gui/text_edit.cpp +++ b/scene/gui/text_edit.cpp @@ -2843,19 +2843,30 @@ void TextEdit::_gui_input(const Ref<InputEvent> &p_gui_input) { // No need to indent if we are going upwards. if (auto_indent && !(k->get_command() && k->get_shift())) { - // Indent once again if previous line will end with ':' or '{' and the line is not a comment + // Indent once again if previous line will end with ':','{','[','(' and the line is not a comment // (i.e. colon/brace precedes current cursor position). - if (cursor.column > 0 && (text[cursor.line][cursor.column - 1] == ':' || text[cursor.line][cursor.column - 1] == '{') && !is_line_comment(cursor.line)) { - if (indent_using_spaces) { - ins += space_indent; - } else { - ins += "\t"; - } + if (cursor.column > 0) { + char prev_char = text[cursor.line][cursor.column - 1]; + switch (prev_char) { + case ':': + case '{': + case '[': + case '(': { + if (!is_line_comment(cursor.line)) { + if (indent_using_spaces) { + ins += space_indent; + } else { + ins += "\t"; + } - // No need to move the brace below if we are not taking the text with us. - if (text[cursor.line][cursor.column] == '}' && !k->get_command()) { - brace_indent = true; - ins += "\n" + ins.substr(1, ins.length() - 2); + // No need to move the brace below if we are not taking the text with us. + char closing_char = _get_right_pair_symbol(prev_char); + if ((closing_char != 0) && (closing_char == text[cursor.line][cursor.column]) && !k->get_command()) { + brace_indent = true; + ins += "\n" + ins.substr(1, ins.length() - 2); + } + } + } break; } } } @@ -4751,6 +4762,9 @@ void TextEdit::set_text(String p_text) { selection.active = false; } + cursor_set_line(0); + cursor_set_column(0); + update(); setting_text = false; }; @@ -5052,15 +5066,18 @@ Map<int, TextEdit::Text::ColorRegionInfo> TextEdit::_get_line_color_region_info( void TextEdit::clear_colors() { keywords.clear(); + member_keywords.clear(); color_regions.clear(); color_region_cache.clear(); syntax_highlighting_cache.clear(); text.clear_width_cache(); + update(); } void TextEdit::add_keyword_color(const String &p_keyword, const Color &p_color) { keywords[p_keyword] = p_color; + syntax_highlighting_cache.clear(); update(); } @@ -5077,12 +5094,14 @@ Color TextEdit::get_keyword_color(String p_keyword) const { void TextEdit::add_color_region(const String &p_begin_key, const String &p_end_key, const Color &p_color, bool p_line_only) { color_regions.push_back(ColorRegion(p_begin_key, p_end_key, p_color, p_line_only)); + syntax_highlighting_cache.clear(); text.clear_width_cache(); update(); } void TextEdit::add_member_keyword(const String &p_keyword, const Color &p_color) { member_keywords[p_keyword] = p_color; + syntax_highlighting_cache.clear(); update(); } @@ -5096,6 +5115,7 @@ Color TextEdit::get_member_color(String p_member) const { void TextEdit::clear_member_keywords() { member_keywords.clear(); + syntax_highlighting_cache.clear(); update(); } @@ -6020,6 +6040,7 @@ void TextEdit::undo() { } } + _update_scrollbars(); if (undo_stack_pos->get().type == TextOperation::TYPE_REMOVE) { cursor_set_line(undo_stack_pos->get().to_line); cursor_set_column(undo_stack_pos->get().to_column); @@ -6055,6 +6076,8 @@ void TextEdit::redo() { break; } } + + _update_scrollbars(); cursor_set_line(undo_stack_pos->get().to_line); cursor_set_column(undo_stack_pos->get().to_column); undo_stack_pos = undo_stack_pos->next(); diff --git a/scene/main/node.cpp b/scene/main/node.cpp index 7b6c90766f..217dacfbfe 100644 --- a/scene/main/node.cpp +++ b/scene/main/node.cpp @@ -2832,6 +2832,8 @@ void Node::_bind_methods() { ClassDB::bind_method(D_METHOD("rset_unreliable", "property", "value"), &Node::rset_unreliable); ClassDB::bind_method(D_METHOD("rset_unreliable_id", "peer_id", "property", "value"), &Node::rset_unreliable_id); + ClassDB::bind_method(D_METHOD("update_configuration_warning"), &Node::update_configuration_warning); + BIND_CONSTANT(NOTIFICATION_ENTER_TREE); BIND_CONSTANT(NOTIFICATION_EXIT_TREE); BIND_CONSTANT(NOTIFICATION_MOVED_IN_PARENT); diff --git a/scene/main/scene_tree.cpp b/scene/main/scene_tree.cpp index 830d314245..38ad6886b1 100644 --- a/scene/main/scene_tree.cpp +++ b/scene/main/scene_tree.cpp @@ -78,6 +78,17 @@ bool SceneTreeTimer::is_pause_mode_process() { return process_pause; } +void SceneTreeTimer::release_connections() { + + List<Connection> connections; + get_all_signal_connections(&connections); + + for (List<Connection>::Element *E = connections.front(); E; E = E->next()) { + Connection const &connection = E->get(); + disconnect(connection.signal, connection.target, connection.method); + } +} + SceneTreeTimer::SceneTreeTimer() { time_left = 0; process_pause = true; @@ -611,6 +622,12 @@ void SceneTree::finish() { memdelete(root); //delete root root = NULL; } + + // cleanup timers + for (List<Ref<SceneTreeTimer> >::Element *E = timers.front(); E; E = E->next()) { + E->get()->release_connections(); + } + timers.clear(); } void SceneTree::quit() { diff --git a/scene/main/scene_tree.h b/scene/main/scene_tree.h index d387886d61..ef847ebb5b 100644 --- a/scene/main/scene_tree.h +++ b/scene/main/scene_tree.h @@ -61,6 +61,8 @@ public: void set_pause_mode_process(bool p_pause_mode_process); bool is_pause_mode_process(); + void release_connections(); + SceneTreeTimer(); }; diff --git a/scene/main/viewport.cpp b/scene/main/viewport.cpp index 52ef225364..95536bbb23 100644 --- a/scene/main/viewport.cpp +++ b/scene/main/viewport.cpp @@ -2374,7 +2374,6 @@ void Viewport::_gui_remove_from_modal_stack(List<Control *>::Element *MI, Object List<Control *>::Element *next = MI->next(); gui.modal_stack.erase(MI); - MI = NULL; if (p_prev_focus_owner) { diff --git a/scene/resources/animation.cpp b/scene/resources/animation.cpp index 985b38f913..d932545da4 100644 --- a/scene/resources/animation.cpp +++ b/scene/resources/animation.cpp @@ -2741,77 +2741,77 @@ void Animation::copy_track(int p_track, Ref<Animation> p_to_animation) { void Animation::_bind_methods() { ClassDB::bind_method(D_METHOD("add_track", "type", "at_position"), &Animation::add_track, DEFVAL(-1)); - ClassDB::bind_method(D_METHOD("remove_track", "idx"), &Animation::remove_track); + ClassDB::bind_method(D_METHOD("remove_track", "track_idx"), &Animation::remove_track); ClassDB::bind_method(D_METHOD("get_track_count"), &Animation::get_track_count); - ClassDB::bind_method(D_METHOD("track_get_type", "idx"), &Animation::track_get_type); - ClassDB::bind_method(D_METHOD("track_get_path", "idx"), &Animation::track_get_path); - ClassDB::bind_method(D_METHOD("track_set_path", "idx", "path"), &Animation::track_set_path); + ClassDB::bind_method(D_METHOD("track_get_type", "track_idx"), &Animation::track_get_type); + ClassDB::bind_method(D_METHOD("track_get_path", "track_idx"), &Animation::track_get_path); + ClassDB::bind_method(D_METHOD("track_set_path", "track_idx", "path"), &Animation::track_set_path); ClassDB::bind_method(D_METHOD("find_track", "path"), &Animation::find_track); - ClassDB::bind_method(D_METHOD("track_move_up", "idx"), &Animation::track_move_up); - ClassDB::bind_method(D_METHOD("track_move_down", "idx"), &Animation::track_move_down); - ClassDB::bind_method(D_METHOD("track_move_to", "idx", "to_idx"), &Animation::track_move_to); - ClassDB::bind_method(D_METHOD("track_swap", "idx", "with_idx"), &Animation::track_swap); + ClassDB::bind_method(D_METHOD("track_move_up", "track_idx"), &Animation::track_move_up); + ClassDB::bind_method(D_METHOD("track_move_down", "track_idx"), &Animation::track_move_down); + ClassDB::bind_method(D_METHOD("track_move_to", "track_idx", "to_idx"), &Animation::track_move_to); + ClassDB::bind_method(D_METHOD("track_swap", "track_idx", "with_idx"), &Animation::track_swap); - ClassDB::bind_method(D_METHOD("track_set_imported", "idx", "imported"), &Animation::track_set_imported); - ClassDB::bind_method(D_METHOD("track_is_imported", "idx"), &Animation::track_is_imported); + ClassDB::bind_method(D_METHOD("track_set_imported", "track_idx", "imported"), &Animation::track_set_imported); + ClassDB::bind_method(D_METHOD("track_is_imported", "track_idx"), &Animation::track_is_imported); - ClassDB::bind_method(D_METHOD("track_set_enabled", "idx", "enabled"), &Animation::track_set_enabled); - ClassDB::bind_method(D_METHOD("track_is_enabled", "idx"), &Animation::track_is_enabled); + ClassDB::bind_method(D_METHOD("track_set_enabled", "track_idx", "enabled"), &Animation::track_set_enabled); + ClassDB::bind_method(D_METHOD("track_is_enabled", "track_idx"), &Animation::track_is_enabled); - ClassDB::bind_method(D_METHOD("transform_track_insert_key", "idx", "time", "location", "rotation", "scale"), &Animation::transform_track_insert_key); - ClassDB::bind_method(D_METHOD("track_insert_key", "idx", "time", "key", "transition"), &Animation::track_insert_key, DEFVAL(1)); - ClassDB::bind_method(D_METHOD("track_remove_key", "idx", "key_idx"), &Animation::track_remove_key); - ClassDB::bind_method(D_METHOD("track_remove_key_at_position", "idx", "position"), &Animation::track_remove_key_at_position); - ClassDB::bind_method(D_METHOD("track_set_key_value", "idx", "key", "value"), &Animation::track_set_key_value); - ClassDB::bind_method(D_METHOD("track_set_key_transition", "idx", "key_idx", "transition"), &Animation::track_set_key_transition); - ClassDB::bind_method(D_METHOD("track_set_key_time", "idx", "key_idx", "time"), &Animation::track_set_key_time); - ClassDB::bind_method(D_METHOD("track_get_key_transition", "idx", "key_idx"), &Animation::track_get_key_transition); + ClassDB::bind_method(D_METHOD("transform_track_insert_key", "track_idx", "time", "location", "rotation", "scale"), &Animation::transform_track_insert_key); + ClassDB::bind_method(D_METHOD("track_insert_key", "track_idx", "time", "key", "transition"), &Animation::track_insert_key, DEFVAL(1)); + ClassDB::bind_method(D_METHOD("track_remove_key", "track_idx", "key_idx"), &Animation::track_remove_key); + ClassDB::bind_method(D_METHOD("track_remove_key_at_position", "track_idx", "position"), &Animation::track_remove_key_at_position); + ClassDB::bind_method(D_METHOD("track_set_key_value", "track_idx", "key", "value"), &Animation::track_set_key_value); + ClassDB::bind_method(D_METHOD("track_set_key_transition", "track_idx", "key_idx", "transition"), &Animation::track_set_key_transition); + ClassDB::bind_method(D_METHOD("track_set_key_time", "track_idx", "key_idx", "time"), &Animation::track_set_key_time); + ClassDB::bind_method(D_METHOD("track_get_key_transition", "track_idx", "key_idx"), &Animation::track_get_key_transition); - ClassDB::bind_method(D_METHOD("track_get_key_count", "idx"), &Animation::track_get_key_count); - ClassDB::bind_method(D_METHOD("track_get_key_value", "idx", "key_idx"), &Animation::track_get_key_value); - ClassDB::bind_method(D_METHOD("track_get_key_time", "idx", "key_idx"), &Animation::track_get_key_time); - ClassDB::bind_method(D_METHOD("track_find_key", "idx", "time", "exact"), &Animation::track_find_key, DEFVAL(false)); + ClassDB::bind_method(D_METHOD("track_get_key_count", "track_idx"), &Animation::track_get_key_count); + ClassDB::bind_method(D_METHOD("track_get_key_value", "track_idx", "key_idx"), &Animation::track_get_key_value); + ClassDB::bind_method(D_METHOD("track_get_key_time", "track_idx", "key_idx"), &Animation::track_get_key_time); + ClassDB::bind_method(D_METHOD("track_find_key", "track_idx", "time", "exact"), &Animation::track_find_key, DEFVAL(false)); - ClassDB::bind_method(D_METHOD("track_set_interpolation_type", "idx", "interpolation"), &Animation::track_set_interpolation_type); - ClassDB::bind_method(D_METHOD("track_get_interpolation_type", "idx"), &Animation::track_get_interpolation_type); + ClassDB::bind_method(D_METHOD("track_set_interpolation_type", "track_idx", "interpolation"), &Animation::track_set_interpolation_type); + ClassDB::bind_method(D_METHOD("track_get_interpolation_type", "track_idx"), &Animation::track_get_interpolation_type); - ClassDB::bind_method(D_METHOD("track_set_interpolation_loop_wrap", "idx", "interpolation"), &Animation::track_set_interpolation_loop_wrap); - ClassDB::bind_method(D_METHOD("track_get_interpolation_loop_wrap", "idx"), &Animation::track_get_interpolation_loop_wrap); + ClassDB::bind_method(D_METHOD("track_set_interpolation_loop_wrap", "track_idx", "interpolation"), &Animation::track_set_interpolation_loop_wrap); + ClassDB::bind_method(D_METHOD("track_get_interpolation_loop_wrap", "track_idx"), &Animation::track_get_interpolation_loop_wrap); - ClassDB::bind_method(D_METHOD("transform_track_interpolate", "idx", "time_sec"), &Animation::_transform_track_interpolate); - ClassDB::bind_method(D_METHOD("value_track_set_update_mode", "idx", "mode"), &Animation::value_track_set_update_mode); - ClassDB::bind_method(D_METHOD("value_track_get_update_mode", "idx"), &Animation::value_track_get_update_mode); + ClassDB::bind_method(D_METHOD("transform_track_interpolate", "track_idx", "time_sec"), &Animation::_transform_track_interpolate); + ClassDB::bind_method(D_METHOD("value_track_set_update_mode", "track_idx", "mode"), &Animation::value_track_set_update_mode); + ClassDB::bind_method(D_METHOD("value_track_get_update_mode", "track_idx"), &Animation::value_track_get_update_mode); - ClassDB::bind_method(D_METHOD("value_track_get_key_indices", "idx", "time_sec", "delta"), &Animation::_value_track_get_key_indices); + ClassDB::bind_method(D_METHOD("value_track_get_key_indices", "track_idx", "time_sec", "delta"), &Animation::_value_track_get_key_indices); - ClassDB::bind_method(D_METHOD("method_track_get_key_indices", "idx", "time_sec", "delta"), &Animation::_method_track_get_key_indices); - ClassDB::bind_method(D_METHOD("method_track_get_name", "idx", "key_idx"), &Animation::method_track_get_name); - ClassDB::bind_method(D_METHOD("method_track_get_params", "idx", "key_idx"), &Animation::method_track_get_params); + ClassDB::bind_method(D_METHOD("method_track_get_key_indices", "track_idx", "time_sec", "delta"), &Animation::_method_track_get_key_indices); + ClassDB::bind_method(D_METHOD("method_track_get_name", "track_idx", "key_idx"), &Animation::method_track_get_name); + ClassDB::bind_method(D_METHOD("method_track_get_params", "track_idx", "key_idx"), &Animation::method_track_get_params); - ClassDB::bind_method(D_METHOD("bezier_track_insert_key", "track", "time", "value", "in_handle", "out_handle"), &Animation::bezier_track_insert_key, DEFVAL(Vector2()), DEFVAL(Vector2())); + ClassDB::bind_method(D_METHOD("bezier_track_insert_key", "track_idx", "time", "value", "in_handle", "out_handle"), &Animation::bezier_track_insert_key, DEFVAL(Vector2()), DEFVAL(Vector2())); - ClassDB::bind_method(D_METHOD("bezier_track_set_key_value", "idx", "key_idx", "value"), &Animation::bezier_track_set_key_value); - ClassDB::bind_method(D_METHOD("bezier_track_set_key_in_handle", "idx", "key_idx", "in_handle"), &Animation::bezier_track_set_key_in_handle); - ClassDB::bind_method(D_METHOD("bezier_track_set_key_out_handle", "idx", "key_idx", "out_handle"), &Animation::bezier_track_set_key_out_handle); + ClassDB::bind_method(D_METHOD("bezier_track_set_key_value", "track_idx", "key_idx", "value"), &Animation::bezier_track_set_key_value); + ClassDB::bind_method(D_METHOD("bezier_track_set_key_in_handle", "track_idx", "key_idx", "in_handle"), &Animation::bezier_track_set_key_in_handle); + ClassDB::bind_method(D_METHOD("bezier_track_set_key_out_handle", "track_idx", "key_idx", "out_handle"), &Animation::bezier_track_set_key_out_handle); - ClassDB::bind_method(D_METHOD("bezier_track_get_key_value", "idx", "key_idx"), &Animation::bezier_track_get_key_value); - ClassDB::bind_method(D_METHOD("bezier_track_get_key_in_handle", "idx", "key_idx"), &Animation::bezier_track_get_key_in_handle); - ClassDB::bind_method(D_METHOD("bezier_track_get_key_out_handle", "idx", "key_idx"), &Animation::bezier_track_get_key_out_handle); + ClassDB::bind_method(D_METHOD("bezier_track_get_key_value", "track_idx", "key_idx"), &Animation::bezier_track_get_key_value); + ClassDB::bind_method(D_METHOD("bezier_track_get_key_in_handle", "track_idx", "key_idx"), &Animation::bezier_track_get_key_in_handle); + ClassDB::bind_method(D_METHOD("bezier_track_get_key_out_handle", "track_idx", "key_idx"), &Animation::bezier_track_get_key_out_handle); - ClassDB::bind_method(D_METHOD("bezier_track_interpolate", "track", "time"), &Animation::bezier_track_interpolate); + ClassDB::bind_method(D_METHOD("bezier_track_interpolate", "track_idx", "time"), &Animation::bezier_track_interpolate); - ClassDB::bind_method(D_METHOD("audio_track_insert_key", "track", "time", "stream", "start_offset", "end_offset"), &Animation::audio_track_insert_key, DEFVAL(0), DEFVAL(0)); - ClassDB::bind_method(D_METHOD("audio_track_set_key_stream", "idx", "key_idx", "stream"), &Animation::audio_track_set_key_stream); - ClassDB::bind_method(D_METHOD("audio_track_set_key_start_offset", "idx", "key_idx", "offset"), &Animation::audio_track_set_key_start_offset); - ClassDB::bind_method(D_METHOD("audio_track_set_key_end_offset", "idx", "key_idx", "offset"), &Animation::audio_track_set_key_end_offset); - ClassDB::bind_method(D_METHOD("audio_track_get_key_stream", "idx", "key_idx"), &Animation::audio_track_get_key_stream); - ClassDB::bind_method(D_METHOD("audio_track_get_key_start_offset", "idx", "key_idx"), &Animation::audio_track_get_key_start_offset); - ClassDB::bind_method(D_METHOD("audio_track_get_key_end_offset", "idx", "key_idx"), &Animation::audio_track_get_key_end_offset); + ClassDB::bind_method(D_METHOD("audio_track_insert_key", "track_idx", "time", "stream", "start_offset", "end_offset"), &Animation::audio_track_insert_key, DEFVAL(0), DEFVAL(0)); + ClassDB::bind_method(D_METHOD("audio_track_set_key_stream", "track_idx", "key_idx", "stream"), &Animation::audio_track_set_key_stream); + ClassDB::bind_method(D_METHOD("audio_track_set_key_start_offset", "track_idx", "key_idx", "offset"), &Animation::audio_track_set_key_start_offset); + ClassDB::bind_method(D_METHOD("audio_track_set_key_end_offset", "track_idx", "key_idx", "offset"), &Animation::audio_track_set_key_end_offset); + ClassDB::bind_method(D_METHOD("audio_track_get_key_stream", "track_idx", "key_idx"), &Animation::audio_track_get_key_stream); + ClassDB::bind_method(D_METHOD("audio_track_get_key_start_offset", "track_idx", "key_idx"), &Animation::audio_track_get_key_start_offset); + ClassDB::bind_method(D_METHOD("audio_track_get_key_end_offset", "track_idx", "key_idx"), &Animation::audio_track_get_key_end_offset); - ClassDB::bind_method(D_METHOD("animation_track_insert_key", "track", "time", "animation"), &Animation::animation_track_insert_key); - ClassDB::bind_method(D_METHOD("animation_track_set_key_animation", "idx", "key_idx", "animation"), &Animation::animation_track_set_key_animation); - ClassDB::bind_method(D_METHOD("animation_track_get_key_animation", "idx", "key_idx"), &Animation::animation_track_get_key_animation); + ClassDB::bind_method(D_METHOD("animation_track_insert_key", "track_idx", "time", "animation"), &Animation::animation_track_insert_key); + ClassDB::bind_method(D_METHOD("animation_track_set_key_animation", "track_idx", "key_idx", "animation"), &Animation::animation_track_set_key_animation); + ClassDB::bind_method(D_METHOD("animation_track_get_key_animation", "track_idx", "key_idx"), &Animation::animation_track_get_key_animation); ClassDB::bind_method(D_METHOD("set_length", "time_sec"), &Animation::set_length); ClassDB::bind_method(D_METHOD("get_length"), &Animation::get_length); @@ -2823,7 +2823,7 @@ void Animation::_bind_methods() { ClassDB::bind_method(D_METHOD("get_step"), &Animation::get_step); ClassDB::bind_method(D_METHOD("clear"), &Animation::clear); - ClassDB::bind_method(D_METHOD("copy_track", "track", "to_animation"), &Animation::copy_track); + ClassDB::bind_method(D_METHOD("copy_track", "track_idx", "to_animation"), &Animation::copy_track); ADD_PROPERTY(PropertyInfo(Variant::REAL, "length", PROPERTY_HINT_RANGE, "0.001,99999,0.001"), "set_length", "get_length"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "loop"), "set_loop", "has_loop"); |