summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--core/core_constants.cpp1
-rw-r--r--core/object/object.cpp6
-rw-r--r--core/object/object.h7
-rw-r--r--doc/classes/@GlobalScope.xml79
-rw-r--r--doc/classes/NavigationServer2D.xml3
-rw-r--r--doc/classes/NavigationServer3D.xml3
-rw-r--r--doc/classes/Object.xml6
-rw-r--r--editor/editor_properties.cpp264
-rw-r--r--editor/editor_properties.h34
-rw-r--r--editor/icons/Unlinked.svg1
-rw-r--r--editor/plugins/canvas_item_editor_plugin.cpp2
-rw-r--r--modules/navigation/rvo_agent.cpp3
-rw-r--r--platform/javascript/SCsub6
-rw-r--r--platform/javascript/detect.py15
-rw-r--r--platform/javascript/emscripten_helpers.py6
-rw-r--r--platform/javascript/export/export_plugin.cpp9
-rw-r--r--platform/javascript/export/export_plugin.h15
-rw-r--r--scene/2d/camera_2d.cpp2
-rw-r--r--scene/2d/node_2d.cpp2
-rw-r--r--scene/2d/parallax_background.cpp2
-rw-r--r--scene/2d/parallax_layer.cpp2
-rw-r--r--scene/2d/polygon_2d.cpp7
-rw-r--r--scene/3d/lightmap_gi.cpp157
-rw-r--r--scene/3d/lightmap_gi.h2
-rw-r--r--scene/3d/node_3d.cpp2
-rw-r--r--scene/gui/control.cpp4
-rw-r--r--scene/main/canvas_layer.cpp2
-rw-r--r--scene/resources/material.cpp4
-rw-r--r--thirdparty/README.md2
-rw-r--r--thirdparty/vulkan/vk_mem_alloc.h150
30 files changed, 526 insertions, 272 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/NavigationServer2D.xml b/doc/classes/NavigationServer2D.xml
index 7b0dac99c3..cd9f54caaa 100644
--- a/doc/classes/NavigationServer2D.xml
+++ b/doc/classes/NavigationServer2D.xml
@@ -44,7 +44,8 @@
<argument index="2" name="method" type="StringName" />
<argument index="3" name="userdata" type="Variant" default="null" />
<description>
- Callback called at the end of the RVO process.
+ Callback called at the end of the RVO process. If a callback is created manually and the agent is placed on a navigation map it will calculate avoidance for the agent and dispatch the calculated [code]safe_velocity[/code] to the [code]receiver[/code] object with a signal to the chosen [code]method[/code] name.
+ [b]Note:[/b] Created callbacks are always processed independently of the SceneTree state as long as the agent is on a navigation map and not freed. To disable the dispatch of a callback from an agent use [method agent_set_callback] again with a [code]null[/code] object as the [code]receiver[/code].
</description>
</method>
<method name="agent_set_map" qualifiers="const">
diff --git a/doc/classes/NavigationServer3D.xml b/doc/classes/NavigationServer3D.xml
index d6574dd69a..9ef0f0d631 100644
--- a/doc/classes/NavigationServer3D.xml
+++ b/doc/classes/NavigationServer3D.xml
@@ -44,7 +44,8 @@
<argument index="2" name="method" type="StringName" />
<argument index="3" name="userdata" type="Variant" default="null" />
<description>
- Callback called at the end of the RVO process.
+ Callback called at the end of the RVO process. If a callback is created manually and the agent is placed on a navigation map it will calculate avoidance for the agent and dispatch the calculated [code]safe_velocity[/code] to the [code]receiver[/code] object with a signal to the chosen [code]method[/code] name.
+ [b]Note:[/b] Created callbacks are always processed independently of the SceneTree state as long as the agent is on a navigation map and not freed. To disable the dispatch of a callback from an agent use [method agent_set_callback] again with a [code]null[/code] object as the [code]receiver[/code].
</description>
</method>
<method name="agent_set_map" qualifiers="const">
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..a769260f01 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,9 +197,14 @@ def configure(env):
env.Append(CPPDEFINES=["NO_THREADS"])
if env["gdnative_enabled"]:
- major, minor, patch = get_compiler_version(env)
- 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))
+ cc_version = get_compiler_version(env)
+ cc_semver = (int(cc_version["major"]), int(cc_version["minor"]), int(cc_version["patch"]))
+ if cc_semver < (2, 0, 10):
+ print("GDNative support requires emscripten >= 2.0.10, detected: %s.%s.%s" % cc_semver)
+ sys.exit(255)
+
+ if env["threads_enabled"] and cc_semver < (3, 1, 14):
+ print("Threads and GDNative requires emscripten >= 3.1.14, detected: %s.%s.%s" % cc_semver)
sys.exit(255)
env.Append(CCFLAGS=["-s", "RELOCATABLE=1"])
env.Append(LINKFLAGS=["-s", "RELOCATABLE=1"])
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/camera_2d.cpp b/scene/2d/camera_2d.cpp
index 30a32e3891..2616d1f09e 100644
--- a/scene/2d/camera_2d.cpp
+++ b/scene/2d/camera_2d.cpp
@@ -733,7 +733,7 @@ void Camera2D::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::INT, "anchor_mode", PROPERTY_HINT_ENUM, "Fixed TopLeft,Drag Center"), "set_anchor_mode", "get_anchor_mode");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "rotating"), "set_rotating", "is_rotating");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "current"), "set_current", "is_current");
- ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "zoom"), "set_zoom", "get_zoom");
+ ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "zoom", PROPERTY_HINT_LINK), "set_zoom", "get_zoom");
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "custom_viewport", PROPERTY_HINT_RESOURCE_TYPE, "Viewport", PROPERTY_USAGE_NONE), "set_custom_viewport", "get_custom_viewport");
ADD_PROPERTY(PropertyInfo(Variant::INT, "process_callback", PROPERTY_HINT_ENUM, "Physics,Idle"), "set_process_callback", "get_process_callback");
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/2d/parallax_background.cpp b/scene/2d/parallax_background.cpp
index 506761d959..bd5a01f5a4 100644
--- a/scene/2d/parallax_background.cpp
+++ b/scene/2d/parallax_background.cpp
@@ -179,7 +179,7 @@ void ParallaxBackground::_bind_methods() {
ADD_GROUP("Scroll", "scroll_");
ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "scroll_offset", PROPERTY_HINT_NONE, "suffix:px"), "set_scroll_offset", "get_scroll_offset");
ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "scroll_base_offset", PROPERTY_HINT_NONE, "suffix:px"), "set_scroll_base_offset", "get_scroll_base_offset");
- ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "scroll_base_scale"), "set_scroll_base_scale", "get_scroll_base_scale");
+ ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "scroll_base_scale", PROPERTY_HINT_LINK), "set_scroll_base_scale", "get_scroll_base_scale");
ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "scroll_limit_begin", PROPERTY_HINT_NONE, "suffix:px"), "set_limit_begin", "get_limit_begin");
ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "scroll_limit_end", PROPERTY_HINT_NONE, "suffix:px"), "set_limit_end", "get_limit_end");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "scroll_ignore_camera_zoom"), "set_ignore_camera_zoom", "is_ignore_camera_zoom");
diff --git a/scene/2d/parallax_layer.cpp b/scene/2d/parallax_layer.cpp
index d716f01a82..f0aad1b8a4 100644
--- a/scene/2d/parallax_layer.cpp
+++ b/scene/2d/parallax_layer.cpp
@@ -158,7 +158,7 @@ void ParallaxLayer::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_mirroring"), &ParallaxLayer::get_mirroring);
ADD_GROUP("Motion", "motion_");
- ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "motion_scale"), "set_motion_scale", "get_motion_scale");
+ ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "motion_scale", PROPERTY_HINT_LINK), "set_motion_scale", "get_motion_scale");
ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "motion_offset", PROPERTY_HINT_NONE, "suffix:px"), "set_motion_offset", "get_motion_offset");
ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "motion_mirroring"), "set_mirroring", "get_mirroring");
}
diff --git a/scene/2d/polygon_2d.cpp b/scene/2d/polygon_2d.cpp
index 40858fedca..ba62941d3a 100644
--- a/scene/2d/polygon_2d.cpp
+++ b/scene/2d/polygon_2d.cpp
@@ -635,12 +635,13 @@ void Polygon2D::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::COLOR, "color"), "set_color", "get_color");
ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "offset"), "set_offset", "get_offset");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "antialiased"), "set_antialiased", "get_antialiased");
- ADD_GROUP("Texture2D", "");
+
+ ADD_GROUP("Texture", "texture_");
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "texture", PROPERTY_HINT_RESOURCE_TYPE, "Texture2D"), "set_texture", "get_texture");
- ADD_GROUP("Texture2D", "texture_");
ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "texture_offset", PROPERTY_HINT_NONE, "suffix:px"), "set_texture_offset", "get_texture_offset");
- ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "texture_scale"), "set_texture_scale", "get_texture_scale");
+ ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "texture_scale", PROPERTY_HINT_LINK), "set_texture_scale", "get_texture_scale");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "texture_rotation", PROPERTY_HINT_RANGE, "-360,360,0.1,or_lesser,or_greater,radians"), "set_texture_rotation", "get_texture_rotation");
+
ADD_GROUP("Skeleton", "");
ADD_PROPERTY(PropertyInfo(Variant::NODE_PATH, "skeleton", PROPERTY_HINT_NODE_PATH_VALID_TYPES, "Skeleton2D"), "set_skeleton", "get_skeleton");
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) {
diff --git a/scene/main/canvas_layer.cpp b/scene/main/canvas_layer.cpp
index dbd771bf9c..3a071ef542 100644
--- a/scene/main/canvas_layer.cpp
+++ b/scene/main/canvas_layer.cpp
@@ -330,7 +330,7 @@ void CanvasLayer::_bind_methods() {
ADD_GROUP("Transform", "");
ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "offset", PROPERTY_HINT_NONE, "suffix:px"), "set_offset", "get_offset");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "rotation", PROPERTY_HINT_RANGE, "-1080,1080,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::TRANSFORM2D, "transform", PROPERTY_HINT_NONE, "suffix:px"), "set_transform", "get_transform");
ADD_GROUP("", "");
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "custom_viewport", PROPERTY_HINT_RESOURCE_TYPE, "Viewport", PROPERTY_USAGE_NONE), "set_custom_viewport", "get_custom_viewport");
diff --git a/scene/resources/material.cpp b/scene/resources/material.cpp
index fb50b2d779..bbaaebd22a 100644
--- a/scene/resources/material.cpp
+++ b/scene/resources/material.cpp
@@ -2655,14 +2655,14 @@ void BaseMaterial3D::_bind_methods() {
ADD_PROPERTYI(PropertyInfo(Variant::OBJECT, "detail_normal", PROPERTY_HINT_RESOURCE_TYPE, "Texture2D"), "set_texture", "get_texture", TEXTURE_DETAIL_NORMAL);
ADD_GROUP("UV1", "uv1_");
- ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "uv1_scale"), "set_uv1_scale", "get_uv1_scale");
+ ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "uv1_scale", PROPERTY_HINT_LINK), "set_uv1_scale", "get_uv1_scale");
ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "uv1_offset"), "set_uv1_offset", "get_uv1_offset");
ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "uv1_triplanar"), "set_flag", "get_flag", FLAG_UV1_USE_TRIPLANAR);
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "uv1_triplanar_sharpness", PROPERTY_HINT_EXP_EASING), "set_uv1_triplanar_blend_sharpness", "get_uv1_triplanar_blend_sharpness");
ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "uv1_world_triplanar"), "set_flag", "get_flag", FLAG_UV1_USE_WORLD_TRIPLANAR);
ADD_GROUP("UV2", "uv2_");
- ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "uv2_scale"), "set_uv2_scale", "get_uv2_scale");
+ ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "uv2_scale", PROPERTY_HINT_LINK), "set_uv2_scale", "get_uv2_scale");
ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "uv2_offset"), "set_uv2_offset", "get_uv2_offset");
ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "uv2_triplanar"), "set_flag", "get_flag", FLAG_UV2_USE_TRIPLANAR);
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "uv2_triplanar_sharpness", PROPERTY_HINT_EXP_EASING), "set_uv2_triplanar_blend_sharpness", "get_uv2_triplanar_blend_sharpness");
diff --git a/thirdparty/README.md b/thirdparty/README.md
index 595a9a85ce..3b6932b3e1 100644
--- a/thirdparty/README.md
+++ b/thirdparty/README.md
@@ -709,7 +709,7 @@ Files extracted from upstream source:
SDK release: https://github.com/KhronosGroup/Vulkan-ValidationLayers/blob/master/layers/generated/vk_enum_string_helper.h
`vk_mem_alloc.h` is taken from https://github.com/GPUOpen-LibrariesAndSDKs/VulkanMemoryAllocator
-Version: 3.0.1-development (2022-03-28), commit `5b598e0a359381d7e2a94149210a1b7642024ae5`
+Version: 3.0.1 (2022-06-10), commit `cfdc0f8775ab3258a3b9c4e47d8ce4b6f52a5441`
`vk_mem_alloc.cpp` is a Godot file and should be preserved on updates.
Patches in the `patches` directory should be re-applied after updates.
diff --git a/thirdparty/vulkan/vk_mem_alloc.h b/thirdparty/vulkan/vk_mem_alloc.h
index d96f2dacc0..184ee005d8 100644
--- a/thirdparty/vulkan/vk_mem_alloc.h
+++ b/thirdparty/vulkan/vk_mem_alloc.h
@@ -25,7 +25,7 @@
/** \mainpage Vulkan Memory Allocator
-<b>Version 3.0.1-development (2022-03-28)</b>
+<b>Version 3.0.1 (2022-05-26)</b>
Copyright (c) 2017-2022 Advanced Micro Devices, Inc. All rights reserved. \n
License: MIT
@@ -300,9 +300,9 @@ extern "C" {
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
-//
+//
// INTERFACE
-//
+//
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
@@ -488,7 +488,7 @@ typedef enum VmaMemoryUsage
When using this flag, if you want to map the allocation (using vmaMapMemory() or #VMA_ALLOCATION_CREATE_MAPPED_BIT),
you must pass one of the flags: #VMA_ALLOCATION_CREATE_HOST_ACCESS_SEQUENTIAL_WRITE_BIT or #VMA_ALLOCATION_CREATE_HOST_ACCESS_RANDOM_BIT
in VmaAllocationCreateInfo::flags.
-
+
It can be used only with functions that let the library know `VkBufferCreateInfo` or `VkImageCreateInfo`, e.g.
vmaCreateBuffer(), vmaCreateImage(), vmaFindMemoryTypeIndexForBufferInfo(), vmaFindMemoryTypeIndexForImageInfo()
and not with generic memory allocation functions.
@@ -552,7 +552,7 @@ typedef enum VmaAllocationCreateFlagBits
*/
VMA_ALLOCATION_CREATE_MAPPED_BIT = 0x00000004,
/** \deprecated Preserved for backward compatibility. Consider using vmaSetAllocationName() instead.
-
+
Set this flag to treat VmaAllocationCreateInfo::pUserData as pointer to a
null-terminated string. Instead of copying pointer value, a local copy of the
string is made and stored in allocation's `pName`. The string is automatically
@@ -579,14 +579,14 @@ typedef enum VmaAllocationCreateFlagBits
*/
VMA_ALLOCATION_CREATE_WITHIN_BUDGET_BIT = 0x00000100,
/** \brief Set this flag if the allocated memory will have aliasing resources.
-
+
Usage of this flag prevents supplying `VkMemoryDedicatedAllocateInfoKHR` when #VMA_ALLOCATION_CREATE_DEDICATED_MEMORY_BIT is specified.
Otherwise created dedicated memory will not be suitable for aliasing resources, resulting in Vulkan Validation Layer errors.
*/
VMA_ALLOCATION_CREATE_CAN_ALIAS_BIT = 0x00000200,
/**
Requests possibility to map the allocation (using vmaMapMemory() or #VMA_ALLOCATION_CREATE_MAPPED_BIT).
-
+
- If you use #VMA_MEMORY_USAGE_AUTO or other `VMA_MEMORY_USAGE_AUTO*` value,
you must use this flag to be able to map the allocation. Otherwise, mapping is incorrect.
- If you use other value of #VmaMemoryUsage, this flag is ignored and mapping is always possible in memory types that are `HOST_VISIBLE`.
@@ -602,7 +602,7 @@ typedef enum VmaAllocationCreateFlagBits
VMA_ALLOCATION_CREATE_HOST_ACCESS_SEQUENTIAL_WRITE_BIT = 0x00000400,
/**
Requests possibility to map the allocation (using vmaMapMemory() or #VMA_ALLOCATION_CREATE_MAPPED_BIT).
-
+
- If you use #VMA_MEMORY_USAGE_AUTO or other `VMA_MEMORY_USAGE_AUTO*` value,
you must use this flag to be able to map the allocation. Otherwise, mapping is incorrect.
- If you use other value of #VmaMemoryUsage, this flag is ignored and mapping is always possible in memory types that are `HOST_VISIBLE`.
@@ -724,7 +724,7 @@ typedef enum VmaDefragmentationFlagBits
VMA_DEFRAGMENTATION_FLAG_ALGORITHM_EXTENSIVE_BIT = 0x8,
/// A bit mask to extract only `ALGORITHM` bits from entire set of flags.
- VMA_DEFRAGMENTATION_FLAG_ALGORITHM_MASK =
+ VMA_DEFRAGMENTATION_FLAG_ALGORITHM_MASK =
VMA_DEFRAGMENTATION_FLAG_ALGORITHM_FAST_BIT |
VMA_DEFRAGMENTATION_FLAG_ALGORITHM_BALANCED_BIT |
VMA_DEFRAGMENTATION_FLAG_ALGORITHM_FULL_BIT |
@@ -980,7 +980,7 @@ typedef struct VmaVulkanFunctions
#if VMA_DEDICATED_ALLOCATION || VMA_VULKAN_VERSION >= 1001000
/// Fetch "vkGetBufferMemoryRequirements2" on Vulkan >= 1.1, fetch "vkGetBufferMemoryRequirements2KHR" when using VK_KHR_dedicated_allocation extension.
PFN_vkGetBufferMemoryRequirements2KHR VMA_NULLABLE vkGetBufferMemoryRequirements2KHR;
- /// Fetch "vkGetImageMemoryRequirements 2" on Vulkan >= 1.1, fetch "vkGetImageMemoryRequirements2KHR" when using VK_KHR_dedicated_allocation extension.
+ /// Fetch "vkGetImageMemoryRequirements2" on Vulkan >= 1.1, fetch "vkGetImageMemoryRequirements2KHR" when using VK_KHR_dedicated_allocation extension.
PFN_vkGetImageMemoryRequirements2KHR VMA_NULLABLE vkGetImageMemoryRequirements2KHR;
#endif
#if VMA_BIND_MEMORY2 || VMA_VULKAN_VERSION >= 1001000
@@ -1117,19 +1117,19 @@ typedef struct VmaStatistics
*/
uint32_t blockCount;
/** \brief Number of #VmaAllocation objects allocated.
-
+
Dedicated allocations have their own blocks, so each one adds 1 to `allocationCount` as well as `blockCount`.
*/
uint32_t allocationCount;
/** \brief Number of bytes allocated in `VkDeviceMemory` blocks.
-
+
\note To avoid confusion, please be aware that what Vulkan calls an "allocation" - a whole `VkDeviceMemory` object
(e.g. as in `VkPhysicalDeviceLimits::maxMemoryAllocationCount`) is called a "block" in VMA, while VMA calls
"allocation" a #VmaAllocation object that represents a memory region sub-allocated from such block, usually for a single buffer or image.
*/
VkDeviceSize blockBytes;
/** \brief Total number of bytes occupied by all #VmaAllocation objects.
-
+
Always less or equal than `blockBytes`.
Difference `(blockBytes - allocationBytes)` is the amount of memory allocated from Vulkan
but unused by any #VmaAllocation.
@@ -1387,9 +1387,9 @@ typedef struct VmaAllocationInfo
*/
void* VMA_NULLABLE pUserData;
/** \brief Custom allocation name that was set with vmaSetAllocationName().
-
+
It can change after call to vmaSetAllocationName() for this allocation.
-
+
Another way to set custom name is to pass it in VmaAllocationCreateInfo::pUserData with
additional flag #VMA_ALLOCATION_CREATE_USER_DATA_COPY_STRING_BIT set [DEPRECATED].
*/
@@ -1429,7 +1429,7 @@ typedef struct VmaDefragmentationMove
/// Allocation that should be moved.
VmaAllocation VMA_NOT_NULL srcAllocation;
/** \brief Temporary allocation pointing to destination memory that will replace `srcAllocation`.
-
+
\warning Do not store this allocation in your data structures! It exists only temporarily, for the duration of the defragmentation pass,
to be used for binding new buffer/image to the destination memory using e.g. vmaBindBufferMemory().
vmaEndDefragmentationPass() will destroy it and make `srcAllocation` point to this memory.
@@ -1446,16 +1446,16 @@ typedef struct VmaDefragmentationPassMoveInfo
/// Number of elements in the `pMoves` array.
uint32_t moveCount;
/** \brief Array of moves to be performed by the user in the current defragmentation pass.
-
+
Pointer to an array of `moveCount` elements, owned by VMA, created in vmaBeginDefragmentationPass(), destroyed in vmaEndDefragmentationPass().
For each element, you should:
-
+
1. Create a new buffer/image in the place pointed by VmaDefragmentationMove::dstMemory + VmaDefragmentationMove::dstOffset.
2. Copy data from the VmaDefragmentationMove::srcAllocation e.g. using `vkCmdCopyBuffer`, `vkCmdCopyImage`.
3. Make sure these commands finished executing on the GPU.
4. Destroy the old buffer/image.
-
+
Only then you can finish defragmentation pass by calling vmaEndDefragmentationPass().
After this call, the allocation will point to the new place in memory.
@@ -1539,7 +1539,7 @@ typedef struct VmaVirtualAllocationCreateInfo
typedef struct VmaVirtualAllocationInfo
{
/** \brief Offset of the allocation.
-
+
Offset at which the allocation was made.
*/
VkDeviceSize offset;
@@ -2364,7 +2364,7 @@ vkDestroyBuffer(device, buffer, allocationCallbacks);
vmaFreeMemory(allocator, allocation);
\endcode
-It it safe to pass null as buffer and/or allocation.
+It is safe to pass null as buffer and/or allocation.
*/
VMA_CALL_PRE void VMA_CALL_POST vmaDestroyBuffer(
VmaAllocator VMA_NOT_NULL allocator,
@@ -2396,7 +2396,7 @@ vkDestroyImage(device, image, allocationCallbacks);
vmaFreeMemory(allocator, allocation);
\endcode
-It it safe to pass null as image and/or allocation.
+It is safe to pass null as image and/or allocation.
*/
VMA_CALL_PRE void VMA_CALL_POST vmaDestroyImage(
VmaAllocator VMA_NOT_NULL allocator,
@@ -2555,9 +2555,9 @@ VMA_CALL_PRE void VMA_CALL_POST vmaFreeStatsString(
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
-//
+//
// IMPLEMENTATION
-//
+//
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
@@ -2578,6 +2578,9 @@ VMA_CALL_PRE void VMA_CALL_POST vmaFreeStatsString(
#ifdef _MSC_VER
#include <intrin.h> // For functions like __popcnt, _BitScanForward etc.
#endif
+#if __cplusplus >= 202002L || _MSVC_LANG >= 202002L // C++20
+ #include <bit> // For std::popcount
+#endif
/*******************************************************************************
CONFIGURATION SECTION
@@ -3180,12 +3183,16 @@ But you need to check in runtime whether user's CPU supports these, as some old
*/
static inline uint32_t VmaCountBitsSet(uint32_t v)
{
+#if __cplusplus >= 202002L || _MSVC_LANG >= 202002L // C++20
+ return std::popcount(v);
+#else
uint32_t c = v - ((v >> 1) & 0x55555555);
c = ((c >> 2) & 0x33333333) + (c & 0x33333333);
c = ((c >> 4) + c) & 0x0F0F0F0F;
c = ((c >> 8) + c) & 0x00FF00FF;
c = ((c >> 16) + c) & 0x0000FFFF;
return c;
+#endif
}
static inline uint8_t VmaBitScanLSB(uint64_t mask)
@@ -3374,60 +3381,6 @@ static inline bool VmaStrIsEmpty(const char* pStr)
return pStr == VMA_NULL || *pStr == '\0';
}
-#if VMA_STATS_STRING_ENABLED
-static const char* VmaAlgorithmToStr(uint32_t algorithm)
-{
- switch (algorithm)
- {
- case VMA_POOL_CREATE_LINEAR_ALGORITHM_BIT:
- return "Linear";
- case 0:
- return "TLSF";
- default:
- VMA_ASSERT(0);
- return "";
- }
-}
-#endif // VMA_STATS_STRING_ENABLED
-
-#ifndef VMA_SORT
-template<typename Iterator, typename Compare>
-Iterator VmaQuickSortPartition(Iterator beg, Iterator end, Compare cmp)
-{
- Iterator centerValue = end; --centerValue;
- Iterator insertIndex = beg;
- for (Iterator memTypeIndex = beg; memTypeIndex < centerValue; ++memTypeIndex)
- {
- if (cmp(*memTypeIndex, *centerValue))
- {
- if (insertIndex != memTypeIndex)
- {
- VMA_SWAP(*memTypeIndex, *insertIndex);
- }
- ++insertIndex;
- }
- }
- if (insertIndex != centerValue)
- {
- VMA_SWAP(*insertIndex, *centerValue);
- }
- return insertIndex;
-}
-
-template<typename Iterator, typename Compare>
-void VmaQuickSort(Iterator beg, Iterator end, Compare cmp)
-{
- if (beg < end)
- {
- Iterator it = VmaQuickSortPartition<Iterator, Compare>(beg, end, cmp);
- VmaQuickSort<Iterator, Compare>(beg, it, cmp);
- VmaQuickSort<Iterator, Compare>(it + 1, end, cmp);
- }
-}
-
-#define VMA_SORT(beg, end, cmp) VmaQuickSort(beg, end, cmp)
-#endif // VMA_SORT
-
/*
Returns true if two memory blocks occupy overlapping pages.
ResourceA must be in less memory offset than ResourceB.
@@ -5073,7 +5026,7 @@ public:
VmaIntrusiveLinkedList& operator=(VmaIntrusiveLinkedList&& src);
VmaIntrusiveLinkedList& operator=(const VmaIntrusiveLinkedList&) = delete;
~VmaIntrusiveLinkedList() { VMA_HEAVY_ASSERT(IsEmpty()); }
-
+
size_t GetCount() const { return m_Count; }
bool IsEmpty() const { return m_Count == 0; }
ItemType* Front() { return m_Front; }
@@ -5485,7 +5438,7 @@ public:
// Writes a string value inside "".
// pStr can contain any ANSI characters, including '"', new line etc. - they will be properly escaped.
void WriteString(const char* pStr);
-
+
// Begins writing a string value.
// Call BeginString, ContinueString, ContinueString, ..., EndString instead of
// WriteString to conveniently build the string content incrementally, made of
@@ -6463,7 +6416,7 @@ void VmaBlockMetadata::DebugLogAllocation(VkDeviceSize offset, VkDeviceSize size
(uint32_t)allocation->GetSuballocationType());
#endif // VMA_STATS_STRING_ENABLED
}
-
+
}
#if VMA_STATS_STRING_ENABLED
@@ -10941,7 +10894,7 @@ public:
uint32_t GetAlgorithm() const { return m_Algorithm; }
bool HasExplicitBlockSize() const { return m_ExplicitBlockSize; }
float GetPriority() const { return m_Priority; }
- void* const GetAllocationNextPtr() const { return m_pMemoryAllocateNext; }
+ const void* GetAllocationNextPtr() const { return m_pMemoryAllocateNext; }
// To be used only while the m_Mutex is locked. Used during defragmentation.
size_t GetBlockCount() const { return m_Blocks.size(); }
// To be used only while the m_Mutex is locked. Used during defragmentation.
@@ -12783,7 +12736,7 @@ void VmaBlockVector::IncrementallySortBlocks()
void VmaBlockVector::SortByFreeSize()
{
VMA_SORT(m_Blocks.begin(), m_Blocks.end(),
- [](auto* b1, auto* b2)
+ [](VmaDeviceMemoryBlock* b1, VmaDeviceMemoryBlock* b2) -> bool
{
return b1->m_pMetadata->GetSumFreeSize() < b2->m_pMetadata->GetSumFreeSize();
});
@@ -13029,7 +12982,7 @@ VmaDefragmentationContext_T::VmaDefragmentationContext_T(
}
}
}
-
+
switch (m_Algorithm)
{
case 0: // Default algorithm
@@ -13155,7 +13108,7 @@ VkResult VmaDefragmentationContext_T::DefragmentPassEnd(VmaDefragmentationPassMo
vector = m_pBlockVectors[vectorIndex];
VMA_ASSERT(vector != VMA_NULL);
}
-
+
switch (move.operation)
{
case VMA_DEFRAGMENTATION_MOVE_OPERATION_COPY:
@@ -13452,7 +13405,7 @@ bool VmaDefragmentationContext_T::ReallocWithinBlock(VmaBlockVector& vector, Vma
case CounterStatus::Pass:
break;
}
-
+
VkDeviceSize offset = moveData.move.srcAllocation->GetOffset();
if (offset != 0 && metadata->GetSumFreeSize() >= moveData.size)
{
@@ -13636,7 +13589,7 @@ bool VmaDefragmentationContext_T::ComputeDefragmentation_Balanced(VmaBlockVector
prevFreeRegionSize = nextFreeRegionSize;
}
}
-
+
// No moves perfomed, update statistics to current vector state
if (startMoveCount == m_Moves.size() && !update)
{
@@ -13923,7 +13876,7 @@ void VmaDefragmentationContext_T::UpdateVectorStatistics(VmaBlockVector& vector,
state.avgFreeSize /= freeCount;
}
-bool VmaDefragmentationContext_T::MoveDataToFreeBlocks(VmaSuballocationType currentType,
+bool VmaDefragmentationContext_T::MoveDataToFreeBlocks(VmaSuballocationType currentType,
VmaBlockVector& vector, size_t firstFreeBlock,
bool& texturePresent, bool& bufferPresent, bool& otherPresent)
{
@@ -15919,6 +15872,7 @@ void VmaAllocator_T::UpdateVulkanBudget()
void VmaAllocator_T::FillAllocation(const VmaAllocation hAllocation, uint8_t pattern)
{
if(VMA_DEBUG_INITIALIZE_ALLOCATIONS &&
+ hAllocation->IsMappingAllowed() &&
(m_MemProps.memoryTypes[hAllocation->GetMemoryTypeIndex()].propertyFlags & VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT) != 0)
{
void* pData = VMA_NULL;
@@ -16010,8 +15964,8 @@ void VmaAllocator_T::PrintDetailedMap(VmaJsonWriter& json)
json.ContinueString_Size(index++);
if (pool->GetName())
{
- json.WriteString(" - ");
- json.WriteString(pool->GetName());
+ json.ContinueString(" - ");
+ json.ContinueString(pool->GetName());
}
json.EndString();
@@ -18427,7 +18381,7 @@ for(;;)
VmaAllocationInfo allocInfo;
vmaGetAllocationInfo(allocator, pMoves[i].srcAllocation, &allocInfo);
MyEngineResourceData* resData = (MyEngineResourceData*)allocInfo.pUserData;
-
+
// Recreate and bind this buffer/image at: pass.pMoves[i].dstMemory, pass.pMoves[i].dstOffset.
VkImageCreateInfo imgCreateInfo = ...
VkImage newImg;
@@ -18439,7 +18393,7 @@ for(;;)
// Issue a vkCmdCopyBuffer/vkCmdCopyImage to copy its content to the new place.
vkCmdCopyImage(cmdBuf, resData->img, ..., newImg, ...);
}
-
+
// Make sure the copy commands finished executing.
vkWaitForFences(...);
@@ -18451,7 +18405,7 @@ for(;;)
}
// Update appropriate descriptors to point to the new places...
-
+
res = vmaEndDefragmentationPass(allocator, defragCtx, &pass);
if(res == VK_SUCCESS)
break;
@@ -18605,7 +18559,7 @@ To do that, fill VmaAllocationCreateInfo::pUserData field when creating
an allocation. It is an opaque `void*` pointer. You can use it e.g. as a pointer,
some handle, index, key, ordinal number or any other value that would associate
the allocation with your custom metadata.
-It it useful to identify appropriate data structures in your engine given #VmaAllocation,
+It is useful to identify appropriate data structures in your engine given #VmaAllocation,
e.g. when doing \ref defragmentation.
\code
@@ -18836,14 +18790,14 @@ To do it, define macro `VMA_DEBUG_INITIALIZE_ALLOCATIONS` to 1.
#include "vk_mem_alloc.h"
\endcode
-It makes memory of all new allocations initialized to bit pattern `0xDCDCDCDC`.
+It makes memory of new allocations initialized to bit pattern `0xDCDCDCDC`.
Before an allocation is destroyed, its memory is filled with bit pattern `0xEFEFEFEF`.
Memory is automatically mapped and unmapped if necessary.
If you find these values while debugging your program, good chances are that you incorrectly
read Vulkan memory that is allocated but not initialized, or already freed, respectively.
-Memory initialization works only with memory types that are `HOST_VISIBLE`.
+Memory initialization works only with memory types that are `HOST_VISIBLE` and with allocations that can be mapped.
It works also with dedicated allocations.
\section debugging_memory_usage_margins Margins
@@ -19116,13 +19070,13 @@ so you need to create another "staging" allocation and perform explicit transfer
VkBufferCreateInfo bufCreateInfo = { VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO };
bufCreateInfo.size = 65536;
bufCreateInfo.usage = VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT;
-
+
VmaAllocationCreateInfo allocCreateInfo = {};
allocCreateInfo.usage = VMA_MEMORY_USAGE_AUTO;
allocCreateInfo.flags = VMA_ALLOCATION_CREATE_HOST_ACCESS_SEQUENTIAL_WRITE_BIT |
VMA_ALLOCATION_CREATE_HOST_ACCESS_ALLOW_TRANSFER_INSTEAD_BIT |
VMA_ALLOCATION_CREATE_MAPPED_BIT;
-
+
VkBuffer buf;
VmaAllocation alloc;
VmaAllocationInfo allocInfo;