summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--core/io/marshalls.cpp10
-rw-r--r--core/undo_redo.cpp23
-rw-r--r--core/undo_redo.h3
-rw-r--r--doc/classes/EncodedObjectAsID.xml22
-rw-r--r--doc/classes/LineEdit.xml2
-rw-r--r--doc/classes/Node.xml9
-rw-r--r--doc/classes/NodePath.xml55
-rw-r--r--doc/classes/Object.xml1
-rw-r--r--doc/classes/TextEdit.xml2
-rw-r--r--doc/classes/UndoRedo.xml21
-rw-r--r--editor/editor_help_search.cpp6
-rw-r--r--editor/editor_node.cpp92
-rw-r--r--editor/editor_node.h14
-rw-r--r--scene/main/node.cpp15
14 files changed, 187 insertions, 88 deletions
diff --git a/core/io/marshalls.cpp b/core/io/marshalls.cpp
index 7494603462..3c9c5bc2bb 100644
--- a/core/io/marshalls.cpp
+++ b/core/io/marshalls.cpp
@@ -37,13 +37,11 @@
#include <limits.h>
#include <stdio.h>
-#define _S(a) ((int32_t)a)
-#define ERR_FAIL_ADD_OF(a, b, err) ERR_FAIL_COND_V(_S(b) < 0 || _S(a) < 0 || _S(a) > INT_MAX - _S(b), err)
-#define ERR_FAIL_MUL_OF(a, b, err) ERR_FAIL_COND_V(_S(a) < 0 || _S(b) <= 0 || _S(a) > INT_MAX / _S(b), err)
-
void EncodedObjectAsID::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_object_id", "id"), &EncodedObjectAsID::set_object_id);
ClassDB::bind_method(D_METHOD("get_object_id"), &EncodedObjectAsID::get_object_id);
+
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "object_id"), "set_object_id", "get_object_id");
}
void EncodedObjectAsID::set_object_id(ObjectID p_id) {
@@ -59,6 +57,10 @@ EncodedObjectAsID::EncodedObjectAsID() :
id(0) {
}
+#define _S(a) ((int32_t)a)
+#define ERR_FAIL_ADD_OF(a, b, err) ERR_FAIL_COND_V(_S(b) < 0 || _S(a) < 0 || _S(a) > INT_MAX - _S(b), err)
+#define ERR_FAIL_MUL_OF(a, b, err) ERR_FAIL_COND_V(_S(a) < 0 || _S(b) <= 0 || _S(a) > INT_MAX / _S(b), err)
+
#define ENCODE_MASK 0xFF
#define ENCODE_FLAG_64 1 << 16
#define ENCODE_FLAG_OBJECT_AS_ID 1 << 16
diff --git a/core/undo_redo.cpp b/core/undo_redo.cpp
index f7ca6d3bde..f0c2b8eb9b 100644
--- a/core/undo_redo.cpp
+++ b/core/undo_redo.cpp
@@ -336,6 +336,7 @@ bool UndoRedo::redo() {
_process_operation_list(actions.write[current_action].do_ops.front());
version++;
+ emit_signal("version_changed");
return true;
}
@@ -348,6 +349,8 @@ bool UndoRedo::undo() {
_process_operation_list(actions.write[current_action].undo_ops.front());
current_action--;
version--;
+ emit_signal("version_changed");
+
return true;
}
@@ -359,18 +362,30 @@ void UndoRedo::clear_history(bool p_increase_version) {
while (actions.size())
_pop_history_tail();
- if (p_increase_version)
+ if (p_increase_version) {
version++;
+ emit_signal("version_changed");
+ }
}
String UndoRedo::get_current_action_name() const {
ERR_FAIL_COND_V(action_level > 0, "");
if (current_action < 0)
- return ""; //nothing to redo
+ return "";
return actions[current_action].name;
}
+bool UndoRedo::has_undo() {
+
+ return current_action >= 0;
+}
+
+bool UndoRedo::has_redo() {
+
+ return (current_action + 1) < actions.size();
+}
+
uint64_t UndoRedo::get_version() const {
return version;
@@ -523,10 +538,14 @@ void UndoRedo::_bind_methods() {
ClassDB::bind_method(D_METHOD("add_undo_reference", "object"), &UndoRedo::add_undo_reference);
ClassDB::bind_method(D_METHOD("clear_history", "increase_version"), &UndoRedo::clear_history, DEFVAL(true));
ClassDB::bind_method(D_METHOD("get_current_action_name"), &UndoRedo::get_current_action_name);
+ ClassDB::bind_method(D_METHOD("has_undo"), &UndoRedo::has_undo);
+ ClassDB::bind_method(D_METHOD("has_redo"), &UndoRedo::has_redo);
ClassDB::bind_method(D_METHOD("get_version"), &UndoRedo::get_version);
ClassDB::bind_method(D_METHOD("redo"), &UndoRedo::redo);
ClassDB::bind_method(D_METHOD("undo"), &UndoRedo::undo);
+ ADD_SIGNAL(MethodInfo("version_changed"));
+
BIND_ENUM_CONSTANT(MERGE_DISABLE);
BIND_ENUM_CONSTANT(MERGE_ENDS);
BIND_ENUM_CONSTANT(MERGE_ALL);
diff --git a/core/undo_redo.h b/core/undo_redo.h
index e2cc6c659b..276d00d9af 100644
--- a/core/undo_redo.h
+++ b/core/undo_redo.h
@@ -118,6 +118,9 @@ public:
String get_current_action_name() const;
void clear_history(bool p_increase_version = true);
+ bool has_undo();
+ bool has_redo();
+
uint64_t get_version() const;
void set_commit_notify_callback(CommitNotifyCallback p_callback, void *p_ud);
diff --git a/doc/classes/EncodedObjectAsID.xml b/doc/classes/EncodedObjectAsID.xml
index 1822f6c199..6efdda48ef 100644
--- a/doc/classes/EncodedObjectAsID.xml
+++ b/doc/classes/EncodedObjectAsID.xml
@@ -1,27 +1,21 @@
<?xml version="1.0" encoding="UTF-8" ?>
<class name="EncodedObjectAsID" inherits="Reference" category="Core" version="3.2">
<brief_description>
+ Holds a reference to an [Object]'s instance ID.
</brief_description>
<description>
+ Utility class which holds a reference to the internal identifier of an [Object] instance, as given by [method Object.get_instance_id]. This ID can then be used to retrieve the object instance with [method @GDScript.instance_from_id].
+ This class is used internally by the editor inspector and script debugger, but can also be used in plugins to pass and display objects as their IDs.
</description>
<tutorials>
</tutorials>
<methods>
- <method name="get_object_id" qualifiers="const">
- <return type="int">
- </return>
- <description>
- </description>
- </method>
- <method name="set_object_id">
- <return type="void">
- </return>
- <argument index="0" name="id" type="int">
- </argument>
- <description>
- </description>
- </method>
</methods>
+ <members>
+ <member name="object_id" type="int" setter="set_object_id" getter="get_object_id">
+ The [Object] identifier stored in this [EncodedObjectAsID] instance. The object instance can be retrieved with [method @GDScript.instance_from_id].
+ </member>
+ </members>
<constants>
</constants>
</class>
diff --git a/doc/classes/LineEdit.xml b/doc/classes/LineEdit.xml
index 184987d2dd..333f6a3671 100644
--- a/doc/classes/LineEdit.xml
+++ b/doc/classes/LineEdit.xml
@@ -200,6 +200,8 @@
</theme_item>
<theme_item name="font_color_selected" type="Color">
</theme_item>
+ <theme_item name="font_color_uneditable" type="Color">
+ </theme_item>
<theme_item name="minimum_spaces" type="int">
</theme_item>
<theme_item name="normal" type="StyleBox">
diff --git a/doc/classes/Node.xml b/doc/classes/Node.xml
index 1fb2e7350f..e8b43ead85 100644
--- a/doc/classes/Node.xml
+++ b/doc/classes/Node.xml
@@ -268,6 +268,14 @@
<argument index="0" name="path" type="NodePath">
</argument>
<description>
+ Fetches a node and one of its resources as specified by the [NodePath]'s subname (e.g. [code]Area2D/CollisionShape2D:shape[/code]). If several nested resources are specified in the [NodePath], the last one will be fetched.
+ The return value is an array of size 3: the first index points to the [Node] (or [code]null[/code] if not found), the second index points to the [Resource] (or [code]null[/code] if not found), and the third index is the remaining [NodePath], if any.
+ For example, assuming that [code]Area2D/CollisionShape2D[/code] is a valid node and that its [code]shape[/code] property has been assigned a [RectangleShape2D] resource, one could have this kind of output:
+ [codeblock]
+ print(get_node_and_resource("Area2D/CollisionShape2D")) # [[CollisionShape2D:1161], Null, ]
+ print(get_node_and_resource("Area2D/CollisionShape2D:shape")) # [[CollisionShape2D:1161], [RectangleShape2D:1156], ]
+ print(get_node_and_resource("Area2D/CollisionShape2D:shape:extents")) # [[CollisionShape2D:1161], [RectangleShape2D:1156], :extents]
+ [/codeblock]
</description>
</method>
<method name="get_node_or_null" qualifiers="const">
@@ -359,6 +367,7 @@
<argument index="0" name="path" type="NodePath">
</argument>
<description>
+ Returns [code]true[/code] if the [NodePath] points to a valid node and its subname points to a valid resource, e.g. [code]Area2D/CollisionShape2D:shape[/code]. Properties with a non-[Resource] type (e.g. nodes or primitive math types) are not considered resources.
</description>
</method>
<method name="is_a_parent_of" qualifiers="const">
diff --git a/doc/classes/NodePath.xml b/doc/classes/NodePath.xml
index 554858d895..2879a83efb 100644
--- a/doc/classes/NodePath.xml
+++ b/doc/classes/NodePath.xml
@@ -4,9 +4,9 @@
Pre-parsed scene tree path.
</brief_description>
<description>
- A pre-parsed relative or absolute path in a scene tree, for use with [method Node.get_node] and similar functions. It can reference a node, a resource within a node, or a property of a node or resource. For instance, [code]"Path2D/PathFollow2D/Sprite:texture:size"[/code] would refer to the size property of the texture resource on the node named "Sprite" which is a child of the other named nodes in the path. Note that if you want to get a resource, you must end the path with a colon, otherwise the last element will be used as a property name.
+ A pre-parsed relative or absolute path in a scene tree, for use with [method Node.get_node] and similar functions. It can reference a node, a resource within a node, or a property of a node or resource. For instance, [code]"Path2D/PathFollow2D/Sprite:texture:size"[/code] would refer to the [code]size[/code] property of the [code]texture[/code] resource on the node named [code]"Sprite"[/code] which is a child of the other named nodes in the path.
You will usually just pass a string to [method Node.get_node] and it will be automatically converted, but you may occasionally want to parse a path ahead of time with [NodePath] or the literal syntax [code]@"path"[/code]. Exporting a [NodePath] variable will give you a node selection widget in the properties panel of the editor, which can often be useful.
- A [NodePath] is made up of a list of node names, a list of "subnode" (resource) names, and the name of a property in the final node or resource.
+ A [NodePath] is composed of a list of slash-separated node names (like a filesystem path) and an optional colon-separated list of "subnames" which can be resources or properties.
</description>
<tutorials>
</tutorials>
@@ -18,18 +18,46 @@
</argument>
<description>
Create a NodePath from a string, e.g. "Path2D/PathFollow2D/Sprite:texture:size". A path is absolute if it starts with a slash. Absolute paths are only valid in the global scene tree, not within individual scenes. In a relative path, [code]"."[/code] and [code]".."[/code] indicate the current node and its parent.
+ The "subnames" optionally included after the path to the target node can point to resources or properties, and can also be nested.
+ Examples of valid NodePaths (assuming that those nodes exist and have the referenced resources or properties):
+ [codeblock]
+ # Points to the Sprite node
+ "Path2D/PathFollow2D/Sprite"
+ # Points to the Sprite node and its 'texture' resource.
+ # get_node() would retrieve "Sprite", while get_node_and_resource()
+ # would retrieve both the Sprite node and the 'texture' resource.
+ "Path2D/PathFollow2D/Sprite:texture"
+ # Points to the Sprite node and its 'position' property.
+ "Path2D/PathFollow2D/Sprite:position"
+ # Points to the Sprite node and the 'x' component of its 'position' property.
+ "Path2D/PathFollow2D/Sprite:position:x"
+ # Absolute path (from 'root')
+ "/root/Level/Path2D"
+ [/codeblock]
</description>
</method>
<method name="get_as_property_path">
<return type="NodePath">
</return>
<description>
+ Returns a node path with a colon character ([code]:[/code]) prepended, transforming it to a pure property path with no node name (defaults to resolving from the current node).
+ [codeblock]
+ # This will be parsed as a node path to the 'x' property in the 'position' node
+ var node_path = NodePath("position:x")
+ # This will be parsed as a node path to the 'x' component of the 'position' property in the current node
+ var property_path = node_path.get_as_property_path()
+ print(property_path) # :position:x
</description>
</method>
<method name="get_concatenated_subnames">
<return type="String">
</return>
<description>
+ Returns all subnames concatenated with a colon character ([code]:[/code]) as separator, i.e. the right side of the first colon in a node path.
+ [codeblock]
+ var nodepath = NodePath("Path2D/PathFollow2D/Sprite:texture:load_path")
+ print(nodepath.get_concatenated_subnames()) # texture:load_path
+ [/codeblock]
</description>
</method>
<method name="get_name">
@@ -38,14 +66,21 @@
<argument index="0" name="idx" type="int">
</argument>
<description>
- Get the node name indicated by [code]idx[/code] (0 to [method get_name_count])
+ Get the node name indicated by [code]idx[/code] (0 to [method get_name_count]).
+ [codeblock]
+ var node_path = NodePath("Path2D/PathFollow2D/Sprite")
+ print(node_path.get_name(0)) # Path2D
+ print(node_path.get_name(1)) # PathFollow2D
+ print(node_path.get_name(2)) # Sprite
+ [/codeblock]
</description>
</method>
<method name="get_name_count">
<return type="int">
</return>
<description>
- Get the number of node names which make up the path.
+ Get the number of node names which make up the path. Subnames (see [method get_subname_count]) are not included.
+ For example, [code]"Path2D/PathFollow2D/Sprite"[code] has 3 names.
</description>
</method>
<method name="get_subname">
@@ -54,21 +89,27 @@
<argument index="0" name="idx" type="int">
</argument>
<description>
- Get the resource name indicated by [code]idx[/code] (0 to [method get_subname_count])
+ Get the resource or property name indicated by [code]idx[/code] (0 to [method get_subname_count]).
+ [codeblock]
+ var node_path = NodePath("Path2D/PathFollow2D/Sprite:texture:load_path")
+ print(node_path.get_subname(0)) # texture
+ print(node_path.get_subname(1)) # load_path
+ [/codeblock]
</description>
</method>
<method name="get_subname_count">
<return type="int">
</return>
<description>
- Get the number of resource names in the path.
+ Get the number of resource or property names ("subnames") in the path. Each subname is listed after a colon character ([code]:[/code]) in the node path.
+ For example, [code]"Path2D/PathFollow2D/Sprite:texture:load_path"[/code] has 2 subnames.
</description>
</method>
<method name="is_absolute">
<return type="bool">
</return>
<description>
- Returns [code]true[/code] if the node path is absolute (not relative).
+ Returns [code]true[/code] if the node path is absolute (as opposed to relative), which means that it starts with a slash character ([code]/[/code]). Absolute node paths can be used to access the root node ([code]"/root"[/code]) or autoloads (e.g. [code]"/global"[/code] if a "global" autoload was registered).
</description>
</method>
<method name="is_empty">
diff --git a/doc/classes/Object.xml b/doc/classes/Object.xml
index 548a0c18bb..a1fba1ac8d 100644
--- a/doc/classes/Object.xml
+++ b/doc/classes/Object.xml
@@ -203,6 +203,7 @@
</return>
<description>
Returns the object's unique instance ID.
+ This ID can be saved in [EncodedObjectAsID], and can be used to retrieve the object instance with [method @GDScript.instance_from_id].
</description>
</method>
<method name="get_meta" qualifiers="const">
diff --git a/doc/classes/TextEdit.xml b/doc/classes/TextEdit.xml
index 8c87a4f2e7..00db5ef2b9 100644
--- a/doc/classes/TextEdit.xml
+++ b/doc/classes/TextEdit.xml
@@ -572,6 +572,8 @@
<theme_item name="font_color" type="Color">
Sets the font [Color].
</theme_item>
+ <theme_item name="font_color_readonly" type="Color">
+ </theme_item>
<theme_item name="font_color_selected" type="Color">
</theme_item>
<theme_item name="function_color" type="Color">
diff --git a/doc/classes/UndoRedo.xml b/doc/classes/UndoRedo.xml
index c0b73cd8e3..b6e458b43f 100644
--- a/doc/classes/UndoRedo.xml
+++ b/doc/classes/UndoRedo.xml
@@ -141,6 +141,20 @@
This is useful mostly to check if something changed from a saved version.
</description>
</method>
+ <method name="has_redo">
+ <return type="bool">
+ </return>
+ <description>
+ Returns [code]true[/code] if an 'redo' action is available.
+ </description>
+ </method>
+ <method name="has_undo">
+ <return type="bool">
+ </return>
+ <description>
+ Returns [code]true[/code] if an 'undo' action is available.
+ </description>
+ </method>
<method name="is_commiting_action" qualifiers="const">
<return type="bool">
</return>
@@ -162,6 +176,13 @@
</description>
</method>
</methods>
+ <signals>
+ <signal name="version_changed">
+ <description>
+ Called when [method undo] or [method redo] was called.
+ </description>
+ </signal>
+ </signals>
<constants>
<constant name="MERGE_DISABLE" value="0" enum="MergeMode">
Makes [code]do[/code]/[code]undo[/code] operations stay in separate actions.
diff --git a/editor/editor_help_search.cpp b/editor/editor_help_search.cpp
index 55ab38ba6c..4ec24c76f2 100644
--- a/editor/editor_help_search.cpp
+++ b/editor/editor_help_search.cpp
@@ -260,7 +260,11 @@ bool EditorHelpSearch::Runner::_is_class_disabled_by_feature_profile(const Strin
StringName class_name = p_class;
while (class_name != StringName()) {
- if (!ClassDB::class_exists(class_name) || profile->is_class_disabled(class_name)) {
+ if (!ClassDB::class_exists(class_name)) {
+ return false;
+ }
+
+ if (profile->is_class_disabled(class_name)) {
return true;
}
class_name = ClassDB::get_parent_class(class_name);
diff --git a/editor/editor_node.cpp b/editor/editor_node.cpp
index 1f08f3d787..3d640b4d35 100644
--- a/editor/editor_node.cpp
+++ b/editor/editor_node.cpp
@@ -260,24 +260,25 @@ void EditorNode::_notification(int p_what) {
last_checked_version = editor_data.get_undo_redo().get_version();
}
- //update the circle
+ // update the animation frame of the update spinner
uint64_t frame = Engine::get_singleton()->get_frames_drawn();
uint32_t tick = OS::get_singleton()->get_ticks_msec();
- if (frame != circle_step_frame && (tick - circle_step_msec) > (1000 / 8)) {
+ if (frame != update_spinner_step_frame && (tick - update_spinner_step_msec) > (1000 / 8)) {
- circle_step++;
- if (circle_step >= 8)
- circle_step = 0;
+ update_spinner_step++;
+ if (update_spinner_step >= 8)
+ update_spinner_step = 0;
- circle_step_msec = tick;
- circle_step_frame = frame + 1;
+ update_spinner_step_msec = tick;
+ update_spinner_step_frame = frame + 1;
- // update the circle itself only when its enabled
- if (!update_menu->get_popup()->is_item_checked(3)) {
- update_menu->set_icon(gui_base->get_icon("Progress" + itos(circle_step + 1), "EditorIcons"));
+ // update the icon itself only when the spinner is visible
+ if (EditorSettings::get_singleton()->get("interface/editor/show_update_spinner")) {
+ update_spinner->set_icon(gui_base->get_icon("Progress" + itos(update_spinner_step + 1), "EditorIcons"));
}
}
+
editor_selection->update();
scene_root->set_size_override(true, Size2(ProjectSettings::get_singleton()->get("display/window/size/width"), ProjectSettings::get_singleton()->get("display/window/size/height")));
@@ -400,10 +401,8 @@ void EditorNode::_notification(int p_what) {
scene_tab_add->set_icon(gui_base->get_icon("Add", "EditorIcons"));
// clear_button->set_icon(gui_base->get_icon("Close", "EditorIcons")); don't have access to that node. needs to become a class property
- update_menu->set_icon(gui_base->get_icon("Collapse", "EditorIcons"));
dock_tab_move_left->set_icon(theme->get_icon("Back", "EditorIcons"));
dock_tab_move_right->set_icon(theme->get_icon("Forward", "EditorIcons"));
- update_menu->set_icon(gui_base->get_icon("Progress1", "EditorIcons"));
PopupMenu *p = help_menu->get_popup();
p->set_item_icon(p->get_item_index(HELP_SEARCH), gui_base->get_icon("HelpSearch", "EditorIcons"));
@@ -412,6 +411,8 @@ void EditorNode::_notification(int p_what) {
p->set_item_icon(p->get_item_index(HELP_ISSUES), gui_base->get_icon("Instance", "EditorIcons"));
p->set_item_icon(p->get_item_index(HELP_COMMUNITY), gui_base->get_icon("Instance", "EditorIcons"));
p->set_item_icon(p->get_item_index(HELP_ABOUT), gui_base->get_icon("Godot", "EditorIcons"));
+
+ _update_update_spinner();
}
if (p_what == Control::NOTIFICATION_RESIZED) {
@@ -419,6 +420,17 @@ void EditorNode::_notification(int p_what) {
}
}
+void EditorNode::_update_update_spinner() {
+ update_spinner->set_visible(EditorSettings::get_singleton()->get("interface/editor/show_update_spinner"));
+
+ bool update_continuously = EditorSettings::get_singleton()->get("interface/editor/update_continuously");
+ PopupMenu *update_popup = update_spinner->get_popup();
+ update_popup->set_item_checked(update_popup->get_item_index(SETTINGS_UPDATE_CONTINUOUSLY), update_continuously);
+ update_popup->set_item_checked(update_popup->get_item_index(SETTINGS_UPDATE_WHEN_CHANGED), !update_continuously);
+
+ OS::get_singleton()->set_low_processor_usage_mode(!update_continuously);
+}
+
void EditorNode::_on_plugin_ready(Object *p_script, const String &p_activate_name) {
Ref<Script> script = Object::cast_to<Script>(p_script);
if (script.is_null())
@@ -2426,28 +2438,21 @@ void EditorNode::_menu_option_confirm(int p_option, bool p_confirmed) {
EditorSettings::get_singleton()->set_project_metadata("debug_options", "run_reload_scripts", !ischecked);
} break;
- case SETTINGS_UPDATE_ALWAYS: {
-
- update_menu->get_popup()->set_item_checked(0, true);
- update_menu->get_popup()->set_item_checked(1, false);
- OS::get_singleton()->set_low_processor_usage_mode(false);
- EditorSettings::get_singleton()->set_project_metadata("editor_options", "update_always", true);
+ case SETTINGS_UPDATE_CONTINUOUSLY: {
+ EditorSettings::get_singleton()->set("interface/editor/update_continuously", true);
+ _update_update_spinner();
show_accept(TTR("This option is deprecated. Situations where refresh must be forced are now considered a bug. Please report."), TTR("OK"));
} break;
- case SETTINGS_UPDATE_CHANGES: {
+ case SETTINGS_UPDATE_WHEN_CHANGED: {
- update_menu->get_popup()->set_item_checked(0, false);
- update_menu->get_popup()->set_item_checked(1, true);
- OS::get_singleton()->set_low_processor_usage_mode(true);
- EditorSettings::get_singleton()->set_project_metadata("editor_options", "update_always", false);
+ EditorSettings::get_singleton()->set("interface/editor/update_continuously", false);
+ _update_update_spinner();
} break;
case SETTINGS_UPDATE_SPINNER_HIDE: {
- update_menu->set_icon(gui_base->get_icon("Collapse", "EditorIcons"));
- update_menu->get_popup()->toggle_item_checked(3);
- bool checked = update_menu->get_popup()->is_item_checked(3);
- EditorSettings::get_singleton()->set_project_metadata("editor_options", "update_spinner_hide", checked);
+ EditorSettings::get_singleton()->set("interface/editor/show_update_spinner", false);
+ _update_update_spinner();
} break;
case SETTINGS_PREFERENCES: {
@@ -5440,6 +5445,8 @@ EditorNode::EditorNode() {
EDITOR_DEF("run/auto_save/save_before_running", true);
EDITOR_DEF_RST("interface/editor/save_each_scene_on_quit", true);
EDITOR_DEF("interface/editor/quit_confirmation", true);
+ EDITOR_DEF("interface/editor/show_update_spinner", false);
+ EDITOR_DEF("interface/editor/update_continuously", false);
EDITOR_DEF_RST("interface/scene_tabs/restore_scenes_on_load", false);
EDITOR_DEF_RST("interface/scene_tabs/show_thumbnail_on_hover", true);
EDITOR_DEF_RST("interface/inspector/capitalize_properties", true);
@@ -6037,22 +6044,17 @@ EditorNode::EditorNode() {
layout_dialog->set_size(Size2(225, 270) * EDSCALE);
layout_dialog->connect("name_confirmed", this, "_dialog_action");
- update_menu = memnew(MenuButton);
- update_menu->set_tooltip(TTR("Spins when the editor window redraws."));
- right_menu_hb->add_child(update_menu);
- update_menu->set_icon(gui_base->get_icon("Progress1", "EditorIcons"));
- update_menu->get_popup()->connect("id_pressed", this, "_menu_option");
- p = update_menu->get_popup();
- p->add_radio_check_item(TTR("Update Always"), SETTINGS_UPDATE_ALWAYS);
- p->add_radio_check_item(TTR("Update Changes"), SETTINGS_UPDATE_CHANGES);
+ update_spinner = memnew(MenuButton);
+ update_spinner->set_tooltip(TTR("Spins when the editor window redraws."));
+ right_menu_hb->add_child(update_spinner);
+ update_spinner->set_icon(gui_base->get_icon("Progress1", "EditorIcons"));
+ update_spinner->get_popup()->connect("id_pressed", this, "_menu_option");
+ p = update_spinner->get_popup();
+ p->add_radio_check_item(TTR("Update Continuously"), SETTINGS_UPDATE_CONTINUOUSLY);
+ p->add_radio_check_item(TTR("Update When Changed"), SETTINGS_UPDATE_WHEN_CHANGED);
p->add_separator();
- p->add_check_item(TTR("Disable Update Spinner"), SETTINGS_UPDATE_SPINNER_HIDE);
- int update_always = EditorSettings::get_singleton()->get_project_metadata("editor_options", "update_always", false);
- int hide_spinner = EditorSettings::get_singleton()->get_project_metadata("editor_options", "update_spinner_hide", false);
- _menu_option(update_always ? SETTINGS_UPDATE_ALWAYS : SETTINGS_UPDATE_CHANGES);
- if (hide_spinner) {
- _menu_option(SETTINGS_UPDATE_SPINNER_HIDE);
- }
+ p->add_item(TTR("Hide Update Spinner"), SETTINGS_UPDATE_SPINNER_HIDE);
+ _update_update_spinner();
// Instantiate and place editor docks
@@ -6341,9 +6343,9 @@ EditorNode::EditorNode() {
particles_mat_convert.instance();
resource_conversion_plugins.push_back(particles_mat_convert);
}
- circle_step_msec = OS::get_singleton()->get_ticks_msec();
- circle_step_frame = Engine::get_singleton()->get_frames_drawn();
- circle_step = 0;
+ update_spinner_step_msec = OS::get_singleton()->get_ticks_msec();
+ update_spinner_step_frame = Engine::get_singleton()->get_frames_drawn();
+ update_spinner_step = 0;
editor_plugin_screen = NULL;
editor_plugins_over = memnew(EditorPluginList);
diff --git a/editor/editor_node.h b/editor/editor_node.h
index 46b9befcd6..8222f6213b 100644
--- a/editor/editor_node.h
+++ b/editor/editor_node.h
@@ -182,8 +182,8 @@ private:
RUN_DEBUG_NAVIGATION,
RUN_DEPLOY_REMOTE_DEBUG,
RUN_RELOAD_SCRIPTS,
- SETTINGS_UPDATE_ALWAYS,
- SETTINGS_UPDATE_CHANGES,
+ SETTINGS_UPDATE_CONTINUOUSLY,
+ SETTINGS_UPDATE_WHEN_CHANGED,
SETTINGS_UPDATE_SPINNER_HIDE,
SETTINGS_PREFERENCES,
SETTINGS_LAYOUT_SAVE,
@@ -328,7 +328,7 @@ private:
CheckButton *file_export_lib_merge;
LineEdit *file_export_password;
String current_path;
- MenuButton *update_menu;
+ MenuButton *update_spinner;
String defer_load_scene;
String defer_export;
@@ -394,9 +394,9 @@ private:
bool waiting_for_sources_changed;
- uint32_t circle_step_msec;
- uint64_t circle_step_frame;
- int circle_step;
+ uint32_t update_spinner_step_msec;
+ uint64_t update_spinner_step_frame;
+ int update_spinner_step;
Vector<EditorPlugin *> editor_plugins;
EditorPlugin *editor_plugin_screen;
@@ -629,6 +629,8 @@ private:
void _license_tree_selected();
+ void _update_update_spinner();
+
Vector<Ref<EditorResourceConversionPlugin> > resource_conversion_plugins;
PrintHandlerList print_handler;
diff --git a/scene/main/node.cpp b/scene/main/node.cpp
index ee23b24b3c..26186638d7 100644
--- a/scene/main/node.cpp
+++ b/scene/main/node.cpp
@@ -2477,21 +2477,18 @@ bool Node::has_node_and_resource(const NodePath &p_path) const {
if (!has_node(p_path))
return false;
- Node *node = get_node(p_path);
-
- bool result = false;
-
- node->get_indexed(p_path.get_subnames(), &result);
+ RES res;
+ Vector<StringName> leftover_path;
+ Node *node = get_node_and_resource(p_path, res, leftover_path, false);
- return result;
+ return (node && res.is_valid());
}
Array Node::_get_node_and_resource(const NodePath &p_path) {
- Node *node;
RES res;
Vector<StringName> leftover_path;
- node = get_node_and_resource(p_path, res, leftover_path);
+ Node *node = get_node_and_resource(p_path, res, leftover_path, false);
Array result;
if (node)
@@ -2521,7 +2518,7 @@ Node *Node::get_node_and_resource(const NodePath &p_path, RES &r_res, Vector<Str
int j = 0;
// If not p_last_is_property, we shouldn't consider the last one as part of the resource
- for (; j < p_path.get_subname_count() - p_last_is_property; j++) {
+ for (; j < p_path.get_subname_count() - (int)p_last_is_property; j++) {
RES new_res = j == 0 ? node->get(p_path.get_subname(j)) : r_res->get(p_path.get_subname(j));
if (new_res.is_null()) {