diff options
-rw-r--r-- | core/core_constants.cpp | 1 | ||||
-rw-r--r-- | core/object/object.cpp | 6 | ||||
-rw-r--r-- | core/object/object.h | 7 | ||||
-rw-r--r-- | doc/classes/@GlobalScope.xml | 79 | ||||
-rw-r--r-- | doc/classes/Object.xml | 6 | ||||
-rw-r--r-- | editor/editor_properties.cpp | 264 | ||||
-rw-r--r-- | editor/editor_properties.h | 34 | ||||
-rw-r--r-- | editor/icons/Unlinked.svg | 1 | ||||
-rw-r--r-- | editor/plugins/canvas_item_editor_plugin.cpp | 2 | ||||
-rw-r--r-- | modules/navigation/rvo_agent.cpp | 3 | ||||
-rw-r--r-- | platform/javascript/SCsub | 6 | ||||
-rw-r--r-- | platform/javascript/detect.py | 17 | ||||
-rw-r--r-- | platform/javascript/emscripten_helpers.py | 6 | ||||
-rw-r--r-- | platform/javascript/export/export_plugin.cpp | 9 | ||||
-rw-r--r-- | platform/javascript/export/export_plugin.h | 15 | ||||
-rw-r--r-- | scene/2d/node_2d.cpp | 2 | ||||
-rw-r--r-- | scene/3d/lightmap_gi.cpp | 157 | ||||
-rw-r--r-- | scene/3d/lightmap_gi.h | 2 | ||||
-rw-r--r-- | scene/3d/node_3d.cpp | 2 | ||||
-rw-r--r-- | scene/gui/control.cpp | 4 |
20 files changed, 463 insertions, 160 deletions
diff --git a/core/core_constants.cpp b/core/core_constants.cpp index bbc937d575..4f22c99656 100644 --- a/core/core_constants.cpp +++ b/core/core_constants.cpp @@ -552,6 +552,7 @@ void register_global_constants() { BIND_CORE_ENUM_CONSTANT(PROPERTY_HINT_ENUM_SUGGESTION); BIND_CORE_ENUM_CONSTANT(PROPERTY_HINT_EXP_EASING); BIND_CORE_ENUM_CONSTANT(PROPERTY_HINT_LENGTH); + BIND_CORE_ENUM_CONSTANT(PROPERTY_HINT_LINK); BIND_CORE_ENUM_CONSTANT(PROPERTY_HINT_KEY_ACCEL); BIND_CORE_ENUM_CONSTANT(PROPERTY_HINT_FLAGS); diff --git a/core/object/object.cpp b/core/object/object.cpp index 0912ea55f0..9dec417b11 100644 --- a/core/object/object.cpp +++ b/core/object/object.cpp @@ -1196,7 +1196,7 @@ Array Object::_get_signal_list() const { return ret; } -Array Object::_get_signal_connection_list(const String &p_signal) const { +Array Object::_get_signal_connection_list(const StringName &p_signal) const { List<Connection> conns; get_all_signal_connections(&conns); @@ -1422,11 +1422,11 @@ void Object::_disconnect(const StringName &p_signal, const Callable &p_callable, } } -void Object::_set_bind(const String &p_set, const Variant &p_value) { +void Object::_set_bind(const StringName &p_set, const Variant &p_value) { set(p_set, p_value); } -Variant Object::_get_bind(const String &p_name) const { +Variant Object::_get_bind(const StringName &p_name) const { return get(p_name); } diff --git a/core/object/object.h b/core/object/object.h index 988d261d77..7cbedd29d9 100644 --- a/core/object/object.h +++ b/core/object/object.h @@ -52,6 +52,7 @@ enum PropertyHint { PROPERTY_HINT_ENUM_SUGGESTION, ///< hint_text= "val1,val2,val3,etc" PROPERTY_HINT_EXP_EASING, /// exponential easing function (Math::ease) use "attenuation" hint string to revert (flip h), "full" to also include in/out. (ie: "attenuation,inout") PROPERTY_HINT_LENGTH, ///< hint_text= "length" (as integer) + PROPERTY_HINT_LINK, PROPERTY_HINT_KEY_ACCEL, ///< hint_text= "length" (as integer) PROPERTY_HINT_FLAGS, ///< hint_text= "flag1,flag2,etc" (as bit flags) PROPERTY_HINT_LAYERS_2D_RENDER, @@ -523,10 +524,10 @@ private: bool _has_user_signal(const StringName &p_name) const; Error _emit_signal(const Variant **p_args, int p_argcount, Callable::CallError &r_error); Array _get_signal_list() const; - Array _get_signal_connection_list(const String &p_signal) const; + Array _get_signal_connection_list(const StringName &p_signal) const; Array _get_incoming_connections() const; - void _set_bind(const String &p_set, const Variant &p_value); - Variant _get_bind(const String &p_name) const; + void _set_bind(const StringName &p_set, const Variant &p_value); + Variant _get_bind(const StringName &p_name) const; void _set_indexed_bind(const NodePath &p_name, const Variant &p_value); Variant _get_indexed_bind(const NodePath &p_name) const; diff --git a/doc/classes/@GlobalScope.xml b/doc/classes/@GlobalScope.xml index dce96fb315..18ea29857b 100644 --- a/doc/classes/@GlobalScope.xml +++ b/doc/classes/@GlobalScope.xml @@ -2419,63 +2419,66 @@ <constant name="PROPERTY_HINT_LENGTH" value="5" enum="PropertyHint"> Deprecated hint, unused. </constant> - <constant name="PROPERTY_HINT_KEY_ACCEL" value="6" enum="PropertyHint"> + <constant name="PROPERTY_HINT_LINK" value="6" enum="PropertyHint"> + Hints that a vector property should allow linking values (e.g. to edit both [code]x[/code] and [code]y[/code] together). + </constant> + <constant name="PROPERTY_HINT_KEY_ACCEL" value="7" enum="PropertyHint"> Deprecated hint, unused. </constant> - <constant name="PROPERTY_HINT_FLAGS" value="7" enum="PropertyHint"> + <constant name="PROPERTY_HINT_FLAGS" value="8" enum="PropertyHint"> Hints that an integer property is a bitmask with named bit flags. For example, to allow toggling bits 0, 1, 2 and 4, the hint could be something like [code]"Bit0,Bit1,Bit2,,Bit4"[/code]. </constant> - <constant name="PROPERTY_HINT_LAYERS_2D_RENDER" value="8" enum="PropertyHint"> + <constant name="PROPERTY_HINT_LAYERS_2D_RENDER" value="9" enum="PropertyHint"> Hints that an integer property is a bitmask using the optionally named 2D render layers. </constant> - <constant name="PROPERTY_HINT_LAYERS_2D_PHYSICS" value="9" enum="PropertyHint"> + <constant name="PROPERTY_HINT_LAYERS_2D_PHYSICS" value="10" enum="PropertyHint"> Hints that an integer property is a bitmask using the optionally named 2D physics layers. </constant> - <constant name="PROPERTY_HINT_LAYERS_2D_NAVIGATION" value="10" enum="PropertyHint"> + <constant name="PROPERTY_HINT_LAYERS_2D_NAVIGATION" value="11" enum="PropertyHint"> Hints that an integer property is a bitmask using the optionally named 2D navigation layers. </constant> - <constant name="PROPERTY_HINT_LAYERS_3D_RENDER" value="11" enum="PropertyHint"> + <constant name="PROPERTY_HINT_LAYERS_3D_RENDER" value="12" enum="PropertyHint"> Hints that an integer property is a bitmask using the optionally named 3D render layers. </constant> - <constant name="PROPERTY_HINT_LAYERS_3D_PHYSICS" value="12" enum="PropertyHint"> + <constant name="PROPERTY_HINT_LAYERS_3D_PHYSICS" value="13" enum="PropertyHint"> Hints that an integer property is a bitmask using the optionally named 3D physics layers. </constant> - <constant name="PROPERTY_HINT_LAYERS_3D_NAVIGATION" value="13" enum="PropertyHint"> + <constant name="PROPERTY_HINT_LAYERS_3D_NAVIGATION" value="14" enum="PropertyHint"> Hints that an integer property is a bitmask using the optionally named 2D navigation layers. </constant> - <constant name="PROPERTY_HINT_FILE" value="14" enum="PropertyHint"> + <constant name="PROPERTY_HINT_FILE" value="15" enum="PropertyHint"> Hints that a string property is a path to a file. Editing it will show a file dialog for picking the path. The hint string can be a set of filters with wildcards like [code]"*.png,*.jpg"[/code]. </constant> - <constant name="PROPERTY_HINT_DIR" value="15" enum="PropertyHint"> + <constant name="PROPERTY_HINT_DIR" value="16" enum="PropertyHint"> Hints that a string property is a path to a directory. Editing it will show a file dialog for picking the path. </constant> - <constant name="PROPERTY_HINT_GLOBAL_FILE" value="16" enum="PropertyHint"> + <constant name="PROPERTY_HINT_GLOBAL_FILE" value="17" enum="PropertyHint"> Hints that a string property is an absolute path to a file outside the project folder. Editing it will show a file dialog for picking the path. The hint string can be a set of filters with wildcards like [code]"*.png,*.jpg"[/code]. </constant> - <constant name="PROPERTY_HINT_GLOBAL_DIR" value="17" enum="PropertyHint"> + <constant name="PROPERTY_HINT_GLOBAL_DIR" value="18" enum="PropertyHint"> Hints that a string property is an absolute path to a directory outside the project folder. Editing it will show a file dialog for picking the path. </constant> - <constant name="PROPERTY_HINT_RESOURCE_TYPE" value="18" enum="PropertyHint"> + <constant name="PROPERTY_HINT_RESOURCE_TYPE" value="19" enum="PropertyHint"> Hints that a property is an instance of a [Resource]-derived type, optionally specified via the hint string (e.g. [code]"Texture2D"[/code]). Editing it will show a popup menu of valid resource types to instantiate. </constant> - <constant name="PROPERTY_HINT_MULTILINE_TEXT" value="19" enum="PropertyHint"> + <constant name="PROPERTY_HINT_MULTILINE_TEXT" value="20" enum="PropertyHint"> Hints that a string property is text with line breaks. Editing it will show a text input field where line breaks can be typed. </constant> - <constant name="PROPERTY_HINT_PLACEHOLDER_TEXT" value="20" enum="PropertyHint"> + <constant name="PROPERTY_HINT_PLACEHOLDER_TEXT" value="21" enum="PropertyHint"> Hints that a string property should have a placeholder text visible on its input field, whenever the property is empty. The hint string is the placeholder text to use. </constant> - <constant name="PROPERTY_HINT_COLOR_NO_ALPHA" value="21" enum="PropertyHint"> + <constant name="PROPERTY_HINT_COLOR_NO_ALPHA" value="22" enum="PropertyHint"> Hints that a color property should be edited without changing its alpha component, i.e. only R, G and B channels are edited. </constant> - <constant name="PROPERTY_HINT_IMAGE_COMPRESS_LOSSY" value="22" enum="PropertyHint"> + <constant name="PROPERTY_HINT_IMAGE_COMPRESS_LOSSY" value="23" enum="PropertyHint"> Hints that an image is compressed using lossy compression. </constant> - <constant name="PROPERTY_HINT_IMAGE_COMPRESS_LOSSLESS" value="23" enum="PropertyHint"> + <constant name="PROPERTY_HINT_IMAGE_COMPRESS_LOSSLESS" value="24" enum="PropertyHint"> Hints that an image is compressed using lossless compression. </constant> - <constant name="PROPERTY_HINT_OBJECT_ID" value="24" enum="PropertyHint"> + <constant name="PROPERTY_HINT_OBJECT_ID" value="25" enum="PropertyHint"> </constant> - <constant name="PROPERTY_HINT_TYPE_STRING" value="25" enum="PropertyHint"> + <constant name="PROPERTY_HINT_TYPE_STRING" value="26" enum="PropertyHint"> Hint that a property represents a particular type. If a property is [constant TYPE_STRING], allows to set a type from the create dialog. If you need to create an [Array] to contain elements of a specific type, the [code]hint_string[/code] must encode nested types using [code]":"[/code] and [code]"/"[/code] for specifying [Resource] types. For instance: [codeblock] hint_string = "%s:" % [TYPE_INT] # Array of inteters. @@ -2485,43 +2488,43 @@ [/codeblock] [b]Note:[/b] The final colon is required to specify for properly detecting built-in types. </constant> - <constant name="PROPERTY_HINT_NODE_PATH_TO_EDITED_NODE" value="26" enum="PropertyHint"> + <constant name="PROPERTY_HINT_NODE_PATH_TO_EDITED_NODE" value="27" enum="PropertyHint"> </constant> - <constant name="PROPERTY_HINT_METHOD_OF_VARIANT_TYPE" value="27" enum="PropertyHint"> + <constant name="PROPERTY_HINT_METHOD_OF_VARIANT_TYPE" value="28" enum="PropertyHint"> </constant> - <constant name="PROPERTY_HINT_METHOD_OF_BASE_TYPE" value="28" enum="PropertyHint"> + <constant name="PROPERTY_HINT_METHOD_OF_BASE_TYPE" value="29" enum="PropertyHint"> </constant> - <constant name="PROPERTY_HINT_METHOD_OF_INSTANCE" value="29" enum="PropertyHint"> + <constant name="PROPERTY_HINT_METHOD_OF_INSTANCE" value="30" enum="PropertyHint"> </constant> - <constant name="PROPERTY_HINT_METHOD_OF_SCRIPT" value="30" enum="PropertyHint"> + <constant name="PROPERTY_HINT_METHOD_OF_SCRIPT" value="31" enum="PropertyHint"> </constant> - <constant name="PROPERTY_HINT_PROPERTY_OF_VARIANT_TYPE" value="31" enum="PropertyHint"> + <constant name="PROPERTY_HINT_PROPERTY_OF_VARIANT_TYPE" value="32" enum="PropertyHint"> </constant> - <constant name="PROPERTY_HINT_PROPERTY_OF_BASE_TYPE" value="32" enum="PropertyHint"> + <constant name="PROPERTY_HINT_PROPERTY_OF_BASE_TYPE" value="33" enum="PropertyHint"> </constant> - <constant name="PROPERTY_HINT_PROPERTY_OF_INSTANCE" value="33" enum="PropertyHint"> + <constant name="PROPERTY_HINT_PROPERTY_OF_INSTANCE" value="34" enum="PropertyHint"> </constant> - <constant name="PROPERTY_HINT_PROPERTY_OF_SCRIPT" value="34" enum="PropertyHint"> + <constant name="PROPERTY_HINT_PROPERTY_OF_SCRIPT" value="35" enum="PropertyHint"> </constant> - <constant name="PROPERTY_HINT_OBJECT_TOO_BIG" value="35" enum="PropertyHint"> + <constant name="PROPERTY_HINT_OBJECT_TOO_BIG" value="36" enum="PropertyHint"> </constant> - <constant name="PROPERTY_HINT_NODE_PATH_VALID_TYPES" value="36" enum="PropertyHint"> + <constant name="PROPERTY_HINT_NODE_PATH_VALID_TYPES" value="37" enum="PropertyHint"> </constant> - <constant name="PROPERTY_HINT_SAVE_FILE" value="37" enum="PropertyHint"> + <constant name="PROPERTY_HINT_SAVE_FILE" value="38" enum="PropertyHint"> </constant> - <constant name="PROPERTY_HINT_INT_IS_OBJECTID" value="38" enum="PropertyHint"> + <constant name="PROPERTY_HINT_INT_IS_OBJECTID" value="39" enum="PropertyHint"> </constant> - <constant name="PROPERTY_HINT_INT_IS_POINTER" value="40" enum="PropertyHint"> + <constant name="PROPERTY_HINT_INT_IS_POINTER" value="41" enum="PropertyHint"> </constant> - <constant name="PROPERTY_HINT_ARRAY_TYPE" value="39" enum="PropertyHint"> + <constant name="PROPERTY_HINT_ARRAY_TYPE" value="40" enum="PropertyHint"> </constant> - <constant name="PROPERTY_HINT_LOCALE_ID" value="41" enum="PropertyHint"> + <constant name="PROPERTY_HINT_LOCALE_ID" value="42" enum="PropertyHint"> Hints that a string property is a locale code. Editing it will show a locale dialog for picking language and country. </constant> - <constant name="PROPERTY_HINT_LOCALIZABLE_STRING" value="42" enum="PropertyHint"> + <constant name="PROPERTY_HINT_LOCALIZABLE_STRING" value="43" enum="PropertyHint"> Hints that a dictionary property is string translation map. Dictionary keys are locale codes and, values are translated strings. </constant> - <constant name="PROPERTY_HINT_MAX" value="43" enum="PropertyHint"> + <constant name="PROPERTY_HINT_MAX" value="44" enum="PropertyHint"> </constant> <constant name="PROPERTY_USAGE_NONE" value="0" enum="PropertyUsageFlags"> </constant> diff --git a/doc/classes/Object.xml b/doc/classes/Object.xml index 42844794b0..11ae7cc2b0 100644 --- a/doc/classes/Object.xml +++ b/doc/classes/Object.xml @@ -325,7 +325,7 @@ </method> <method name="get" qualifiers="const"> <return type="Variant" /> - <argument index="0" name="property" type="String" /> + <argument index="0" name="property" type="StringName" /> <description> Returns the [Variant] value of the given [code]property[/code]. If the [code]property[/code] doesn't exist, this will return [code]null[/code]. [b]Note:[/b] In C#, the property name must be specified as snake_case if it is defined by a built-in Godot node. This doesn't apply to user-defined properties where you should use the same convention as in the C# source (typically PascalCase). @@ -399,7 +399,7 @@ </method> <method name="get_signal_connection_list" qualifiers="const"> <return type="Array" /> - <argument index="0" name="signal" type="String" /> + <argument index="0" name="signal" type="StringName" /> <description> Returns an [Array] of connections for the given [code]signal[/code]. </description> @@ -490,7 +490,7 @@ </method> <method name="set"> <return type="void" /> - <argument index="0" name="property" type="String" /> + <argument index="0" name="property" type="StringName" /> <argument index="1" name="value" type="Variant" /> <description> Assigns a new value to the given property. If the [code]property[/code] does not exist or the given value's type doesn't match, nothing will happen. diff --git a/editor/editor_properties.cpp b/editor/editor_properties.cpp index ddf1974070..a5c02c70d9 100644 --- a/editor/editor_properties.cpp +++ b/editor/editor_properties.cpp @@ -1597,6 +1597,18 @@ void EditorPropertyVector2::_value_changed(double val, const String &p_name) { return; } + if (linked->is_pressed()) { + setting = true; + if (p_name == "x") { + spin[1]->set_value(spin[0]->get_value() * ratio_yx); + } + + if (p_name == "y") { + spin[0]->set_value(spin[1]->get_value() * ratio_xy); + } + setting = false; + } + Vector2 v2; v2.x = spin[0]->get_value(); v2.y = spin[1]->get_value(); @@ -1609,12 +1621,28 @@ void EditorPropertyVector2::update_property() { spin[0]->set_value(val.x); spin[1]->set_value(val.y); setting = false; + _update_ratio(); +} + +void EditorPropertyVector2::_update_ratio() { + linked->set_modulate(Color(1, 1, 1, linked->is_pressed() ? 1.0 : 0.5)); + + if (spin[0]->get_value() != 0 && spin[1]->get_value() != 0) { + ratio_xy = spin[0]->get_value() / spin[1]->get_value(); + ratio_yx = spin[1]->get_value() / spin[0]->get_value(); + } else { + ratio_xy = 1.0; + ratio_yx = 1.0; + } } void EditorPropertyVector2::_notification(int p_what) { switch (p_what) { case NOTIFICATION_ENTER_TREE: case NOTIFICATION_THEME_CHANGED: { + linked->set_normal_texture(get_theme_icon(SNAME("Unlinked"), SNAME("EditorIcons"))); + linked->set_pressed_texture(get_theme_icon(SNAME("Instance"), SNAME("EditorIcons"))); + const Color *colors = _get_property_colors(); for (int i = 0; i < 2; i++) { spin[i]->add_theme_color_override("label_color", colors[i]); @@ -1623,10 +1651,7 @@ void EditorPropertyVector2::_notification(int p_what) { } } -void EditorPropertyVector2::_bind_methods() { -} - -void EditorPropertyVector2::setup(double p_min, double p_max, double p_step, bool p_no_slider, const String &p_suffix) { +void EditorPropertyVector2::setup(double p_min, double p_max, double p_step, bool p_no_slider, bool p_link, const String &p_suffix) { for (int i = 0; i < 2; i++) { spin[i]->set_min(p_min); spin[i]->set_max(p_max); @@ -1636,24 +1661,34 @@ void EditorPropertyVector2::setup(double p_min, double p_max, double p_step, boo spin[i]->set_allow_lesser(true); spin[i]->set_suffix(p_suffix); } + + if (!p_link) { + linked->hide(); + } else { + linked->set_pressed(true); + } } EditorPropertyVector2::EditorPropertyVector2(bool p_force_wide) { bool horizontal = p_force_wide || bool(EDITOR_GET("interface/inspector/horizontal_vector2_editing")); + HBoxContainer *hb = memnew(HBoxContainer); + hb->set_h_size_flags(SIZE_EXPAND_FILL); + BoxContainer *bc; if (p_force_wide) { bc = memnew(HBoxContainer); - add_child(bc); + hb->add_child(bc); } else if (horizontal) { bc = memnew(HBoxContainer); - add_child(bc); - set_bottom_editor(bc); + hb->add_child(bc); + set_bottom_editor(hb); } else { bc = memnew(VBoxContainer); - add_child(bc); + hb->add_child(bc); } + bc->set_h_size_flags(SIZE_EXPAND_FILL); static const char *desc[2] = { "x", "y" }; for (int i = 0; i < 2; i++) { @@ -1668,6 +1703,13 @@ EditorPropertyVector2::EditorPropertyVector2(bool p_force_wide) { } } + linked = memnew(TextureButton); + linked->set_toggle_mode(true); + linked->set_stretch_mode(TextureButton::STRETCH_KEEP_CENTERED); + linked->connect(SNAME("pressed"), callable_mp(this, &EditorPropertyVector2::_update_ratio)); + hb->add_child(linked); + + add_child(hb); if (!horizontal) { set_label_reference(spin[0]); //show text and buttons around this } @@ -1789,6 +1831,25 @@ void EditorPropertyVector3::_value_changed(double val, const String &p_name) { return; } + if (linked->is_pressed()) { + setting = true; + if (p_name == "x") { + spin[1]->set_value(spin[0]->get_value() * ratio_yx); + spin[2]->set_value(spin[0]->get_value() * ratio_zx); + } + + if (p_name == "y") { + spin[0]->set_value(spin[1]->get_value() * ratio_xy); + spin[2]->set_value(spin[1]->get_value() * ratio_zy); + } + + if (p_name == "z") { + spin[0]->set_value(spin[2]->get_value() * ratio_xz); + spin[1]->set_value(spin[2]->get_value() * ratio_yz); + } + setting = false; + } + Vector3 v3; v3.x = spin[0]->get_value(); v3.y = spin[1]->get_value(); @@ -1803,6 +1864,27 @@ void EditorPropertyVector3::_value_changed(double val, const String &p_name) { void EditorPropertyVector3::update_property() { update_using_vector(get_edited_object()->get(get_edited_property())); + _update_ratio(); +} + +void EditorPropertyVector3::_update_ratio() { + linked->set_modulate(Color(1, 1, 1, linked->is_pressed() ? 1.0 : 0.5)); + + if (spin[0]->get_value() != 0 && spin[1]->get_value() != 0) { + ratio_yx = spin[1]->get_value() / spin[0]->get_value(); + ratio_zx = spin[2]->get_value() / spin[0]->get_value(); + ratio_xy = spin[0]->get_value() / spin[1]->get_value(); + ratio_zy = spin[2]->get_value() / spin[1]->get_value(); + ratio_xz = spin[0]->get_value() / spin[2]->get_value(); + ratio_yz = spin[1]->get_value() / spin[2]->get_value(); + } else { + ratio_yx = 1.0; + ratio_zx = 1.0; + ratio_xy = 1.0; + ratio_zy = 1.0; + ratio_xz = 1.0; + ratio_yz = 1.0; + } } void EditorPropertyVector3::update_using_vector(Vector3 p_vector) { @@ -1836,6 +1918,9 @@ void EditorPropertyVector3::_notification(int p_what) { switch (p_what) { case NOTIFICATION_ENTER_TREE: case NOTIFICATION_THEME_CHANGED: { + linked->set_normal_texture(get_theme_icon(SNAME("Unlinked"), SNAME("EditorIcons"))); + linked->set_pressed_texture(get_theme_icon(SNAME("Instance"), SNAME("EditorIcons"))); + const Color *colors = _get_property_colors(); for (int i = 0; i < 3; i++) { spin[i]->add_theme_color_override("label_color", colors[i]); @@ -1847,7 +1932,7 @@ void EditorPropertyVector3::_notification(int p_what) { void EditorPropertyVector3::_bind_methods() { } -void EditorPropertyVector3::setup(double p_min, double p_max, double p_step, bool p_no_slider, const String &p_suffix, bool p_angle_in_radians) { +void EditorPropertyVector3::setup(double p_min, double p_max, double p_step, bool p_no_slider, bool p_link, const String &p_suffix, bool p_angle_in_radians) { angle_in_radians = p_angle_in_radians; for (int i = 0; i < 3; i++) { spin[i]->set_min(p_min); @@ -1858,24 +1943,34 @@ void EditorPropertyVector3::setup(double p_min, double p_max, double p_step, boo spin[i]->set_allow_lesser(true); spin[i]->set_suffix(p_suffix); } + + if (!p_link) { + linked->hide(); + } else { + linked->set_pressed(true); + } } EditorPropertyVector3::EditorPropertyVector3(bool p_force_wide) { bool horizontal = p_force_wide || bool(EDITOR_GET("interface/inspector/horizontal_vector_types_editing")); + HBoxContainer *hb = memnew(HBoxContainer); + hb->set_h_size_flags(SIZE_EXPAND_FILL); + BoxContainer *bc; if (p_force_wide) { bc = memnew(HBoxContainer); - add_child(bc); + hb->add_child(bc); } else if (horizontal) { bc = memnew(HBoxContainer); - add_child(bc); - set_bottom_editor(bc); + hb->add_child(bc); + set_bottom_editor(hb); } else { bc = memnew(VBoxContainer); - add_child(bc); + hb->add_child(bc); } + bc->set_h_size_flags(SIZE_EXPAND_FILL); static const char *desc[3] = { "x", "y", "z" }; for (int i = 0; i < 3; i++) { @@ -1890,6 +1985,13 @@ EditorPropertyVector3::EditorPropertyVector3(bool p_force_wide) { } } + linked = memnew(TextureButton); + linked->set_toggle_mode(true); + linked->set_stretch_mode(TextureButton::STRETCH_KEEP_CENTERED); + linked->connect(SNAME("pressed"), callable_mp(this, &EditorPropertyVector3::_update_ratio)); + hb->add_child(linked); + + add_child(hb); if (!horizontal) { set_label_reference(spin[0]); //show text and buttons around this } @@ -1908,6 +2010,18 @@ void EditorPropertyVector2i::_value_changed(double val, const String &p_name) { return; } + if (linked->is_pressed()) { + setting = true; + if (p_name == "x") { + spin[1]->set_value(spin[0]->get_value() * ratio_yx); + } + + if (p_name == "y") { + spin[0]->set_value(spin[1]->get_value() * ratio_xy); + } + setting = false; + } + Vector2i v2; v2.x = spin[0]->get_value(); v2.y = spin[1]->get_value(); @@ -1920,12 +2034,28 @@ void EditorPropertyVector2i::update_property() { spin[0]->set_value(val.x); spin[1]->set_value(val.y); setting = false; + _update_ratio(); +} + +void EditorPropertyVector2i::_update_ratio() { + linked->set_modulate(Color(1, 1, 1, linked->is_pressed() ? 1.0 : 0.5)); + + if (spin[0]->get_value() != 0 && spin[1]->get_value() != 0) { + ratio_xy = spin[0]->get_value() / spin[1]->get_value(); + ratio_yx = spin[1]->get_value() / spin[0]->get_value(); + } else { + ratio_xy = 1.0; + ratio_yx = 1.0; + } } void EditorPropertyVector2i::_notification(int p_what) { switch (p_what) { case NOTIFICATION_ENTER_TREE: case NOTIFICATION_THEME_CHANGED: { + linked->set_normal_texture(get_theme_icon(SNAME("Unlinked"), SNAME("EditorIcons"))); + linked->set_pressed_texture(get_theme_icon(SNAME("Instance"), SNAME("EditorIcons"))); + const Color *colors = _get_property_colors(); for (int i = 0; i < 2; i++) { spin[i]->add_theme_color_override("label_color", colors[i]); @@ -1934,10 +2064,7 @@ void EditorPropertyVector2i::_notification(int p_what) { } } -void EditorPropertyVector2i::_bind_methods() { -} - -void EditorPropertyVector2i::setup(int p_min, int p_max, bool p_no_slider, const String &p_suffix) { +void EditorPropertyVector2i::setup(int p_min, int p_max, bool p_no_slider, bool p_link, const String &p_suffix) { for (int i = 0; i < 2; i++) { spin[i]->set_min(p_min); spin[i]->set_max(p_max); @@ -1947,24 +2074,34 @@ void EditorPropertyVector2i::setup(int p_min, int p_max, bool p_no_slider, const spin[i]->set_allow_lesser(true); spin[i]->set_suffix(p_suffix); } + + if (!p_link) { + linked->hide(); + } else { + linked->set_pressed(true); + } } EditorPropertyVector2i::EditorPropertyVector2i(bool p_force_wide) { bool horizontal = p_force_wide || bool(EDITOR_GET("interface/inspector/horizontal_vector2_editing")); + HBoxContainer *hb = memnew(HBoxContainer); + hb->set_h_size_flags(SIZE_EXPAND_FILL); + BoxContainer *bc; if (p_force_wide) { bc = memnew(HBoxContainer); - add_child(bc); + hb->add_child(bc); } else if (horizontal) { bc = memnew(HBoxContainer); - add_child(bc); - set_bottom_editor(bc); + hb->add_child(bc); + set_bottom_editor(hb); } else { bc = memnew(VBoxContainer); - add_child(bc); + hb->add_child(bc); } + bc->set_h_size_flags(SIZE_EXPAND_FILL); static const char *desc[2] = { "x", "y" }; for (int i = 0; i < 2; i++) { @@ -1979,6 +2116,13 @@ EditorPropertyVector2i::EditorPropertyVector2i(bool p_force_wide) { } } + linked = memnew(TextureButton); + linked->set_toggle_mode(true); + linked->set_stretch_mode(TextureButton::STRETCH_KEEP_CENTERED); + linked->connect(SNAME("pressed"), callable_mp(this, &EditorPropertyVector2i::_update_ratio)); + hb->add_child(linked); + + add_child(hb); if (!horizontal) { set_label_reference(spin[0]); //show text and buttons around this } @@ -2100,6 +2244,25 @@ void EditorPropertyVector3i::_value_changed(double val, const String &p_name) { return; } + if (linked->is_pressed()) { + setting = true; + if (p_name == "x") { + spin[1]->set_value(spin[0]->get_value() * ratio_yx); + spin[2]->set_value(spin[0]->get_value() * ratio_zx); + } + + if (p_name == "y") { + spin[0]->set_value(spin[1]->get_value() * ratio_xy); + spin[2]->set_value(spin[1]->get_value() * ratio_zy); + } + + if (p_name == "z") { + spin[0]->set_value(spin[2]->get_value() * ratio_xz); + spin[1]->set_value(spin[2]->get_value() * ratio_yz); + } + setting = false; + } + Vector3i v3; v3.x = spin[0]->get_value(); v3.y = spin[1]->get_value(); @@ -2114,12 +2277,36 @@ void EditorPropertyVector3i::update_property() { spin[1]->set_value(val.y); spin[2]->set_value(val.z); setting = false; + _update_ratio(); +} + +void EditorPropertyVector3i::_update_ratio() { + linked->set_modulate(Color(1, 1, 1, linked->is_pressed() ? 1.0 : 0.5)); + + if (spin[0]->get_value() != 0 && spin[1]->get_value() != 0) { + ratio_yx = spin[1]->get_value() / spin[0]->get_value(); + ratio_zx = spin[2]->get_value() / spin[0]->get_value(); + ratio_xy = spin[0]->get_value() / spin[1]->get_value(); + ratio_zy = spin[2]->get_value() / spin[1]->get_value(); + ratio_xz = spin[0]->get_value() / spin[2]->get_value(); + ratio_yz = spin[1]->get_value() / spin[2]->get_value(); + } else { + ratio_yx = 1.0; + ratio_zx = 1.0; + ratio_xy = 1.0; + ratio_zy = 1.0; + ratio_xz = 1.0; + ratio_yz = 1.0; + } } void EditorPropertyVector3i::_notification(int p_what) { switch (p_what) { case NOTIFICATION_ENTER_TREE: case NOTIFICATION_THEME_CHANGED: { + linked->set_normal_texture(get_theme_icon(SNAME("Unlinked"), SNAME("EditorIcons"))); + linked->set_pressed_texture(get_theme_icon(SNAME("Instance"), SNAME("EditorIcons"))); + const Color *colors = _get_property_colors(); for (int i = 0; i < 3; i++) { spin[i]->add_theme_color_override("label_color", colors[i]); @@ -2131,7 +2318,7 @@ void EditorPropertyVector3i::_notification(int p_what) { void EditorPropertyVector3i::_bind_methods() { } -void EditorPropertyVector3i::setup(int p_min, int p_max, bool p_no_slider, const String &p_suffix) { +void EditorPropertyVector3i::setup(int p_min, int p_max, bool p_no_slider, bool p_link, const String &p_suffix) { for (int i = 0; i < 3; i++) { spin[i]->set_min(p_min); spin[i]->set_max(p_max); @@ -2141,22 +2328,31 @@ void EditorPropertyVector3i::setup(int p_min, int p_max, bool p_no_slider, const spin[i]->set_allow_lesser(true); spin[i]->set_suffix(p_suffix); } + + if (!p_link) { + linked->hide(); + } else { + linked->set_pressed(true); + } } EditorPropertyVector3i::EditorPropertyVector3i(bool p_force_wide) { bool horizontal = p_force_wide || bool(EDITOR_GET("interface/inspector/horizontal_vector_types_editing")); + HBoxContainer *hb = memnew(HBoxContainer); + hb->set_h_size_flags(SIZE_EXPAND_FILL); + BoxContainer *bc; if (p_force_wide) { bc = memnew(HBoxContainer); - add_child(bc); + hb->add_child(bc); } else if (horizontal) { bc = memnew(HBoxContainer); - add_child(bc); - set_bottom_editor(bc); + hb->add_child(bc); + set_bottom_editor(hb); } else { bc = memnew(VBoxContainer); - add_child(bc); + hb->add_child(bc); } static const char *desc[3] = { "x", "y", "z" }; @@ -2171,7 +2367,15 @@ EditorPropertyVector3i::EditorPropertyVector3i(bool p_force_wide) { spin[i]->set_h_size_flags(SIZE_EXPAND_FILL); } } + bc->set_h_size_flags(SIZE_EXPAND_FILL); + + linked = memnew(TextureButton); + linked->set_toggle_mode(true); + linked->set_stretch_mode(TextureButton::STRETCH_KEEP_CENTERED); + linked->connect(SNAME("pressed"), callable_mp(this, &EditorPropertyVector3i::_update_ratio)); + hb->add_child(linked); + add_child(hb); if (!horizontal) { set_label_reference(spin[0]); //show text and buttons around this } @@ -3608,14 +3812,14 @@ EditorProperty *EditorInspectorDefaultPlugin::get_editor_for_property(Object *p_ EditorPropertyVector2 *editor = memnew(EditorPropertyVector2(p_wide)); EditorPropertyRangeHint hint = _parse_range_hint(p_hint, p_hint_text, default_float_step); - editor->setup(hint.min, hint.max, hint.step, hint.hide_slider, hint.suffix); + editor->setup(hint.min, hint.max, hint.step, hint.hide_slider, p_hint == PROPERTY_HINT_LINK, hint.suffix); return editor; } break; case Variant::VECTOR2I: { EditorPropertyVector2i *editor = memnew(EditorPropertyVector2i(p_wide)); EditorPropertyRangeHint hint = _parse_range_hint(p_hint, p_hint_text, 1); - editor->setup(hint.min, hint.max, hint.hide_slider, hint.suffix); + editor->setup(hint.min, hint.max, hint.hide_slider, p_hint == PROPERTY_HINT_LINK, hint.suffix); return editor; } break; @@ -3635,14 +3839,14 @@ EditorProperty *EditorInspectorDefaultPlugin::get_editor_for_property(Object *p_ case Variant::VECTOR3: { EditorPropertyVector3 *editor = memnew(EditorPropertyVector3(p_wide)); EditorPropertyRangeHint hint = _parse_range_hint(p_hint, p_hint_text, default_float_step); - editor->setup(hint.min, hint.max, hint.step, hint.hide_slider, hint.suffix, hint.radians); + editor->setup(hint.min, hint.max, hint.step, hint.hide_slider, p_hint == PROPERTY_HINT_LINK, hint.suffix, hint.radians); return editor; } break; case Variant::VECTOR3I: { EditorPropertyVector3i *editor = memnew(EditorPropertyVector3i(p_wide)); EditorPropertyRangeHint hint = _parse_range_hint(p_hint, p_hint_text, 1); - editor->setup(hint.min, hint.max, hint.hide_slider, hint.suffix); + editor->setup(hint.min, hint.max, hint.hide_slider, p_hint == PROPERTY_HINT_LINK, hint.suffix); return editor; } break; diff --git a/editor/editor_properties.h b/editor/editor_properties.h index 6513eb0390..a3b98b7724 100644 --- a/editor/editor_properties.h +++ b/editor/editor_properties.h @@ -451,16 +451,19 @@ class EditorPropertyVector2 : public EditorProperty { GDCLASS(EditorPropertyVector2, EditorProperty); EditorSpinSlider *spin[2]; bool setting = false; + double ratio_xy = 1.0; + double ratio_yx = 1.0; + TextureButton *linked = nullptr; + void _update_ratio(); void _value_changed(double p_val, const String &p_name); protected: virtual void _set_read_only(bool p_read_only) override; void _notification(int p_what); - static void _bind_methods(); public: virtual void update_property() override; - void setup(double p_min, double p_max, double p_step, bool p_no_slider, const String &p_suffix = String()); + void setup(double p_min, double p_max, double p_step, bool p_no_slider, bool p_link = false, const String &p_suffix = String()); EditorPropertyVector2(bool p_force_wide = false); }; @@ -486,6 +489,14 @@ class EditorPropertyVector3 : public EditorProperty { EditorSpinSlider *spin[3]; bool setting = false; bool angle_in_radians = false; + double ratio_yx = 1.0; + double ratio_zx = 1.0; + double ratio_xy = 1.0; + double ratio_zy = 1.0; + double ratio_xz = 1.0; + double ratio_yz = 1.0; + TextureButton *linked = nullptr; + void _update_ratio(); void _value_changed(double p_val, const String &p_name); protected: @@ -497,7 +508,7 @@ public: virtual void update_property() override; virtual void update_using_vector(Vector3 p_vector); virtual Vector3 get_vector(); - void setup(double p_min, double p_max, double p_step, bool p_no_slider, const String &p_suffix = String(), bool p_angle_in_radians = false); + void setup(double p_min, double p_max, double p_step, bool p_no_slider, bool p_link = false, const String &p_suffix = String(), bool p_angle_in_radians = false); EditorPropertyVector3(bool p_force_wide = false); }; @@ -505,16 +516,19 @@ class EditorPropertyVector2i : public EditorProperty { GDCLASS(EditorPropertyVector2i, EditorProperty); EditorSpinSlider *spin[2]; bool setting = false; + double ratio_xy = 1.0; + double ratio_yx = 1.0; + TextureButton *linked = nullptr; + void _update_ratio(); void _value_changed(double p_val, const String &p_name); protected: virtual void _set_read_only(bool p_read_only) override; void _notification(int p_what); - static void _bind_methods(); public: virtual void update_property() override; - void setup(int p_min, int p_max, bool p_no_slider, const String &p_suffix = String()); + void setup(int p_min, int p_max, bool p_no_slider, bool p_link = false, const String &p_suffix = String()); EditorPropertyVector2i(bool p_force_wide = false); }; @@ -539,6 +553,14 @@ class EditorPropertyVector3i : public EditorProperty { GDCLASS(EditorPropertyVector3i, EditorProperty); EditorSpinSlider *spin[3]; bool setting = false; + double ratio_yx = 1.0; + double ratio_zx = 1.0; + double ratio_xy = 1.0; + double ratio_zy = 1.0; + double ratio_xz = 1.0; + double ratio_yz = 1.0; + TextureButton *linked = nullptr; + void _update_ratio(); void _value_changed(double p_val, const String &p_name); protected: @@ -548,7 +570,7 @@ protected: public: virtual void update_property() override; - void setup(int p_min, int p_max, bool p_no_slider, const String &p_suffix = String()); + void setup(int p_min, int p_max, bool p_no_slider, bool p_link = false, const String &p_suffix = String()); EditorPropertyVector3i(bool p_force_wide = false); }; diff --git a/editor/icons/Unlinked.svg b/editor/icons/Unlinked.svg new file mode 100644 index 0000000000..6c831eacad --- /dev/null +++ b/editor/icons/Unlinked.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16"><defs><clipPath id="a"><path d="M0 0h16v16H0z"/></clipPath></defs><g clip-path="url(#a)" fill="#e0e0e0"><path d="M1.136 12.036a3.994 3.994 0 0 1-.137-1.047 4.007 4.007 0 0 1 2.965-3.853 1 1 0 0 1 1.225.707 1 1 0 0 1 .034.25 1 1 0 0 1-.741.975 2 2 0 0 0-1.483 1.926 1.994 1.994 0 0 0 .068.523 2 2 0 0 0 2.45 1.415 2 2 0 0 0 1.484-1.931 2 2 0 0 0-.068-.523 1 1 0 0 1-.034-.25 1 1 0 0 1 .742-.975 1 1 0 0 1 1.225.707 3.991 3.991 0 0 1 .137 1.046 4.007 4.007 0 0 1-2.965 3.852 3.993 3.993 0 0 1-1.035.137 4.006 4.006 0 0 1-3.867-2.959zM9.965 8.863a1 1 0 0 1-.742-.975 1 1 0 0 1 .034-.25 1 1 0 0 1 1.225-.706 2 2 0 0 0 2.449-1.415A1.994 1.994 0 0 0 13 4.994a2 2 0 0 0-1.483-1.926 2 2 0 0 0-2.45 1.414 1 1 0 0 1-1.224.707 1 1 0 0 1-.742-.975 1 1 0 0 1 .034-.25 4 4 0 0 1 4.9-2.829A4.008 4.008 0 0 1 15 4.988a3.993 3.993 0 0 1-.137 1.047 4.006 4.006 0 0 1-3.862 2.966 3.989 3.989 0 0 1-1.036-.138zM5.5 4a.5.5 0 0 1-.5-.5v-2a.5.5 0 0 1 .5-.5.5.5 0 0 1 .5.5v2a.5.5 0 0 1-.5.5zM4.5 5a.5.5 0 0 1-.354-.146l-2-2a.5.5 0 0 1 0-.707.5.5 0 0 1 .707 0l2 2A.5.5 0 0 1 4.5 5zM3.5 6h-2a.5.5 0 0 1-.5-.5.5.5 0 0 1 .5-.5h2a.5.5 0 0 1 .5.5.5.5 0 0 1-.5.5z"/></g></svg> diff --git a/editor/plugins/canvas_item_editor_plugin.cpp b/editor/plugins/canvas_item_editor_plugin.cpp index 83b0d74dd2..1ea0299d4e 100644 --- a/editor/plugins/canvas_item_editor_plugin.cpp +++ b/editor/plugins/canvas_item_editor_plugin.cpp @@ -1289,7 +1289,7 @@ void CanvasItemEditor::_zoom_callback(Vector2 p_scroll_vec, Vector2 p_origin, bo zoom_widget->set_zoom_by_increments(-scroll_sign, p_alt); if (!Math::is_equal_approx(ABS(p_scroll_vec.y), (real_t)1.0)) { // Handle high-precision (analog) scrolling. - zoom_widget->set_zoom(zoom * ((zoom_widget->get_zoom() / zoom - 1.f) * p_scroll_vec.y + 1.f)); + zoom_widget->set_zoom(zoom * ((zoom_widget->get_zoom() / zoom - 1.f) * ABS(p_scroll_vec.y) + 1.f)); } _zoom_on_position(zoom_widget->get_zoom(), p_origin); } diff --git a/modules/navigation/rvo_agent.cpp b/modules/navigation/rvo_agent.cpp index a6a5660c0c..4ec72ad43f 100644 --- a/modules/navigation/rvo_agent.cpp +++ b/modules/navigation/rvo_agent.cpp @@ -65,8 +65,9 @@ void RvoAgent::dispatch_callback() { return; } Object *obj = ObjectDB::get_instance(callback.id); - if (obj == nullptr) { + if (!obj) { callback.id = ObjectID(); + return; } Callable::CallError responseCallError; diff --git a/platform/javascript/SCsub b/platform/javascript/SCsub index 8d9ba82fd4..4827dc4627 100644 --- a/platform/javascript/SCsub +++ b/platform/javascript/SCsub @@ -37,6 +37,8 @@ for ext in env["JS_EXTERNS"]: build = [] if env["gdnative_enabled"]: build_targets = ["#bin/godot${PROGSUFFIX}.js", "#bin/godot${PROGSUFFIX}.wasm"] + if env["threads_enabled"]: + build_targets.append("#bin/godot${PROGSUFFIX}.worker.js") # Reset libraries. The main runtime will only link emscripten libraries, not godot ones. sys_env["LIBS"] = [] # We use IDBFS. Since Emscripten 1.39.1 it needs to be linked explicitly. @@ -58,7 +60,7 @@ if env["gdnative_enabled"]: wasm_env.Append(CCFLAGS=["-s", "SIDE_MODULE=2"]) wasm_env.Append(LINKFLAGS=["-s", "SIDE_MODULE=2"]) wasm = wasm_env.add_program("#bin/godot.side${PROGSUFFIX}.wasm", javascript_files) - build = [sys[0], sys[1], wasm[0]] + build = sys + [wasm[0]] else: build_targets = ["#bin/godot${PROGSUFFIX}.js", "#bin/godot${PROGSUFFIX}.wasm"] if env["threads_enabled"]: @@ -87,5 +89,5 @@ wrap_list = [ js_wrapped = env.Textfile("#bin/godot", [env.File(f) for f in wrap_list], TEXTFILESUFFIX="${PROGSUFFIX}.wrapped.js") # Extra will be the thread worker, or the GDNative side, or None -extra = build[2] if len(build) > 2 else None +extra = build[2:] if len(build) > 2 else None env.CreateTemplateZip(js_wrapped, build[1], extra) diff --git a/platform/javascript/detect.py b/platform/javascript/detect.py index 4a9652fc1c..15fd63811c 100644 --- a/platform/javascript/detect.py +++ b/platform/javascript/detect.py @@ -185,10 +185,6 @@ def configure(env): if env["javascript_eval"]: env.Append(CPPDEFINES=["JAVASCRIPT_EVAL_ENABLED"]) - if env["threads_enabled"] and env["gdnative_enabled"]: - print("Threads and GDNative support can't be both enabled due to WebAssembly limitations") - sys.exit(255) - # Thread support (via SharedArrayBuffer). if env["threads_enabled"]: env.Append(CPPDEFINES=["PTHREAD_NO_RENAME"]) @@ -201,10 +197,21 @@ def configure(env): env.Append(CPPDEFINES=["NO_THREADS"]) if env["gdnative_enabled"]: - major, minor, patch = get_compiler_version(env) + emcc_version = get_compiler_version(env) + major = int(emcc_version["major"]) + minor = int(emcc_version["minor"]) + patch = int(emcc_version["patch"]) if major < 2 or (major == 2 and minor == 0 and patch < 10): print("GDNative support requires emscripten >= 2.0.10, detected: %s.%s.%s" % (major, minor, patch)) sys.exit(255) + if ( + env["threads_enabled"] + and major < 3 + or (major == 3 and minor < 1) + or (major == 3 and minor == 1 and patch < 14) + ): + print("Threads and GDNative requires emscripten => 3.1.14, detected: %s.%s.%s" % (major, minor, patch)) + sys.exit(255) env.Append(CCFLAGS=["-s", "RELOCATABLE=1"]) env.Append(LINKFLAGS=["-s", "RELOCATABLE=1"]) # Weak symbols are broken upstream: https://github.com/emscripten-core/emscripten/issues/12819 diff --git a/platform/javascript/emscripten_helpers.py b/platform/javascript/emscripten_helpers.py index 4dad2d5204..3cb1d75e52 100644 --- a/platform/javascript/emscripten_helpers.py +++ b/platform/javascript/emscripten_helpers.py @@ -52,10 +52,10 @@ def create_template_zip(env, js, wasm, extra): ] # GDNative/Threads specific if env["gdnative_enabled"]: - in_files.append(extra) # Runtime + in_files.append(extra.pop()) # Runtime out_files.append(zip_dir.File(binary_name + ".side.wasm")) - elif env["threads_enabled"]: - in_files.append(extra) # Worker + if env["threads_enabled"]: + in_files.append(extra.pop()) # Worker out_files.append(zip_dir.File(binary_name + ".worker.js")) service_worker = "#misc/dist/html/service-worker.js" diff --git a/platform/javascript/export/export_plugin.cpp b/platform/javascript/export/export_plugin.cpp index 128834c90f..901580c140 100644 --- a/platform/javascript/export/export_plugin.cpp +++ b/platform/javascript/export/export_plugin.cpp @@ -215,7 +215,7 @@ Error EditorExportPlatformJavaScript::_build_pwa(const Ref<EditorExportPreset> & cache_files.push_back(name + ".icon.png"); cache_files.push_back(name + ".apple-touch-icon.png"); } - if (mode == EXPORT_MODE_THREADS) { + if (mode & EXPORT_MODE_THREADS) { cache_files.push_back(name + ".worker.js"); cache_files.push_back(name + ".audio.worklet.js"); } @@ -225,7 +225,7 @@ Error EditorExportPlatformJavaScript::_build_pwa(const Ref<EditorExportPreset> & Array opt_cache_files; opt_cache_files.push_back(name + ".wasm"); opt_cache_files.push_back(name + ".pck"); - if (mode == EXPORT_MODE_GDNATIVE) { + if (mode & EXPORT_MODE_GDNATIVE) { opt_cache_files.push_back(name + ".side.wasm"); for (int i = 0; i < p_shared_objects.size(); i++) { opt_cache_files.push_back(p_shared_objects[i].path.get_file()); @@ -317,9 +317,10 @@ void EditorExportPlatformJavaScript::get_preset_features(const Ref<EditorExportP } } ExportMode mode = (ExportMode)(int)p_preset->get("variant/export_type"); - if (mode == EXPORT_MODE_THREADS) { + if (mode & EXPORT_MODE_THREADS) { r_features->push_back("threads"); - } else if (mode == EXPORT_MODE_GDNATIVE) { + } + if (mode & EXPORT_MODE_GDNATIVE) { r_features->push_back("wasm32"); } } diff --git a/platform/javascript/export/export_plugin.h b/platform/javascript/export/export_plugin.h index 2d6cbfde38..1aaec5454d 100644 --- a/platform/javascript/export/export_plugin.h +++ b/platform/javascript/export/export_plugin.h @@ -61,19 +61,16 @@ class EditorExportPlatformJavaScript : public EditorExportPlatform { EXPORT_MODE_NORMAL = 0, EXPORT_MODE_THREADS = 1, EXPORT_MODE_GDNATIVE = 2, + EXPORT_MODE_THREADS_GDNATIVE = 3, }; String _get_template_name(ExportMode p_mode, bool p_debug) const { String name = "webassembly"; - switch (p_mode) { - case EXPORT_MODE_THREADS: - name += "_threads"; - break; - case EXPORT_MODE_GDNATIVE: - name += "_gdnative"; - break; - default: - break; + if (p_mode & EXPORT_MODE_GDNATIVE) { + name += "_gdnative"; + } + if (p_mode & EXPORT_MODE_THREADS) { + name += "_threads"; } if (p_debug) { name += "_debug.zip"; diff --git a/scene/2d/node_2d.cpp b/scene/2d/node_2d.cpp index 6fa18d393e..b2b848d380 100644 --- a/scene/2d/node_2d.cpp +++ b/scene/2d/node_2d.cpp @@ -439,7 +439,7 @@ void Node2D::_bind_methods() { ADD_GROUP("Transform", ""); ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "position", PROPERTY_HINT_RANGE, "-99999,99999,0.001,or_lesser,or_greater,noslider,suffix:px"), "set_position", "get_position"); ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "rotation", PROPERTY_HINT_RANGE, "-360,360,0.1,or_lesser,or_greater,radians"), "set_rotation", "get_rotation"); - ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "scale"), "set_scale", "get_scale"); + ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "scale", PROPERTY_HINT_LINK), "set_scale", "get_scale"); ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "skew", PROPERTY_HINT_RANGE, "-89.9,89.9,0.1,radians"), "set_skew", "get_skew"); ADD_PROPERTY(PropertyInfo(Variant::TRANSFORM2D, "transform", PROPERTY_HINT_NONE, "suffix:px", PROPERTY_USAGE_NONE), "set_transform", "get_transform"); diff --git a/scene/3d/lightmap_gi.cpp b/scene/3d/lightmap_gi.cpp index 5c63bdcf1d..9d1d8721e6 100644 --- a/scene/3d/lightmap_gi.cpp +++ b/scene/3d/lightmap_gi.cpp @@ -73,7 +73,7 @@ void LightmapGIData::clear_users() { } void LightmapGIData::_set_user_data(const Array &p_data) { - ERR_FAIL_COND(p_data.size() <= 0); + ERR_FAIL_COND(p_data.is_empty()); ERR_FAIL_COND((p_data.size() % 4) != 0); for (int i = 0; i < p_data.size(); i += 4) { @@ -92,6 +92,95 @@ Array LightmapGIData::_get_user_data() const { return ret; } +void LightmapGIData::_set_light_textures_data(const Array &p_data) { + ERR_FAIL_COND(p_data.is_empty()); + + if (p_data.size() == 1) { + set_light_texture(p_data[0]); + } else { + Vector<Ref<Image>> images; + for (int i = 0; i < p_data.size(); i++) { + Ref<TextureLayered> texture = p_data[i]; + for (int j = 0; j < texture->get_layers(); j++) { + images.push_back(texture->get_layer_data(j)); + } + } + + Ref<Texture2DArray> combined_texture; + combined_texture.instantiate(); + + combined_texture->create_from_images(images); + set_light_texture(combined_texture); + } +} + +Array LightmapGIData::_get_light_textures_data() const { + Array ret; + if (light_texture.is_null()) { + return ret; + } + + Vector<Ref<Image>> images; + for (int i = 0; i < light_texture->get_layers(); i++) { + images.push_back(light_texture->get_layer_data(i)); + } + + int slice_count = images.size(); + int slice_width = images[0]->get_width(); + int slice_height = images[0]->get_height(); + + int slices_per_texture = Image::MAX_HEIGHT / slice_height; + int texture_count = Math::ceil(slice_count / (float)slices_per_texture); + + ret.resize(texture_count); + + String base_name = get_path().get_basename(); + + int last_count = slice_count % slices_per_texture; + for (int i = 0; i < texture_count; i++) { + int texture_slice_count = (i == texture_count - 1 && last_count != 0) ? last_count : slices_per_texture; + + Ref<Image> texture_image; + texture_image.instantiate(); + + texture_image->create(slice_width, slice_height * texture_slice_count, false, images[0]->get_format()); + + for (int j = 0; j < texture_slice_count; j++) { + texture_image->blit_rect(images[i * slices_per_texture + j], Rect2(0, 0, slice_width, slice_height), Point2(0, slice_height * j)); + } + + String texture_path = texture_count > 1 ? base_name + "_" + itos(i) + ".exr" : base_name + ".exr"; + + Ref<ConfigFile> config; + config.instantiate(); + + if (FileAccess::exists(texture_path + ".import")) { + config->load(texture_path + ".import"); + } + + config->set_value("remap", "importer", "2d_array_texture"); + config->set_value("remap", "type", "CompressedTexture2DArray"); + if (!config->has_section_key("params", "compress/mode")) { + config->set_value("params", "compress/mode", 2); //user may want another compression, so leave it be + } + config->set_value("params", "compress/channel_pack", 1); + config->set_value("params", "mipmaps/generate", false); + config->set_value("params", "slices/horizontal", 1); + config->set_value("params", "slices/vertical", texture_slice_count); + + config->save(texture_path + ".import"); + + Error err = texture_image->save_exr(texture_path, false); + ERR_FAIL_COND_V(err, ret); + ResourceLoader::import(texture_path); + Ref<TextureLayered> t = ResourceLoader::load(texture_path); //if already loaded, it will be updated on refocus? + ERR_FAIL_COND_V(t.is_null(), ret); + ret[i] = t; + } + + return ret; +} + RID LightmapGIData::get_rid() const { return lightmap; } @@ -188,6 +277,9 @@ void LightmapGIData::_bind_methods() { ClassDB::bind_method(D_METHOD("set_light_texture", "light_texture"), &LightmapGIData::set_light_texture); ClassDB::bind_method(D_METHOD("get_light_texture"), &LightmapGIData::get_light_texture); + ClassDB::bind_method(D_METHOD("_set_light_textures_data", "data"), &LightmapGIData::_set_light_textures_data); + ClassDB::bind_method(D_METHOD("_get_light_textures_data"), &LightmapGIData::_get_light_textures_data); + ClassDB::bind_method(D_METHOD("set_uses_spherical_harmonics", "uses_spherical_harmonics"), &LightmapGIData::set_uses_spherical_harmonics); ClassDB::bind_method(D_METHOD("is_using_spherical_harmonics"), &LightmapGIData::is_using_spherical_harmonics); @@ -199,7 +291,8 @@ void LightmapGIData::_bind_methods() { ClassDB::bind_method(D_METHOD("_set_probe_data", "data"), &LightmapGIData::_set_probe_data); ClassDB::bind_method(D_METHOD("_get_probe_data"), &LightmapGIData::_get_probe_data); - ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "light_texture", PROPERTY_HINT_RESOURCE_TYPE, "TextureLayered"), "set_light_texture", "get_light_texture"); + ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "light_texture", PROPERTY_HINT_RESOURCE_TYPE, "TextureLayered", PROPERTY_USAGE_EDITOR | PROPERTY_USAGE_NETWORK), "set_light_texture", "get_light_texture"); // property usage default but no save + ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "light_textures", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR | PROPERTY_USAGE_INTERNAL), "_set_light_textures_data", "_get_light_textures_data"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "uses_spherical_harmonics", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR | PROPERTY_USAGE_INTERNAL), "set_uses_spherical_harmonics", "is_using_spherical_harmonics"); ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "user_data", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR | PROPERTY_USAGE_INTERNAL), "_set_user_data", "_get_user_data"); ADD_PROPERTY(PropertyInfo(Variant::DICTIONARY, "probe_data", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR | PROPERTY_USAGE_INTERNAL), "_set_probe_data", "_get_probe_data"); @@ -953,53 +1046,6 @@ LightmapGI::BakeError LightmapGI::bake(Node *p_from_node, String p_image_data_pa return BAKE_ERROR_MESHES_INVALID; } - /* POSTBAKE: Save Textures */ - - Ref<TextureLayered> texture; - { - Vector<Ref<Image>> images; - for (int i = 0; i < lightmapper->get_bake_texture_count(); i++) { - images.push_back(lightmapper->get_bake_texture(i)); - } - //we assume they are all the same, so let's create a large one for saving - Ref<Image> large_image; - large_image.instantiate(); - - large_image->create(images[0]->get_width(), images[0]->get_height() * images.size(), false, images[0]->get_format()); - - for (int i = 0; i < lightmapper->get_bake_texture_count(); i++) { - large_image->blit_rect(images[i], Rect2(0, 0, images[i]->get_width(), images[i]->get_height()), Point2(0, images[i]->get_height() * i)); - } - - String base_path = p_image_data_path.get_basename() + ".exr"; - - Ref<ConfigFile> config; - - config.instantiate(); - if (FileAccess::exists(base_path + ".import")) { - config->load(base_path + ".import"); - } - - config->set_value("remap", "importer", "2d_array_texture"); - config->set_value("remap", "type", "CompressedTexture2DArray"); - if (!config->has_section_key("params", "compress/mode")) { - config->set_value("params", "compress/mode", 2); //user may want another compression, so leave it be - } - config->set_value("params", "compress/channel_pack", 1); - config->set_value("params", "mipmaps/generate", false); - config->set_value("params", "slices/horizontal", 1); - config->set_value("params", "slices/vertical", images.size()); - - config->save(base_path + ".import"); - - Error err = large_image->save_exr(base_path, false); - ERR_FAIL_COND_V(err, BAKE_ERROR_CANT_CREATE_IMAGE); - ResourceLoader::import(base_path); - Ref<Texture> t = ResourceLoader::load(base_path); //if already loaded, it will be updated on refocus? - ERR_FAIL_COND_V(t.is_null(), BAKE_ERROR_CANT_CREATE_IMAGE); - texture = t; - } - /* POSTBAKE: Save Light Data */ Ref<LightmapGIData> data; @@ -1011,6 +1057,17 @@ LightmapGI::BakeError LightmapGI::bake(Node *p_from_node, String p_image_data_pa data.instantiate(); } + Ref<Texture2DArray> texture; + { + Vector<Ref<Image>> images; + for (int i = 0; i < lightmapper->get_bake_texture_count(); i++) { + images.push_back(lightmapper->get_bake_texture(i)); + } + + texture.instantiate(); + texture->create_from_images(images); + } + data->set_light_texture(texture); data->set_uses_spherical_harmonics(directional); @@ -1161,8 +1218,8 @@ LightmapGI::BakeError LightmapGI::bake(Node *p_from_node, String p_image_data_pa /* Compute a BSP tree of the simplices, so it's easy to find the exact one */ } - Error err = ResourceSaver::save(p_image_data_path, data); data->set_path(p_image_data_path); + Error err = ResourceSaver::save(p_image_data_path, data); if (err != OK) { return BAKE_ERROR_CANT_CREATE_IMAGE; diff --git a/scene/3d/lightmap_gi.h b/scene/3d/lightmap_gi.h index d29d7a7c28..b39cde429d 100644 --- a/scene/3d/lightmap_gi.h +++ b/scene/3d/lightmap_gi.h @@ -61,6 +61,8 @@ class LightmapGIData : public Resource { Array _get_user_data() const; void _set_probe_data(const Dictionary &p_data); Dictionary _get_probe_data() const; + void _set_light_textures_data(const Array &p_data); + Array _get_light_textures_data() const; protected: static void _bind_methods(); diff --git a/scene/3d/node_3d.cpp b/scene/3d/node_3d.cpp index a76d57a09f..6e36815f2b 100644 --- a/scene/3d/node_3d.cpp +++ b/scene/3d/node_3d.cpp @@ -984,7 +984,7 @@ void Node3D::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "rotation", PROPERTY_HINT_RANGE, "-360,360,0.1,or_lesser,or_greater,radians", PROPERTY_USAGE_EDITOR), "set_rotation", "get_rotation"); ADD_PROPERTY(PropertyInfo(Variant::QUATERNION, "quaternion", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_EDITOR), "set_quaternion", "get_quaternion"); ADD_PROPERTY(PropertyInfo(Variant::BASIS, "basis", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_EDITOR), "set_basis", "get_basis"); - ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "scale", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_EDITOR), "set_scale", "get_scale"); + ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "scale", PROPERTY_HINT_LINK, "", PROPERTY_USAGE_EDITOR), "set_scale", "get_scale"); ADD_PROPERTY(PropertyInfo(Variant::INT, "rotation_edit_mode", PROPERTY_HINT_ENUM, "Euler,Quaternion,Basis"), "set_rotation_edit_mode", "get_rotation_edit_mode"); ADD_PROPERTY(PropertyInfo(Variant::INT, "rotation_order", PROPERTY_HINT_ENUM, "XYZ,XZY,YXZ,YZX,ZXY,ZYX"), "set_rotation_order", "get_rotation_order"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "top_level"), "set_as_top_level", "is_set_as_top_level"); diff --git a/scene/gui/control.cpp b/scene/gui/control.cpp index 3db1719226..5ddc38a0b9 100644 --- a/scene/gui/control.cpp +++ b/scene/gui/control.cpp @@ -478,6 +478,10 @@ void Control::_validate_property(PropertyInfo &property) const { } } + if (property.name == "scale") { + property.hint = PROPERTY_HINT_LINK; + } + // Validate which positioning properties should be displayed depending on the parent and the layout mode. Node *parent_node = get_parent_control(); if (!parent_node) { |