summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.github/workflows/static_checks.yml2
-rw-r--r--core/core_constants.cpp1
-rw-r--r--core/extension/native_extension.cpp9
-rw-r--r--core/input/input_event.cpp18
-rw-r--r--core/object/object.cpp6
-rw-r--r--core/object/object.h7
-rw-r--r--core/string/ustring.cpp24
-rw-r--r--core/string/ustring.h4
-rw-r--r--core/variant/variant_call.cpp4
-rw-r--r--doc/classes/@GlobalScope.xml79
-rw-r--r--doc/classes/AnimationLibrary.xml8
-rw-r--r--doc/classes/BaseMaterial3D.xml1
-rw-r--r--doc/classes/Button.xml3
-rw-r--r--doc/classes/CurveTexture.xml8
-rw-r--r--doc/classes/CurveXYZTexture.xml7
-rw-r--r--doc/classes/FontData.xml14
-rw-r--r--doc/classes/GradientTexture1D.xml2
-rw-r--r--doc/classes/GradientTexture2D.xml2
-rw-r--r--doc/classes/LightmapGI.xml44
-rw-r--r--doc/classes/LightmapGIData.xml10
-rw-r--r--doc/classes/LightmapProbe.xml3
-rw-r--r--doc/classes/Lightmapper.xml3
-rw-r--r--doc/classes/LightmapperRD.xml3
-rw-r--r--doc/classes/MeshInstance2D.xml2
-rw-r--r--doc/classes/NavigationAgent2D.xml17
-rw-r--r--doc/classes/NavigationAgent3D.xml17
-rw-r--r--doc/classes/NavigationRegion2D.xml4
-rw-r--r--doc/classes/NavigationRegion3D.xml4
-rw-r--r--doc/classes/NavigationServer2D.xml33
-rw-r--r--doc/classes/NavigationServer3D.xml33
-rw-r--r--doc/classes/OS.xml5
-rw-r--r--doc/classes/Object.xml6
-rw-r--r--doc/classes/ProjectSettings.xml12
-rw-r--r--doc/classes/String.xml8
-rw-r--r--doc/classes/TextServer.xml22
-rw-r--r--doc/classes/TextServerExtension.xml22
-rw-r--r--doc/classes/TileData.xml6
-rw-r--r--doc/classes/TileMap.xml23
-rw-r--r--doc/classes/WorldEnvironment.xml1
-rwxr-xr-xdoc/tools/make_rst.py47
-rw-r--r--editor/debugger/editor_debugger_node.cpp72
-rw-r--r--editor/debugger/editor_debugger_node.h1
-rw-r--r--editor/debugger/script_editor_debugger.cpp2
-rw-r--r--editor/editor_node.cpp4
-rw-r--r--editor/editor_properties.cpp269
-rw-r--r--editor/editor_properties.h36
-rw-r--r--editor/editor_properties_array_dict.cpp78
-rw-r--r--editor/editor_properties_array_dict.h8
-rw-r--r--editor/editor_property_name_processor.cpp1
-rw-r--r--editor/editor_themes.cpp13
-rw-r--r--editor/editor_toaster.cpp14
-rw-r--r--editor/icons/TerrainConnect.svg1
-rw-r--r--editor/icons/TerrainPath.svg1
-rw-r--r--editor/icons/Unlinked.svg1
-rw-r--r--editor/import/dynamic_font_import_settings.cpp9
-rw-r--r--editor/import/resource_importer_dynamic_font.cpp7
-rw-r--r--editor/import/resource_importer_scene.cpp38
-rw-r--r--editor/import/resource_importer_texture.cpp6
-rw-r--r--editor/plugins/canvas_item_editor_plugin.cpp23
-rw-r--r--editor/plugins/tiles/tile_data_editors.cpp165
-rw-r--r--editor/plugins/tiles/tile_map_editor.cpp429
-rw-r--r--editor/plugins/tiles/tile_map_editor.h20
-rw-r--r--editor/plugins/tiles/tile_set_atlas_source_editor.cpp3
-rw-r--r--editor/plugins/tiles/tile_set_editor.cpp7
-rw-r--r--main/main.cpp22
-rwxr-xr-xmisc/hooks/pre-commit-make-rst2
-rw-r--r--modules/csg/csg_shape.cpp6
-rw-r--r--modules/gdscript/gdscript_compiler.cpp93
-rw-r--r--modules/gdscript/tests/scripts/parser/features/match_dictionary.gd43
-rw-r--r--modules/gdscript/tests/scripts/parser/features/match_dictionary.out15
-rw-r--r--modules/gdscript/tests/scripts/parser/features/match_multiple_patterns_with_array.gd26
-rw-r--r--modules/gdscript/tests/scripts/parser/features/match_multiple_patterns_with_array.out9
-rw-r--r--modules/gridmap/grid_map.cpp10
-rw-r--r--modules/gridmap/grid_map.h2
-rw-r--r--modules/mono/glue/GodotSharp/GodotSharp/Core/Attributes/AssemblyHasScriptsAttribute.cs10
-rw-r--r--modules/mono/glue/GodotSharp/GodotSharp/Core/Attributes/DisableGodotGeneratorsAttribute.cs3
-rw-r--r--modules/mono/glue/GodotSharp/GodotSharp/Core/Attributes/ExportAttribute.cs8
-rw-r--r--modules/mono/glue/GodotSharp/GodotSharp/Core/Attributes/GodotMethodAttribute.cs7
-rw-r--r--modules/mono/glue/GodotSharp/GodotSharp/Core/Attributes/RPCAttributes.cs6
-rw-r--r--modules/mono/glue/GodotSharp/GodotSharp/Core/Attributes/ScriptPathAttribute.cs7
-rw-r--r--modules/mono/glue/GodotSharp/GodotSharp/Core/Dispatcher.cs7
-rw-r--r--modules/mono/glue/GodotSharp/GodotSharp/Core/GodotSynchronizationContext.cs3
-rw-r--r--modules/mono/glue/GodotSharp/GodotSharp/Core/GodotTaskScheduler.cs21
-rw-r--r--modules/mono/glue/GodotSharp/GodotSharp/Core/Interfaces/IAwaitable.cs7
-rw-r--r--modules/mono/glue/GodotSharp/GodotSharp/Core/Interfaces/IAwaiter.cs7
-rw-r--r--modules/mono/glue/GodotSharp/GodotSharp/Core/Interfaces/ISerializationListener.cs3
-rw-r--r--modules/navigation/godot_navigation_server.cpp12
-rw-r--r--modules/navigation/godot_navigation_server.h6
-rw-r--r--modules/navigation/nav_map.cpp6
-rw-r--r--modules/navigation/nav_map.h2
-rw-r--r--modules/navigation/nav_region.cpp8
-rw-r--r--modules/navigation/nav_region.h6
-rw-r--r--modules/navigation/rvo_agent.cpp3
-rw-r--r--modules/noise/noise_texture.cpp4
-rw-r--r--modules/text_server_adv/text_server_adv.cpp77
-rw-r--r--modules/text_server_adv/text_server_adv.h6
-rw-r--r--modules/text_server_fb/text_server_fb.cpp74
-rw-r--r--modules/text_server_fb/text_server_fb.h6
-rw-r--r--modules/webrtc/doc_classes/WebRTCPeerConnection.xml7
-rw-r--r--modules/webrtc/doc_classes/WebRTCPeerConnectionExtension.xml5
-rw-r--r--modules/webrtc/webrtc_peer_connection.cpp7
-rw-r--r--modules/webrtc/webrtc_peer_connection_extension.cpp7
-rw-r--r--modules/webrtc/webrtc_peer_connection_extension.h2
-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/area_2d.cpp2
-rw-r--r--scene/2d/back_buffer_copy.cpp2
-rw-r--r--scene/2d/camera_2d.cpp14
-rw-r--r--scene/2d/canvas_group.cpp4
-rw-r--r--scene/2d/collision_polygon_2d.cpp2
-rw-r--r--scene/2d/cpu_particles_2d.cpp2
-rw-r--r--scene/2d/gpu_particles_2d.cpp4
-rw-r--r--scene/2d/navigation_agent_2d.cpp48
-rw-r--r--scene/2d/navigation_agent_2d.h10
-rw-r--r--scene/2d/navigation_region_2d.cpp14
-rw-r--r--scene/2d/navigation_region_2d.h4
-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/physics_body_2d.cpp6
-rw-r--r--scene/2d/polygon_2d.cpp9
-rw-r--r--scene/2d/shape_cast_2d.cpp4
-rw-r--r--scene/2d/tile_map.cpp609
-rw-r--r--scene/2d/tile_map.h38
-rw-r--r--scene/3d/area_3d.cpp2
-rw-r--r--scene/3d/fog_volume.cpp2
-rw-r--r--scene/3d/gpu_particles_3d.cpp2
-rw-r--r--scene/3d/gpu_particles_collision_3d.cpp2
-rw-r--r--scene/3d/joint_3d.cpp42
-rw-r--r--scene/3d/label_3d.cpp12
-rw-r--r--scene/3d/light_3d.cpp29
-rw-r--r--scene/3d/lightmap_gi.cpp157
-rw-r--r--scene/3d/lightmap_gi.h2
-rw-r--r--scene/3d/navigation_agent_3d.cpp48
-rw-r--r--scene/3d/navigation_agent_3d.h10
-rw-r--r--scene/3d/navigation_region_3d.cpp14
-rw-r--r--scene/3d/navigation_region_3d.h4
-rw-r--r--scene/3d/node_3d.cpp2
-rw-r--r--scene/3d/occluder_instance_3d.cpp8
-rw-r--r--scene/3d/physics_body_3d.cpp12
-rw-r--r--scene/3d/skeleton_ik_3d.cpp2
-rw-r--r--scene/3d/sprite_3d.cpp8
-rw-r--r--scene/3d/visual_instance_3d.cpp8
-rw-r--r--scene/3d/voxel_gi.cpp2
-rw-r--r--scene/animation/animation_blend_tree.cpp10
-rw-r--r--scene/animation/animation_node_state_machine.cpp2
-rw-r--r--scene/animation/animation_player.cpp2
-rw-r--r--scene/animation/root_motion_view.cpp4
-rw-r--r--scene/gui/button.cpp24
-rw-r--r--scene/gui/button.h4
-rw-r--r--scene/gui/control.cpp6
-rw-r--r--scene/gui/graph_edit.cpp8
-rw-r--r--scene/gui/graph_node.cpp2
-rw-r--r--scene/gui/item_list.cpp4
-rw-r--r--scene/gui/nine_patch_rect.cpp10
-rw-r--r--scene/gui/popup.cpp11
-rw-r--r--scene/gui/popup.h4
-rw-r--r--scene/gui/popup_menu.cpp25
-rw-r--r--scene/gui/popup_menu.h2
-rw-r--r--scene/gui/reference_rect.cpp2
-rw-r--r--scene/gui/rich_text_label.cpp25
-rw-r--r--scene/gui/scroll_bar.cpp2
-rw-r--r--scene/gui/scroll_container.cpp4
-rw-r--r--scene/gui/split_container.cpp2
-rw-r--r--scene/gui/tab_bar.cpp2
-rw-r--r--scene/gui/text_edit.cpp10
-rw-r--r--scene/gui/texture_progress_bar.cpp12
-rw-r--r--scene/gui/video_stream_player.cpp2
-rw-r--r--scene/main/canvas_layer.cpp6
-rw-r--r--scene/main/http_request.cpp6
-rw-r--r--scene/main/scene_tree.cpp6
-rw-r--r--scene/main/viewport.cpp4
-rw-r--r--scene/main/window.cpp50
-rw-r--r--scene/multiplayer/multiplayer_synchronizer.cpp5
-rw-r--r--scene/resources/animation.cpp2
-rw-r--r--scene/resources/animation_library.cpp6
-rw-r--r--scene/resources/environment.cpp4
-rw-r--r--scene/resources/font.cpp37
-rw-r--r--scene/resources/font.h6
-rw-r--r--scene/resources/material.cpp27
-rw-r--r--scene/resources/mesh.cpp4
-rw-r--r--scene/resources/mesh_library.cpp4
-rw-r--r--scene/resources/navigation_mesh.cpp22
-rw-r--r--scene/resources/primitive_meshes.cpp14
-rw-r--r--scene/resources/separation_ray_shape_2d.cpp2
-rw-r--r--scene/resources/separation_ray_shape_3d.cpp2
-rw-r--r--scene/resources/skeleton_modification_2d_twoboneik.cpp4
-rw-r--r--scene/resources/style_box.cpp62
-rw-r--r--scene/resources/texture.cpp26
-rw-r--r--scene/resources/theme.cpp4
-rw-r--r--scene/resources/tile_set.cpp351
-rw-r--r--scene/resources/tile_set.h52
-rw-r--r--scene/resources/visual_shader.cpp15
-rw-r--r--scene/resources/world_2d.cpp4
-rw-r--r--scene/resources/world_3d.cpp4
-rw-r--r--servers/audio/audio_stream.cpp2
-rw-r--r--servers/audio/effects/audio_effect_capture.cpp2
-rw-r--r--servers/audio/effects/audio_effect_chorus.cpp40
-rw-r--r--servers/audio/effects/audio_effect_compressor.cpp4
-rw-r--r--servers/audio/effects/audio_effect_delay.cpp12
-rw-r--r--servers/audio/effects/audio_effect_distortion.cpp2
-rw-r--r--servers/audio/effects/audio_effect_filter.cpp2
-rw-r--r--servers/audio/effects/audio_effect_limiter.cpp6
-rw-r--r--servers/audio/effects/audio_effect_phaser.cpp6
-rw-r--r--servers/audio/effects/audio_effect_reverb.cpp2
-rw-r--r--servers/audio/effects/audio_effect_spectrum_analyzer.cpp2
-rw-r--r--servers/audio/effects/audio_effect_stereo_enhance.cpp2
-rw-r--r--servers/audio/effects/audio_stream_generator.cpp4
-rw-r--r--servers/navigation_server_2d.cpp10
-rw-r--r--servers/navigation_server_2d.h6
-rw-r--r--servers/navigation_server_3d.cpp6
-rw-r--r--servers/navigation_server_3d.h6
-rw-r--r--servers/rendering/renderer_rd/renderer_scene_render_rd.cpp12
-rw-r--r--servers/rendering/shader_language.cpp490
-rw-r--r--servers/rendering/shader_language.h1
-rw-r--r--servers/text/text_server_extension.cpp25
-rw-r--r--servers/text/text_server_extension.h8
-rw-r--r--servers/text_server.cpp5
-rw-r--r--servers/text_server.h5
-rw-r--r--thirdparty/README.md2
-rw-r--r--thirdparty/vulkan/vk_mem_alloc.h150
224 files changed, 3385 insertions, 1819 deletions
diff --git a/.github/workflows/static_checks.yml b/.github/workflows/static_checks.yml
index 5531509007..d7d07b7022 100644
--- a/.github/workflows/static_checks.yml
+++ b/.github/workflows/static_checks.yml
@@ -54,4 +54,4 @@ jobs:
- name: Documentation checks
run: |
- doc/tools/make_rst.py --dry-run doc/classes modules
+ doc/tools/make_rst.py --dry-run --color doc/classes modules
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/extension/native_extension.cpp b/core/extension/native_extension.cpp
index 5738b42049..ac9d2ca8a6 100644
--- a/core/extension/native_extension.cpp
+++ b/core/extension/native_extension.cpp
@@ -295,9 +295,12 @@ Error NativeExtension::open_library(const String &p_path, const String &p_entry_
GDNativeInitializationFunction initialization_function = (GDNativeInitializationFunction)entry_funcptr;
- initialization_function(&gdnative_interface, this, &initialization);
- level_initialized = -1;
- return OK;
+ if (initialization_function(&gdnative_interface, this, &initialization)) {
+ level_initialized = -1;
+ return OK;
+ } else {
+ return FAILED;
+ }
}
void NativeExtension::close_library() {
diff --git a/core/input/input_event.cpp b/core/input/input_event.cpp
index 2d4c203748..32e025417e 100644
--- a/core/input/input_event.cpp
+++ b/core/input/input_event.cpp
@@ -525,8 +525,8 @@ void InputEventMouse::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_global_position"), &InputEventMouse::get_global_position);
ADD_PROPERTY(PropertyInfo(Variant::INT, "button_mask"), "set_button_mask", "get_button_mask");
- ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "position"), "set_position", "get_position");
- ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "global_position"), "set_global_position", "get_global_position");
+ ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "position", PROPERTY_HINT_NONE, "suffix:px"), "set_position", "get_position");
+ ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "global_position", PROPERTY_HINT_NONE, "suffix:px"), "set_global_position", "get_global_position");
}
///////////////////////////////////
@@ -867,8 +867,8 @@ void InputEventMouseMotion::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "tilt"), "set_tilt", "get_tilt");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "pressure"), "set_pressure", "get_pressure");
- ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "relative"), "set_relative", "get_relative");
- ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "velocity"), "set_velocity", "get_velocity");
+ ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "relative", PROPERTY_HINT_NONE, "suffix:px"), "set_relative", "get_relative");
+ ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "velocity", PROPERTY_HINT_NONE, "suffix:px/s"), "set_velocity", "get_velocity");
}
///////////////////////////////////
@@ -1167,7 +1167,7 @@ void InputEventScreenTouch::_bind_methods() {
//ClassDB::bind_method(D_METHOD("is_pressed"),&InputEventScreenTouch::is_pressed);
ADD_PROPERTY(PropertyInfo(Variant::INT, "index"), "set_index", "get_index");
- ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "position"), "set_position", "get_position");
+ ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "position", PROPERTY_HINT_NONE, "suffix:px"), "set_position", "get_position");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "pressed"), "set_pressed", "is_pressed");
}
@@ -1260,9 +1260,9 @@ void InputEventScreenDrag::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_velocity"), &InputEventScreenDrag::get_velocity);
ADD_PROPERTY(PropertyInfo(Variant::INT, "index"), "set_index", "get_index");
- ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "position"), "set_position", "get_position");
- ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "relative"), "set_relative", "get_relative");
- ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "velocity"), "set_velocity", "get_velocity");
+ ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "position", PROPERTY_HINT_NONE, "suffix:px"), "set_position", "get_position");
+ ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "relative", PROPERTY_HINT_NONE, "suffix:px"), "set_relative", "get_relative");
+ ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "velocity", PROPERTY_HINT_NONE, "suffix:px/s"), "set_velocity", "get_velocity");
}
///////////////////////////////////
@@ -1362,7 +1362,7 @@ void InputEventGesture::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_position", "position"), &InputEventGesture::set_position);
ClassDB::bind_method(D_METHOD("get_position"), &InputEventGesture::get_position);
- ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "position"), "set_position", "get_position");
+ ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "position", PROPERTY_HINT_NONE, "suffix:px"), "set_position", "get_position");
}
Vector2 InputEventGesture::get_position() const {
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/core/string/ustring.cpp b/core/string/ustring.cpp
index d189f3224b..df1aae5370 100644
--- a/core/string/ustring.cpp
+++ b/core/string/ustring.cpp
@@ -3359,36 +3359,36 @@ String String::repeat(int p_count) const {
return new_string;
}
-String String::left(int p_pos) const {
- if (p_pos < 0) {
- p_pos = length() + p_pos;
+String String::left(int p_len) const {
+ if (p_len < 0) {
+ p_len = length() + p_len;
}
- if (p_pos <= 0) {
+ if (p_len <= 0) {
return "";
}
- if (p_pos >= length()) {
+ if (p_len >= length()) {
return *this;
}
- return substr(0, p_pos);
+ return substr(0, p_len);
}
-String String::right(int p_pos) const {
- if (p_pos < 0) {
- p_pos = length() + p_pos;
+String String::right(int p_len) const {
+ if (p_len < 0) {
+ p_len = length() + p_len;
}
- if (p_pos <= 0) {
+ if (p_len <= 0) {
return "";
}
- if (p_pos >= length()) {
+ if (p_len >= length()) {
return *this;
}
- return substr(length() - p_pos);
+ return substr(length() - p_len);
}
char32_t String::unicode_at(int p_idx) const {
diff --git a/core/string/ustring.h b/core/string/ustring.h
index e4f6c3327a..11d0974381 100644
--- a/core/string/ustring.h
+++ b/core/string/ustring.h
@@ -356,8 +356,8 @@ public:
int count(const String &p_string, int p_from = 0, int p_to = 0) const;
int countn(const String &p_string, int p_from = 0, int p_to = 0) const;
- String left(int p_pos) const;
- String right(int p_pos) const;
+ String left(int p_len) const;
+ String right(int p_len) const;
String indent(const String &p_prefix) const;
String dedent() const;
String strip_edges(bool left = true, bool right = true) const;
diff --git a/core/variant/variant_call.cpp b/core/variant/variant_call.cpp
index 741d3e5b8f..b335f2fcf4 100644
--- a/core/variant/variant_call.cpp
+++ b/core/variant/variant_call.cpp
@@ -1402,8 +1402,8 @@ static void _register_variant_builtin_methods() {
bind_method(String, to_upper, sarray(), varray());
bind_method(String, to_lower, sarray(), varray());
- bind_method(String, left, sarray("position"), varray());
- bind_method(String, right, sarray("position"), varray());
+ bind_method(String, left, sarray("length"), varray());
+ bind_method(String, right, sarray("length"), varray());
bind_method(String, strip_edges, sarray("left", "right"), varray(true, true));
bind_method(String, strip_escapes, sarray(), varray());
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/AnimationLibrary.xml b/doc/classes/AnimationLibrary.xml
index 0a731edadd..d856c65dfc 100644
--- a/doc/classes/AnimationLibrary.xml
+++ b/doc/classes/AnimationLibrary.xml
@@ -51,18 +51,18 @@
</members>
<signals>
<signal name="animation_added">
- <argument index="0" name="name" type="Animation" />
+ <argument index="0" name="name" type="StringName" />
<description>
</description>
</signal>
<signal name="animation_removed">
- <argument index="0" name="name" type="Animation" />
+ <argument index="0" name="name" type="StringName" />
<description>
</description>
</signal>
<signal name="animation_renamed">
- <argument index="0" name="name" type="Animation" />
- <argument index="1" name="to_name" type="Animation" />
+ <argument index="0" name="name" type="StringName" />
+ <argument index="1" name="to_name" type="StringName" />
<description>
</description>
</signal>
diff --git a/doc/classes/BaseMaterial3D.xml b/doc/classes/BaseMaterial3D.xml
index a9c6030809..d3ae85101d 100644
--- a/doc/classes/BaseMaterial3D.xml
+++ b/doc/classes/BaseMaterial3D.xml
@@ -359,6 +359,7 @@
</member>
<member name="texture_filter" type="int" setter="set_texture_filter" getter="get_texture_filter" enum="BaseMaterial3D.TextureFilter" default="3">
Filter flags for the texture. See [enum TextureFilter] for options.
+ [b]Note:[/b] [member heightmap_texture] is always sampled with linear filtering, even if nearest-neighbor filtering is selected here. This is to ensure the heightmap effect looks as intended. If you need sharper height transitions between pixels, resize the heightmap texture in an image editor with nearest-neighbor filtering.
</member>
<member name="texture_repeat" type="bool" setter="set_flag" getter="get_flag" default="true">
Repeat flags for the texture. See [enum TextureFilter] for options.
diff --git a/doc/classes/Button.xml b/doc/classes/Button.xml
index d85d02fbfb..4ece57fa81 100644
--- a/doc/classes/Button.xml
+++ b/doc/classes/Button.xml
@@ -92,6 +92,9 @@
<member name="text_direction" type="int" setter="set_text_direction" getter="get_text_direction" enum="Control.TextDirection" default="0">
Base text writing direction.
</member>
+ <member name="text_overrun_behavior" type="int" setter="set_text_overrun_behavior" getter="get_text_overrun_behavior" enum="TextParagraph.OverrunBehavior" default="0">
+ Sets the clipping behavior when the text exceeds the node's bounding rectangle. See [enum TextParagraph.OverrunBehavior] for a description of all modes.
+ </member>
</members>
<theme_items>
<theme_item name="font_color" data_type="color" type="Color" default="Color(0.875, 0.875, 0.875, 1)">
diff --git a/doc/classes/CurveTexture.xml b/doc/classes/CurveTexture.xml
index 6aa39e453e..85473fc237 100644
--- a/doc/classes/CurveTexture.xml
+++ b/doc/classes/CurveTexture.xml
@@ -5,23 +5,27 @@
</brief_description>
<description>
Renders a given [Curve] provided to it. Simplifies the task of drawing curves and/or saving them as image files.
+ If you need to store up to 3 curves within a single texture, use [CurveXYZTexture] instead. See also [GradientTexture1D] and [GradientTexture2D].
</description>
<tutorials>
</tutorials>
<members>
<member name="curve" type="Curve" setter="set_curve" getter="get_curve">
- The [code]curve[/code] rendered onto the texture.
+ The [Curve] that is rendered onto the texture.
</member>
<member name="texture_mode" type="int" setter="set_texture_mode" getter="get_texture_mode" enum="CurveTexture.TextureMode" default="0">
+ The format the texture should be generated with. When passing a CurveTexture as a input to a [Shader], this may need to be adjusted.
</member>
<member name="width" type="int" setter="set_width" getter="get_width" default="256">
- The width of the texture.
+ The width of the texture (in pixels). Higher values make it possible to represent high-frequency data better (such as sudden direction changes), at the cost of increased generation time and memory usage.
</member>
</members>
<constants>
<constant name="TEXTURE_MODE_RGB" value="0" enum="TextureMode">
+ Store the curve equally across the red, green and blue channels. This uses more video memory, but is more compatible with shaders that only read the green and blue values.
</constant>
<constant name="TEXTURE_MODE_RED" value="1" enum="TextureMode">
+ Store the curve only in the red channel. This saves video memory, but some custom shaders may not be able to work with this.
</constant>
</constants>
</class>
diff --git a/doc/classes/CurveXYZTexture.xml b/doc/classes/CurveXYZTexture.xml
index d289e394aa..e3f2e8fc45 100644
--- a/doc/classes/CurveXYZTexture.xml
+++ b/doc/classes/CurveXYZTexture.xml
@@ -1,19 +1,26 @@
<?xml version="1.0" encoding="UTF-8" ?>
<class name="CurveXYZTexture" inherits="Texture2D" version="4.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../class.xsd">
<brief_description>
+ A texture that shows 3 different curves (stored on the red, green and blue color channels).
</brief_description>
<description>
+ Renders 3 given [Curve]s provided to it, on the red, green and blue channels respectively. Compared to using separate [CurveTexture]s, this further simplifies the task of drawing curves and/or saving them as image files.
+ If you only need to store one curve within a single texture, use [CurveTexture] instead. See also [GradientTexture1D] and [GradientTexture2D].
</description>
<tutorials>
</tutorials>
<members>
<member name="curve_x" type="Curve" setter="set_curve_x" getter="get_curve_x">
+ The [Curve] that is rendered onto the texture's red channel.
</member>
<member name="curve_y" type="Curve" setter="set_curve_y" getter="get_curve_y">
+ The [Curve] that is rendered onto the texture's green channel.
</member>
<member name="curve_z" type="Curve" setter="set_curve_z" getter="get_curve_z">
+ The [Curve] that is rendered onto the texture's blue channel.
</member>
<member name="width" type="int" setter="set_width" getter="get_width" default="256">
+ The width of the texture (in pixels). Higher values make it possible to represent high-frequency data better (such as sudden direction changes), at the cost of increased generation time and memory usage.
</member>
</members>
</class>
diff --git a/doc/classes/FontData.xml b/doc/classes/FontData.xml
index a423d7a4e4..d32e7b3a94 100644
--- a/doc/classes/FontData.xml
+++ b/doc/classes/FontData.xml
@@ -3,7 +3,7 @@
<brief_description>
Font source data and prerendered glyph cache, imported from dynamic or bitmap font.
Supported font formats:
- - Dynamic font importer: TrueType (.ttf), OpenType (.otf), WOFF (.woff), WOFF2 (.woff2), Type 1 (.pfb, .pfm).
+ - Dynamic font importer: TrueType (.ttf), TrueType collection (.ttc), OpenType (.otf), OpenType collection (.otc), WOFF (.woff), WOFF2 (.woff2), Type 1 (.pfb, .pfm).
- Bitmap font importer: AngelCode BMFont (.fnt, .font), text and binary (version 3) format variants.
- Monospace image font importer: All supported image formats.
</brief_description>
@@ -87,6 +87,12 @@
Returns font descent (number of pixels below the baseline).
</description>
</method>
+ <method name="get_face_count" qualifiers="const">
+ <return type="int" />
+ <description>
+ Returns number of faces in the TrueType / OpenType collection.
+ </description>
+ </method>
<method name="get_glyph_advance" qualifiers="const">
<return type="Vector2" />
<argument index="0" name="cache_index" type="int" />
@@ -318,7 +324,8 @@
<return type="int" enum="Error" />
<argument index="0" name="path" type="String" />
<description>
- Loads a TrueType (.ttf), OpenType (.otf), WOFF (.woff), WOFF2 (.woff2) or Type 1 (.pfb, .pfm) dynamic font from file [code]path[/code].
+ Loads a TrueType (.ttf), TrueType collection (.ttc), OpenType (.otf), OpenType collection (.otc), WOFF (.woff), WOFF2 (.woff2) or Type 1 (.pfb, .pfm) dynamic font from file [code]path[/code].
+ [b]Note:[/b] Use [member face_index] to select specific face from the collection file.
[b]Warning:[/b] This method should only be used in the editor or in cases when you need to load external fonts at run-time, such as fonts located at the [code]user://[/code] directory.
</description>
</method>
@@ -570,6 +577,9 @@
<member name="embolden" type="float" setter="set_embolden" getter="get_embolden" default="0.0">
If is not equal to zero, emboldens the font outlines. Negative values reduce the outline thickness.
</member>
+ <member name="face_index" type="int" setter="set_face_index" getter="get_face_index" default="0">
+ Active face index in the TrueType / OpenType collection file.
+ </member>
<member name="fixed_size" type="int" setter="set_fixed_size" getter="get_fixed_size" default="0">
Font size, used only for the bitmap fonts.
</member>
diff --git a/doc/classes/GradientTexture1D.xml b/doc/classes/GradientTexture1D.xml
index a124753a9f..3254754ac1 100644
--- a/doc/classes/GradientTexture1D.xml
+++ b/doc/classes/GradientTexture1D.xml
@@ -4,7 +4,7 @@
Gradient-filled texture.
</brief_description>
<description>
- GradientTexture1D uses a [Gradient] to fill the texture data. The gradient will be filled from left to right using colors obtained from the gradient. This means the texture does not necessarily represent an exact copy of the gradient, but instead an interpolation of samples obtained from the gradient at fixed steps (see [member width]).
+ GradientTexture1D uses a [Gradient] to fill the texture data. The gradient will be filled from left to right using colors obtained from the gradient. This means the texture does not necessarily represent an exact copy of the gradient, but instead an interpolation of samples obtained from the gradient at fixed steps (see [member width]). See also [GradientTexture2D], [CurveTexture] and [CurveXYZTexture].
</description>
<tutorials>
</tutorials>
diff --git a/doc/classes/GradientTexture2D.xml b/doc/classes/GradientTexture2D.xml
index 4362578932..7561f1b947 100644
--- a/doc/classes/GradientTexture2D.xml
+++ b/doc/classes/GradientTexture2D.xml
@@ -4,7 +4,7 @@
Gradient-filled 2D texture.
</brief_description>
<description>
- The texture uses a [Gradient] to fill the texture data in 2D space. The gradient is filled according to the specified [member fill] and [member repeat] types using colors obtained from the gradient. The texture does not necessarily represent an exact copy of the gradient, but instead an interpolation of samples obtained from the gradient at fixed steps (see [member width] and [member height]).
+ The texture uses a [Gradient] to fill the texture data in 2D space. The gradient is filled according to the specified [member fill] and [member repeat] types using colors obtained from the gradient. The texture does not necessarily represent an exact copy of the gradient, but instead an interpolation of samples obtained from the gradient at fixed steps (see [member width] and [member height]). See also [GradientTexture1D], [CurveTexture] and [CurveXYZTexture].
</description>
<tutorials>
</tutorials>
diff --git a/doc/classes/LightmapGI.xml b/doc/classes/LightmapGI.xml
index ee98356962..ffde0d95ce 100644
--- a/doc/classes/LightmapGI.xml
+++ b/doc/classes/LightmapGI.xml
@@ -4,80 +4,122 @@
Computes and stores baked lightmaps for fast global illumination.
</brief_description>
<description>
- The [LightmapGI] node is used to compute and store baked lightmaps. Lightmaps are used to provide high-quality indirect lighting with very little light leaking. [LightmapGI] can also provide rough reflections using spherical harmonics if [member directional] is enabled. Dynamic objects can receive indirect lighting thanks to [i]light probes[/i], which can be automatically placed by setting [member generate_probes_subdiv]. Additional lightmap probes can also be added by creating [LightmapProbe] nodes. The downside is that lightmaps are fully static and cannot be baked in an exported project. Baking a [LightmapGI] node is also slower compared to [VoxelGI].
+ The [LightmapGI] node is used to compute and store baked lightmaps. Lightmaps are used to provide high-quality indirect lighting with very little light leaking. [LightmapGI] can also provide rough reflections using spherical harmonics if [member directional] is enabled. Dynamic objects can receive indirect lighting thanks to [i]light probes[/i], which can be automatically placed by setting [member generate_probes_subdiv] to a value other than [constant GENERATE_PROBES_DISABLED]. Additional lightmap probes can also be added by creating [LightmapProbe] nodes. The downside is that lightmaps are fully static and cannot be baked in an exported project. Baking a [LightmapGI] node is also slower compared to [VoxelGI].
[b]Procedural generation:[/b] Lightmap baking functionality is only available in the editor. This means [LightmapGI] is not suited to procedurally generated or user-built levels. For procedurally generated or user-built levels, use [VoxelGI] or SDFGI instead (see [member Environment.sdfgi_enabled]).
[b]Performance:[/b] [LightmapGI] provides the best possible run-time performance for global illumination. It is suitable for low-end hardware including integrated graphics and mobile devices.
+ [b]Note:[/b] Due to how lightmaps work, most properties only have a visible effect once lightmaps are baked again.
+ [b]Note:[/b] Lightmap baking on [CSGShape3D]s and [PrimitiveMesh]es is not supported, as these cannot store UV2 data required for baking.
+ [b]Note:[/b] If no custom lightmappers are installed, [LightmapGI] can only be baked when using the Vulkan backend (Clustered or Mobile), not OpenGL.
</description>
<tutorials>
</tutorials>
<members>
<member name="bias" type="float" setter="set_bias" getter="get_bias" default="0.0005">
+ The bias to use when computing shadows. Increasing [member bias] can fix shadow acne on the resulting baked lightmap, but can introduce peter-panning (shadows not connecting to their casters). Real-time [Light3D] shadows are not affected by this [member bias] property.
</member>
<member name="bounces" type="int" setter="set_bounces" getter="get_bounces" default="1">
+ Number of light bounces that are taken into account during baking. Higher values result in brighter, more realistic lighting, at the cost of longer bake times. If set to [code]0[/code], only environment lighting, direct light and emissive lighting is baked.
</member>
<member name="directional" type="bool" setter="set_directional" getter="is_directional" default="false">
+ If [code]true[/code], bakes lightmaps to contain directional information as spherical harmonics. This results in more realistic lighting appearance, especially with normal mapped materials and for lights that their have direct light baked ([member Light3D.light_bake_mode] set to [constant Light3D.BAKE_STATIC]). The directional information is also used to provide rough reflections for static and dynamic objects. This has a small run-time performance cost as the shader has to perform more work to interpret the direction information from the lightmap. Directional lightmaps also take longer to bake and result in larger file sizes.
+ [b]Note:[/b] The property's name has no relationship with [DirectionalLight3D]. [member directional] works with all light types.
</member>
<member name="environment_custom_color" type="Color" setter="set_environment_custom_color" getter="get_environment_custom_color">
+ The color to use for environment lighting. Only effective if [member environment_mode] is [constant ENVIRONMENT_MODE_CUSTOM_COLOR].
</member>
<member name="environment_custom_energy" type="float" setter="set_environment_custom_energy" getter="get_environment_custom_energy">
+ The color multiplier to use for environment lighting. Only effective if [member environment_mode] is [constant ENVIRONMENT_MODE_CUSTOM_COLOR].
</member>
<member name="environment_custom_sky" type="Sky" setter="set_environment_custom_sky" getter="get_environment_custom_sky">
+ The sky to use as a source of environment lighting. Only effective if [member environment_mode] is [constant ENVIRONMENT_MODE_CUSTOM_SKY].
</member>
<member name="environment_mode" type="int" setter="set_environment_mode" getter="get_environment_mode" enum="LightmapGI.EnvironmentMode" default="0">
+ The environment mode to use when baking lightmaps.
</member>
<member name="generate_probes_subdiv" type="int" setter="set_generate_probes" getter="get_generate_probes" enum="LightmapGI.GenerateProbes" default="0">
+ The level of subdivision to use when automatically generating [LightmapProbe]s for dynamic object lighting. Higher values result in more accurate indirect lighting on dynamic objects, at the cost of longer bake times and larger file sizes.
+ [b]Note:[/b] Automatically generated [LightmapProbe]s are not visible as nodes in the Scene tree dock, and cannot be modified this way after they are generated.
+ [b]Note:[/b] Regardless of [member generate_probes_subdiv], direct lighting on dynamic objects is always applied using [Light3D] nodes in real-time.
</member>
<member name="interior" type="bool" setter="set_interior" getter="is_interior" default="false">
+ If [code]true[/code], ignore environment lighting when baking lightmaps.
</member>
<member name="light_data" type="LightmapGIData" setter="set_light_data" getter="get_light_data">
+ The [LightmapGIData] associated to this [LightmapGI] node. This resource is automatically created after baking, and is not meant to be created manually.
</member>
<member name="max_texture_size" type="int" setter="set_max_texture_size" getter="get_max_texture_size" default="16384">
+ The maximum texture size for the generated texture atlas. Higher values will result in fewer slices being generated, but may not work on all hardware as a result of hardware limitations on texture sizes. Leave [member max_texture_size] at its default value of [code]16384[/code] if unsure.
</member>
<member name="quality" type="int" setter="set_bake_quality" getter="get_bake_quality" enum="LightmapGI.BakeQuality" default="1">
+ The quality preset to use when baking lightmaps. This affects bake times, but output file sizes remain mostly identical across quality levels.
+ To further speed up bake times, decrease [member bounces], disable [member use_denoiser] and increase the lightmap texel size on 3D scenes in the Import doc.
</member>
<member name="use_denoiser" type="bool" setter="set_use_denoiser" getter="is_using_denoiser" default="true">
+ If [code]true[/code], uses a CPU-based denoising algorithm on the generated lightmap. This eliminates most noise within the generated lightmap at the cost of longer bake times. File sizes are generally not impacted significantly by the use of a denoiser, although lossless compression may do a better job at compressing a denoised image.
+ [b]Note:[/b] The built-in denoiser (OpenImageDenoise) may crash when denoising lightmaps in large scenes. If you encounter a crash at the end of lightmap baking, try disabling [member use_denoiser].
</member>
</members>
<constants>
<constant name="BAKE_QUALITY_LOW" value="0" enum="BakeQuality">
+ Low bake quality (fastest bake times). The quality of this preset can be adjusted by changing [member ProjectSettings.rendering/lightmapping/bake_quality/low_quality_ray_count] and [member ProjectSettings.rendering/lightmapping/bake_quality/low_quality_probe_ray_count].
</constant>
<constant name="BAKE_QUALITY_MEDIUM" value="1" enum="BakeQuality">
+ Medium bake quality (fast bake times). The quality of this preset can be adjusted by changing [member ProjectSettings.rendering/lightmapping/bake_quality/medium_quality_ray_count] and [member ProjectSettings.rendering/lightmapping/bake_quality/medium_quality_probe_ray_count].
</constant>
<constant name="BAKE_QUALITY_HIGH" value="2" enum="BakeQuality">
+ High bake quality (slow bake times). The quality of this preset can be adjusted by changing [member ProjectSettings.rendering/lightmapping/bake_quality/high_quality_ray_count] and [member ProjectSettings.rendering/lightmapping/bake_quality/high_quality_probe_ray_count].
</constant>
<constant name="BAKE_QUALITY_ULTRA" value="3" enum="BakeQuality">
+ Highest bake quality (slowest bake times). The quality of this preset can be adjusted by changing [member ProjectSettings.rendering/lightmapping/bake_quality/high_quality_ray_count] and [member ProjectSettings.rendering/lightmapping/bake_quality/ultra_quality_probe_ray_count].
</constant>
<constant name="GENERATE_PROBES_DISABLED" value="0" enum="GenerateProbes">
+ Don't generate lightmap probes for lighting dynamic objects.
</constant>
<constant name="GENERATE_PROBES_SUBDIV_4" value="1" enum="GenerateProbes">
+ Lowest level of subdivision (fastest bake times, smallest file sizes).
</constant>
<constant name="GENERATE_PROBES_SUBDIV_8" value="2" enum="GenerateProbes">
+ Low level of subdivision (fast bake times, small file sizes).
</constant>
<constant name="GENERATE_PROBES_SUBDIV_16" value="3" enum="GenerateProbes">
+ High level of subdivision (slow bake times, large file sizes).
</constant>
<constant name="GENERATE_PROBES_SUBDIV_32" value="4" enum="GenerateProbes">
+ Highest level of subdivision (slowest bake times, largest file sizes).
</constant>
<constant name="BAKE_ERROR_OK" value="0" enum="BakeError">
+ Lightmap baking was successful.
</constant>
<constant name="BAKE_ERROR_NO_LIGHTMAPPER" value="1" enum="BakeError">
+ Lightmap baking failed as there is no lightmapper available in this Godot build.
</constant>
<constant name="BAKE_ERROR_NO_SAVE_PATH" value="2" enum="BakeError">
+ Lightmap baking failed as the [LightmapGIData] save path isn't configured in the resource.
</constant>
<constant name="BAKE_ERROR_NO_MESHES" value="3" enum="BakeError">
+ Lightmap baking failed as there are no meshes whose [member GeometryInstance3D.gi_mode] is [constant GeometryInstance3D.GI_MODE_STATIC] and with valid UV2 mapping in the current scene. You may need to select 3D scenes in the Import dock and change their global illumination mode accordingly.
</constant>
<constant name="BAKE_ERROR_MESHES_INVALID" value="4" enum="BakeError">
+ Lightmap baking failed as the lightmapper failed to analyze some of the meshes marked as static for baking.
</constant>
<constant name="BAKE_ERROR_CANT_CREATE_IMAGE" value="5" enum="BakeError">
+ Lightmap baking failed as the resulting image couldn't be saved or imported by Godot after it was saved.
</constant>
<constant name="BAKE_ERROR_USER_ABORTED" value="6" enum="BakeError">
+ The user aborted the lightmap baking operation (typically by clicking the [b]Cancel[/b] button in the progress dialog).
</constant>
<constant name="ENVIRONMENT_MODE_DISABLED" value="0" enum="EnvironmentMode">
+ Ignore environment lighting when baking lightmaps.
</constant>
<constant name="ENVIRONMENT_MODE_SCENE" value="1" enum="EnvironmentMode">
+ Use the scene's environment lighting when baking lightmaps.
+ [b]Note:[/b] If baking lightmaps in a scene with no [WorldEnvironment] node, this will act like [constant ENVIRONMENT_MODE_DISABLED]. The editor's preview sky and sun is [i]not[/i] taken into account by [LightmapGI] when baking lightmaps.
</constant>
<constant name="ENVIRONMENT_MODE_CUSTOM_SKY" value="2" enum="EnvironmentMode">
+ Use [member environment_custom_sky] as a source of environment lighting when baking lightmaps.
</constant>
<constant name="ENVIRONMENT_MODE_CUSTOM_COLOR" value="3" enum="EnvironmentMode">
+ Use [member environment_custom_color] multiplied by [member environment_custom_energy] as a constant source of environment lighting when baking lightmaps.
</constant>
</constants>
</class>
diff --git a/doc/classes/LightmapGIData.xml b/doc/classes/LightmapGIData.xml
index c2423daef0..20113ac309 100644
--- a/doc/classes/LightmapGIData.xml
+++ b/doc/classes/LightmapGIData.xml
@@ -1,8 +1,10 @@
<?xml version="1.0" encoding="UTF-8" ?>
<class name="LightmapGIData" inherits="Resource" version="4.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../class.xsd">
<brief_description>
+ Contains baked lightmap and dynamic object probe data for [LightmapGI].
</brief_description>
<description>
+ [LightmapGIData] contains baked lightmap and dynamic object probe data for [LightmapGI]. It is replaced every time lightmaps are baked in [LightmapGI].
</description>
<tutorials>
</tutorials>
@@ -14,38 +16,46 @@
<argument index="2" name="slice_index" type="int" />
<argument index="3" name="sub_instance" type="int" />
<description>
+ Adds an object that is considered baked within this [LightmapGIData].
</description>
</method>
<method name="clear_users">
<return type="void" />
<description>
+ Clear all objects that are considred baked within this [LightmapGIData].
</description>
</method>
<method name="get_user_count" qualifiers="const">
<return type="int" />
<description>
+ Returns the number of objects that are considered baked within this [LightmapGIData].
</description>
</method>
<method name="get_user_path" qualifiers="const">
<return type="NodePath" />
<argument index="0" name="user_idx" type="int" />
<description>
+ Returns the [NodePath] of the baked object at index [code]user_idx[/code].
</description>
</method>
<method name="is_using_spherical_harmonics" qualifiers="const">
<return type="bool" />
<description>
+ If [code]true[/code], lightmaps were baked with directional information. See also [member LightmapGI.directional].
</description>
</method>
<method name="set_uses_spherical_harmonics">
<return type="void" />
<argument index="0" name="uses_spherical_harmonics" type="bool" />
<description>
+ If [code]uses_spherical_harmonics[/code] is [code]true[/code], tells the engine to treat the lightmap data as if it was baked with directional information.
+ [b]Note:[/b] Changing this value on already baked lightmaps will not cause them to be baked again. This means the material appearance will look incorrect until lightmaps are baked again, in which case the value set here is discarded as the entire [LightmapGIData] resource is replaced by the lightmapper.
</description>
</method>
</methods>
<members>
<member name="light_texture" type="TextureLayered" setter="set_light_texture" getter="get_light_texture">
+ The lightmap atlas texture generated by the lightmapper.
</member>
</members>
</class>
diff --git a/doc/classes/LightmapProbe.xml b/doc/classes/LightmapProbe.xml
index a5ba6294b9..cb4879b6c7 100644
--- a/doc/classes/LightmapProbe.xml
+++ b/doc/classes/LightmapProbe.xml
@@ -1,8 +1,11 @@
<?xml version="1.0" encoding="UTF-8" ?>
<class name="LightmapProbe" inherits="Node3D" version="4.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../class.xsd">
<brief_description>
+ Represents a single manually placed probe for dynamic object lighting with [LightmapGI].
</brief_description>
<description>
+ [LightmapProbe] represents the position of a single manually placed probe for dynamic object lighting with [LightmapGI].
+ Typically, [LightmapGI] probes are placed automatically by setting [member LightmapGI.generate_probes_subdiv] to a value other than [constant LightmapGI.GENERATE_PROBES_DISABLED]. By creating [LightmapProbe] nodes before baking lightmaps, you can add more probes in specific areas for greater detail, or disable automatic generation and rely only on manually placed probes instead.
</description>
<tutorials>
</tutorials>
diff --git a/doc/classes/Lightmapper.xml b/doc/classes/Lightmapper.xml
index f9a1e2fa99..58ef2ed0cf 100644
--- a/doc/classes/Lightmapper.xml
+++ b/doc/classes/Lightmapper.xml
@@ -1,8 +1,11 @@
<?xml version="1.0" encoding="UTF-8" ?>
<class name="Lightmapper" inherits="RefCounted" version="4.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../class.xsd">
<brief_description>
+ Abstract class extended by lightmappers, for use in [LightmapGI].
</brief_description>
<description>
+ This class should be extended by custom lightmapper classes. Lightmappers can then be used with [LightmapGI] to provide fast baked global illumination in 3D.
+ Godot contains a built-in GPU-based lightmapper [LightmapperRD] that uses compute shaders, but custom lightmappers can be implemented by C++ modules.
</description>
<tutorials>
</tutorials>
diff --git a/doc/classes/LightmapperRD.xml b/doc/classes/LightmapperRD.xml
index 29d95244ce..e4b68a7ef8 100644
--- a/doc/classes/LightmapperRD.xml
+++ b/doc/classes/LightmapperRD.xml
@@ -1,8 +1,11 @@
<?xml version="1.0" encoding="UTF-8" ?>
<class name="LightmapperRD" inherits="Lightmapper" version="4.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../class.xsd">
<brief_description>
+ The built-in GPU-based lightmapper for use with [LightmapGI].
</brief_description>
<description>
+ LightmapperRD ("RD" stands for [RenderingDevice]) is the built-in GPU-based lightmapper for use with [LightmapGI]. On most dedicated GPUs, it can bake lightmaps much faster than most CPU-based lightmappers. LightmapperRD uses compute shaders to bake lightmaps, so it does not require CUDA or OpenCL libraries to be installed to be usable.
+ [b]Note:[/b] Only usable when using the Vulkan backend (Clustered or Mobile), not OpenGL.
</description>
<tutorials>
</tutorials>
diff --git a/doc/classes/MeshInstance2D.xml b/doc/classes/MeshInstance2D.xml
index 96e66f850a..e9666337a1 100644
--- a/doc/classes/MeshInstance2D.xml
+++ b/doc/classes/MeshInstance2D.xml
@@ -4,7 +4,7 @@
Node used for displaying a [Mesh] in 2D.
</brief_description>
<description>
- Node used for displaying a [Mesh] in 2D. Can be constructed from an existing [Sprite2D] via a tool in the editor toolbar. Select "Sprite2D" then "Convert to Mesh2D", select settings in popup and press "Create Mesh2D".
+ Node used for displaying a [Mesh] in 2D. A [MeshInstance2D] can be automatically created from an existing [Sprite2D] via a tool in the editor toolbar. Select the [Sprite2D] node, then choose [b]Sprite2D &gt; Convert to MeshInstance2D[/b] at the top of the 2D editor viewport.
</description>
<tutorials>
<link title="2D meshes">$DOCS_URL/tutorials/2d/2d_meshes.html</link>
diff --git a/doc/classes/NavigationAgent2D.xml b/doc/classes/NavigationAgent2D.xml
index 945947ad9f..0ac9513464 100644
--- a/doc/classes/NavigationAgent2D.xml
+++ b/doc/classes/NavigationAgent2D.xml
@@ -34,6 +34,12 @@
Returns which index the agent is currently on in the navigation path's [PackedVector2Array].
</description>
</method>
+ <method name="get_navigation_map" qualifiers="const">
+ <return type="RID" />
+ <description>
+ Returns the [RID] of the navigation map for this NavigationAgent node. This function returns always the map set on the NavigationAgent node and not the map of the abstract agent on the NavigationServer. If the agent map is changed directly with the NavigationServer API the NavigationAgent node will not be aware of the map change. Use [method set_navigation_map] to change the navigation map for the NavigationAgent and also update the agent on the NavigationServer.
+ </description>
+ </method>
<method name="get_next_location">
<return type="Vector2" />
<description>
@@ -70,6 +76,13 @@
Returns true if the target location is reached. The target location is set using [method set_target_location]. It may not always be possible to reach the target location. It should always be possible to reach the final location though. See [method get_final_location].
</description>
</method>
+ <method name="set_navigation_map">
+ <return type="void" />
+ <argument index="0" name="navigation_map" type="RID" />
+ <description>
+ Sets the [RID] of the navigation map this NavigationAgent node should use and also updates the [code]agent[/code] on the NavigationServer.
+ </description>
+ </method>
<method name="set_target_location">
<return type="void" />
<argument index="0" name="location" type="Vector2" />
@@ -95,8 +108,8 @@
<member name="max_speed" type="float" setter="set_max_speed" getter="get_max_speed" default="200.0">
The maximum speed that an agent can move.
</member>
- <member name="navigable_layers" type="int" setter="set_navigable_layers" getter="get_navigable_layers" default="1">
- A bitfield determining what layers of navigation regions this agent will use to calculate path. Changing it runtime will clear current navigation path and generate new one, according to new layers.
+ <member name="navigation_layers" type="int" setter="set_navigation_layers" getter="get_navigation_layers" default="1">
+ A bitfield determining what navigation layers of navigation regions this agent will use to calculate path. Changing it runtime will clear current navigation path and generate new one, according to new navigation layers.
</member>
<member name="neighbor_dist" type="float" setter="set_neighbor_dist" getter="get_neighbor_dist" default="500.0">
The distance to search for other agents.
diff --git a/doc/classes/NavigationAgent3D.xml b/doc/classes/NavigationAgent3D.xml
index 7f7e058742..cc45a43ffc 100644
--- a/doc/classes/NavigationAgent3D.xml
+++ b/doc/classes/NavigationAgent3D.xml
@@ -34,6 +34,12 @@
Returns which index the agent is currently on in the navigation path's [PackedVector3Array].
</description>
</method>
+ <method name="get_navigation_map" qualifiers="const">
+ <return type="RID" />
+ <description>
+ Returns the [RID] of the navigation map for this NavigationAgent node. This function returns always the map set on the NavigationAgent node and not the map of the abstract agent on the NavigationServer. If the agent map is changed directly with the NavigationServer API the NavigationAgent node will not be aware of the map change. Use [method set_navigation_map] to change the navigation map for the NavigationAgent and also update the agent on the NavigationServer.
+ </description>
+ </method>
<method name="get_next_location">
<return type="Vector3" />
<description>
@@ -70,6 +76,13 @@
Returns true if the target location is reached. The target location is set using [method set_target_location]. It may not always be possible to reach the target location. It should always be possible to reach the final location though. See [method get_final_location].
</description>
</method>
+ <method name="set_navigation_map">
+ <return type="void" />
+ <argument index="0" name="navigation_map" type="RID" />
+ <description>
+ Sets the [RID] of the navigation map this NavigationAgent node should use and also updates the [code]agent[/code] on the NavigationServer.
+ </description>
+ </method>
<method name="set_target_location">
<return type="void" />
<argument index="0" name="location" type="Vector3" />
@@ -101,8 +114,8 @@
<member name="max_speed" type="float" setter="set_max_speed" getter="get_max_speed" default="10.0">
The maximum speed that an agent can move.
</member>
- <member name="navigable_layers" type="int" setter="set_navigable_layers" getter="get_navigable_layers" default="1">
- A bitfield determining what layers of navigation regions this agent will use to calculate path. Changing it runtime will clear current navigation path and generate new one, according to new layers.
+ <member name="navigation_layers" type="int" setter="set_navigation_layers" getter="get_navigation_layers" default="1">
+ A bitfield determining what navigation layers of navigation regions this NavigationAgent will use to calculate path. Changing it runtime will clear current navigation path and generate new one, according to new navigation layers.
</member>
<member name="neighbor_dist" type="float" setter="set_neighbor_dist" getter="get_neighbor_dist" default="50.0">
The distance to search for other agents.
diff --git a/doc/classes/NavigationRegion2D.xml b/doc/classes/NavigationRegion2D.xml
index 542aa8f619..62e64f2a3c 100644
--- a/doc/classes/NavigationRegion2D.xml
+++ b/doc/classes/NavigationRegion2D.xml
@@ -28,8 +28,8 @@
<member name="enter_cost" type="float" setter="set_enter_cost" getter="get_enter_cost" default="0.0">
When pathfinding enters this regions navmesh from another regions navmesh the [code]enter_cost[/code] value is added to the path distance for determining the shortest path.
</member>
- <member name="layers" type="int" setter="set_layers" getter="get_layers" default="1">
- A bitfield determining all layers the region belongs to. These layers can be checked upon when requesting a path with [method NavigationServer2D.map_get_path].
+ <member name="navigation_layers" type="int" setter="set_navigation_layers" getter="get_navigation_layers" default="1">
+ A bitfield determining all navigation layers the region belongs to. These navigation layers can be checked upon when requesting a path with [method NavigationServer2D.map_get_path].
</member>
<member name="navpoly" type="NavigationPolygon" setter="set_navigation_polygon" getter="get_navigation_polygon">
The [NavigationPolygon] resource to use.
diff --git a/doc/classes/NavigationRegion3D.xml b/doc/classes/NavigationRegion3D.xml
index e45bca7f8b..3af7fe5c97 100644
--- a/doc/classes/NavigationRegion3D.xml
+++ b/doc/classes/NavigationRegion3D.xml
@@ -35,8 +35,8 @@
<member name="enter_cost" type="float" setter="set_enter_cost" getter="get_enter_cost" default="0.0">
When pathfinding enters this regions navmesh from another regions navmesh the [code]enter_cost[/code] value is added to the path distance for determining the shortest path.
</member>
- <member name="layers" type="int" setter="set_layers" getter="get_layers" default="1">
- A bitfield determining all layers the region belongs to. These layers can be checked upon when requesting a path with [method NavigationServer3D.map_get_path].
+ <member name="navigation_layers" type="int" setter="set_navigation_layers" getter="get_navigation_layers" default="1">
+ A bitfield determining all navigation layers the region belongs to. These navigation layers can be checked upon when requesting a path with [method NavigationServer3D.map_get_path].
</member>
<member name="navmesh" type="NavigationMesh" setter="set_navigation_mesh" getter="get_navigation_mesh">
The [NavigationMesh] resource to use.
diff --git a/doc/classes/NavigationServer2D.xml b/doc/classes/NavigationServer2D.xml
index 7b0dac99c3..220c12ce7f 100644
--- a/doc/classes/NavigationServer2D.xml
+++ b/doc/classes/NavigationServer2D.xml
@@ -8,7 +8,7 @@
Maps are made up of regions, which are made of navigation polygons. Together, they define the navigable areas in the 2D world.
[b]Note:[/b] Most NavigationServer changes take effect after the next physics frame and not immediately. This includes all changes made to maps, regions or agents by navigation related Nodes in the SceneTree or made through scripts.
For two regions to be connected to each other, they must share a similar edge. An edge is considered connected to another if both of its two vertices are at a distance less than [code]edge_connection_margin[/code] to the respective other edge's vertex.
- You may assign navigation layers to regions with [method NavigationServer2D.region_set_layers], which then can be checked upon when requesting a path with [method NavigationServer2D.map_get_path]. This allows allowing or forbidding some areas to 2D objects.
+ You may assign navigation layers to regions with [method NavigationServer2D.region_set_navigation_layers], which then can be checked upon when requesting a path with [method NavigationServer2D.map_get_path]. This allows allowing or forbidding some areas to 2D objects.
To use the collision avoidance system, you may use agents. You can set an agent's target velocity, then the servers will emit a callback with a modified velocity.
[b]Note:[/b] The collision avoidance system ignores regions. Using the modified velocity as-is might lead to pushing and agent outside of a navigable area. This is a limitation of the collision avoidance system, any more complex situation may require the use of the physics engine.
This server keeps tracks of any call and executes them during the sync phase. This means that you can request any change to the map, using any thread, without worrying.
@@ -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">
@@ -175,9 +176,9 @@
<argument index="1" name="origin" type="Vector2" />
<argument index="2" name="destination" type="Vector2" />
<argument index="3" name="optimize" type="bool" />
- <argument index="4" name="layers" type="int" default="1" />
+ <argument index="4" name="navigation_layers" type="int" default="1" />
<description>
- Returns the navigation path to reach the destination from the origin. [code]layers[/code] is a bitmask of all region layers that are allowed to be in the path.
+ Returns the navigation path to reach the destination from the origin. [code]navigation_layers[/code] is a bitmask of all region navigation layers that are allowed to be in the path.
</description>
</method>
<method name="map_get_regions" qualifiers="const">
@@ -254,18 +255,18 @@
Returns the [code]enter_cost[/code] of this [code]region[/code].
</description>
</method>
- <method name="region_get_layers" qualifiers="const">
- <return type="int" />
+ <method name="region_get_map" qualifiers="const">
+ <return type="RID" />
<argument index="0" name="region" type="RID" />
<description>
- Returns the region's layers.
+ Returns the navigation map [RID] the requested [code]region[/code] is currently assigned to.
</description>
</method>
- <method name="region_get_map" qualifiers="const">
- <return type="RID" />
+ <method name="region_get_navigation_layers" qualifiers="const">
+ <return type="int" />
<argument index="0" name="region" type="RID" />
<description>
- Returns the navigation map [RID] the requested [code]region[/code] is currently assigned to.
+ Returns the region's navigation layers.
</description>
</method>
<method name="region_get_travel_cost" qualifiers="const">
@@ -283,20 +284,20 @@
Sets the [code]enter_cost[/code] for this [code]region[/code].
</description>
</method>
- <method name="region_set_layers" qualifiers="const">
+ <method name="region_set_map" qualifiers="const">
<return type="void" />
<argument index="0" name="region" type="RID" />
- <argument index="1" name="layers" type="int" />
+ <argument index="1" name="map" type="RID" />
<description>
- Set the region's layers. This allows selecting regions from a path request (when using [method NavigationServer2D.map_get_path]).
+ Sets the map for the region.
</description>
</method>
- <method name="region_set_map" qualifiers="const">
+ <method name="region_set_navigation_layers" qualifiers="const">
<return type="void" />
<argument index="0" name="region" type="RID" />
- <argument index="1" name="map" type="RID" />
+ <argument index="1" name="navigation_layers" type="int" />
<description>
- Sets the map for the region.
+ Set the region's navigation layers. This allows selecting regions from a path request (when using [method NavigationServer2D.map_get_path]).
</description>
</method>
<method name="region_set_navpoly" qualifiers="const">
diff --git a/doc/classes/NavigationServer3D.xml b/doc/classes/NavigationServer3D.xml
index d6574dd69a..d2eef49cfd 100644
--- a/doc/classes/NavigationServer3D.xml
+++ b/doc/classes/NavigationServer3D.xml
@@ -8,7 +8,7 @@
Maps are made up of regions, which are made of navigation meshes. Together, they define the navigable areas in the 3D world.
[b]Note:[/b] Most NavigationServer changes take effect after the next physics frame and not immediately. This includes all changes made to maps, regions or agents by navigation related Nodes in the SceneTree or made through scripts.
For two regions to be connected to each other, they must share a similar edge. An edge is considered connected to another if both of its two vertices are at a distance less than [code]edge_connection_margin[/code] to the respective other edge's vertex.
- You may assign navigation layers to regions with [method NavigationServer3D.region_set_layers], which then can be checked upon when requesting a path with [method NavigationServer3D.map_get_path]. This allows allowing or forbidding some areas to 3D objects.
+ You may assign navigation layers to regions with [method NavigationServer3D.region_set_navigation_layers], which then can be checked upon when requesting a path with [method NavigationServer3D.map_get_path]. This allows allowing or forbidding some areas to 3D objects.
To use the collision avoidance system, you may use agents. You can set an agent's target velocity, then the servers will emit a callback with a modified velocity.
[b]Note:[/b] The collision avoidance system ignores regions. Using the modified velocity as-is might lead to pushing and agent outside of a navigable area. This is a limitation of the collision avoidance system, any more complex situation may require the use of the physics engine.
This server keeps tracks of any call and executes them during the sync phase. This means that you can request any change to the map, using any thread, without worrying.
@@ -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">
@@ -193,9 +194,9 @@
<argument index="1" name="origin" type="Vector3" />
<argument index="2" name="destination" type="Vector3" />
<argument index="3" name="optimize" type="bool" />
- <argument index="4" name="layers" type="int" default="1" />
+ <argument index="4" name="navigation_layers" type="int" default="1" />
<description>
- Returns the navigation path to reach the destination from the origin. [code]layers[/code] is a bitmask of all region layers that are allowed to be in the path.
+ Returns the navigation path to reach the destination from the origin. [code]navigation_layers[/code] is a bitmask of all region navigation layers that are allowed to be in the path.
</description>
</method>
<method name="map_get_regions" qualifiers="const">
@@ -304,18 +305,18 @@
Returns the [code]enter_cost[/code] of this [code]region[/code].
</description>
</method>
- <method name="region_get_layers" qualifiers="const">
- <return type="int" />
+ <method name="region_get_map" qualifiers="const">
+ <return type="RID" />
<argument index="0" name="region" type="RID" />
<description>
- Returns the region's layers.
+ Returns the navigation map [RID] the requested [code]region[/code] is currently assigned to.
</description>
</method>
- <method name="region_get_map" qualifiers="const">
- <return type="RID" />
+ <method name="region_get_navigation_layers" qualifiers="const">
+ <return type="int" />
<argument index="0" name="region" type="RID" />
<description>
- Returns the navigation map [RID] the requested [code]region[/code] is currently assigned to.
+ Returns the region's navigation layers.
</description>
</method>
<method name="region_get_travel_cost" qualifiers="const">
@@ -333,20 +334,20 @@
Sets the [code]enter_cost[/code] for this [code]region[/code].
</description>
</method>
- <method name="region_set_layers" qualifiers="const">
+ <method name="region_set_map" qualifiers="const">
<return type="void" />
<argument index="0" name="region" type="RID" />
- <argument index="1" name="layers" type="int" />
+ <argument index="1" name="map" type="RID" />
<description>
- Set the region's layers. This allows selecting regions from a path request (when using [method NavigationServer3D.map_get_path]).
+ Sets the map for the region.
</description>
</method>
- <method name="region_set_map" qualifiers="const">
+ <method name="region_set_navigation_layers" qualifiers="const">
<return type="void" />
<argument index="0" name="region" type="RID" />
- <argument index="1" name="map" type="RID" />
+ <argument index="1" name="navigation_layers" type="int" />
<description>
- Sets the map for the region.
+ Set the region's navigation layers. This allows selecting regions from a path request (when using [method NavigationServer3D.map_get_path]).
</description>
</method>
<method name="region_set_navmesh" qualifiers="const">
diff --git a/doc/classes/OS.xml b/doc/classes/OS.xml
index 2512dec4b3..e6d5ea61da 100644
--- a/doc/classes/OS.xml
+++ b/doc/classes/OS.xml
@@ -469,7 +469,12 @@
<argument index="0" name="path" type="String" />
<description>
Moves the file or directory to the system's recycle bin. See also [method Directory.remove].
+ The method takes only global paths, so you may need to use [method ProjectSettings.globalize_path]. Do not use it for files in [code]res://[/code] as it will not work in exported project.
[b]Note:[/b] If the user has disabled the recycle bin on their system, the file will be permanently deleted instead.
+ [codeblock]
+ var file_to_remove = "user://slot1.sav"
+ OS.move_to_trash(ProjectSettings.globalize_path(file_to_remove))
+ [/codeblock]
</description>
</method>
<method name="open_midi_inputs">
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/doc/classes/ProjectSettings.xml b/doc/classes/ProjectSettings.xml
index 8a3677c0b4..25f0a997ba 100644
--- a/doc/classes/ProjectSettings.xml
+++ b/doc/classes/ProjectSettings.xml
@@ -1714,28 +1714,40 @@
<member name="rendering/global_illumination/voxel_gi/quality" type="int" setter="" getter="" default="0">
</member>
<member name="rendering/lightmapping/bake_performance/max_rays_per_pass" type="int" setter="" getter="" default="32">
+ The maximum number of rays that can be thrown per pass when baking lightmaps with [LightmapGI]. Depending on the scene, adjusting this value may result in higher GPU utilization when baking lightmaps, leading to faster bake times.
</member>
<member name="rendering/lightmapping/bake_performance/max_rays_per_probe_pass" type="int" setter="" getter="" default="64">
+ The maximum number of rays that can be thrown per pass when baking dynamic object lighting in [LightmapProbe]s with [LightmapGI]. Depending on the scene, adjusting this value may result in higher GPU utilization when baking lightmaps, leading to faster bake times.
</member>
<member name="rendering/lightmapping/bake_performance/region_size" type="int" setter="" getter="" default="512">
+ The region size to use when baking lightmaps with [LightmapGI].
</member>
<member name="rendering/lightmapping/bake_quality/high_quality_probe_ray_count" type="int" setter="" getter="" default="512">
+ The number of rays to use for baking dynamic object lighting in [LightmapProbe]s when [member LightmapGI.quality] is [constant LightmapGI.BAKE_QUALITY_HIGH].
</member>
<member name="rendering/lightmapping/bake_quality/high_quality_ray_count" type="int" setter="" getter="" default="256">
+ The number of rays to use for baking lightmaps with [LightmapGI] when [member LightmapGI.quality] is [constant LightmapGI.BAKE_QUALITY_HIGH].
</member>
<member name="rendering/lightmapping/bake_quality/low_quality_probe_ray_count" type="int" setter="" getter="" default="64">
+ The number of rays to use for baking dynamic object lighting in [LightmapProbe]s when [member LightmapGI.quality] is [constant LightmapGI.BAKE_QUALITY_LOW].
</member>
<member name="rendering/lightmapping/bake_quality/low_quality_ray_count" type="int" setter="" getter="" default="16">
+ The number of rays to use for baking lightmaps with [LightmapGI] when [member LightmapGI.quality] is [constant LightmapGI.BAKE_QUALITY_LOW].
</member>
<member name="rendering/lightmapping/bake_quality/medium_quality_probe_ray_count" type="int" setter="" getter="" default="256">
+ The number of rays to use for baking dynamic object lighting in [LightmapProbe]s when [member LightmapGI.quality] is [constant LightmapGI.BAKE_QUALITY_MEDIUM].
</member>
<member name="rendering/lightmapping/bake_quality/medium_quality_ray_count" type="int" setter="" getter="" default="64">
+ The number of rays to use for baking lightmaps with [LightmapGI] when [member LightmapGI.quality] is [constant LightmapGI.BAKE_QUALITY_MEDIUM].
</member>
<member name="rendering/lightmapping/bake_quality/ultra_quality_probe_ray_count" type="int" setter="" getter="" default="2048">
+ The number of rays to use for baking dynamic object lighting in [LightmapProbe]s when [member LightmapGI.quality] is [constant LightmapGI.BAKE_QUALITY_ULTRA].
</member>
<member name="rendering/lightmapping/bake_quality/ultra_quality_ray_count" type="int" setter="" getter="" default="1024">
+ The number of rays to use for baking lightmaps with [LightmapGI] when [member LightmapGI.quality] is [constant LightmapGI.BAKE_QUALITY_ULTRA].
</member>
<member name="rendering/lightmapping/probe_capture/update_speed" type="float" setter="" getter="" default="15">
+ The framerate-independent update speed when representing dynamic object lighting from [LightmapProbe]s. Higher values make dynamic object lighting update faster. Higher values can prevent fast-moving objects from having "outdated" indirect lighting displayed on them, at the cost of possible flickering when an object moves from a bright area to a shaded area.
</member>
<member name="rendering/limits/cluster_builder/max_clustered_elements" type="float" setter="" getter="" default="512">
</member>
diff --git a/doc/classes/String.xml b/doc/classes/String.xml
index 1f3d5596aa..f4d453700c 100644
--- a/doc/classes/String.xml
+++ b/doc/classes/String.xml
@@ -412,9 +412,9 @@
</method>
<method name="left" qualifiers="const">
<return type="String" />
- <argument index="0" name="position" type="int" />
+ <argument index="0" name="length" type="int" />
<description>
- Returns a number of characters from the left of the string. If negative [code]position[/code] is used, the characters are counted downwards from [String]'s length.
+ Returns a number of characters from the left of the string. If negative [code]length[/code] is used, the characters are counted downwards from [String]'s length.
Examples:
[codeblock]
print("sample text".left(3)) #prints "sam"
@@ -599,9 +599,9 @@
</method>
<method name="right" qualifiers="const">
<return type="String" />
- <argument index="0" name="position" type="int" />
+ <argument index="0" name="length" type="int" />
<description>
- Returns a number of characters from the right of the string. If negative [code]position[/code] is used, the characters are counted downwards from [String]'s length.
+ Returns a number of characters from the right of the string. If negative [code]length[/code] is used, the characters are counted downwards from [String]'s length.
Examples:
[codeblock]
print("sample text".right(3)) #prints "ext"
diff --git a/doc/classes/TextServer.xml b/doc/classes/TextServer.xml
index 2f57b76374..19be38b323 100644
--- a/doc/classes/TextServer.xml
+++ b/doc/classes/TextServer.xml
@@ -121,6 +121,20 @@
Returns font embolden strength.
</description>
</method>
+ <method name="font_get_face_count" qualifiers="const">
+ <return type="int" />
+ <argument index="0" name="font_rid" type="RID" />
+ <description>
+ Returns number of faces in the TrueType / OpenType collection.
+ </description>
+ </method>
+ <method name="font_get_face_index" qualifiers="const">
+ <return type="int" />
+ <argument index="0" name="font_rid" type="RID" />
+ <description>
+ Recturns an active face index in the TrueType / OpenType collection.
+ </description>
+ </method>
<method name="font_get_fixed_size" qualifiers="const">
<return type="int" />
<argument index="0" name="font_rid" type="RID" />
@@ -593,6 +607,14 @@
Sets font embolden strength. If [code]strength[/code] is not equal to zero, emboldens the font outlines. Negative values reduce the outline thickness.
</description>
</method>
+ <method name="font_set_face_index">
+ <return type="void" />
+ <argument index="0" name="font_rid" type="RID" />
+ <argument index="1" name="face_index" type="int" />
+ <description>
+ Sets an active face index in the TrueType / OpenType collection.
+ </description>
+ </method>
<method name="font_set_fixed_size">
<return type="void" />
<argument index="0" name="font_rid" type="RID" />
diff --git a/doc/classes/TextServerExtension.xml b/doc/classes/TextServerExtension.xml
index 434d6f909c..b3be858ca1 100644
--- a/doc/classes/TextServerExtension.xml
+++ b/doc/classes/TextServerExtension.xml
@@ -114,6 +114,20 @@
Returns font embolden strength.
</description>
</method>
+ <method name="font_get_face_count" qualifiers="virtual const">
+ <return type="int" />
+ <argument index="0" name="font_rid" type="RID" />
+ <description>
+ Returns number of faces in the TrueType / OpenType collection.
+ </description>
+ </method>
+ <method name="font_get_face_index" qualifiers="virtual const">
+ <return type="int" />
+ <argument index="0" name="font_rid" type="RID" />
+ <description>
+ Returns an active face index in the TrueType / OpenType collection.
+ </description>
+ </method>
<method name="font_get_fixed_size" qualifiers="virtual const">
<return type="int" />
<argument index="0" name="font_rid" type="RID" />
@@ -590,6 +604,14 @@
Sets font embolden strength. If [code]strength[/code] is not equal to zero, emboldens the font outlines. Negative values reduce the outline thickness.
</description>
</method>
+ <method name="font_set_face_index" qualifiers="virtual">
+ <return type="void" />
+ <argument index="0" name="font_rid" type="RID" />
+ <argument index="1" name="face_index" type="int" />
+ <description>
+ Sets an active face index in the TrueType / OpenType collection.
+ </description>
+ </method>
<method name="font_set_fixed_size" qualifiers="virtual">
<return type="void" />
<argument index="0" name="font_rid" type="RID" />
diff --git a/doc/classes/TileData.xml b/doc/classes/TileData.xml
index d5c2693f8b..0c2961fd5e 100644
--- a/doc/classes/TileData.xml
+++ b/doc/classes/TileData.xml
@@ -79,7 +79,7 @@
Returns the occluder polygon of the tile for the TileSet occlusion layer with index [code]layer_id[/code].
</description>
</method>
- <method name="get_peering_bit_terrain" qualifiers="const">
+ <method name="get_terrain_peering_bit" qualifiers="const">
<return type="int" />
<argument index="0" name="peering_bit" type="int" enum="TileSet.CellNeighbor" />
<description>
@@ -185,7 +185,7 @@
Sets the occluder for the TileSet occlusion layer with index [code]layer_id[/code].
</description>
</method>
- <method name="set_peering_bit_terrain">
+ <method name="set_terrain_peering_bit">
<return type="void" />
<argument index="0" name="peering_bit" type="int" enum="TileSet.CellNeighbor" />
<argument index="1" name="terrain" type="int" />
@@ -205,6 +205,8 @@
</member>
<member name="probability" type="float" setter="set_probability" getter="get_probability" default="1.0">
</member>
+ <member name="terrain" type="int" setter="set_terrain" getter="get_terrain" default="-1">
+ </member>
<member name="terrain_set" type="int" setter="set_terrain_set" getter="get_terrain_set" default="-1">
</member>
<member name="texture_offset" type="Vector2i" setter="set_texture_offset" getter="get_texture_offset" default="Vector2i(0, 0)">
diff --git a/doc/classes/TileMap.xml b/doc/classes/TileMap.xml
index 259c800a78..d532f583e6 100644
--- a/doc/classes/TileMap.xml
+++ b/doc/classes/TileMap.xml
@@ -243,15 +243,30 @@
- The alternative tile identifier [code]alternative_tile[/code] identifies a tile alternative the source is a [TileSetAtlasSource], and the scene for a [TileSetScenesCollectionSource].
</description>
</method>
- <method name="set_cells_from_surrounding_terrains">
+ <method name="set_cells_terrain_connect">
<return type="void" />
<argument index="0" name="layer" type="int" />
<argument index="1" name="cells" type="Vector2i[]" />
<argument index="2" name="terrain_set" type="int" />
- <argument index="3" name="ignore_empty_terrains" type="bool" default="true" />
+ <argument index="3" name="terrain" type="int" />
+ <argument index="4" name="ignore_empty_terrains" type="bool" default="true" />
<description>
- Updates all the cells in the [code]cells[/code] coordinates array and replace them by tiles that matches the surrounding cells terrains. Only cells form the given [code]terrain_set[/code] are considered.
- If [code]ignore_empty_terrains[/code] is true, zones with no terrain defined are ignored to select the tiles.
+ Update all the cells in the [code]cells[/code] coordinates array so that they use the given [code]terrain[/code] for the given [code]terrain_set[/code]. If an updated cell has the same terrain as one of its neighboring cells, this function tries to join the two. This function might update neighboring tiles if needed to create correct terrain transitions. If [code]ignore_empty_terrains[/code] is true, empty terrains will be ignored when trying to find the best fitting tile for the given terrain constraints.
+ If [code]ignore_empty_terrains[/code] is true, empty terrains will be ignored when trying to find the best fitting tile for the given terrain constraints.
+ [b]Note:[/b] To work correctly, [code]set_cells_terrain_connect[/code] requires the TileMap's TileSet to have terrains set up with all required terrain combinations. Otherwise, it may produce unexpected results.
+ </description>
+ </method>
+ <method name="set_cells_terrain_path">
+ <return type="void" />
+ <argument index="0" name="layer" type="int" />
+ <argument index="1" name="path" type="Vector2i[]" />
+ <argument index="2" name="terrain_set" type="int" />
+ <argument index="3" name="terrain" type="int" />
+ <argument index="4" name="ignore_empty_terrains" type="bool" default="true" />
+ <description>
+ Update all the cells in the [code]cells[/code] coordinates array so that they use the given [code]terrain[/code] for the given [code]terrain_set[/code]. The function will also connect two successive cell in the path with the same terrain. This function might update neighboring tiles if needed to create correct terrain transitions.
+ If [code]ignore_empty_terrains[/code] is true, empty terrains will be ignored when trying to find the best fitting tile for the given terrain constraints.
+ [b]Note:[/b] To work correctly, [code]set_cells_terrain_path[/code] requires the TileMap's TileSet to have terrains set up with all required terrain combinations. Otherwise, it may produce unexpected results.
</description>
</method>
<method name="set_layer_enabled">
diff --git a/doc/classes/WorldEnvironment.xml b/doc/classes/WorldEnvironment.xml
index 8afe169874..ed8f0b9a04 100644
--- a/doc/classes/WorldEnvironment.xml
+++ b/doc/classes/WorldEnvironment.xml
@@ -16,6 +16,7 @@
</tutorials>
<members>
<member name="camera_effects" type="CameraEffects" setter="set_camera_effects" getter="get_camera_effects">
+ The [CameraEffects] resource used by this [WorldEnvironment], defining the default properties. This [CameraEffects] resource will be used by all [Camera3D]s that do not define their own [CameraEffects].
</member>
<member name="environment" type="Environment" setter="set_environment" getter="get_environment">
The [Environment] resource used by this [WorldEnvironment], defining the default properties.
diff --git a/doc/tools/make_rst.py b/doc/tools/make_rst.py
index 2e227ce578..f59f2ff872 100755
--- a/doc/tools/make_rst.py
+++ b/doc/tools/make_rst.py
@@ -4,7 +4,9 @@
import argparse
import os
+import platform
import re
+import sys
import xml.etree.ElementTree as ET
from collections import OrderedDict
@@ -55,9 +57,11 @@ BASE_STRINGS = [
]
strings_l10n = {}
+STYLES = {}
+
def print_error(error, state): # type: (str, State) -> None
- print("ERROR: {}".format(error))
+ print("{}{}ERROR:{} {}{}".format(STYLES["red"], STYLES["bold"], STYLES["regular"], error, STYLES["reset"]))
state.num_errors += 1
@@ -399,10 +403,26 @@ def parse_arguments(root): # type: (ET.Element) -> List[ParameterDef]
def main(): # type: () -> None
+ # Enable ANSI escape code support on Windows 10 and later (for colored console output).
+ # <https://bugs.python.org/issue29059>
+ if platform.system().lower() == "windows":
+ from ctypes import windll, c_int, byref
+
+ stdout_handle = windll.kernel32.GetStdHandle(c_int(-11))
+ mode = c_int(0)
+ windll.kernel32.GetConsoleMode(c_int(stdout_handle), byref(mode))
+ mode = c_int(mode.value | 4)
+ windll.kernel32.SetConsoleMode(c_int(stdout_handle), mode)
+
parser = argparse.ArgumentParser()
parser.add_argument("path", nargs="+", help="A path to an XML file or a directory containing XML files to parse.")
parser.add_argument("--filter", default="", help="The filepath pattern for XML files to filter.")
parser.add_argument("--lang", "-l", default="en", help="Language to use for section headings.")
+ parser.add_argument(
+ "--color",
+ action="store_true",
+ help="If passed, force colored output even if stdout is not a TTY (useful for continuous integration).",
+ )
group = parser.add_mutually_exclusive_group()
group.add_argument("--output", "-o", default=".", help="The directory to save output .rst files in.")
group.add_argument(
@@ -412,6 +432,13 @@ def main(): # type: () -> None
)
args = parser.parse_args()
+ should_color = args.color or (hasattr(sys.stdout, "isatty") and sys.stdout.isatty())
+ STYLES["red"] = "\x1b[91m" if should_color else ""
+ STYLES["green"] = "\x1b[92m" if should_color else ""
+ STYLES["bold"] = "\x1b[1m" if should_color else ""
+ STYLES["regular"] = "\x1b[22m" if should_color else ""
+ STYLES["reset"] = "\x1b[0m" if should_color else ""
+
# Retrieve heading translations for the given language.
if not args.dry_run and args.lang != "en":
lang_file = os.path.join(
@@ -464,17 +491,17 @@ def main(): # type: () -> None
try:
tree = ET.parse(cur_file)
except ET.ParseError as e:
- print_error("{}.xml: Parse error while reading the file: {}".format(cur_file, e), state)
+ print_error("{}: Parse error while reading the file: {}".format(cur_file, e), state)
continue
doc = tree.getroot()
if "version" not in doc.attrib:
- print_error('{}.xml: "version" attribute missing from "doc".'.format(cur_file), state)
+ print_error('{}: "version" attribute missing from "doc".'.format(cur_file), state)
continue
name = doc.attrib["name"]
if name in classes:
- print_error('{}.xml: Duplicate class "{}".'.format(cur_file, name), state)
+ print_error('{}: Duplicate class "{}".'.format(cur_file, name), state)
continue
classes[name] = (doc, cur_file)
@@ -499,16 +526,22 @@ def main(): # type: () -> None
make_rst_class(class_def, state, args.dry_run, args.output)
if state.num_errors == 0:
- print("No errors found in the class reference XML.")
+ print("{}No errors found in the class reference XML.{}".format(STYLES["green"], STYLES["reset"]))
if not args.dry_run:
print("Wrote reStructuredText files for each class to: %s" % args.output)
else:
if state.num_errors >= 2:
print(
- "%d errors were found in the class reference XML. Please check the messages above." % state.num_errors
+ "{}{} errors were found in the class reference XML. Please check the messages above.{}".format(
+ STYLES["red"], state.num_errors, STYLES["reset"]
+ )
)
else:
- print("1 error was found in the class reference XML. Please check the messages above.")
+ print(
+ "{}1 error was found in the class reference XML. Please check the messages above.{}".format(
+ STYLES["red"], STYLES["reset"]
+ )
+ )
exit(1)
diff --git a/editor/debugger/editor_debugger_node.cpp b/editor/debugger/editor_debugger_node.cpp
index bc28b11a71..e13af59d69 100644
--- a/editor/debugger/editor_debugger_node.cpp
+++ b/editor/debugger/editor_debugger_node.cpp
@@ -103,6 +103,7 @@ ScriptEditorDebugger *EditorDebuggerNode::_add_debugger() {
node->connect("remote_object_updated", callable_mp(this, &EditorDebuggerNode::_remote_object_updated), varray(id));
node->connect("remote_object_property_updated", callable_mp(this, &EditorDebuggerNode::_remote_object_property_updated), varray(id));
node->connect("remote_object_requested", callable_mp(this, &EditorDebuggerNode::_remote_object_requested), varray(id));
+ node->connect("errors_cleared", callable_mp(this, &EditorDebuggerNode::_update_errors));
if (tabs->get_tab_count() > 0) {
get_debugger(0)->clear_style();
@@ -267,40 +268,7 @@ void EditorDebuggerNode::_notification(int p_what) {
}
server->poll();
- // Errors and warnings
- int error_count = 0;
- int warning_count = 0;
- _for_all(tabs, [&](ScriptEditorDebugger *dbg) {
- error_count += dbg->get_error_count();
- warning_count += dbg->get_warning_count();
- });
-
- if (error_count != last_error_count || warning_count != last_warning_count) {
- _for_all(tabs, [&](ScriptEditorDebugger *dbg) {
- dbg->update_tabs();
- });
-
- if (error_count == 0 && warning_count == 0) {
- debugger_button->set_text(TTR("Debugger"));
- debugger_button->remove_theme_color_override("font_color");
- debugger_button->set_icon(Ref<Texture2D>());
- } else {
- debugger_button->set_text(TTR("Debugger") + " (" + itos(error_count + warning_count) + ")");
- if (error_count >= 1 && warning_count >= 1) {
- debugger_button->set_icon(get_theme_icon(SNAME("ErrorWarning"), SNAME("EditorIcons")));
- // Use error color to represent the highest level of severity reported.
- debugger_button->add_theme_color_override("font_color", get_theme_color(SNAME("error_color"), SNAME("Editor")));
- } else if (error_count >= 1) {
- debugger_button->set_icon(get_theme_icon(SNAME("Error"), SNAME("EditorIcons")));
- debugger_button->add_theme_color_override("font_color", get_theme_color(SNAME("error_color"), SNAME("Editor")));
- } else {
- debugger_button->set_icon(get_theme_icon(SNAME("Warning"), SNAME("EditorIcons")));
- debugger_button->add_theme_color_override("font_color", get_theme_color(SNAME("warning_color"), SNAME("Editor")));
- }
- }
- last_error_count = error_count;
- last_warning_count = warning_count;
- }
+ _update_errors();
// Remote scene tree update
remote_scene_tree_timeout -= get_process_delta_time();
@@ -361,6 +329,42 @@ void EditorDebuggerNode::_notification(int p_what) {
}
}
+void EditorDebuggerNode::_update_errors() {
+ int error_count = 0;
+ int warning_count = 0;
+ _for_all(tabs, [&](ScriptEditorDebugger *dbg) {
+ error_count += dbg->get_error_count();
+ warning_count += dbg->get_warning_count();
+ });
+
+ if (error_count != last_error_count || warning_count != last_warning_count) {
+ _for_all(tabs, [&](ScriptEditorDebugger *dbg) {
+ dbg->update_tabs();
+ });
+
+ if (error_count == 0 && warning_count == 0) {
+ debugger_button->set_text(TTR("Debugger"));
+ debugger_button->remove_theme_color_override("font_color");
+ debugger_button->set_icon(Ref<Texture2D>());
+ } else {
+ debugger_button->set_text(TTR("Debugger") + " (" + itos(error_count + warning_count) + ")");
+ if (error_count >= 1 && warning_count >= 1) {
+ debugger_button->set_icon(get_theme_icon(SNAME("ErrorWarning"), SNAME("EditorIcons")));
+ // Use error color to represent the highest level of severity reported.
+ debugger_button->add_theme_color_override("font_color", get_theme_color(SNAME("error_color"), SNAME("Editor")));
+ } else if (error_count >= 1) {
+ debugger_button->set_icon(get_theme_icon(SNAME("Error"), SNAME("EditorIcons")));
+ debugger_button->add_theme_color_override("font_color", get_theme_color(SNAME("error_color"), SNAME("Editor")));
+ } else {
+ debugger_button->set_icon(get_theme_icon(SNAME("Warning"), SNAME("EditorIcons")));
+ debugger_button->add_theme_color_override("font_color", get_theme_color(SNAME("warning_color"), SNAME("Editor")));
+ }
+ }
+ last_error_count = error_count;
+ last_warning_count = warning_count;
+ }
+}
+
void EditorDebuggerNode::_debugger_stopped(int p_id) {
ScriptEditorDebugger *dbg = get_debugger(p_id);
ERR_FAIL_COND(!dbg);
diff --git a/editor/debugger/editor_debugger_node.h b/editor/debugger/editor_debugger_node.h
index 87457fc09a..8dc53690eb 100644
--- a/editor/debugger/editor_debugger_node.h
+++ b/editor/debugger/editor_debugger_node.h
@@ -116,6 +116,7 @@ private:
ScriptEditorDebugger *_add_debugger();
EditorDebuggerRemoteObject *get_inspected_remote_object();
+ void _update_errors();
friend class DebuggerEditorPlugin;
friend class DebugAdapterParser;
diff --git a/editor/debugger/script_editor_debugger.cpp b/editor/debugger/script_editor_debugger.cpp
index 9184846408..05409dbeeb 100644
--- a/editor/debugger/script_editor_debugger.cpp
+++ b/editor/debugger/script_editor_debugger.cpp
@@ -1465,6 +1465,7 @@ void ScriptEditorDebugger::_clear_errors_list() {
error_tree->clear();
error_count = 0;
warning_count = 0;
+ emit_signal(SNAME("errors_cleared"));
update_tabs();
expand_all_button->set_disabled(true);
@@ -1626,6 +1627,7 @@ void ScriptEditorDebugger::_bind_methods() {
ADD_SIGNAL(MethodInfo("debug_data", PropertyInfo(Variant::STRING, "msg"), PropertyInfo(Variant::ARRAY, "data")));
ADD_SIGNAL(MethodInfo("set_breakpoint", PropertyInfo("script"), PropertyInfo(Variant::INT, "line"), PropertyInfo(Variant::BOOL, "enabled")));
ADD_SIGNAL(MethodInfo("clear_breakpoints"));
+ ADD_SIGNAL(MethodInfo("errors_cleared"));
}
void ScriptEditorDebugger::add_debugger_plugin(const Ref<Script> &p_script) {
diff --git a/editor/editor_node.cpp b/editor/editor_node.cpp
index 61f8ab1936..e0a5cab167 100644
--- a/editor/editor_node.cpp
+++ b/editor/editor_node.cpp
@@ -4863,7 +4863,7 @@ bool EditorNode::has_scenes_in_session() {
bool EditorNode::ensure_main_scene(bool p_from_native) {
pick_main_scene->set_meta("from_native", p_from_native); // Whether from play button or native run.
- String main_scene = GLOBAL_DEF("application/run/main_scene", "");
+ String main_scene = GLOBAL_DEF_BASIC("application/run/main_scene", "");
if (main_scene.is_empty()) {
current_menu_option = -1;
@@ -4929,7 +4929,7 @@ bool EditorNode::is_run_playing() const {
String EditorNode::get_run_playing_scene() const {
String run_filename = editor_run.get_running_scene();
if (run_filename.is_empty() && is_run_playing()) {
- run_filename = GLOBAL_DEF("application/run/main_scene", ""); // Must be the main scene then.
+ run_filename = GLOBAL_DEF_BASIC("application/run/main_scene", ""); // Must be the main scene then.
}
return run_filename;
diff --git a/editor/editor_properties.cpp b/editor/editor_properties.cpp
index 521f237fb1..a5c02c70d9 100644
--- a/editor/editor_properties.cpp
+++ b/editor/editor_properties.cpp
@@ -1259,12 +1259,13 @@ void EditorPropertyInteger::update_property() {
void EditorPropertyInteger::_bind_methods() {
}
-void EditorPropertyInteger::setup(int64_t p_min, int64_t p_max, int64_t p_step, bool p_allow_greater, bool p_allow_lesser) {
+void EditorPropertyInteger::setup(int64_t p_min, int64_t p_max, int64_t p_step, bool p_allow_greater, bool p_allow_lesser, const String &p_suffix) {
spin->set_min(p_min);
spin->set_max(p_max);
spin->set_step(p_step);
spin->set_allow_greater(p_allow_greater);
spin->set_allow_lesser(p_allow_lesser);
+ spin->set_suffix(p_suffix);
}
EditorPropertyInteger::EditorPropertyInteger() {
@@ -1596,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();
@@ -1608,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]);
@@ -1622,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);
@@ -1635,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++) {
@@ -1667,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
}
@@ -1788,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();
@@ -1802,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) {
@@ -1835,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]);
@@ -1846,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);
@@ -1857,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++) {
@@ -1889,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
}
@@ -1907,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();
@@ -1919,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]);
@@ -1933,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);
@@ -1946,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++) {
@@ -1978,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
}
@@ -2099,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();
@@ -2113,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]);
@@ -2130,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);
@@ -2140,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" };
@@ -2170,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
}
@@ -3492,7 +3697,7 @@ EditorProperty *EditorInspectorDefaultPlugin::get_editor_for_property(Object *p_
EditorPropertyInteger *editor = memnew(EditorPropertyInteger);
EditorPropertyRangeHint hint = _parse_range_hint(p_hint, p_hint_text, 1);
- editor->setup(hint.min, hint.max, hint.step, hint.greater, hint.lesser);
+ editor->setup(hint.min, hint.max, hint.step, hint.greater, hint.lesser, hint.suffix);
return editor;
}
@@ -3607,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;
@@ -3634,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 a3990db678..a3b98b7724 100644
--- a/editor/editor_properties.h
+++ b/editor/editor_properties.h
@@ -368,7 +368,7 @@ protected:
public:
virtual void update_property() override;
- void setup(int64_t p_min, int64_t p_max, int64_t p_step, bool p_allow_greater, bool p_allow_lesser);
+ void setup(int64_t p_min, int64_t p_max, int64_t p_step, bool p_allow_greater, bool p_allow_lesser, const String &p_suffix = String());
EditorPropertyInteger();
};
@@ -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/editor_properties_array_dict.cpp b/editor/editor_properties_array_dict.cpp
index b3a1f35218..f47c6e298b 100644
--- a/editor/editor_properties_array_dict.cpp
+++ b/editor/editor_properties_array_dict.cpp
@@ -217,11 +217,11 @@ void EditorPropertyArray::update_property() {
if (array.get_type() == Variant::NIL) {
edit->set_text(vformat(TTR("(Nil) %s"), array_type_name));
edit->set_pressed(false);
- if (vbox) {
+ if (container) {
set_bottom_editor(nullptr);
- memdelete(vbox);
+ memdelete(container);
button_add_item = nullptr;
- vbox = nullptr;
+ container = nullptr;
}
return;
}
@@ -241,10 +241,14 @@ void EditorPropertyArray::update_property() {
if (unfolded) {
updating = true;
- if (!vbox) {
- vbox = memnew(VBoxContainer);
- add_child(vbox);
- set_bottom_editor(vbox);
+ if (!container) {
+ container = memnew(MarginContainer);
+ container->set_theme_type_variation("MarginContainer4px");
+ add_child(container);
+ set_bottom_editor(container);
+
+ VBoxContainer *vbox = memnew(VBoxContainer);
+ container->add_child(vbox);
HBoxContainer *hbox = memnew(HBoxContainer);
vbox->add_child(hbox);
@@ -372,11 +376,11 @@ void EditorPropertyArray::update_property() {
updating = false;
} else {
- if (vbox) {
+ if (container) {
set_bottom_editor(nullptr);
- memdelete(vbox);
+ memdelete(container);
button_add_item = nullptr;
- vbox = nullptr;
+ container = nullptr;
}
}
}
@@ -687,7 +691,7 @@ EditorPropertyArray::EditorPropertyArray() {
add_child(edit);
add_focusable(edit);
- vbox = nullptr;
+ container = nullptr;
property_vbox = nullptr;
size_slider = nullptr;
button_add_item = nullptr;
@@ -791,11 +795,11 @@ void EditorPropertyDictionary::update_property() {
if (updated_val.get_type() == Variant::NIL) {
edit->set_text(TTR("Dictionary (Nil)")); // This provides symmetry with the array property.
edit->set_pressed(false);
- if (vbox) {
+ if (container) {
set_bottom_editor(nullptr);
- memdelete(vbox);
+ memdelete(container);
button_add_item = nullptr;
- vbox = nullptr;
+ container = nullptr;
}
return;
}
@@ -812,10 +816,14 @@ void EditorPropertyDictionary::update_property() {
if (unfolded) {
updating = true;
- if (!vbox) {
- vbox = memnew(VBoxContainer);
- add_child(vbox);
- set_bottom_editor(vbox);
+ if (!container) {
+ container = memnew(MarginContainer);
+ container->set_theme_type_variation("MarginContainer4px");
+ add_child(container);
+ set_bottom_editor(container);
+
+ VBoxContainer *vbox = memnew(VBoxContainer);
+ container->add_child(vbox);
property_vbox = memnew(VBoxContainer);
property_vbox->set_h_size_flags(SIZE_EXPAND_FILL);
@@ -1116,11 +1124,11 @@ void EditorPropertyDictionary::update_property() {
updating = false;
} else {
- if (vbox) {
+ if (container) {
set_bottom_editor(nullptr);
- memdelete(vbox);
+ memdelete(container);
button_add_item = nullptr;
- vbox = nullptr;
+ container = nullptr;
}
}
}
@@ -1188,7 +1196,7 @@ EditorPropertyDictionary::EditorPropertyDictionary() {
add_child(edit);
add_focusable(edit);
- vbox = nullptr;
+ container = nullptr;
button_add_item = nullptr;
paginator = nullptr;
change_type = memnew(PopupMenu);
@@ -1250,11 +1258,11 @@ void EditorPropertyLocalizableString::update_property() {
if (updated_val.get_type() == Variant::NIL) {
edit->set_text(TTR("Localizable String (Nil)")); // This provides symmetry with the array property.
edit->set_pressed(false);
- if (vbox) {
+ if (container) {
set_bottom_editor(nullptr);
- memdelete(vbox);
+ memdelete(container);
button_add_item = nullptr;
- vbox = nullptr;
+ container = nullptr;
}
return;
}
@@ -1271,10 +1279,14 @@ void EditorPropertyLocalizableString::update_property() {
if (unfolded) {
updating = true;
- if (!vbox) {
- vbox = memnew(VBoxContainer);
- add_child(vbox);
- set_bottom_editor(vbox);
+ if (!container) {
+ container = memnew(MarginContainer);
+ container->set_theme_type_variation("MarginContainer4px");
+ add_child(container);
+ set_bottom_editor(container);
+
+ VBoxContainer *vbox = memnew(VBoxContainer);
+ container->add_child(vbox);
property_vbox = memnew(VBoxContainer);
property_vbox->set_h_size_flags(SIZE_EXPAND_FILL);
@@ -1351,11 +1363,11 @@ void EditorPropertyLocalizableString::update_property() {
updating = false;
} else {
- if (vbox) {
+ if (container) {
set_bottom_editor(nullptr);
- memdelete(vbox);
+ memdelete(container);
button_add_item = nullptr;
- vbox = nullptr;
+ container = nullptr;
}
}
}
@@ -1410,7 +1422,7 @@ EditorPropertyLocalizableString::EditorPropertyLocalizableString() {
add_child(edit);
add_focusable(edit);
- vbox = nullptr;
+ container = nullptr;
button_add_item = nullptr;
paginator = nullptr;
updating = false;
diff --git a/editor/editor_properties_array_dict.h b/editor/editor_properties_array_dict.h
index 070353c538..44623149d0 100644
--- a/editor/editor_properties_array_dict.h
+++ b/editor/editor_properties_array_dict.h
@@ -89,7 +89,7 @@ class EditorPropertyArray : public EditorProperty {
int page_index = 0;
int changing_type_index;
Button *edit = nullptr;
- VBoxContainer *vbox = nullptr;
+ MarginContainer *container = nullptr;
VBoxContainer *property_vbox = nullptr;
EditorSpinSlider *size_slider = nullptr;
Button *button_add_item = nullptr;
@@ -146,9 +146,9 @@ class EditorPropertyDictionary : public EditorProperty {
int page_index = 0;
int changing_type_index;
Button *edit = nullptr;
- VBoxContainer *vbox = nullptr;
+ MarginContainer *container = nullptr;
VBoxContainer *property_vbox = nullptr;
- EditorSpinSlider *size_slider = nullptr;
+ EditorSpinSlider *size_sliderv;
Button *button_add_item = nullptr;
EditorPaginator *paginator = nullptr;
@@ -181,7 +181,7 @@ class EditorPropertyLocalizableString : public EditorProperty {
int page_length = 20;
int page_index = 0;
Button *edit = nullptr;
- VBoxContainer *vbox = nullptr;
+ MarginContainer *container = nullptr;
VBoxContainer *property_vbox = nullptr;
EditorSpinSlider *size_slider = nullptr;
Button *button_add_item = nullptr;
diff --git a/editor/editor_property_name_processor.cpp b/editor/editor_property_name_processor.cpp
index 1e7638bf72..397afc0653 100644
--- a/editor/editor_property_name_processor.cpp
+++ b/editor/editor_property_name_processor.cpp
@@ -213,6 +213,7 @@ EditorPropertyNameProcessor::EditorPropertyNameProcessor() {
capitalize_string_remaps["stdout"] = "stdout";
capitalize_string_remaps["sv"] = "SV";
capitalize_string_remaps["svg"] = "SVG";
+ capitalize_string_remaps["taa"] = "TAA";
capitalize_string_remaps["tcp"] = "TCP";
capitalize_string_remaps["ui"] = "UI";
capitalize_string_remaps["url"] = "URL";
diff --git a/editor/editor_themes.cpp b/editor/editor_themes.cpp
index 5ce6ca4823..7a80cf36a8 100644
--- a/editor/editor_themes.cpp
+++ b/editor/editor_themes.cpp
@@ -1283,6 +1283,13 @@ Ref<Theme> create_editor_theme(const Ref<Theme> p_theme) {
theme->set_constant("h_separation", "VFlowContainer", default_margin_size * EDSCALE);
theme->set_constant("v_separation", "VFlowContainer", default_margin_size * EDSCALE);
+ // Custom theme type for MarginContainer with 4px margins.
+ theme->set_type_variation("MarginContainer4px", "MarginContainer");
+ theme->set_constant("margin_left", "MarginContainer4px", 4 * EDSCALE);
+ theme->set_constant("margin_top", "MarginContainer4px", 4 * EDSCALE);
+ theme->set_constant("margin_right", "MarginContainer4px", 4 * EDSCALE);
+ theme->set_constant("margin_bottom", "MarginContainer4px", 4 * EDSCALE);
+
// Window
// Prevent corner artifacts between window title and body.
@@ -1626,7 +1633,11 @@ Ref<Theme> create_editor_theme(const Ref<Theme> p_theme) {
theme->set_stylebox("preview_picker_label", "ThemeEditor", theme_preview_picker_label_sb);
// Dictionary editor add item.
- theme->set_stylebox("DictionaryAddItem", "EditorStyles", make_flat_stylebox(prop_subsection_color, 4, 4, 4, 4, corner_radius));
+ // Expand to the left and right by 4px to compensate for the dictionary editor margins.
+ Ref<StyleBoxFlat> style_dictionary_add_item = make_flat_stylebox(prop_subsection_color, 0, 4, 0, 4, corner_radius);
+ style_dictionary_add_item->set_expand_margin_size(SIDE_LEFT, 4 * EDSCALE);
+ style_dictionary_add_item->set_expand_margin_size(SIDE_RIGHT, 4 * EDSCALE);
+ theme->set_stylebox("DictionaryAddItem", "EditorStyles", style_dictionary_add_item);
// adaptive script theme constants
// for comments and elements with lower relevance
diff --git a/editor/editor_toaster.cpp b/editor/editor_toaster.cpp
index 7ca88bd2a2..4986bccc35 100644
--- a/editor/editor_toaster.cpp
+++ b/editor/editor_toaster.cpp
@@ -234,6 +234,16 @@ void EditorToaster::_auto_hide_or_free_toasts() {
to_delete[i]->queue_delete();
toasts.erase(to_delete[i]);
}
+
+ if (toasts.is_empty()) {
+ main_button->set_tooltip(TTR("No notifications."));
+ main_button->set_modulate(Color(0.5, 0.5, 0.5));
+ main_button->set_disabled(true);
+ } else {
+ main_button->set_tooltip(TTR("Show notifications."));
+ main_button->set_modulate(Color(1, 1, 1));
+ main_button->set_disabled(false);
+ }
}
void EditorToaster::_draw_button() {
@@ -508,6 +518,9 @@ EditorToaster::EditorToaster() {
// Main button.
main_button = memnew(Button);
+ main_button->set_tooltip(TTR("No notifications."));
+ main_button->set_modulate(Color(0.5, 0.5, 0.5));
+ main_button->set_disabled(true);
main_button->set_flat(true);
main_button->connect("pressed", callable_mp(this, &EditorToaster::_set_notifications_enabled), varray(true));
main_button->connect("pressed", callable_mp(this, &EditorToaster::_repop_old));
@@ -521,6 +534,7 @@ EditorToaster::EditorToaster() {
add_child(disable_notifications_panel);
disable_notifications_button = memnew(Button);
+ disable_notifications_button->set_tooltip(TTR("Silence the notifications."));
disable_notifications_button->set_flat(true);
disable_notifications_button->connect("pressed", callable_mp(this, &EditorToaster::_set_notifications_enabled), varray(false));
disable_notifications_panel->add_child(disable_notifications_button);
diff --git a/editor/icons/TerrainConnect.svg b/editor/icons/TerrainConnect.svg
new file mode 100644
index 0000000000..3b6b8fd5a2
--- /dev/null
+++ b/editor/icons/TerrainConnect.svg
@@ -0,0 +1 @@
+<svg height="32" viewBox="0 0 16 16" width="32" xmlns="http://www.w3.org/2000/svg"><g fill="#e0e0e0"><circle cx="8" cy="8" r="2.000028" stroke-width="1.09711"/><g stroke-width=".5" transform="translate(0 -1036.4)"><path d="m7 1039.9h-1l2-2.5 2 2.5h-1v2h-2z"/><path d="m3.5606601 1041.3748-.7071068.707-.3535533-3.1818 3.1819804.3535-.7071067.7071.7071067.7071-1.4142135 1.4142z"/><path d="m11.0252 1039.9606-.707-.7071 3.1818-.3535-.3535 3.1819-.7071-.7071-.7071.7071-1.4142-1.4142z"/><path d="m12.43934 1047.4252.707107-.707.353553 3.1818-3.18198-.3535.707106-.7071-.707106-.7071 1.414214-1.4142z"/><path d="m4.9748005 1048.8394.707.7071-3.1818.3535.3535-3.1819.7071.7071.7071-.7071 1.4142 1.4142z"/><path d="m12.5 1043.4v-1l2.5 2-2.5 2v-1h-2v-2z"/><path d="m9 1048.9h1l-2 2.5-2-2.5h1v-2h2z"/><path d="m3.5 1045.4v1l-2.5-2 2.5-2v1h2v2z"/></g></g></svg>
diff --git a/editor/icons/TerrainPath.svg b/editor/icons/TerrainPath.svg
new file mode 100644
index 0000000000..6352bbd37e
--- /dev/null
+++ b/editor/icons/TerrainPath.svg
@@ -0,0 +1 @@
+<svg height="32" viewBox="0 0 16 16" width="32" xmlns="http://www.w3.org/2000/svg"><g fill="#e0e0e0" transform="translate(0 -1036.4)"><circle cx="3" cy="1049.4" r="2.000028" stroke-width="1.09711"/><circle cx="13" cy="1039.4" r="2.000028" stroke-width="1.09711"/><path d="m7 1038.4v10h-4v2h4 2v-2-8h4v-2h-4z" stroke-width=".46291"/></g></svg>
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/import/dynamic_font_import_settings.cpp b/editor/import/dynamic_font_import_settings.cpp
index b361dcd036..5e203a3e39 100644
--- a/editor/import/dynamic_font_import_settings.cpp
+++ b/editor/import/dynamic_font_import_settings.cpp
@@ -454,7 +454,11 @@ void DynamicFontImportSettings::_add_glyph_range_item(int32_t p_start, int32_t p
void DynamicFontImportSettings::_main_prop_changed(const String &p_edited_property) {
// Update font preview.
- if (p_edited_property == "antialiased") {
+ if (p_edited_property == "face_index") {
+ if (font_preview->get_data_count() > 0) {
+ font_preview->get_data(0)->set_face_index(import_settings_data->get("face_index"));
+ }
+ } else if (p_edited_property == "antialiased") {
if (font_preview->get_data_count() > 0) {
font_preview->get_data(0)->set_antialiased(import_settings_data->get("antialiased"));
}
@@ -945,6 +949,7 @@ void DynamicFontImportSettings::_notification(int p_what) {
void DynamicFontImportSettings::_re_import() {
HashMap<StringName, Variant> main_settings;
+ main_settings["face_index"] = import_settings_data->get("face_index");
main_settings["antialiased"] = import_settings_data->get("antialiased");
main_settings["generate_mipmaps"] = import_settings_data->get("generate_mipmaps");
main_settings["multichannel_signed_distance_field"] = import_settings_data->get("multichannel_signed_distance_field");
@@ -1299,6 +1304,7 @@ void DynamicFontImportSettings::open_settings(const String &p_path) {
import_settings_data->notify_property_list_changed();
if (font_preview->get_data_count() > 0) {
+ font_preview->get_data(0)->set_face_index(import_settings_data->get("face_index"));
font_preview->get_data(0)->set_antialiased(import_settings_data->get("antialiased"));
font_preview->get_data(0)->set_multichannel_signed_distance_field(import_settings_data->get("multichannel_signed_distance_field"));
font_preview->get_data(0)->set_msdf_pixel_range(import_settings_data->get("msdf_pixel_range"));
@@ -1360,6 +1366,7 @@ DynamicFontImportSettings *DynamicFontImportSettings::get_singleton() {
DynamicFontImportSettings::DynamicFontImportSettings() {
singleton = this;
+ options_general.push_back(ResourceImporter::ImportOption(PropertyInfo(Variant::INT, "face_index"), 0));
options_general.push_back(ResourceImporter::ImportOption(PropertyInfo(Variant::BOOL, "antialiased"), true));
options_general.push_back(ResourceImporter::ImportOption(PropertyInfo(Variant::BOOL, "generate_mipmaps"), false));
options_general.push_back(ResourceImporter::ImportOption(PropertyInfo(Variant::BOOL, "multichannel_signed_distance_field", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_UPDATE_ALL_IF_MODIFIED), true));
diff --git a/editor/import/resource_importer_dynamic_font.cpp b/editor/import/resource_importer_dynamic_font.cpp
index 04f6a0b7af..a92b0fe280 100644
--- a/editor/import/resource_importer_dynamic_font.cpp
+++ b/editor/import/resource_importer_dynamic_font.cpp
@@ -50,7 +50,9 @@ void ResourceImporterDynamicFont::get_recognized_extensions(List<String> *p_exte
if (p_extensions) {
#ifdef MODULE_FREETYPE_ENABLED
p_extensions->push_back("ttf");
+ p_extensions->push_back("ttc");
p_extensions->push_back("otf");
+ p_extensions->push_back("otc");
p_extensions->push_back("woff");
p_extensions->push_back("woff2");
p_extensions->push_back("pfb");
@@ -101,6 +103,8 @@ String ResourceImporterDynamicFont::get_preset_name(int p_idx) const {
void ResourceImporterDynamicFont::get_import_options(const String &p_path, List<ImportOption> *r_options, int p_preset) const {
bool msdf = p_preset == PRESET_MSDF;
+ r_options->push_back(ImportOption(PropertyInfo(Variant::INT, "face_index"), 0));
+
r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL, "antialiased"), true));
r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL, "generate_mipmaps"), false));
r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL, "multichannel_signed_distance_field", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_UPDATE_ALL_IF_MODIFIED), (msdf) ? true : false));
@@ -179,6 +183,8 @@ void ResourceImporterDynamicFont::show_advanced_options(const String &p_path) {
Error ResourceImporterDynamicFont::import(const String &p_source_file, const String &p_save_path, const HashMap<StringName, Variant> &p_options, List<String> *r_platform_variants, List<String> *r_gen_files, Variant *r_metadata) {
print_verbose("Importing dynamic font from: " + p_source_file);
+ int face_index = p_options["face_index"];
+
bool antialiased = p_options["antialiased"];
bool generate_mipmaps = p_options["generate_mipmaps"];
bool msdf = p_options["multichannel_signed_distance_field"];
@@ -200,6 +206,7 @@ Error ResourceImporterDynamicFont::import(const String &p_source_file, const Str
Ref<FontData> font;
font.instantiate();
font->set_data(data);
+ font->set_face_index(face_index);
font->set_antialiased(antialiased);
font->set_generate_mipmaps(generate_mipmaps);
font->set_multichannel_signed_distance_field(msdf);
diff --git a/editor/import/resource_importer_scene.cpp b/editor/import/resource_importer_scene.cpp
index 80230bc316..f2975b1d7a 100644
--- a/editor/import/resource_importer_scene.cpp
+++ b/editor/import/resource_importer_scene.cpp
@@ -658,6 +658,44 @@ Node *ResourceImporterScene::_pre_fix_node(Node *p_node, Node *p_root, HashMap<R
}
}
}
+ } else if (_teststr(name, "vehicle")) {
+ if (isroot) {
+ return p_node;
+ }
+
+ Node *owner = p_node->get_owner();
+ Node3D *s = Object::cast_to<Node3D>(p_node);
+ VehicleBody3D *bv = memnew(VehicleBody3D);
+ String n = _fixstr(p_node->get_name(), "vehicle");
+ bv->set_name(n);
+ p_node->replace_by(bv);
+ p_node->set_name(n);
+ bv->add_child(p_node);
+ bv->set_owner(owner);
+ p_node->set_owner(owner);
+ bv->set_transform(s->get_transform());
+ s->set_transform(Transform3D());
+
+ p_node = bv;
+ } else if (_teststr(name, "wheel")) {
+ if (isroot) {
+ return p_node;
+ }
+
+ Node *owner = p_node->get_owner();
+ Node3D *s = Object::cast_to<Node3D>(p_node);
+ VehicleWheel3D *bv = memnew(VehicleWheel3D);
+ String n = _fixstr(p_node->get_name(), "wheel");
+ bv->set_name(n);
+ p_node->replace_by(bv);
+ p_node->set_name(n);
+ bv->add_child(p_node);
+ bv->set_owner(owner);
+ p_node->set_owner(owner);
+ bv->set_transform(s->get_transform());
+ s->set_transform(Transform3D());
+
+ p_node = bv;
} else if (Object::cast_to<ImporterMeshInstance3D>(p_node)) {
//last attempt, maybe collision inside the mesh data
diff --git a/editor/import/resource_importer_texture.cpp b/editor/import/resource_importer_texture.cpp
index 71b8c54422..deb3047864 100644
--- a/editor/import/resource_importer_texture.cpp
+++ b/editor/import/resource_importer_texture.cpp
@@ -104,13 +104,13 @@ void ResourceImporterTexture::update_imports() {
bool changed = false;
if (E.value.flags & MAKE_NORMAL_FLAG && int(cf->get_value("params", "compress/normal_map")) == 0) {
- print_line(vformat("%s: Texture detected as used as a normal map in 3D. Enabling red-green texture compression to reduce memory usage (blue channel is discarded).", String(E.key)));
+ print_line(vformat(TTR("%s: Texture detected as used as a normal map in 3D. Enabling red-green texture compression to reduce memory usage (blue channel is discarded)."), String(E.key)));
cf->set_value("params", "compress/normal_map", 1);
changed = true;
}
if (E.value.flags & MAKE_ROUGHNESS_FLAG && int(cf->get_value("params", "roughness/mode")) == 0) {
- print_line(vformat("%s: Texture detected as used as a roughness map in 3D. Enabling roughness limiter based on the detected associated normal map at %s.", String(E.key), E.value.normal_path_for_roughness));
+ print_line(vformat(TTR("%s: Texture detected as used as a roughness map in 3D. Enabling roughness limiter based on the detected associated normal map at %s."), String(E.key), E.value.normal_path_for_roughness));
cf->set_value("params", "roughness/mode", E.value.channel_for_roughness + 2);
cf->set_value("params", "roughness/src_normal", E.value.normal_path_for_roughness);
changed = true;
@@ -127,7 +127,7 @@ void ResourceImporterTexture::update_imports() {
cf->set_value("params", "compress/mode", COMPRESS_BASIS_UNIVERSAL);
compress_string = "Basis Universal";
}
- print_line(vformat("%s: Texture detected as used in 3D. Enabling mipmap generation and setting the texture compression mode to %s.", String(E.key), compress_string));
+ print_line(vformat(TTR("%s: Texture detected as used in 3D. Enabling mipmap generation and setting the texture compression mode to %s."), String(E.key), compress_string));
cf->set_value("params", "mipmaps/generate", true);
changed = true;
}
diff --git a/editor/plugins/canvas_item_editor_plugin.cpp b/editor/plugins/canvas_item_editor_plugin.cpp
index bfe9e202d6..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);
}
@@ -4089,6 +4089,8 @@ void CanvasItemEditor::_button_tool_select(int p_index) {
void CanvasItemEditor::_insert_animation_keys(bool p_location, bool p_rotation, bool p_scale, bool p_on_existing) {
const HashMap<Node *, Object *> &selection = editor_selection->get_selection();
+ AnimationTrackEditor *te = AnimationPlayerEditor::get_singleton()->get_track_editor();
+ te->make_insert_queue();
for (const KeyValue<Node *, Object *> &E : selection) {
CanvasItem *canvas_item = Object::cast_to<CanvasItem>(E.key);
if (!canvas_item || !canvas_item->is_visible_in_tree()) {
@@ -4103,13 +4105,13 @@ void CanvasItemEditor::_insert_animation_keys(bool p_location, bool p_rotation,
Node2D *n2d = Object::cast_to<Node2D>(canvas_item);
if (key_pos && p_location) {
- AnimationPlayerEditor::get_singleton()->get_track_editor()->insert_node_value_key(n2d, "position", n2d->get_position(), p_on_existing);
+ te->insert_node_value_key(n2d, "position", n2d->get_position(), p_on_existing);
}
if (key_rot && p_rotation) {
- AnimationPlayerEditor::get_singleton()->get_track_editor()->insert_node_value_key(n2d, "rotation", n2d->get_rotation(), p_on_existing);
+ te->insert_node_value_key(n2d, "rotation", n2d->get_rotation(), p_on_existing);
}
if (key_scale && p_scale) {
- AnimationPlayerEditor::get_singleton()->get_track_editor()->insert_node_value_key(n2d, "scale", n2d->get_scale(), p_on_existing);
+ te->insert_node_value_key(n2d, "scale", n2d->get_scale(), p_on_existing);
}
if (n2d->has_meta("_edit_bone_") && n2d->get_parent_item()) {
@@ -4135,13 +4137,13 @@ void CanvasItemEditor::_insert_animation_keys(bool p_location, bool p_rotation,
if (has_chain && ik_chain.size()) {
for (Node2D *&F : ik_chain) {
if (key_pos) {
- AnimationPlayerEditor::get_singleton()->get_track_editor()->insert_node_value_key(F, "position", F->get_position(), p_on_existing);
+ te->insert_node_value_key(F, "position", F->get_position(), p_on_existing);
}
if (key_rot) {
- AnimationPlayerEditor::get_singleton()->get_track_editor()->insert_node_value_key(F, "rotation", F->get_rotation(), p_on_existing);
+ te->insert_node_value_key(F, "rotation", F->get_rotation(), p_on_existing);
}
if (key_scale) {
- AnimationPlayerEditor::get_singleton()->get_track_editor()->insert_node_value_key(F, "scale", F->get_scale(), p_on_existing);
+ te->insert_node_value_key(F, "scale", F->get_scale(), p_on_existing);
}
}
}
@@ -4151,16 +4153,17 @@ void CanvasItemEditor::_insert_animation_keys(bool p_location, bool p_rotation,
Control *ctrl = Object::cast_to<Control>(canvas_item);
if (key_pos) {
- AnimationPlayerEditor::get_singleton()->get_track_editor()->insert_node_value_key(ctrl, "rect_position", ctrl->get_position(), p_on_existing);
+ te->insert_node_value_key(ctrl, "rect_position", ctrl->get_position(), p_on_existing);
}
if (key_rot) {
- AnimationPlayerEditor::get_singleton()->get_track_editor()->insert_node_value_key(ctrl, "rect_rotation", ctrl->get_rotation(), p_on_existing);
+ te->insert_node_value_key(ctrl, "rect_rotation", ctrl->get_rotation(), p_on_existing);
}
if (key_scale) {
- AnimationPlayerEditor::get_singleton()->get_track_editor()->insert_node_value_key(ctrl, "rect_size", ctrl->get_size(), p_on_existing);
+ te->insert_node_value_key(ctrl, "rect_size", ctrl->get_size(), p_on_existing);
}
}
}
+ te->commit_insert_queue();
}
void CanvasItemEditor::_update_override_camera_button(bool p_game_running) {
diff --git a/editor/plugins/tiles/tile_data_editors.cpp b/editor/plugins/tiles/tile_data_editors.cpp
index d035c038d3..ec45341970 100644
--- a/editor/plugins/tiles/tile_data_editors.cpp
+++ b/editor/plugins/tiles/tile_data_editors.cpp
@@ -1676,10 +1676,15 @@ void TileDataTerrainsEditor::forward_draw_over_atlas(TileAtlasView *p_tile_atlas
Vector<Color> color;
color.push_back(Color(1.0, 1.0, 1.0, 0.5));
+ Vector<Vector2> polygon = tile_set->get_terrain_polygon(terrain_set);
+ if (Geometry2D::is_point_in_polygon(xform.affine_inverse().xform(mouse_pos), polygon)) {
+ p_canvas_item->draw_set_transform_matrix(p_transform * xform);
+ p_canvas_item->draw_polygon(polygon, color);
+ }
for (int i = 0; i < TileSet::CELL_NEIGHBOR_MAX; i++) {
TileSet::CellNeighbor bit = TileSet::CellNeighbor(i);
- if (tile_set->is_valid_peering_bit_terrain(terrain_set, bit)) {
- Vector<Vector2> polygon = tile_set->get_terrain_bit_polygon(terrain_set, bit);
+ if (tile_set->is_valid_terrain_peering_bit(terrain_set, bit)) {
+ polygon = tile_set->get_terrain_peering_bit_polygon(terrain_set, bit);
if (Geometry2D::is_point_in_polygon(xform.affine_inverse().xform(mouse_pos), polygon)) {
p_canvas_item->draw_set_transform_matrix(p_transform * xform);
p_canvas_item->draw_polygon(polygon, color);
@@ -1806,10 +1811,19 @@ void TileDataTerrainsEditor::forward_draw_over_atlas(TileAtlasView *p_tile_atlas
Rect2i texture_region = p_tile_set_atlas_source->get_tile_texture_region(coords);
Vector2i position = texture_region.get_center() + p_tile_set_atlas_source->get_tile_effective_texture_offset(coords, 0);
+ Vector<Vector2> polygon = tile_set->get_terrain_polygon(terrain_set);
+ for (int j = 0; j < polygon.size(); j++) {
+ polygon.write[j] += position;
+ }
+ if (!Geometry2D::intersect_polygons(polygon, mouse_pos_rect_polygon).is_empty()) {
+ // Draw terrain.
+ p_canvas_item->draw_polygon(polygon, color);
+ }
+
for (int i = 0; i < TileSet::CELL_NEIGHBOR_MAX; i++) {
TileSet::CellNeighbor bit = TileSet::CellNeighbor(i);
- if (tile_set->is_valid_peering_bit_terrain(terrain_set, bit)) {
- Vector<Vector2> polygon = tile_set->get_terrain_bit_polygon(terrain_set, bit);
+ if (tile_set->is_valid_terrain_peering_bit(terrain_set, bit)) {
+ polygon = tile_set->get_terrain_peering_bit_polygon(terrain_set, bit);
for (int j = 0; j < polygon.size(); j++) {
polygon.write[j] += position;
}
@@ -1850,10 +1864,16 @@ void TileDataTerrainsEditor::forward_draw_over_alternatives(TileAtlasView *p_til
Vector<Color> color;
color.push_back(Color(1.0, 1.0, 1.0, 0.5));
+ Vector<Vector2> polygon = tile_set->get_terrain_polygon(terrain_set);
+ if (Geometry2D::is_point_in_polygon(xform.affine_inverse().xform(mouse_pos), polygon)) {
+ p_canvas_item->draw_set_transform_matrix(p_transform * xform);
+ p_canvas_item->draw_polygon(polygon, color);
+ }
+
for (int i = 0; i < TileSet::CELL_NEIGHBOR_MAX; i++) {
TileSet::CellNeighbor bit = TileSet::CellNeighbor(i);
- if (tile_set->is_valid_peering_bit_terrain(terrain_set, bit)) {
- Vector<Vector2> polygon = tile_set->get_terrain_bit_polygon(terrain_set, bit);
+ if (tile_set->is_valid_terrain_peering_bit(terrain_set, bit)) {
+ polygon = tile_set->get_terrain_peering_bit_polygon(terrain_set, bit);
if (Geometry2D::is_point_in_polygon(xform.affine_inverse().xform(mouse_pos), polygon)) {
p_canvas_item->draw_set_transform_matrix(p_transform * xform);
p_canvas_item->draw_polygon(polygon, color);
@@ -1926,10 +1946,11 @@ void TileDataTerrainsEditor::forward_painting_atlas_gui_input(TileAtlasView *p_t
if (!drag_modified.has(cell)) {
Dictionary dict;
dict["terrain_set"] = tile_data->get_terrain_set();
+ dict["terrain"] = tile_data->get_terrain();
Array array;
for (int j = 0; j < TileSet::CELL_NEIGHBOR_MAX; j++) {
TileSet::CellNeighbor bit = TileSet::CellNeighbor(j);
- array.push_back(tile_data->is_valid_peering_bit_terrain(bit) ? tile_data->get_peering_bit_terrain(bit) : -1);
+ array.push_back(tile_data->is_valid_terrain_peering_bit(bit) ? tile_data->get_terrain_peering_bit(bit) : -1);
}
dict["terrain_peering_bits"] = array;
drag_modified[cell] = dict;
@@ -1958,10 +1979,11 @@ void TileDataTerrainsEditor::forward_painting_atlas_gui_input(TileAtlasView *p_t
if (!drag_modified.has(cell)) {
Dictionary dict;
dict["terrain_set"] = tile_data->get_terrain_set();
+ dict["terrain"] = tile_data->get_terrain();
Array array;
for (int j = 0; j < TileSet::CELL_NEIGHBOR_MAX; j++) {
TileSet::CellNeighbor bit = TileSet::CellNeighbor(j);
- array.push_back(tile_data->is_valid_peering_bit_terrain(bit) ? tile_data->get_peering_bit_terrain(bit) : -1);
+ array.push_back(tile_data->is_valid_terrain_peering_bit(bit) ? tile_data->get_terrain_peering_bit(bit) : -1);
}
dict["terrain_peering_bits"] = array;
drag_modified[cell] = dict;
@@ -1970,12 +1992,17 @@ void TileDataTerrainsEditor::forward_painting_atlas_gui_input(TileAtlasView *p_t
// Set the terrains bits.
Rect2i texture_region = p_tile_set_atlas_source->get_tile_texture_region(coords);
Vector2i position = texture_region.get_center() + p_tile_set_atlas_source->get_tile_effective_texture_offset(coords, 0);
+
+ Vector<Vector2> polygon = tile_set->get_terrain_polygon(tile_data->get_terrain_set());
+ if (Geometry2D::is_segment_intersecting_polygon(mm->get_position() - position, drag_last_pos - position, polygon)) {
+ tile_data->set_terrain(terrain);
+ }
for (int j = 0; j < TileSet::CELL_NEIGHBOR_MAX; j++) {
TileSet::CellNeighbor bit = TileSet::CellNeighbor(j);
- if (tile_data->is_valid_peering_bit_terrain(bit)) {
- Vector<Vector2> polygon = tile_set->get_terrain_bit_polygon(tile_data->get_terrain_set(), bit);
+ if (tile_data->is_valid_terrain_peering_bit(bit)) {
+ polygon = tile_set->get_terrain_peering_bit_polygon(tile_data->get_terrain_set(), bit);
if (Geometry2D::is_segment_intersecting_polygon(mm->get_position() - position, drag_last_pos - position, polygon)) {
- tile_data->set_peering_bit_terrain(bit, terrain);
+ tile_data->set_terrain_peering_bit(bit, terrain);
}
}
}
@@ -2000,12 +2027,17 @@ void TileDataTerrainsEditor::forward_painting_atlas_gui_input(TileAtlasView *p_t
Vector2i position = texture_region.get_center() + p_tile_set_atlas_source->get_tile_effective_texture_offset(coords, 0);
dummy_object->set("terrain_set", terrain_set);
dummy_object->set("terrain", -1);
+
+ Vector<Vector2> polygon = tile_set->get_terrain_polygon(terrain_set);
+ if (Geometry2D::is_point_in_polygon(mb->get_position() - position, polygon)) {
+ dummy_object->set("terrain", tile_data->get_terrain());
+ }
for (int i = 0; i < TileSet::CELL_NEIGHBOR_MAX; i++) {
TileSet::CellNeighbor bit = TileSet::CellNeighbor(i);
- if (tile_set->is_valid_peering_bit_terrain(terrain_set, bit)) {
- Vector<Vector2> polygon = tile_set->get_terrain_bit_polygon(terrain_set, bit);
+ if (tile_set->is_valid_terrain_peering_bit(terrain_set, bit)) {
+ polygon = tile_set->get_terrain_peering_bit_polygon(terrain_set, bit);
if (Geometry2D::is_point_in_polygon(mb->get_position() - position, polygon)) {
- dummy_object->set("terrain", tile_data->get_peering_bit_terrain(bit));
+ dummy_object->set("terrain", tile_data->get_terrain_peering_bit(bit));
}
}
}
@@ -2044,10 +2076,11 @@ void TileDataTerrainsEditor::forward_painting_atlas_gui_input(TileAtlasView *p_t
// Save the old terrain_set and terrains bits.
Dictionary dict;
dict["terrain_set"] = tile_data->get_terrain_set();
+ dict["terrain"] = tile_data->get_terrain();
Array array;
for (int i = 0; i < TileSet::CELL_NEIGHBOR_MAX; i++) {
TileSet::CellNeighbor bit = TileSet::CellNeighbor(i);
- array.push_back(tile_data->is_valid_peering_bit_terrain(bit) ? tile_data->get_peering_bit_terrain(bit) : -1);
+ array.push_back(tile_data->is_valid_terrain_peering_bit(bit) ? tile_data->get_terrain_peering_bit(bit) : -1);
}
dict["terrain_peering_bits"] = array;
drag_modified[cell] = dict;
@@ -2085,10 +2118,11 @@ void TileDataTerrainsEditor::forward_painting_atlas_gui_input(TileAtlasView *p_t
// Save the old terrain_set and terrains bits.
Dictionary dict;
dict["terrain_set"] = tile_data->get_terrain_set();
+ dict["terrain"] = tile_data->get_terrain();
Array array;
for (int i = 0; i < TileSet::CELL_NEIGHBOR_MAX; i++) {
TileSet::CellNeighbor bit = TileSet::CellNeighbor(i);
- array.push_back(tile_data->is_valid_peering_bit_terrain(bit) ? tile_data->get_peering_bit_terrain(bit) : -1);
+ array.push_back(tile_data->is_valid_terrain_peering_bit(bit) ? tile_data->get_terrain_peering_bit(bit) : -1);
}
dict["terrain_peering_bits"] = array;
drag_modified[cell] = dict;
@@ -2097,12 +2131,16 @@ void TileDataTerrainsEditor::forward_painting_atlas_gui_input(TileAtlasView *p_t
Rect2i texture_region = p_tile_set_atlas_source->get_tile_texture_region(coords);
Vector2i position = texture_region.get_center() + p_tile_set_atlas_source->get_tile_effective_texture_offset(coords, 0);
+ Vector<Vector2> polygon = tile_set->get_terrain_polygon(terrain_set);
+ if (Geometry2D::is_point_in_polygon(mb->get_position() - position, polygon)) {
+ tile_data->set_terrain(terrain);
+ }
for (int i = 0; i < TileSet::CELL_NEIGHBOR_MAX; i++) {
TileSet::CellNeighbor bit = TileSet::CellNeighbor(i);
- if (tile_set->is_valid_peering_bit_terrain(terrain_set, bit)) {
- Vector<Vector2> polygon = tile_set->get_terrain_bit_polygon(terrain_set, bit);
+ if (tile_set->is_valid_terrain_peering_bit(terrain_set, bit)) {
+ polygon = tile_set->get_terrain_peering_bit_polygon(terrain_set, bit);
if (Geometry2D::is_point_in_polygon(mb->get_position() - position, polygon)) {
- tile_data->set_peering_bit_terrain(bit, terrain);
+ tile_data->set_terrain_peering_bit(bit, terrain);
}
}
}
@@ -2138,10 +2176,11 @@ void TileDataTerrainsEditor::forward_painting_atlas_gui_input(TileAtlasView *p_t
TileData *tile_data = p_tile_set_atlas_source->get_tile_data(coords, 0);
undo_redo->add_undo_property(p_tile_set_atlas_source, vformat("%d:%d/%d/terrain_set", coords.x, coords.y, E.alternative_tile), tile_data->get_terrain_set());
undo_redo->add_do_property(p_tile_set_atlas_source, vformat("%d:%d/%d/terrain_set", coords.x, coords.y, E.alternative_tile), drag_painted_value);
+ undo_redo->add_undo_property(p_tile_set_atlas_source, vformat("%d:%d/%d/terrain", coords.x, coords.y, E.alternative_tile), tile_data->get_terrain());
for (int i = 0; i < TileSet::CELL_NEIGHBOR_MAX; i++) {
TileSet::CellNeighbor bit = TileSet::CellNeighbor(i);
- if (tile_data->is_valid_peering_bit_terrain(bit)) {
- undo_redo->add_undo_property(p_tile_set_atlas_source, vformat("%d:%d/%d/terrains_peering_bit/" + String(TileSet::CELL_NEIGHBOR_ENUM_TO_TEXT[i]), coords.x, coords.y, E.alternative_tile), tile_data->get_peering_bit_terrain(bit));
+ if (tile_data->is_valid_terrain_peering_bit(bit)) {
+ undo_redo->add_undo_property(p_tile_set_atlas_source, vformat("%d:%d/%d/terrains_peering_bit/" + String(TileSet::CELL_NEIGHBOR_ENUM_TO_TEXT[i]), coords.x, coords.y, E.alternative_tile), tile_data->get_terrain_peering_bit(bit));
}
}
}
@@ -2154,10 +2193,11 @@ void TileDataTerrainsEditor::forward_painting_atlas_gui_input(TileAtlasView *p_t
Vector2i coords = E.key.get_atlas_coords();
undo_redo->add_do_property(p_tile_set_atlas_source, vformat("%d:%d/%d/terrain_set", coords.x, coords.y, E.key.alternative_tile), drag_painted_value);
undo_redo->add_undo_property(p_tile_set_atlas_source, vformat("%d:%d/%d/terrain_set", coords.x, coords.y, E.key.alternative_tile), dict["terrain_set"]);
+ undo_redo->add_undo_property(p_tile_set_atlas_source, vformat("%d:%d/%d/terrain", coords.x, coords.y, E.key.alternative_tile), dict["terrain"]);
Array array = dict["terrain_peering_bits"];
for (int i = 0; i < array.size(); i++) {
TileSet::CellNeighbor bit = TileSet::CellNeighbor(i);
- if (tile_set->is_valid_peering_bit_terrain(dict["terrain_set"], bit)) {
+ if (tile_set->is_valid_terrain_peering_bit(dict["terrain_set"], bit)) {
undo_redo->add_undo_property(p_tile_set_atlas_source, vformat("%d:%d/%d/terrains_peering_bit/" + String(TileSet::CELL_NEIGHBOR_ENUM_TO_TEXT[i]), coords.x, coords.y, E.key.alternative_tile), array[i]);
}
}
@@ -2172,13 +2212,15 @@ void TileDataTerrainsEditor::forward_painting_atlas_gui_input(TileAtlasView *p_t
for (KeyValue<TileMapCell, Variant> &E : drag_modified) {
Dictionary dict = E.value;
Vector2i coords = E.key.get_atlas_coords();
+ undo_redo->add_do_property(p_tile_set_atlas_source, vformat("%d:%d/%d/terrain", coords.x, coords.y, E.key.alternative_tile), terrain);
+ undo_redo->add_undo_property(p_tile_set_atlas_source, vformat("%d:%d/%d/terrain", coords.x, coords.y, E.key.alternative_tile), dict["terrain"]);
Array array = dict["terrain_peering_bits"];
for (int i = 0; i < array.size(); i++) {
TileSet::CellNeighbor bit = TileSet::CellNeighbor(i);
- if (tile_set->is_valid_peering_bit_terrain(terrain_set, bit)) {
+ if (tile_set->is_valid_terrain_peering_bit(terrain_set, bit)) {
undo_redo->add_do_property(p_tile_set_atlas_source, vformat("%d:%d/%d/terrains_peering_bit/" + String(TileSet::CELL_NEIGHBOR_ENUM_TO_TEXT[i]), coords.x, coords.y, E.key.alternative_tile), terrain);
}
- if (tile_set->is_valid_peering_bit_terrain(dict["terrain_set"], bit)) {
+ if (tile_set->is_valid_terrain_peering_bit(dict["terrain_set"], bit)) {
undo_redo->add_undo_property(p_tile_set_atlas_source, vformat("%d:%d/%d/terrains_peering_bit/" + String(TileSet::CELL_NEIGHBOR_ENUM_TO_TEXT[i]), coords.x, coords.y, E.key.alternative_tile), array[i]);
}
}
@@ -2224,20 +2266,30 @@ void TileDataTerrainsEditor::forward_painting_atlas_gui_input(TileAtlasView *p_t
Vector2i coords = E.get_atlas_coords();
TileData *tile_data = p_tile_set_atlas_source->get_tile_data(coords, 0);
+ Rect2i texture_region = p_tile_set_atlas_source->get_tile_texture_region(coords);
+ Vector2i position = texture_region.get_center() + p_tile_set_atlas_source->get_tile_effective_texture_offset(coords, 0);
+
+ Vector<Vector2> polygon = tile_set->get_terrain_polygon(terrain_set);
+ for (int j = 0; j < polygon.size(); j++) {
+ polygon.write[j] += position;
+ }
+ if (!Geometry2D::intersect_polygons(polygon, mouse_pos_rect_polygon).is_empty()) {
+ // Draw terrain.
+ undo_redo->add_do_property(p_tile_set_atlas_source, vformat("%d:%d/%d/terrain", coords.x, coords.y, E.alternative_tile), terrain);
+ undo_redo->add_undo_property(p_tile_set_atlas_source, vformat("%d:%d/%d/terrain", coords.x, coords.y, E.alternative_tile), tile_data->get_terrain());
+ }
+
for (int i = 0; i < TileSet::CELL_NEIGHBOR_MAX; i++) {
TileSet::CellNeighbor bit = TileSet::CellNeighbor(i);
- if (tile_set->is_valid_peering_bit_terrain(terrain_set, bit)) {
- Rect2i texture_region = p_tile_set_atlas_source->get_tile_texture_region(coords);
- Vector2i position = texture_region.get_center() + p_tile_set_atlas_source->get_tile_effective_texture_offset(coords, 0);
-
- Vector<Vector2> polygon = tile_set->get_terrain_bit_polygon(terrain_set, bit);
+ if (tile_set->is_valid_terrain_peering_bit(terrain_set, bit)) {
+ polygon = tile_set->get_terrain_peering_bit_polygon(terrain_set, bit);
for (int j = 0; j < polygon.size(); j++) {
polygon.write[j] += position;
}
if (!Geometry2D::intersect_polygons(polygon, mouse_pos_rect_polygon).is_empty()) {
// Draw bit.
undo_redo->add_do_property(p_tile_set_atlas_source, vformat("%d:%d/%d/terrains_peering_bit/" + String(TileSet::CELL_NEIGHBOR_ENUM_TO_TEXT[i]), coords.x, coords.y, E.alternative_tile), terrain);
- undo_redo->add_undo_property(p_tile_set_atlas_source, vformat("%d:%d/%d/terrains_peering_bit/" + String(TileSet::CELL_NEIGHBOR_ENUM_TO_TEXT[i]), coords.x, coords.y, E.alternative_tile), tile_data->get_peering_bit_terrain(bit));
+ undo_redo->add_undo_property(p_tile_set_atlas_source, vformat("%d:%d/%d/terrains_peering_bit/" + String(TileSet::CELL_NEIGHBOR_ENUM_TO_TEXT[i]), coords.x, coords.y, E.alternative_tile), tile_data->get_terrain_peering_bit(bit));
}
}
}
@@ -2267,10 +2319,11 @@ void TileDataTerrainsEditor::forward_painting_alternatives_gui_input(TileAtlasVi
if (!drag_modified.has(cell)) {
Dictionary dict;
dict["terrain_set"] = tile_data->get_terrain_set();
+ dict["terrain"] = tile_data->get_terrain();
Array array;
for (int j = 0; j < TileSet::CELL_NEIGHBOR_MAX; j++) {
TileSet::CellNeighbor bit = TileSet::CellNeighbor(j);
- array.push_back(tile_data->is_valid_peering_bit_terrain(bit) ? tile_data->get_peering_bit_terrain(bit) : -1);
+ array.push_back(tile_data->is_valid_terrain_peering_bit(bit) ? tile_data->get_terrain_peering_bit(bit) : -1);
}
dict["terrain_peering_bits"] = array;
drag_modified[cell] = dict;
@@ -2300,10 +2353,11 @@ void TileDataTerrainsEditor::forward_painting_alternatives_gui_input(TileAtlasVi
if (!drag_modified.has(cell)) {
Dictionary dict;
dict["terrain_set"] = tile_data->get_terrain_set();
+ dict["terrain"] = tile_data->get_terrain();
Array array;
for (int j = 0; j < TileSet::CELL_NEIGHBOR_MAX; j++) {
TileSet::CellNeighbor bit = TileSet::CellNeighbor(j);
- array.push_back(tile_data->is_valid_peering_bit_terrain(bit) ? tile_data->get_peering_bit_terrain(bit) : -1);
+ array.push_back(tile_data->is_valid_terrain_peering_bit(bit) ? tile_data->get_terrain_peering_bit(bit) : -1);
}
dict["terrain_peering_bits"] = array;
drag_modified[cell] = dict;
@@ -2312,12 +2366,18 @@ void TileDataTerrainsEditor::forward_painting_alternatives_gui_input(TileAtlasVi
// Set the terrains bits.
Rect2i texture_region = p_tile_atlas_view->get_alternative_tile_rect(coords, alternative_tile);
Vector2i position = texture_region.get_center() + p_tile_set_atlas_source->get_tile_effective_texture_offset(coords, alternative_tile);
+
+ Vector<Vector2> polygon = tile_set->get_terrain_polygon(tile_data->get_terrain_set());
+ if (Geometry2D::is_segment_intersecting_polygon(mm->get_position() - position, drag_last_pos - position, polygon)) {
+ tile_data->set_terrain(terrain);
+ }
+
for (int j = 0; j < TileSet::CELL_NEIGHBOR_MAX; j++) {
TileSet::CellNeighbor bit = TileSet::CellNeighbor(j);
- if (tile_data->is_valid_peering_bit_terrain(bit)) {
- Vector<Vector2> polygon = tile_set->get_terrain_bit_polygon(tile_data->get_terrain_set(), bit);
+ if (tile_data->is_valid_terrain_peering_bit(bit)) {
+ polygon = tile_set->get_terrain_peering_bit_polygon(tile_data->get_terrain_set(), bit);
if (Geometry2D::is_segment_intersecting_polygon(mm->get_position() - position, drag_last_pos - position, polygon)) {
- tile_data->set_peering_bit_terrain(bit, terrain);
+ tile_data->set_terrain_peering_bit(bit, terrain);
}
}
}
@@ -2343,12 +2403,18 @@ void TileDataTerrainsEditor::forward_painting_alternatives_gui_input(TileAtlasVi
Vector2i position = texture_region.get_center() + p_tile_set_atlas_source->get_tile_effective_texture_offset(coords, alternative_tile);
dummy_object->set("terrain_set", terrain_set);
dummy_object->set("terrain", -1);
+
+ Vector<Vector2> polygon = tile_set->get_terrain_polygon(terrain_set);
+ if (Geometry2D::is_point_in_polygon(mb->get_position() - position, polygon)) {
+ dummy_object->set("terrain", tile_data->get_terrain());
+ }
+
for (int i = 0; i < TileSet::CELL_NEIGHBOR_MAX; i++) {
TileSet::CellNeighbor bit = TileSet::CellNeighbor(i);
- if (tile_set->is_valid_peering_bit_terrain(terrain_set, bit)) {
- Vector<Vector2> polygon = tile_set->get_terrain_bit_polygon(terrain_set, bit);
+ if (tile_set->is_valid_terrain_peering_bit(terrain_set, bit)) {
+ polygon = tile_set->get_terrain_peering_bit_polygon(terrain_set, bit);
if (Geometry2D::is_point_in_polygon(mb->get_position() - position, polygon)) {
- dummy_object->set("terrain", tile_data->get_peering_bit_terrain(bit));
+ dummy_object->set("terrain", tile_data->get_terrain_peering_bit(bit));
}
}
}
@@ -2380,7 +2446,7 @@ void TileDataTerrainsEditor::forward_painting_alternatives_gui_input(TileAtlasVi
Array array;
for (int i = 0; i < TileSet::CELL_NEIGHBOR_MAX; i++) {
TileSet::CellNeighbor bit = TileSet::CellNeighbor(i);
- array.push_back(tile_data->is_valid_peering_bit_terrain(bit) ? tile_data->get_peering_bit_terrain(bit) : -1);
+ array.push_back(tile_data->is_valid_terrain_peering_bit(bit) ? tile_data->get_terrain_peering_bit(bit) : -1);
}
dict["terrain_peering_bits"] = array;
drag_modified[cell] = dict;
@@ -2405,10 +2471,11 @@ void TileDataTerrainsEditor::forward_painting_alternatives_gui_input(TileAtlasVi
// Save the old terrain_set and terrains bits.
Dictionary dict;
dict["terrain_set"] = tile_data->get_terrain_set();
+ dict["terrain"] = tile_data->get_terrain();
Array array;
for (int i = 0; i < TileSet::CELL_NEIGHBOR_MAX; i++) {
TileSet::CellNeighbor bit = TileSet::CellNeighbor(i);
- array.push_back(tile_data->is_valid_peering_bit_terrain(bit) ? tile_data->get_peering_bit_terrain(bit) : -1);
+ array.push_back(tile_data->is_valid_terrain_peering_bit(bit) ? tile_data->get_terrain_peering_bit(bit) : -1);
}
dict["terrain_peering_bits"] = array;
drag_modified[cell] = dict;
@@ -2416,12 +2483,17 @@ void TileDataTerrainsEditor::forward_painting_alternatives_gui_input(TileAtlasVi
// Set the terrain bit.
Rect2i texture_region = p_tile_atlas_view->get_alternative_tile_rect(coords, alternative_tile);
Vector2i position = texture_region.get_center() + p_tile_set_atlas_source->get_tile_effective_texture_offset(coords, alternative_tile);
+
+ Vector<Vector2> polygon = tile_set->get_terrain_polygon(terrain_set);
+ if (Geometry2D::is_point_in_polygon(mb->get_position() - position, polygon)) {
+ tile_data->set_terrain(terrain);
+ }
for (int i = 0; i < TileSet::CELL_NEIGHBOR_MAX; i++) {
TileSet::CellNeighbor bit = TileSet::CellNeighbor(i);
- if (tile_set->is_valid_peering_bit_terrain(terrain_set, bit)) {
- Vector<Vector2> polygon = tile_set->get_terrain_bit_polygon(terrain_set, bit);
+ if (tile_set->is_valid_terrain_peering_bit(terrain_set, bit)) {
+ polygon = tile_set->get_terrain_peering_bit_polygon(terrain_set, bit);
if (Geometry2D::is_point_in_polygon(mb->get_position() - position, polygon)) {
- tile_data->set_peering_bit_terrain(bit, terrain);
+ tile_data->set_terrain_peering_bit(bit, terrain);
}
}
}
@@ -2437,6 +2509,7 @@ void TileDataTerrainsEditor::forward_painting_alternatives_gui_input(TileAtlasVi
Vector2i coords = E.key.get_atlas_coords();
undo_redo->add_undo_property(p_tile_set_atlas_source, vformat("%d:%d/%d/terrain_set", coords.x, coords.y, E.key.alternative_tile), dict["terrain_set"]);
undo_redo->add_do_property(p_tile_set_atlas_source, vformat("%d:%d/%d/terrain_set", coords.x, coords.y, E.key.alternative_tile), drag_painted_value);
+ undo_redo->add_undo_property(p_tile_set_atlas_source, vformat("%d:%d/%d/terrain", coords.x, coords.y, E.key.alternative_tile), dict["terrain"]);
Array array = dict["terrain_peering_bits"];
for (int i = 0; i < array.size(); i++) {
undo_redo->add_undo_property(p_tile_set_atlas_source, vformat("%d:%d/%d/terrains_peering_bit/" + String(TileSet::CELL_NEIGHBOR_ENUM_TO_TEXT[i]), coords.x, coords.y, E.key.alternative_tile), array[i]);
@@ -2452,13 +2525,15 @@ void TileDataTerrainsEditor::forward_painting_alternatives_gui_input(TileAtlasVi
for (KeyValue<TileMapCell, Variant> &E : drag_modified) {
Dictionary dict = E.value;
Vector2i coords = E.key.get_atlas_coords();
+ undo_redo->add_do_property(p_tile_set_atlas_source, vformat("%d:%d/%d/terrain", coords.x, coords.y, E.key.alternative_tile), terrain);
+ undo_redo->add_undo_property(p_tile_set_atlas_source, vformat("%d:%d/%d/terrain", coords.x, coords.y, E.key.alternative_tile), dict["terrain"]);
Array array = dict["terrain_peering_bits"];
for (int i = 0; i < array.size(); i++) {
TileSet::CellNeighbor bit = TileSet::CellNeighbor(i);
- if (tile_set->is_valid_peering_bit_terrain(terrain_set, bit)) {
+ if (tile_set->is_valid_terrain_peering_bit(terrain_set, bit)) {
undo_redo->add_do_property(p_tile_set_atlas_source, vformat("%d:%d/%d/terrains_peering_bit/" + String(TileSet::CELL_NEIGHBOR_ENUM_TO_TEXT[i]), coords.x, coords.y, E.key.alternative_tile), terrain);
}
- if (tile_set->is_valid_peering_bit_terrain(dict["terrain_set"], bit)) {
+ if (tile_set->is_valid_terrain_peering_bit(dict["terrain_set"], bit)) {
undo_redo->add_undo_property(p_tile_set_atlas_source, vformat("%d:%d/%d/terrains_peering_bit/" + String(TileSet::CELL_NEIGHBOR_ENUM_TO_TEXT[i]), coords.x, coords.y, E.key.alternative_tile), array[i]);
}
}
diff --git a/editor/plugins/tiles/tile_map_editor.cpp b/editor/plugins/tiles/tile_map_editor.cpp
index cd8aca2a8e..d2f3eab31c 100644
--- a/editor/plugins/tiles/tile_map_editor.cpp
+++ b/editor/plugins/tiles/tile_map_editor.cpp
@@ -2028,7 +2028,6 @@ TileMapEditorTilesPlugin::TileMapEditorTilesPlugin() {
// --- Toolbar ---
toolbar = memnew(HBoxContainer);
- toolbar->set_h_size_flags(Control::SIZE_EXPAND_FILL);
HBoxContainer *tilemap_tiles_tools_buttons = memnew(HBoxContainer);
@@ -2321,7 +2320,7 @@ Vector<TileMapEditorPlugin::TabData> TileMapEditorTerrainsPlugin::get_tabs() con
return tabs;
}
-HashMap<Vector2i, TileMapCell> TileMapEditorTerrainsPlugin::_draw_terrains(const HashMap<Vector2i, TileSet::TerrainsPattern> &p_to_paint, int p_terrain_set) const {
+HashMap<Vector2i, TileMapCell> TileMapEditorTerrainsPlugin::_draw_terrain_path_or_connect(const Vector<Vector2i> &p_to_paint, int p_terrain_set, int p_terrain, bool p_connect) const {
TileMap *tile_map = Object::cast_to<TileMap>(ObjectDB::get_instance(tile_map_id));
if (!tile_map) {
return HashMap<Vector2i, TileMapCell>();
@@ -2332,105 +2331,87 @@ HashMap<Vector2i, TileMapCell> TileMapEditorTerrainsPlugin::_draw_terrains(const
return HashMap<Vector2i, TileMapCell>();
}
- HashMap<Vector2i, TileMapCell> output;
-
- // Add the constraints from the added tiles.
- RBSet<TileMap::TerrainConstraint> added_tiles_constraints_set;
- for (const KeyValue<Vector2i, TileSet::TerrainsPattern> &E_to_paint : p_to_paint) {
- Vector2i coords = E_to_paint.key;
- TileSet::TerrainsPattern terrains_pattern = E_to_paint.value;
-
- RBSet<TileMap::TerrainConstraint> cell_constraints = tile_map->get_terrain_constraints_from_added_tile(coords, p_terrain_set, terrains_pattern);
- for (const TileMap::TerrainConstraint &E : cell_constraints) {
- added_tiles_constraints_set.insert(E);
- }
- }
-
- // Build the list of potential tiles to replace.
- RBSet<Vector2i> potential_to_replace;
- for (const KeyValue<Vector2i, TileSet::TerrainsPattern> &E_to_paint : p_to_paint) {
- Vector2i coords = E_to_paint.key;
- for (int i = 0; i < TileSet::CELL_NEIGHBOR_MAX; i++) {
- if (tile_map->is_existing_neighbor(TileSet::CellNeighbor(i))) {
- Vector2i neighbor = tile_map->get_neighbor_cell(coords, TileSet::CellNeighbor(i));
- if (!p_to_paint.has(neighbor)) {
- potential_to_replace.insert(neighbor);
- }
- }
- }
+ HashMap<Vector2i, TileSet::TerrainsPattern> terrain_fill_output;
+ if (p_connect) {
+ terrain_fill_output = tile_map->terrain_fill_connect(tile_map_layer, p_to_paint, p_terrain_set, p_terrain, false);
+ } else {
+ terrain_fill_output = tile_map->terrain_fill_path(tile_map_layer, p_to_paint, p_terrain_set, p_terrain, false);
}
- // Set of tiles to replace
- RBSet<Vector2i> to_replace;
-
- // Add the central tiles to the one to replace.
- for (const KeyValue<Vector2i, TileSet::TerrainsPattern> &E_to_paint : p_to_paint) {
- to_replace.insert(E_to_paint.key);
+ // Make the painted path a set for faster lookups
+ HashSet<Vector2i> painted_set;
+ for (Vector2i coords : p_to_paint) {
+ painted_set.insert(coords);
}
- // Add the constraints from the surroundings of the modified areas.
- RBSet<TileMap::TerrainConstraint> removed_cells_constraints_set;
- bool to_replace_modified = true;
- while (to_replace_modified) {
- // Get the constraints from the removed cells.
- removed_cells_constraints_set = tile_map->get_terrain_constraints_from_removed_cells_list(tile_map_layer, to_replace, p_terrain_set, false);
-
- // Filter the sources to make sure they are in the potential_to_replace.
- RBMap<TileMap::TerrainConstraint, RBSet<Vector2i>> per_constraint_tiles;
- for (const TileMap::TerrainConstraint &E : removed_cells_constraints_set) {
- HashMap<Vector2i, TileSet::CellNeighbor> sources_of_constraint = E.get_overlapping_coords_and_peering_bits();
- for (const KeyValue<Vector2i, TileSet::CellNeighbor> &E_source_tile_of_constraint : sources_of_constraint) {
- if (potential_to_replace.has(E_source_tile_of_constraint.key)) {
- per_constraint_tiles[E].insert(E_source_tile_of_constraint.key);
- }
- }
- }
-
- to_replace_modified = false;
- for (const TileMap::TerrainConstraint &E : added_tiles_constraints_set) {
- TileMap::TerrainConstraint c = E;
- // Check if we have a conflict in constraints.
- if (removed_cells_constraints_set.has(c) && removed_cells_constraints_set.find(c)->get().get_terrain() != c.get_terrain()) {
- // If we do, we search for a neighbor to remove.
- if (per_constraint_tiles.has(c) && !per_constraint_tiles[c].is_empty()) {
- // Remove it.
- Vector2i to_add_to_remove = per_constraint_tiles[c].front()->get();
- potential_to_replace.erase(to_add_to_remove);
- to_replace.insert(to_add_to_remove);
- to_replace_modified = true;
- for (KeyValue<TileMap::TerrainConstraint, RBSet<Vector2i>> &E_source_tiles_of_constraint : per_constraint_tiles) {
- E_source_tiles_of_constraint.value.erase(to_add_to_remove);
+ HashMap<Vector2i, TileMapCell> output;
+ for (const KeyValue<Vector2i, TileSet::TerrainsPattern> &E : terrain_fill_output) {
+ if (painted_set.has(E.key)) {
+ // Paint a random tile with the correct terrain for the painted path.
+ output[E.key] = tile_set->get_random_tile_from_terrains_pattern(p_terrain_set, E.value);
+ } else {
+ // Avoids updating the painted path from the output if the new pattern is the same as before.
+ bool keep_old = false;
+ TileMapCell cell = tile_map->get_cell(tile_map_layer, E.key);
+ if (cell.source_id != TileSet::INVALID_SOURCE) {
+ TileSetSource *source = *tile_set->get_source(cell.source_id);
+ TileSetAtlasSource *atlas_source = Object::cast_to<TileSetAtlasSource>(source);
+ if (atlas_source) {
+ // Get tile data.
+ TileData *tile_data = atlas_source->get_tile_data(cell.get_atlas_coords(), cell.alternative_tile);
+ if (tile_data && tile_data->get_terrains_pattern() == E.value) {
+ keep_old = true;
}
- break;
}
}
+ if (!keep_old) {
+ output[E.key] = tile_set->get_random_tile_from_terrains_pattern(p_terrain_set, E.value);
+ }
}
}
+ return output;
+}
- // Combine all constraints together.
- RBSet<TileMap::TerrainConstraint> constraints = removed_cells_constraints_set;
- for (const TileMap::TerrainConstraint &E : added_tiles_constraints_set) {
- constraints.insert(E);
+HashMap<Vector2i, TileMapCell> TileMapEditorTerrainsPlugin::_draw_terrain_pattern(const Vector<Vector2i> &p_to_paint, int p_terrain_set, TileSet::TerrainsPattern p_terrains_pattern) const {
+ TileMap *tile_map = Object::cast_to<TileMap>(ObjectDB::get_instance(tile_map_id));
+ if (!tile_map) {
+ return HashMap<Vector2i, TileMapCell>();
}
- // Remove the central tiles from the ones to replace.
- for (const KeyValue<Vector2i, TileSet::TerrainsPattern> &E_to_paint : p_to_paint) {
- to_replace.erase(E_to_paint.key);
+ Ref<TileSet> tile_set = tile_map->get_tileset();
+ if (!tile_set.is_valid()) {
+ return HashMap<Vector2i, TileMapCell>();
}
- // Run WFC to fill the holes with the constraints.
- HashMap<Vector2i, TileSet::TerrainsPattern> wfc_output = tile_map->terrain_wave_function_collapse(to_replace, p_terrain_set, constraints);
+ HashMap<Vector2i, TileSet::TerrainsPattern> terrain_fill_output = tile_map->terrain_fill_pattern(tile_map_layer, p_to_paint, p_terrain_set, p_terrains_pattern, false);
- // Actually paint the tiles.
- for (const KeyValue<Vector2i, TileSet::TerrainsPattern> &E_to_paint : p_to_paint) {
- output[E_to_paint.key] = tile_set->get_random_tile_from_terrains_pattern(p_terrain_set, E_to_paint.value);
+ // Make the painted path a set for faster lookups
+ HashSet<Vector2i> painted_set;
+ for (Vector2i coords : p_to_paint) {
+ painted_set.insert(coords);
}
- // Use the WFC run for the output.
- for (const KeyValue<Vector2i, TileSet::TerrainsPattern> &E : wfc_output) {
- output[E.key] = tile_set->get_random_tile_from_terrains_pattern(p_terrain_set, E.value);
+ HashMap<Vector2i, TileMapCell> output;
+ for (const KeyValue<Vector2i, TileSet::TerrainsPattern> &E : terrain_fill_output) {
+ if (painted_set.has(E.key)) {
+ // Paint a random tile with the correct terrain for the painted path.
+ output[E.key] = tile_set->get_random_tile_from_terrains_pattern(p_terrain_set, E.value);
+ } else {
+ // Avoids updating the painted path from the output if the new pattern is the same as before.
+ TileMapCell cell = tile_map->get_cell(tile_map_layer, E.key);
+ if (cell.source_id != TileSet::INVALID_SOURCE) {
+ TileSetSource *source = *tile_set->get_source(cell.source_id);
+ TileSetAtlasSource *atlas_source = Object::cast_to<TileSetAtlasSource>(source);
+ if (atlas_source) {
+ // Get tile data.
+ TileData *tile_data = atlas_source->get_tile_data(cell.get_atlas_coords(), cell.alternative_tile);
+ if (tile_data && !(tile_data->get_terrains_pattern() == E.value)) {
+ output[E.key] = tile_set->get_random_tile_from_terrains_pattern(p_terrain_set, E.value);
+ }
+ }
+ }
+ }
}
-
return output;
}
@@ -2445,19 +2426,21 @@ HashMap<Vector2i, TileMapCell> TileMapEditorTerrainsPlugin::_draw_line(Vector2i
return HashMap<Vector2i, TileMapCell>();
}
- TileSet::TerrainsPattern terrains_pattern;
- if (p_erase) {
- terrains_pattern = TileSet::TerrainsPattern(*tile_set, selected_terrain_set);
- } else {
- terrains_pattern = selected_terrains_pattern;
- }
+ if (selected_type == SELECTED_TYPE_CONNECT) {
+ return _draw_terrain_path_or_connect(TileMapEditor::get_line(tile_map, p_start_cell, p_end_cell), selected_terrain_set, selected_terrain, true);
+ } else if (selected_type == SELECTED_TYPE_PATH) {
+ return _draw_terrain_path_or_connect(TileMapEditor::get_line(tile_map, p_start_cell, p_end_cell), selected_terrain_set, selected_terrain, false);
+ } else { // SELECTED_TYPE_PATTERN
+ TileSet::TerrainsPattern terrains_pattern;
+ if (p_erase) {
+ terrains_pattern = TileSet::TerrainsPattern(*tile_set, selected_terrain_set);
+ } else {
+ terrains_pattern = selected_terrains_pattern;
+ }
- Vector<Vector2i> line = TileMapEditor::get_line(tile_map, p_start_cell, p_end_cell);
- HashMap<Vector2i, TileSet::TerrainsPattern> to_draw;
- for (int i = 0; i < line.size(); i++) {
- to_draw[line[i]] = terrains_pattern;
+ Vector<Vector2i> line = TileMapEditor::get_line(tile_map, p_start_cell, p_end_cell);
+ return _draw_terrain_pattern(line, selected_terrain_set, terrains_pattern);
}
- return _draw_terrains(to_draw, selected_terrain_set);
}
HashMap<Vector2i, TileMapCell> TileMapEditorTerrainsPlugin::_draw_rect(Vector2i p_start_cell, Vector2i p_end_cell, bool p_erase) {
@@ -2471,25 +2454,29 @@ HashMap<Vector2i, TileMapCell> TileMapEditorTerrainsPlugin::_draw_rect(Vector2i
return HashMap<Vector2i, TileMapCell>();
}
- TileSet::TerrainsPattern terrains_pattern;
- if (p_erase) {
- terrains_pattern = TileSet::TerrainsPattern(*tile_set, selected_terrain_set);
- } else {
- terrains_pattern = selected_terrains_pattern;
- }
-
Rect2i rect;
rect.set_position(p_start_cell);
rect.set_end(p_end_cell);
rect = rect.abs();
- HashMap<Vector2i, TileSet::TerrainsPattern> to_draw;
+ Vector<Vector2i> to_draw;
for (int x = rect.position.x; x <= rect.get_end().x; x++) {
for (int y = rect.position.y; y <= rect.get_end().y; y++) {
- to_draw[Vector2i(x, y)] = terrains_pattern;
+ to_draw.append(Vector2i(x, y));
}
}
- return _draw_terrains(to_draw, selected_terrain_set);
+
+ if (selected_type == SELECTED_TYPE_CONNECT || selected_type == SELECTED_TYPE_PATH) {
+ return _draw_terrain_path_or_connect(to_draw, selected_terrain_set, selected_terrain, true);
+ } else { // SELECTED_TYPE_PATTERN
+ TileSet::TerrainsPattern terrains_pattern;
+ if (p_erase) {
+ terrains_pattern = TileSet::TerrainsPattern(*tile_set, selected_terrain_set);
+ } else {
+ terrains_pattern = selected_terrains_pattern;
+ }
+ return _draw_terrain_pattern(to_draw, selected_terrain_set, terrains_pattern);
+ }
}
RBSet<Vector2i> TileMapEditorTerrainsPlugin::_get_cells_for_bucket_fill(Vector2i p_coords, bool p_contiguous) {
@@ -2614,20 +2601,23 @@ HashMap<Vector2i, TileMapCell> TileMapEditorTerrainsPlugin::_draw_bucket_fill(Ve
return HashMap<Vector2i, TileMapCell>();
}
- TileSet::TerrainsPattern terrains_pattern;
- if (p_erase) {
- terrains_pattern = TileSet::TerrainsPattern(*tile_set, selected_terrain_set);
- } else {
- terrains_pattern = selected_terrains_pattern;
- }
-
RBSet<Vector2i> cells_to_draw = _get_cells_for_bucket_fill(p_coords, p_contiguous);
- HashMap<Vector2i, TileSet::TerrainsPattern> to_draw;
- for (const Vector2i &coords : cells_to_draw) {
- to_draw[coords] = terrains_pattern;
+ Vector<Vector2i> cells_to_draw_as_vector;
+ for (Vector2i cell : cells_to_draw) {
+ cells_to_draw_as_vector.append(cell);
}
- return _draw_terrains(to_draw, selected_terrain_set);
+ if (selected_type == SELECTED_TYPE_CONNECT || selected_type == SELECTED_TYPE_PATH) {
+ return _draw_terrain_path_or_connect(cells_to_draw_as_vector, selected_terrain_set, selected_terrain, true);
+ } else { // SELECTED_TYPE_PATTERN
+ TileSet::TerrainsPattern terrains_pattern;
+ if (p_erase) {
+ terrains_pattern = TileSet::TerrainsPattern(*tile_set, selected_terrain_set);
+ } else {
+ terrains_pattern = selected_terrains_pattern;
+ }
+ return _draw_terrain_pattern(cells_to_draw_as_vector, selected_terrain_set, terrains_pattern);
+ }
}
void TileMapEditorTerrainsPlugin::_stop_dragging() {
@@ -2696,11 +2686,13 @@ void TileMapEditorTerrainsPlugin::_stop_dragging() {
if (tree_item) {
for (int i = 0; i < terrains_tile_list->get_item_count(); i++) {
Dictionary metadata_dict = terrains_tile_list->get_item_metadata(i);
- TileSet::TerrainsPattern in_meta_terrains_pattern(*tile_set, new_terrain_set);
- in_meta_terrains_pattern.set_terrains_from_array(metadata_dict["terrains_pattern"]);
- if (in_meta_terrains_pattern == terrains_pattern) {
- terrains_tile_list->select(i);
- break;
+ if (int(metadata_dict["type"]) == SELECTED_TYPE_PATTERN) {
+ TileSet::TerrainsPattern in_meta_terrains_pattern(*tile_set, new_terrain_set);
+ in_meta_terrains_pattern.from_array(metadata_dict["terrains_pattern"]);
+ if (in_meta_terrains_pattern == terrains_pattern) {
+ terrains_tile_list->select(i);
+ break;
+ }
}
}
} else {
@@ -2773,22 +2765,33 @@ void TileMapEditorTerrainsPlugin::_update_selection() {
}
// Get the selected terrain.
- selected_terrains_pattern = TileSet::TerrainsPattern();
selected_terrain_set = -1;
+ selected_terrains_pattern = TileSet::TerrainsPattern();
TreeItem *selected_tree_item = terrains_tree->get_selected();
if (selected_tree_item && selected_tree_item->get_metadata(0)) {
Dictionary metadata_dict = selected_tree_item->get_metadata(0);
// Selected terrain
selected_terrain_set = metadata_dict["terrain_set"];
+ selected_terrain = metadata_dict["terrain_id"];
- // Selected tile
+ // Selected mode/terrain pattern
if (erase_button->is_pressed()) {
+ selected_type = SELECTED_TYPE_PATTERN;
selected_terrains_pattern = TileSet::TerrainsPattern(*tile_set, selected_terrain_set);
} else if (terrains_tile_list->is_anything_selected()) {
metadata_dict = terrains_tile_list->get_item_metadata(terrains_tile_list->get_selected_items()[0]);
- selected_terrains_pattern = TileSet::TerrainsPattern(*tile_set, selected_terrain_set);
- selected_terrains_pattern.set_terrains_from_array(metadata_dict["terrains_pattern"]);
+ if (int(metadata_dict["type"]) == SELECTED_TYPE_CONNECT) {
+ selected_type = SELECTED_TYPE_CONNECT;
+ } else if (int(metadata_dict["type"]) == SELECTED_TYPE_PATH) {
+ selected_type = SELECTED_TYPE_PATH;
+ } else if (int(metadata_dict["type"]) == SELECTED_TYPE_PATTERN) {
+ selected_type = SELECTED_TYPE_PATTERN;
+ selected_terrains_pattern = TileSet::TerrainsPattern(*tile_set, selected_terrain_set);
+ selected_terrains_pattern.from_array(metadata_dict["terrains_pattern"]);
+ } else {
+ ERR_FAIL();
+ }
}
}
}
@@ -2865,7 +2868,7 @@ bool TileMapEditorTerrainsPlugin::forward_canvas_gui_input(const Ref<InputEvent>
} else {
// Paint otherwise.
if (tool_buttons_group->get_pressed_button() == paint_tool_button && !Input::get_singleton()->is_key_pressed(Key::CTRL) && !Input::get_singleton()->is_key_pressed(Key::SHIFT)) {
- if (selected_terrain_set < 0 || !selected_terrains_pattern.is_valid()) {
+ if (selected_terrain_set < 0 || selected_terrain < 0 || (selected_type == SELECTED_TYPE_PATTERN && !selected_terrains_pattern.is_valid())) {
return true;
}
@@ -2880,21 +2883,21 @@ bool TileMapEditorTerrainsPlugin::forward_canvas_gui_input(const Ref<InputEvent>
tile_map->set_cell(tile_map_layer, E.key, E.value.source_id, E.value.get_atlas_coords(), E.value.alternative_tile);
}
} else if (tool_buttons_group->get_pressed_button() == line_tool_button || (tool_buttons_group->get_pressed_button() == paint_tool_button && Input::get_singleton()->is_key_pressed(Key::SHIFT) && !Input::get_singleton()->is_key_pressed(Key::CTRL))) {
- if (selected_terrain_set < 0 || !selected_terrains_pattern.is_valid()) {
+ if (selected_terrain_set < 0 || selected_terrain < 0 || (selected_type == SELECTED_TYPE_PATTERN && !selected_terrains_pattern.is_valid())) {
return true;
}
drag_type = DRAG_TYPE_LINE;
drag_start_mouse_pos = mpos;
drag_modified.clear();
} else if (tool_buttons_group->get_pressed_button() == rect_tool_button || (tool_buttons_group->get_pressed_button() == paint_tool_button && Input::get_singleton()->is_key_pressed(Key::SHIFT) && Input::get_singleton()->is_key_pressed(Key::CTRL))) {
- if (selected_terrain_set < 0 || !selected_terrains_pattern.is_valid()) {
+ if (selected_terrain_set < 0 || selected_terrain < 0 || (selected_type == SELECTED_TYPE_PATTERN && !selected_terrains_pattern.is_valid())) {
return true;
}
drag_type = DRAG_TYPE_RECT;
drag_start_mouse_pos = mpos;
drag_modified.clear();
} else if (tool_buttons_group->get_pressed_button() == bucket_tool_button) {
- if (selected_terrain_set < 0 || !selected_terrains_pattern.is_valid()) {
+ if (selected_terrain_set < 0 || selected_terrain < 0 || (selected_type == SELECTED_TYPE_PATTERN && !selected_terrains_pattern.is_valid())) {
return true;
}
drag_type = DRAG_TYPE_BUCKET;
@@ -3105,11 +3108,18 @@ void TileMapEditorTerrainsPlugin::_update_terrains_cache() {
cell.alternative_tile = alternative_id;
TileSet::TerrainsPattern terrains_pattern = tile_data->get_terrains_pattern();
+
+ // Terrain center bit
+ int terrain = terrains_pattern.get_terrain();
+ if (terrain >= 0 && terrain < (int)per_terrain_terrains_patterns[terrain_set].size()) {
+ per_terrain_terrains_patterns[terrain_set][terrain].insert(terrains_pattern);
+ }
+
// Terrain bits.
for (int i = 0; i < TileSet::CELL_NEIGHBOR_MAX; i++) {
TileSet::CellNeighbor bit = TileSet::CellNeighbor(i);
- if (tile_set->is_valid_peering_bit_terrain(terrain_set, bit)) {
- int terrain = terrains_pattern.get_terrain(bit);
+ if (tile_set->is_valid_terrain_peering_bit(terrain_set, bit)) {
+ terrain = terrains_pattern.get_terrain_peering_bit(bit);
if (terrain >= 0 && terrain < (int)per_terrain_terrains_patterns[terrain_set].size()) {
per_terrain_terrains_patterns[terrain_set][terrain].insert(terrains_pattern);
}
@@ -3191,6 +3201,19 @@ void TileMapEditorTerrainsPlugin::_update_tiles_list() {
ERR_FAIL_INDEX(selected_terrain_set, tile_set->get_terrain_sets_count());
ERR_FAIL_INDEX(selected_terrain_id, tile_set->get_terrains_count(selected_terrain_set));
+ // Add the two first generic modes
+ int item_index = terrains_tile_list->add_icon_item(main_vbox_container->get_theme_icon(SNAME("TerrainConnect"), SNAME("EditorIcons")));
+ terrains_tile_list->set_item_tooltip(item_index, TTR("Connect mode: paints a terrain, then connects it with the surrounding tiles with the same terrain."));
+ Dictionary list_metadata_dict;
+ list_metadata_dict["type"] = SELECTED_TYPE_CONNECT;
+ terrains_tile_list->set_item_metadata(item_index, list_metadata_dict);
+
+ item_index = terrains_tile_list->add_icon_item(main_vbox_container->get_theme_icon(SNAME("TerrainPath"), SNAME("EditorIcons")));
+ terrains_tile_list->set_item_tooltip(item_index, TTR("Path mode: paints a terrain, thens connects it to the previous tile painted withing the same stroke."));
+ list_metadata_dict = Dictionary();
+ list_metadata_dict["type"] = SELECTED_TYPE_PATH;
+ terrains_tile_list->set_item_metadata(item_index, list_metadata_dict);
+
// Sort the items in a map by the number of corresponding terrains.
RBMap<int, RBSet<TileSet::TerrainsPattern>> sorted;
@@ -3200,7 +3223,7 @@ void TileMapEditorTerrainsPlugin::_update_tiles_list() {
for (int i = 0; i < TileSet::CELL_NEIGHBOR_MAX; i++) {
TileSet::CellNeighbor bit = TileSet::CellNeighbor(i);
- if (tile_set->is_valid_peering_bit_terrain(selected_terrain_set, bit) && E.get_terrain(bit) == selected_terrain_id) {
+ if (tile_set->is_valid_terrain_peering_bit(selected_terrain_set, bit) && E.get_terrain_peering_bit(bit) == selected_terrain_id) {
count++;
}
}
@@ -3241,12 +3264,13 @@ void TileMapEditorTerrainsPlugin::_update_tiles_list() {
}
// Create the ItemList's item.
- int item_index = terrains_tile_list->add_item("");
+ item_index = terrains_tile_list->add_item("");
terrains_tile_list->set_item_icon(item_index, icon);
terrains_tile_list->set_item_icon_region(item_index, region);
terrains_tile_list->set_item_icon_transposed(item_index, transpose);
- Dictionary list_metadata_dict;
- list_metadata_dict["terrains_pattern"] = terrains_pattern.get_terrains_as_array();
+ list_metadata_dict = Dictionary();
+ list_metadata_dict["type"] = SELECTED_TYPE_PATTERN;
+ list_metadata_dict["terrains_pattern"] = terrains_pattern.as_array();
terrains_tile_list->set_item_metadata(item_index, list_metadata_dict);
}
}
@@ -3264,6 +3288,8 @@ void TileMapEditorTerrainsPlugin::_update_theme() {
picker_button->set_icon(main_vbox_container->get_theme_icon(SNAME("ColorPick"), SNAME("EditorIcons")));
erase_button->set_icon(main_vbox_container->get_theme_icon(SNAME("Eraser"), SNAME("EditorIcons")));
+
+ _update_tiles_list();
}
void TileMapEditorTerrainsPlugin::edit(ObjectID p_tile_map_id, int p_tile_map_layer) {
@@ -3303,7 +3329,7 @@ TileMapEditorTerrainsPlugin::TileMapEditorTerrainsPlugin() {
terrains_tile_list->set_h_size_flags(Control::SIZE_EXPAND_FILL);
terrains_tile_list->set_max_columns(0);
terrains_tile_list->set_same_column_width(true);
- terrains_tile_list->set_fixed_icon_size(Size2(30, 30) * EDSCALE);
+ terrains_tile_list->set_fixed_icon_size(Size2(32, 32) * EDSCALE);
terrains_tile_list->set_texture_filter(CanvasItem::TEXTURE_FILTER_NEAREST);
tilemap_tab_terrains->add_child(terrains_tile_list);
@@ -3396,7 +3422,7 @@ void TileMapEditor::_notification(int p_what) {
advanced_menu_button->set_icon(get_theme_icon(SNAME("Tools"), SNAME("EditorIcons")));
toggle_grid_button->set_icon(get_theme_icon(SNAME("Grid"), SNAME("EditorIcons")));
toggle_grid_button->set_pressed(EditorSettings::get_singleton()->get("editors/tiles_editor/display_grid"));
- toogle_highlight_selected_layer_button->set_icon(get_theme_icon(SNAME("TileMapHighlightSelected"), SNAME("EditorIcons")));
+ toggle_highlight_selected_layer_button->set_icon(get_theme_icon(SNAME("TileMapHighlightSelected"), SNAME("EditorIcons")));
} break;
case NOTIFICATION_INTERNAL_PROCESS: {
@@ -3431,64 +3457,13 @@ void TileMapEditor::_on_grid_toggled(bool p_pressed) {
CanvasItemEditor::get_singleton()->update_viewport();
}
-void TileMapEditor::_layers_selection_button_draw() {
- if (!has_theme_icon(SNAME("arrow"), SNAME("OptionButton"))) {
+void TileMapEditor::_layers_selection_item_selected(int p_index) {
+ TileMap *tile_map = Object::cast_to<TileMap>(ObjectDB::get_instance(tile_map_id));
+ if (!tile_map || tile_map->get_layers_count() <= 0) {
return;
}
- RID ci = layers_selection_button->get_canvas_item();
- Ref<Texture2D> arrow = Control::get_theme_icon(SNAME("arrow"), SNAME("OptionButton"));
-
- Color clr = Color(1, 1, 1);
- if (get_theme_constant(SNAME("modulate_arrow"))) {
- switch (layers_selection_button->get_draw_mode()) {
- case BaseButton::DRAW_PRESSED:
- clr = get_theme_color(SNAME("font_pressed_color"));
- break;
- case BaseButton::DRAW_HOVER:
- clr = get_theme_color(SNAME("font_hover_color"));
- break;
- case BaseButton::DRAW_DISABLED:
- clr = get_theme_color(SNAME("font_disabled_color"));
- break;
- default:
- if (layers_selection_button->has_focus()) {
- clr = get_theme_color(SNAME("font_focus_color"));
- } else {
- clr = get_theme_color(SNAME("font_color"));
- }
- }
- }
-
- Size2 size = layers_selection_button->get_size();
-
- Point2 ofs;
- if (is_layout_rtl()) {
- ofs = Point2(get_theme_constant(SNAME("arrow_margin"), SNAME("OptionButton")), int(Math::abs((size.height - arrow->get_height()) / 2)));
- } else {
- ofs = Point2(size.width - arrow->get_width() - get_theme_constant(SNAME("arrow_margin"), SNAME("OptionButton")), int(Math::abs((size.height - arrow->get_height()) / 2)));
- }
- Rect2 dst_rect = Rect2(ofs, arrow->get_size());
- if (!layers_selection_button->is_pressed()) {
- dst_rect.size = -dst_rect.size;
- }
- arrow->draw_rect(ci, dst_rect, false, clr);
-}
-
-void TileMapEditor::_layers_selection_button_pressed() {
- if (!layers_selection_popup->is_visible()) {
- Size2 size = layers_selection_popup->get_contents_minimum_size();
- size.x = MAX(size.x, layers_selection_button->get_size().x);
- layers_selection_popup->set_position(layers_selection_button->get_screen_position() - Size2(0, size.y * get_global_transform().get_scale().y));
- layers_selection_popup->set_size(size);
- layers_selection_popup->popup();
- } else {
- layers_selection_popup->hide();
- }
-}
-
-void TileMapEditor::_layers_selection_id_pressed(int p_id) {
- tile_map_layer = p_id;
+ tile_map_layer = p_index;
_update_layers_selection();
}
@@ -3671,8 +3646,6 @@ void TileMapEditor::_layers_select_next_or_previous(bool p_next) {
}
void TileMapEditor::_update_layers_selection() {
- layers_selection_popup->clear();
-
TileMap *tile_map = Object::cast_to<TileMap>(ObjectDB::get_instance(tile_map_id));
if (!tile_map) {
return;
@@ -3699,32 +3672,23 @@ void TileMapEditor::_update_layers_selection() {
} else {
tile_map_layer = -1;
}
- tile_map->set_selected_layer(toogle_highlight_selected_layer_button->is_pressed() ? tile_map_layer : -1);
+ tile_map->set_selected_layer(toggle_highlight_selected_layer_button->is_pressed() ? tile_map_layer : -1);
- // Build the list of layers.
- for (int i = 0; i < tile_map->get_layers_count(); i++) {
- String name = tile_map->get_layer_name(i);
- layers_selection_popup->add_item(name.is_empty() ? vformat(TTR("Layer #%d"), i) : name, i);
- layers_selection_popup->set_item_as_radio_checkable(i, true);
- layers_selection_popup->set_item_disabled(i, !tile_map->is_layer_enabled(i));
- layers_selection_popup->set_item_checked(i, i == tile_map_layer);
- }
+ layers_selection_button->clear();
+ if (tile_map->get_layers_count() > 0) {
+ // Build the list of layers.
+ for (int i = 0; i < tile_map->get_layers_count(); i++) {
+ String name = tile_map->get_layer_name(i);
+ layers_selection_button->add_item(name.is_empty() ? vformat(TTR("Layer %d"), i) : name, i);
+ layers_selection_button->set_item_disabled(i, !tile_map->is_layer_enabled(i));
+ }
- // Update the button label.
- if (tile_map_layer >= 0) {
- layers_selection_button->set_text(layers_selection_popup->get_item_text(tile_map_layer));
+ layers_selection_button->set_disabled(false);
+ layers_selection_button->select(tile_map_layer);
} else {
- layers_selection_button->set_text(TTR("Select a layer"));
- }
-
- // Set button minimum width.
- Size2 min_button_size = Size2(layers_selection_popup->get_contents_minimum_size().x, 0);
- if (has_theme_icon(SNAME("arrow"), SNAME("OptionButton"))) {
- Ref<Texture2D> arrow = Control::get_theme_icon(SNAME("arrow"), SNAME("OptionButton"));
- min_button_size.x += arrow->get_size().x;
+ layers_selection_button->set_disabled(true);
+ layers_selection_button->set_text(TTR("No Layers"));
}
- layers_selection_button->set_custom_minimum_size(min_button_size);
- layers_selection_button->update();
tabs_plugins[tabs_bar->get_current_tab()]->edit(tile_map_id, tile_map_layer);
}
@@ -4001,7 +3965,6 @@ TileMapEditor::TileMapEditor() {
// TabBar.
tabs_bar = memnew(TabBar);
- tabs_bar->set_tab_alignment(TabBar::ALIGNMENT_CENTER);
tabs_bar->set_clip_tabs(false);
for (int plugin_index = 0; plugin_index < tile_map_editor_plugins.size(); plugin_index++) {
Vector<TileMapEditorPlugin::TabData> tabs_vector = tile_map_editor_plugins[plugin_index]->get_tabs();
@@ -4030,31 +3993,23 @@ TileMapEditor::TileMapEditor() {
}
// Wide empty separation control.
- Control *h_empty_space = memnew(Control);
- h_empty_space->set_h_size_flags(SIZE_EXPAND_FILL);
- tile_map_toolbar->add_child(h_empty_space);
+ tile_map_toolbar->add_spacer();
// Layer selector.
- layers_selection_popup = memnew(PopupMenu);
- layers_selection_popup->connect("id_pressed", callable_mp(this, &TileMapEditor::_layers_selection_id_pressed));
- layers_selection_popup->set_flag(Window::FLAG_POPUP, false);
-
- layers_selection_button = memnew(Button);
- layers_selection_button->set_toggle_mode(true);
- layers_selection_button->connect("draw", callable_mp(this, &TileMapEditor::_layers_selection_button_draw));
- layers_selection_button->connect("pressed", callable_mp(this, &TileMapEditor::_layers_selection_button_pressed));
- layers_selection_button->connect("hidden", callable_mp((Window *)layers_selection_popup, &Popup::hide));
- layers_selection_button->set_tooltip(TTR("Tile Map Layer"));
- layers_selection_button->add_child(layers_selection_popup);
+ layers_selection_button = memnew(OptionButton);
+ layers_selection_button->set_custom_minimum_size(Size2(200, 0));
+ layers_selection_button->set_text_overrun_behavior(TextParagraph::OVERRUN_TRIM_ELLIPSIS);
+ layers_selection_button->set_tooltip(TTR("TileMap Layers"));
+ layers_selection_button->connect("item_selected", callable_mp(this, &TileMapEditor::_layers_selection_item_selected));
tile_map_toolbar->add_child(layers_selection_button);
- toogle_highlight_selected_layer_button = memnew(Button);
- toogle_highlight_selected_layer_button->set_flat(true);
- toogle_highlight_selected_layer_button->set_toggle_mode(true);
- toogle_highlight_selected_layer_button->set_pressed(true);
- toogle_highlight_selected_layer_button->connect("pressed", callable_mp(this, &TileMapEditor::_update_layers_selection));
- toogle_highlight_selected_layer_button->set_tooltip(TTR("Highlight Selected TileMap Layer"));
- tile_map_toolbar->add_child(toogle_highlight_selected_layer_button);
+ toggle_highlight_selected_layer_button = memnew(Button);
+ toggle_highlight_selected_layer_button->set_flat(true);
+ toggle_highlight_selected_layer_button->set_toggle_mode(true);
+ toggle_highlight_selected_layer_button->set_pressed(true);
+ toggle_highlight_selected_layer_button->connect("pressed", callable_mp(this, &TileMapEditor::_update_layers_selection));
+ toggle_highlight_selected_layer_button->set_tooltip(TTR("Highlight Selected TileMap Layer"));
+ tile_map_toolbar->add_child(toggle_highlight_selected_layer_button);
tile_map_toolbar->add_child(memnew(VSeparator));
diff --git a/editor/plugins/tiles/tile_map_editor.h b/editor/plugins/tiles/tile_map_editor.h
index 7158ebff59..ff586ebbfe 100644
--- a/editor/plugins/tiles/tile_map_editor.h
+++ b/editor/plugins/tiles/tile_map_editor.h
@@ -40,6 +40,7 @@
#include "scene/gui/check_box.h"
#include "scene/gui/item_list.h"
#include "scene/gui/menu_button.h"
+#include "scene/gui/option_button.h"
#include "scene/gui/separator.h"
#include "scene/gui/spin_box.h"
#include "scene/gui/split_container.h"
@@ -268,14 +269,22 @@ private:
HashMap<Vector2i, TileMapCell> drag_modified;
// Painting
- HashMap<Vector2i, TileMapCell> _draw_terrains(const HashMap<Vector2i, TileSet::TerrainsPattern> &p_to_paint, int p_terrain_set) const;
+ HashMap<Vector2i, TileMapCell> _draw_terrain_path_or_connect(const Vector<Vector2i> &p_to_paint, int p_terrain_set, int p_terrain, bool p_connect) const;
+ HashMap<Vector2i, TileMapCell> _draw_terrain_pattern(const Vector<Vector2i> &p_to_paint, int p_terrain_set, TileSet::TerrainsPattern p_terrains_pattern) const;
HashMap<Vector2i, TileMapCell> _draw_line(Vector2i p_start_cell, Vector2i p_end_cell, bool p_erase);
HashMap<Vector2i, TileMapCell> _draw_rect(Vector2i p_start_cell, Vector2i p_end_cell, bool p_erase);
RBSet<Vector2i> _get_cells_for_bucket_fill(Vector2i p_coords, bool p_contiguous);
HashMap<Vector2i, TileMapCell> _draw_bucket_fill(Vector2i p_coords, bool p_contiguous, bool p_erase);
void _stop_dragging();
+ enum SelectedType {
+ SELECTED_TYPE_CONNECT = 0,
+ SELECTED_TYPE_PATH,
+ SELECTED_TYPE_PATTERN,
+ };
+ SelectedType selected_type;
int selected_terrain_set = -1;
+ int selected_terrain = -1;
TileSet::TerrainsPattern selected_terrains_pattern;
void _update_selection();
@@ -319,12 +328,9 @@ private:
// Toolbar.
HBoxContainer *tile_map_toolbar = nullptr;
- PopupMenu *layers_selection_popup = nullptr;
- Button *layers_selection_button = nullptr;
- Button *toogle_highlight_selected_layer_button = nullptr;
- void _layers_selection_button_draw();
- void _layers_selection_button_pressed();
- void _layers_selection_id_pressed(int p_id);
+ OptionButton *layers_selection_button = nullptr;
+ Button *toggle_highlight_selected_layer_button = nullptr;
+ void _layers_selection_item_selected(int p_index);
Button *toggle_grid_button = nullptr;
void _on_grid_toggled(bool p_pressed);
diff --git a/editor/plugins/tiles/tile_set_atlas_source_editor.cpp b/editor/plugins/tiles/tile_set_atlas_source_editor.cpp
index b87aedcf60..66459d3ef9 100644
--- a/editor/plugins/tiles/tile_set_atlas_source_editor.cpp
+++ b/editor/plugins/tiles/tile_set_atlas_source_editor.cpp
@@ -2071,9 +2071,10 @@ void TileSetAtlasSourceEditor::_undo_redo_inspector_callback(Object *p_undo_redo
}
} else if (p_property == "terrain_set") {
int current_terrain_set = tile_data_proxy->get("terrain_set");
+ ADD_UNDO(tile_data_proxy, "terrain");
for (int i = 0; i < TileSet::CELL_NEIGHBOR_MAX; i++) {
TileSet::CellNeighbor bit = TileSet::CellNeighbor(i);
- if (tile_set->is_valid_peering_bit_terrain(current_terrain_set, bit)) {
+ if (tile_set->is_valid_terrain_peering_bit(current_terrain_set, bit)) {
ADD_UNDO(tile_data_proxy, "terrains_peering_bit/" + String(TileSet::CELL_NEIGHBOR_ENUM_TO_TEXT[i]));
}
}
diff --git a/editor/plugins/tiles/tile_set_editor.cpp b/editor/plugins/tiles/tile_set_editor.cpp
index fb4a563992..de373e121b 100644
--- a/editor/plugins/tiles/tile_set_editor.cpp
+++ b/editor/plugins/tiles/tile_set_editor.cpp
@@ -505,7 +505,7 @@ void TileSetEditor::_move_tile_set_array_element(Object *p_undo_redo, Object *p_
for (int terrain_set_index = begin; terrain_set_index < end; terrain_set_index++) {
for (int l = 0; l < TileSet::CELL_NEIGHBOR_MAX; l++) {
TileSet::CellNeighbor bit = TileSet::CellNeighbor(l);
- if (tile_data->is_valid_peering_bit_terrain(bit)) {
+ if (tile_data->is_valid_terrain_peering_bit(bit)) {
ADD_UNDO(tile_data, "terrains_peering_bit/" + String(TileSet::CELL_NEIGHBOR_ENUM_TO_TEXT[l]));
}
}
@@ -513,7 +513,7 @@ void TileSetEditor::_move_tile_set_array_element(Object *p_undo_redo, Object *p_
} else if (components.size() >= 2 && components[0].begins_with("terrain_set_") && components[0].trim_prefix("terrain_set_").is_valid_int() && components[1] == "terrain_") {
for (int terrain_index = 0; terrain_index < TileSet::CELL_NEIGHBOR_MAX; terrain_index++) {
TileSet::CellNeighbor bit = TileSet::CellNeighbor(terrain_index);
- if (tile_data->is_valid_peering_bit_terrain(bit)) {
+ if (tile_data->is_valid_terrain_peering_bit(bit)) {
ADD_UNDO(tile_data, "terrains_peering_bit/" + String(TileSet::CELL_NEIGHBOR_ENUM_TO_TEXT[terrain_index]));
}
}
@@ -607,9 +607,10 @@ void TileSetEditor::_undo_redo_inspector_callback(Object *p_undo_redo, Object *p
if (components.size() == 2 && components[0].begins_with("terrain_set_") && components[0].trim_prefix("terrain_set_").is_valid_int() && components[1] == "mode") {
ADD_UNDO(tile_data, "terrain_set");
+ ADD_UNDO(tile_data, "terrain");
for (int l = 0; l < TileSet::CELL_NEIGHBOR_MAX; l++) {
TileSet::CellNeighbor bit = TileSet::CellNeighbor(l);
- if (tile_data->is_valid_peering_bit_terrain(bit)) {
+ if (tile_data->is_valid_terrain_peering_bit(bit)) {
ADD_UNDO(tile_data, "terrains_peering_bit/" + String(TileSet::CELL_NEIGHBOR_ENUM_TO_TEXT[l]));
}
}
diff --git a/main/main.cpp b/main/main.cpp
index 20270190b3..15166ce152 100644
--- a/main/main.cpp
+++ b/main/main.cpp
@@ -1765,14 +1765,14 @@ Error Main::setup2(Thread::ID p_main_tid_override) {
MAIN_PRINT("Main: Load Boot Image");
- Color clear = GLOBAL_DEF("rendering/environment/defaults/default_clear_color", Color(0.3, 0.3, 0.3));
+ Color clear = GLOBAL_DEF_BASIC("rendering/environment/defaults/default_clear_color", Color(0.3, 0.3, 0.3));
RenderingServer::get_singleton()->set_default_clear_color(clear);
if (show_logo) { //boot logo!
- const bool boot_logo_image = GLOBAL_DEF("application/boot_splash/show_image", true);
- const String boot_logo_path = String(GLOBAL_DEF("application/boot_splash/image", String())).strip_edges();
- const bool boot_logo_scale = GLOBAL_DEF("application/boot_splash/fullsize", true);
- const bool boot_logo_filter = GLOBAL_DEF("application/boot_splash/use_filter", true);
+ const bool boot_logo_image = GLOBAL_DEF_BASIC("application/boot_splash/show_image", true);
+ const String boot_logo_path = String(GLOBAL_DEF_BASIC("application/boot_splash/image", String())).strip_edges();
+ const bool boot_logo_scale = GLOBAL_DEF_BASIC("application/boot_splash/fullsize", true);
+ const bool boot_logo_filter = GLOBAL_DEF_BASIC("application/boot_splash/use_filter", true);
ProjectSettings::get_singleton()->set_custom_property_info("application/boot_splash/image",
PropertyInfo(Variant::STRING,
"application/boot_splash/image",
@@ -1797,10 +1797,10 @@ Error Main::setup2(Thread::ID p_main_tid_override) {
#if defined(TOOLS_ENABLED) && !defined(NO_EDITOR_SPLASH)
const Color boot_bg_color =
- GLOBAL_DEF("application/boot_splash/bg_color",
+ GLOBAL_DEF_BASIC("application/boot_splash/bg_color",
(editor || project_manager) ? boot_splash_editor_bg_color : boot_splash_bg_color);
#else
- const Color boot_bg_color = GLOBAL_DEF("application/boot_splash/bg_color", boot_splash_bg_color);
+ const Color boot_bg_color = GLOBAL_DEF_BASIC("application/boot_splash/bg_color", boot_splash_bg_color);
#endif
if (boot_logo.is_valid()) {
RenderingServer::get_singleton()->set_boot_image(boot_logo, boot_bg_color, boot_logo_scale,
@@ -1832,7 +1832,7 @@ Error Main::setup2(Thread::ID p_main_tid_override) {
MAIN_PRINT("Main: DCC");
RenderingServer::get_singleton()->set_default_clear_color(
- GLOBAL_DEF("rendering/environment/defaults/default_clear_color", Color(0.3, 0.3, 0.3)));
+ GLOBAL_DEF_BASIC("rendering/environment/defaults/default_clear_color", Color(0.3, 0.3, 0.3)));
GLOBAL_DEF("application/config/icon", String());
ProjectSettings::get_singleton()->set_custom_property_info("application/config/icon",
@@ -1958,9 +1958,9 @@ Error Main::setup2(Thread::ID p_main_tid_override) {
// Theme needs modules to be initialized so that sub-resources can be loaded.
initialize_theme();
- GLOBAL_DEF("display/mouse_cursor/custom_image", String());
- GLOBAL_DEF("display/mouse_cursor/custom_image_hotspot", Vector2());
- GLOBAL_DEF("display/mouse_cursor/tooltip_position_offset", Point2(10, 10));
+ GLOBAL_DEF_BASIC("display/mouse_cursor/custom_image", String());
+ GLOBAL_DEF_BASIC("display/mouse_cursor/custom_image_hotspot", Vector2());
+ GLOBAL_DEF_BASIC("display/mouse_cursor/tooltip_position_offset", Point2(10, 10));
ProjectSettings::get_singleton()->set_custom_property_info("display/mouse_cursor/custom_image",
PropertyInfo(Variant::STRING,
"display/mouse_cursor/custom_image",
diff --git a/misc/hooks/pre-commit-make-rst b/misc/hooks/pre-commit-make-rst
index 38b397c494..7d115f1d13 100755
--- a/misc/hooks/pre-commit-make-rst
+++ b/misc/hooks/pre-commit-make-rst
@@ -9,4 +9,4 @@ if [[ "$py_ver" != "3" ]]; then
PYTHON+=3
fi
-$PYTHON doc/tools/make_rst.py doc/classes modules --dry-run
+$PYTHON doc/tools/make_rst.py doc/classes modules --dry-run --color
diff --git a/modules/csg/csg_shape.cpp b/modules/csg/csg_shape.cpp
index 25772bebbe..0f09eb2020 100644
--- a/modules/csg/csg_shape.cpp
+++ b/modules/csg/csg_shape.cpp
@@ -638,7 +638,7 @@ void CSGShape3D::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_meshes"), &CSGShape3D::get_meshes);
ADD_PROPERTY(PropertyInfo(Variant::INT, "operation", PROPERTY_HINT_ENUM, "Union,Intersection,Subtraction"), "set_operation", "get_operation");
- ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "snap", PROPERTY_HINT_RANGE, "0.0001,1,0.001"), "set_snap", "get_snap");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "snap", PROPERTY_HINT_RANGE, "0.0001,1,0.001,suffix:m"), "set_snap", "get_snap");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "calculate_tangents"), "set_calculate_tangents", "is_calculating_tangents");
ADD_GROUP("Collision", "collision_");
@@ -2135,7 +2135,7 @@ void CSGPolygon3D::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::PACKED_VECTOR2_ARRAY, "polygon"), "set_polygon", "get_polygon");
ADD_PROPERTY(PropertyInfo(Variant::INT, "mode", PROPERTY_HINT_ENUM, "Depth,Spin,Path"), "set_mode", "get_mode");
- ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "depth", PROPERTY_HINT_RANGE, "0.01,100.0,0.01,or_greater,exp"), "set_depth", "get_depth");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "depth", PROPERTY_HINT_RANGE, "0.01,100.0,0.01,or_greater,exp,suffix:m"), "set_depth", "get_depth");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "spin_degrees", PROPERTY_HINT_RANGE, "1,360,0.1"), "set_spin_degrees", "get_spin_degrees");
ADD_PROPERTY(PropertyInfo(Variant::INT, "spin_sides", PROPERTY_HINT_RANGE, "3,64,1"), "set_spin_sides", "get_spin_sides");
ADD_PROPERTY(PropertyInfo(Variant::NODE_PATH, "path_node", PROPERTY_HINT_NODE_PATH_VALID_TYPES, "Path3D"), "set_path_node", "get_path_node");
@@ -2145,7 +2145,7 @@ void CSGPolygon3D::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::INT, "path_rotation", PROPERTY_HINT_ENUM, "Polygon,Path,PathFollow"), "set_path_rotation", "get_path_rotation");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "path_local"), "set_path_local", "is_path_local");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "path_continuous_u"), "set_path_continuous_u", "is_path_continuous_u");
- ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "path_u_distance", PROPERTY_HINT_RANGE, "0.0,10.0,0.01,or_greater"), "set_path_u_distance", "get_path_u_distance");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "path_u_distance", PROPERTY_HINT_RANGE, "0.0,10.0,0.01,or_greater,suffix:m"), "set_path_u_distance", "get_path_u_distance");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "path_joined"), "set_path_joined", "is_path_joined");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "smooth_faces"), "set_smooth_faces", "get_smooth_faces");
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "material", PROPERTY_HINT_RESOURCE_TYPE, "BaseMaterial3D,ShaderMaterial"), "set_material", "get_material");
diff --git a/modules/gdscript/gdscript_compiler.cpp b/modules/gdscript/gdscript_compiler.cpp
index 910f94a936..b2cce9d8ee 100644
--- a/modules/gdscript/gdscript_compiler.cpp
+++ b/modules/gdscript/gdscript_compiler.cpp
@@ -1389,25 +1389,9 @@ GDScriptCodeGenerator::Address GDScriptCompiler::_parse_match_pattern(CodeGen &c
codegen.generator->pop_temporary();
codegen.generator->pop_temporary();
- // If this isn't the first, we need to OR with the previous pattern. If it's nested, we use AND instead.
- if (p_is_nested) {
- // Use the previous value as target, since we only need one temporary variable.
- codegen.generator->write_and_right_operand(result_addr);
- codegen.generator->write_end_and(p_previous_test);
- } else if (!p_is_first) {
- // Use the previous value as target, since we only need one temporary variable.
- codegen.generator->write_or_right_operand(result_addr);
- codegen.generator->write_end_or(p_previous_test);
- } else {
- // Just assign this value to the accumulator temporary.
- codegen.generator->write_assign(p_previous_test, result_addr);
- }
- codegen.generator->pop_temporary(); // Remove temp result addr.
-
// Create temporaries outside the loop so they can be reused.
GDScriptCodeGenerator::Address element_addr = codegen.add_temporary();
GDScriptCodeGenerator::Address element_type_addr = codegen.add_temporary();
- GDScriptCodeGenerator::Address test_addr = p_previous_test;
// Evaluate element by element.
for (int i = 0; i < p_pattern->array.size(); i++) {
@@ -1417,7 +1401,7 @@ GDScriptCodeGenerator::Address GDScriptCompiler::_parse_match_pattern(CodeGen &c
}
// Use AND here too, as we don't want to be checking elements if previous test failed (which means this might be an invalid get).
- codegen.generator->write_and_left_operand(test_addr);
+ codegen.generator->write_and_left_operand(result_addr);
// Add index to constant map.
GDScriptCodeGenerator::Address index_addr = codegen.add_constant(i);
@@ -1431,19 +1415,34 @@ GDScriptCodeGenerator::Address GDScriptCompiler::_parse_match_pattern(CodeGen &c
codegen.generator->write_call_utility(element_type_addr, "typeof", typeof_args);
// Try the pattern inside the element.
- test_addr = _parse_match_pattern(codegen, r_error, p_pattern->array[i], element_addr, element_type_addr, p_previous_test, false, true);
+ result_addr = _parse_match_pattern(codegen, r_error, p_pattern->array[i], element_addr, element_type_addr, result_addr, false, true);
if (r_error != OK) {
return GDScriptCodeGenerator::Address();
}
- codegen.generator->write_and_right_operand(test_addr);
- codegen.generator->write_end_and(test_addr);
+ codegen.generator->write_and_right_operand(result_addr);
+ codegen.generator->write_end_and(result_addr);
}
// Remove element temporaries.
codegen.generator->pop_temporary();
codegen.generator->pop_temporary();
- return test_addr;
+ // If this isn't the first, we need to OR with the previous pattern. If it's nested, we use AND instead.
+ if (p_is_nested) {
+ // Use the previous value as target, since we only need one temporary variable.
+ codegen.generator->write_and_right_operand(result_addr);
+ codegen.generator->write_end_and(p_previous_test);
+ } else if (!p_is_first) {
+ // Use the previous value as target, since we only need one temporary variable.
+ codegen.generator->write_or_right_operand(result_addr);
+ codegen.generator->write_end_or(p_previous_test);
+ } else {
+ // Just assign this value to the accumulator temporary.
+ codegen.generator->write_assign(p_previous_test, result_addr);
+ }
+ codegen.generator->pop_temporary(); // Remove temp result addr.
+
+ return p_previous_test;
} break;
case GDScriptParser::PatternNode::PT_DICTIONARY: {
if (p_is_nested) {
@@ -1488,27 +1487,9 @@ GDScriptCodeGenerator::Address GDScriptCompiler::_parse_match_pattern(CodeGen &c
codegen.generator->pop_temporary();
codegen.generator->pop_temporary();
- // If this isn't the first, we need to OR with the previous pattern. If it's nested, we use AND instead.
- if (p_is_nested) {
- // Use the previous value as target, since we only need one temporary variable.
- codegen.generator->write_and_right_operand(result_addr);
- codegen.generator->write_end_and(p_previous_test);
- } else if (!p_is_first) {
- // Use the previous value as target, since we only need one temporary variable.
- codegen.generator->write_or_right_operand(result_addr);
- codegen.generator->write_end_or(p_previous_test);
- } else {
- // Just assign this value to the accumulator temporary.
- codegen.generator->write_assign(p_previous_test, result_addr);
- }
- codegen.generator->pop_temporary(); // Remove temp result addr.
-
// Create temporaries outside the loop so they can be reused.
- temp_type.builtin_type = Variant::BOOL;
- GDScriptCodeGenerator::Address test_result = codegen.add_temporary(temp_type);
GDScriptCodeGenerator::Address element_addr = codegen.add_temporary();
GDScriptCodeGenerator::Address element_type_addr = codegen.add_temporary();
- GDScriptCodeGenerator::Address test_addr = p_previous_test;
// Evaluate element by element.
for (int i = 0; i < p_pattern->dictionary.size(); i++) {
@@ -1519,7 +1500,7 @@ GDScriptCodeGenerator::Address GDScriptCompiler::_parse_match_pattern(CodeGen &c
}
// Use AND here too, as we don't want to be checking elements if previous test failed (which means this might be an invalid get).
- codegen.generator->write_and_left_operand(test_addr);
+ codegen.generator->write_and_left_operand(result_addr);
// Get the pattern key.
GDScriptCodeGenerator::Address pattern_key_addr = _parse_expression(codegen, r_error, element.key);
@@ -1530,11 +1511,11 @@ GDScriptCodeGenerator::Address GDScriptCompiler::_parse_match_pattern(CodeGen &c
// Check if pattern key exists in user's dictionary. This will be AND-ed with next result.
func_args.clear();
func_args.push_back(pattern_key_addr);
- codegen.generator->write_call(test_result, p_value_addr, "has", func_args);
+ codegen.generator->write_call(result_addr, p_value_addr, "has", func_args);
if (element.value_pattern != nullptr) {
// Use AND here too, as we don't want to be checking elements if previous test failed (which means this might be an invalid get).
- codegen.generator->write_and_left_operand(test_result);
+ codegen.generator->write_and_left_operand(result_addr);
// Get actual value from user dictionary.
codegen.generator->write_get(element_addr, pattern_key_addr, p_value_addr);
@@ -1545,16 +1526,16 @@ GDScriptCodeGenerator::Address GDScriptCompiler::_parse_match_pattern(CodeGen &c
codegen.generator->write_call_utility(element_type_addr, "typeof", func_args);
// Try the pattern inside the value.
- test_addr = _parse_match_pattern(codegen, r_error, element.value_pattern, element_addr, element_type_addr, test_addr, false, true);
+ result_addr = _parse_match_pattern(codegen, r_error, element.value_pattern, element_addr, element_type_addr, result_addr, false, true);
if (r_error != OK) {
return GDScriptCodeGenerator::Address();
}
- codegen.generator->write_and_right_operand(test_addr);
- codegen.generator->write_end_and(test_addr);
+ codegen.generator->write_and_right_operand(result_addr);
+ codegen.generator->write_end_and(result_addr);
}
- codegen.generator->write_and_right_operand(test_addr);
- codegen.generator->write_end_and(test_addr);
+ codegen.generator->write_and_right_operand(result_addr);
+ codegen.generator->write_end_and(result_addr);
// Remove pattern key temporary.
if (pattern_key_addr.mode == GDScriptCodeGenerator::Address::TEMPORARY) {
@@ -1565,9 +1546,23 @@ GDScriptCodeGenerator::Address GDScriptCompiler::_parse_match_pattern(CodeGen &c
// Remove element temporaries.
codegen.generator->pop_temporary();
codegen.generator->pop_temporary();
- codegen.generator->pop_temporary();
- return test_addr;
+ // If this isn't the first, we need to OR with the previous pattern. If it's nested, we use AND instead.
+ if (p_is_nested) {
+ // Use the previous value as target, since we only need one temporary variable.
+ codegen.generator->write_and_right_operand(result_addr);
+ codegen.generator->write_end_and(p_previous_test);
+ } else if (!p_is_first) {
+ // Use the previous value as target, since we only need one temporary variable.
+ codegen.generator->write_or_right_operand(result_addr);
+ codegen.generator->write_end_or(p_previous_test);
+ } else {
+ // Just assign this value to the accumulator temporary.
+ codegen.generator->write_assign(p_previous_test, result_addr);
+ }
+ codegen.generator->pop_temporary(); // Remove temp result addr.
+
+ return p_previous_test;
} break;
case GDScriptParser::PatternNode::PT_REST:
// Do nothing.
diff --git a/modules/gdscript/tests/scripts/parser/features/match_dictionary.gd b/modules/gdscript/tests/scripts/parser/features/match_dictionary.gd
new file mode 100644
index 0000000000..377dd25e9e
--- /dev/null
+++ b/modules/gdscript/tests/scripts/parser/features/match_dictionary.gd
@@ -0,0 +1,43 @@
+func foo(x):
+ match x:
+ {"key1": "value1", "key2": "value2"}:
+ print('{"key1": "value1", "key2": "value2"}')
+ {"key1": "value1", "key2"}:
+ print('{"key1": "value1", "key2"}')
+ {"key1", "key2": "value2"}:
+ print('{"key1", "key2": "value2"}')
+ {"key1", "key2"}:
+ print('{"key1", "key2"}')
+ {"key1": "value1"}:
+ print('{"key1": "value1"}')
+ {"key1"}:
+ print('{"key1"}')
+ _:
+ print("wildcard")
+
+func bar(x):
+ match x:
+ {0}:
+ print("0")
+ {1}:
+ print("1")
+ {2}:
+ print("2")
+ _:
+ print("wildcard")
+
+func test():
+ foo({"key1": "value1", "key2": "value2"})
+ foo({"key1": "value1", "key2": ""})
+ foo({"key1": "", "key2": "value2"})
+ foo({"key1": "", "key2": ""})
+ foo({"key1": "value1"})
+ foo({"key1": ""})
+ foo({"key1": "value1", "key2": "value2", "key3": "value3"})
+ foo({"key1": "value1", "key3": ""})
+ foo({"key2": "value2"})
+ foo({"key3": ""})
+ bar({0: "0"})
+ bar({1: "1"})
+ bar({2: "2"})
+ bar({3: "3"})
diff --git a/modules/gdscript/tests/scripts/parser/features/match_dictionary.out b/modules/gdscript/tests/scripts/parser/features/match_dictionary.out
new file mode 100644
index 0000000000..4dee886927
--- /dev/null
+++ b/modules/gdscript/tests/scripts/parser/features/match_dictionary.out
@@ -0,0 +1,15 @@
+GDTEST_OK
+{"key1": "value1", "key2": "value2"}
+{"key1": "value1", "key2"}
+{"key1", "key2": "value2"}
+{"key1", "key2"}
+{"key1": "value1"}
+{"key1"}
+wildcard
+wildcard
+wildcard
+wildcard
+0
+1
+2
+wildcard
diff --git a/modules/gdscript/tests/scripts/parser/features/match_multiple_patterns_with_array.gd b/modules/gdscript/tests/scripts/parser/features/match_multiple_patterns_with_array.gd
new file mode 100644
index 0000000000..dbe223f5f5
--- /dev/null
+++ b/modules/gdscript/tests/scripts/parser/features/match_multiple_patterns_with_array.gd
@@ -0,0 +1,26 @@
+func foo(x):
+ match x:
+ 1, [2]:
+ print('1, [2]')
+ _:
+ print('wildcard')
+
+func bar(x):
+ match x:
+ [1], [2], [3]:
+ print('[1], [2], [3]')
+ [4]:
+ print('[4]')
+ _:
+ print('wildcard')
+
+func test():
+ foo(1)
+ foo([2])
+ foo(2)
+ bar([1])
+ bar([2])
+ bar([3])
+ bar([4])
+ bar([5])
+
diff --git a/modules/gdscript/tests/scripts/parser/features/match_multiple_patterns_with_array.out b/modules/gdscript/tests/scripts/parser/features/match_multiple_patterns_with_array.out
new file mode 100644
index 0000000000..a12b934d67
--- /dev/null
+++ b/modules/gdscript/tests/scripts/parser/features/match_multiple_patterns_with_array.out
@@ -0,0 +1,9 @@
+GDTEST_OK
+1, [2]
+1, [2]
+wildcard
+[1], [2], [3]
+[1], [2], [3]
+[1], [2], [3]
+[4]
+wildcard
diff --git a/modules/gridmap/grid_map.cpp b/modules/gridmap/grid_map.cpp
index 84dd731195..0e34b5907e 100644
--- a/modules/gridmap/grid_map.cpp
+++ b/modules/gridmap/grid_map.cpp
@@ -226,8 +226,8 @@ bool GridMap::is_baking_navigation() {
return bake_navigation;
}
-void GridMap::set_navigation_layers(uint32_t p_layers) {
- navigation_layers = p_layers;
+void GridMap::set_navigation_layers(uint32_t p_navigation_layers) {
+ navigation_layers = p_navigation_layers;
_recreate_octant_data();
}
@@ -548,7 +548,7 @@ bool GridMap::_octant_update(const OctantKey &p_key) {
if (bake_navigation) {
RID region = NavigationServer3D::get_singleton()->region_create();
- NavigationServer3D::get_singleton()->region_set_layers(region, navigation_layers);
+ NavigationServer3D::get_singleton()->region_set_navigation_layers(region, navigation_layers);
NavigationServer3D::get_singleton()->region_set_navmesh(region, navmesh);
NavigationServer3D::get_singleton()->region_set_transform(region, get_global_transform() * nm.xform);
NavigationServer3D::get_singleton()->region_set_map(region, get_world_3d()->get_navigation_map());
@@ -659,7 +659,7 @@ void GridMap::_octant_enter_world(const OctantKey &p_key) {
Ref<NavigationMesh> nm = mesh_library->get_item_navmesh(cell_map[F.key].item);
if (nm.is_valid()) {
RID region = NavigationServer3D::get_singleton()->region_create();
- NavigationServer3D::get_singleton()->region_set_layers(region, navigation_layers);
+ NavigationServer3D::get_singleton()->region_set_navigation_layers(region, navigation_layers);
NavigationServer3D::get_singleton()->region_set_navmesh(region, nm);
NavigationServer3D::get_singleton()->region_set_transform(region, get_global_transform() * F.value.xform);
NavigationServer3D::get_singleton()->region_set_map(region, get_world_3d()->get_navigation_map());
@@ -929,7 +929,7 @@ void GridMap::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "mesh_library", PROPERTY_HINT_RESOURCE_TYPE, "MeshLibrary"), "set_mesh_library", "get_mesh_library");
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "physics_material", PROPERTY_HINT_RESOURCE_TYPE, "PhysicsMaterial"), "set_physics_material", "get_physics_material");
ADD_GROUP("Cell", "cell_");
- ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "cell_size"), "set_cell_size", "get_cell_size");
+ ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "cell_size", PROPERTY_HINT_NONE, "suffix:m"), "set_cell_size", "get_cell_size");
ADD_PROPERTY(PropertyInfo(Variant::INT, "cell_octant_size", PROPERTY_HINT_RANGE, "1,1024,1"), "set_octant_size", "get_octant_size");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "cell_center_x"), "set_center_x", "get_center_x");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "cell_center_y"), "set_center_y", "get_center_y");
diff --git a/modules/gridmap/grid_map.h b/modules/gridmap/grid_map.h
index c79557afea..08ed4d3d12 100644
--- a/modules/gridmap/grid_map.h
+++ b/modules/gridmap/grid_map.h
@@ -238,7 +238,7 @@ public:
void set_bake_navigation(bool p_bake_navigation);
bool is_baking_navigation();
- void set_navigation_layers(uint32_t p_layers);
+ void set_navigation_layers(uint32_t p_navigation_layers);
uint32_t get_navigation_layers();
void set_mesh_library(const Ref<MeshLibrary> &p_mesh_library);
diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Attributes/AssemblyHasScriptsAttribute.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Attributes/AssemblyHasScriptsAttribute.cs
index ef135da51a..2febf37f05 100644
--- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Attributes/AssemblyHasScriptsAttribute.cs
+++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Attributes/AssemblyHasScriptsAttribute.cs
@@ -2,17 +2,27 @@ using System;
namespace Godot
{
+ /// <summary>
+ /// An attribute that determines if an assembly has scripts. If so, what types of scripts the assembly has.
+ /// </summary>
[AttributeUsage(AttributeTargets.Assembly)]
public class AssemblyHasScriptsAttribute : Attribute
{
private readonly bool requiresLookup;
private readonly System.Type[] scriptTypes;
+ /// <summary>
+ /// Constructs a new AssemblyHasScriptsAttribute instance.
+ /// </summary>
public AssemblyHasScriptsAttribute()
{
requiresLookup = true;
}
+ /// <summary>
+ /// Constructs a new AssemblyHasScriptsAttribute instance.
+ /// </summary>
+ /// <param name="scriptTypes">The specified type(s) of scripts.</param>
public AssemblyHasScriptsAttribute(System.Type[] scriptTypes)
{
requiresLookup = false;
diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Attributes/DisableGodotGeneratorsAttribute.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Attributes/DisableGodotGeneratorsAttribute.cs
index e93bc89811..0b00878e8c 100644
--- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Attributes/DisableGodotGeneratorsAttribute.cs
+++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Attributes/DisableGodotGeneratorsAttribute.cs
@@ -2,6 +2,9 @@ using System;
namespace Godot
{
+ /// <summary>
+ /// An attribute that disables Godot Generators.
+ /// </summary>
[AttributeUsage(AttributeTargets.Class)]
public class DisableGodotGeneratorsAttribute : Attribute { }
}
diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Attributes/ExportAttribute.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Attributes/ExportAttribute.cs
index 6adf044886..46eb128d37 100644
--- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Attributes/ExportAttribute.cs
+++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Attributes/ExportAttribute.cs
@@ -2,12 +2,20 @@ using System;
namespace Godot
{
+ /// <summary>
+ /// An attribute used to export objects.
+ /// </summary>
[AttributeUsage(AttributeTargets.Field | AttributeTargets.Property)]
public class ExportAttribute : Attribute
{
private PropertyHint hint;
private string hintString;
+ /// <summary>
+ /// Constructs a new ExportAttribute Instance.
+ /// </summary>
+ /// <param name="hint">A hint to the exported object.</param>
+ /// <param name="hintString">A string representing the exported object.</param>
public ExportAttribute(PropertyHint hint = PropertyHint.None, string hintString = "")
{
this.hint = hint;
diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Attributes/GodotMethodAttribute.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Attributes/GodotMethodAttribute.cs
index 55848769d5..8d4ff0fdb7 100644
--- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Attributes/GodotMethodAttribute.cs
+++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Attributes/GodotMethodAttribute.cs
@@ -2,6 +2,9 @@ using System;
namespace Godot
{
+ /// <summary>
+ /// An attribute for a method.
+ /// </summary>
[AttributeUsage(AttributeTargets.Method)]
internal class GodotMethodAttribute : Attribute
{
@@ -9,6 +12,10 @@ namespace Godot
public string MethodName { get { return methodName; } }
+ /// <summary>
+ /// Constructs a new GodotMethodAttribute instance.
+ /// </summary>
+ /// <param name="methodName">The name of the method.</param>
public GodotMethodAttribute(string methodName)
{
this.methodName = methodName;
diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Attributes/RPCAttributes.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Attributes/RPCAttributes.cs
index b8b9bc660c..f0d37c344d 100644
--- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Attributes/RPCAttributes.cs
+++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Attributes/RPCAttributes.cs
@@ -2,9 +2,15 @@ using System;
namespace Godot
{
+ /// <summary>
+ /// Constructs a new AnyPeerAttribute instance. Members with the AnyPeerAttribute are given authority over their own player.
+ /// </summary>
[AttributeUsage(AttributeTargets.Method)]
public class AnyPeerAttribute : Attribute { }
+ /// <summary>
+ /// Constructs a new AuthorityAttribute instance. Members with the AuthorityAttribute are given authority over the game.
+ /// </summary>
[AttributeUsage(AttributeTargets.Method)]
public class AuthorityAttribute : Attribute { }
}
diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Attributes/ScriptPathAttribute.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Attributes/ScriptPathAttribute.cs
index 12eb1035c3..3ebb6612de 100644
--- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Attributes/ScriptPathAttribute.cs
+++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Attributes/ScriptPathAttribute.cs
@@ -2,11 +2,18 @@ using System;
namespace Godot
{
+ /// <summary>
+ /// An attribute that contains the path to the object's script.
+ /// </summary>
[AttributeUsage(AttributeTargets.Class, AllowMultiple = true)]
public class ScriptPathAttribute : Attribute
{
private string path;
+ /// <summary>
+ /// Constructs a new ScriptPathAttribute instance.
+ /// </summary>
+ /// <param name="path">The file path to the script</param>
public ScriptPathAttribute(string path)
{
this.path = path;
diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Dispatcher.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Dispatcher.cs
index 072e0f20ff..6475237002 100644
--- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Dispatcher.cs
+++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Dispatcher.cs
@@ -4,9 +4,16 @@ namespace Godot
{
public static class Dispatcher
{
+ /// <summary>
+ /// Implements an external instance of GodotTaskScheduler.
+ /// </summary>
+ /// <returns>A GodotTaskScheduler instance.</returns>
[MethodImpl(MethodImplOptions.InternalCall)]
private static extern GodotTaskScheduler godot_icall_DefaultGodotTaskScheduler();
+ /// <summary>
+ /// Initializes the synchronization context as the context of the GodotTaskScheduler.
+ /// </summary>
public static GodotSynchronizationContext SynchronizationContext =>
godot_icall_DefaultGodotTaskScheduler().Context;
}
diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/GodotSynchronizationContext.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/GodotSynchronizationContext.cs
index c01c926e82..1b599beab5 100644
--- a/modules/mono/glue/GodotSharp/GodotSharp/Core/GodotSynchronizationContext.cs
+++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/GodotSynchronizationContext.cs
@@ -14,6 +14,9 @@ namespace Godot
_queue.Add(new KeyValuePair<SendOrPostCallback, object>(d, state));
}
+ /// <summary>
+ /// Calls the Key method on each workItem object in the _queue to activate their callbacks.
+ /// </summary>
public void ExecutePendingContinuations()
{
while (_queue.TryTake(out var workItem))
diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/GodotTaskScheduler.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/GodotTaskScheduler.cs
index 8eaeea50dc..408bed71b2 100644
--- a/modules/mono/glue/GodotSharp/GodotSharp/Core/GodotTaskScheduler.cs
+++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/GodotTaskScheduler.cs
@@ -6,11 +6,25 @@ using System.Threading.Tasks;
namespace Godot
{
+ /// <summary>
+ /// GodotTaskScheduler contains a linked list of tasks to perform as a queue. Methods
+ /// within the class are used to control the queue and perform the contained tasks.
+ /// </summary>
public class GodotTaskScheduler : TaskScheduler
{
+ /// <summary>
+ /// The current synchronization context.
+ /// </summary>
internal GodotSynchronizationContext Context { get; }
+
+ /// <summary>
+ /// The queue of tasks for the task scheduler.
+ /// </summary>
private readonly LinkedList<Task> _tasks = new LinkedList<Task>();
+ /// <summary>
+ /// Constructs a new GodotTaskScheduler instance.
+ /// </summary>
public GodotTaskScheduler()
{
Context = new GodotSynchronizationContext();
@@ -53,12 +67,19 @@ namespace Godot
}
}
+ /// <summary>
+ /// Executes all queued tasks and pending tasks from the current context.
+ /// </summary>
public void Activate()
{
ExecuteQueuedTasks();
Context.ExecutePendingContinuations();
}
+ /// <summary>
+ /// Loops through and attempts to execute each task in _tasks.
+ /// </summary>
+ /// <exception cref="InvalidOperationException"></exception>
private void ExecuteQueuedTasks()
{
while (true)
diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Interfaces/IAwaitable.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Interfaces/IAwaitable.cs
index 0397957d00..e747e03c1e 100644
--- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Interfaces/IAwaitable.cs
+++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Interfaces/IAwaitable.cs
@@ -1,10 +1,17 @@
namespace Godot
{
+ /// <summary>
+ /// An interface that requires a GetAwaiter() method to get a reference to the Awaiter.
+ /// </summary>
public interface IAwaitable
{
IAwaiter GetAwaiter();
}
+ /// <summary>
+ /// A templated interface that requires a GetAwaiter() method to get a reference to the Awaiter.
+ /// </summary>
+ /// <typeparam name="TResult">A reference to the result to be passed out.</typeparam>
public interface IAwaitable<out TResult>
{
IAwaiter<TResult> GetAwaiter();
diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Interfaces/IAwaiter.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Interfaces/IAwaiter.cs
index d3be9d781c..dec225eb29 100644
--- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Interfaces/IAwaiter.cs
+++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Interfaces/IAwaiter.cs
@@ -2,6 +2,9 @@ using System.Runtime.CompilerServices;
namespace Godot
{
+ /// <summary>
+ /// An interface that requires a boolean for completion status and a method that gets the result of completion.
+ /// </summary>
public interface IAwaiter : INotifyCompletion
{
bool IsCompleted { get; }
@@ -9,6 +12,10 @@ namespace Godot
void GetResult();
}
+ /// <summary>
+ /// A templated interface that requires a boolean for completion status and a method that gets the result of completion and returns it.
+ /// </summary>
+ /// <typeparam name="TResult">A reference to the result to be passed out.</typeparam>
public interface IAwaiter<out TResult> : INotifyCompletion
{
bool IsCompleted { get; }
diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Interfaces/ISerializationListener.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Interfaces/ISerializationListener.cs
index c3fa2f3e82..90b4d1b8d3 100644
--- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Interfaces/ISerializationListener.cs
+++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Interfaces/ISerializationListener.cs
@@ -1,5 +1,8 @@
namespace Godot
{
+ /// <summary>
+ /// An interface that requires methods for before and after serialization.
+ /// </summary>
public interface ISerializationListener
{
void OnBeforeSerialize();
diff --git a/modules/navigation/godot_navigation_server.cpp b/modules/navigation/godot_navigation_server.cpp
index f4e719b0c1..2f8cb6c230 100644
--- a/modules/navigation/godot_navigation_server.cpp
+++ b/modules/navigation/godot_navigation_server.cpp
@@ -198,11 +198,11 @@ real_t GodotNavigationServer::map_get_edge_connection_margin(RID p_map) const {
return map->get_edge_connection_margin();
}
-Vector<Vector3> GodotNavigationServer::map_get_path(RID p_map, Vector3 p_origin, Vector3 p_destination, bool p_optimize, uint32_t p_layers) const {
+Vector<Vector3> GodotNavigationServer::map_get_path(RID p_map, Vector3 p_origin, Vector3 p_destination, bool p_optimize, uint32_t p_navigation_layers) const {
const NavMap *map = map_owner.get_or_null(p_map);
ERR_FAIL_COND_V(map == nullptr, Vector<Vector3>());
- return map->get_path(p_origin, p_destination, p_optimize, p_layers);
+ return map->get_path(p_origin, p_destination, p_optimize, p_navigation_layers);
}
Vector3 GodotNavigationServer::map_get_closest_point_to_segment(RID p_map, const Vector3 &p_from, const Vector3 &p_to, const bool p_use_collision) const {
@@ -339,18 +339,18 @@ real_t GodotNavigationServer::region_get_travel_cost(RID p_region) const {
return region->get_travel_cost();
}
-COMMAND_2(region_set_layers, RID, p_region, uint32_t, p_layers) {
+COMMAND_2(region_set_navigation_layers, RID, p_region, uint32_t, p_navigation_layers) {
NavRegion *region = region_owner.get_or_null(p_region);
ERR_FAIL_COND(region == nullptr);
- region->set_layers(p_layers);
+ region->set_navigation_layers(p_navigation_layers);
}
-uint32_t GodotNavigationServer::region_get_layers(RID p_region) const {
+uint32_t GodotNavigationServer::region_get_navigation_layers(RID p_region) const {
NavRegion *region = region_owner.get_or_null(p_region);
ERR_FAIL_COND_V(region == nullptr, 0);
- return region->get_layers();
+ return region->get_navigation_layers();
}
COMMAND_2(region_set_navmesh, RID, p_region, Ref<NavigationMesh>, p_nav_mesh) {
diff --git a/modules/navigation/godot_navigation_server.h b/modules/navigation/godot_navigation_server.h
index 1a7fddb7e6..d931dbaee0 100644
--- a/modules/navigation/godot_navigation_server.h
+++ b/modules/navigation/godot_navigation_server.h
@@ -98,7 +98,7 @@ public:
COMMAND_2(map_set_edge_connection_margin, RID, p_map, real_t, p_connection_margin);
virtual real_t map_get_edge_connection_margin(RID p_map) const override;
- virtual Vector<Vector3> map_get_path(RID p_map, Vector3 p_origin, Vector3 p_destination, bool p_optimize, uint32_t p_layers = 1) const override;
+ virtual Vector<Vector3> map_get_path(RID p_map, Vector3 p_origin, Vector3 p_destination, bool p_optimize, uint32_t p_navigation_layers = 1) const override;
virtual Vector3 map_get_closest_point_to_segment(RID p_map, const Vector3 &p_from, const Vector3 &p_to, const bool p_use_collision = false) const override;
virtual Vector3 map_get_closest_point(RID p_map, const Vector3 &p_point) const override;
@@ -117,8 +117,8 @@ public:
COMMAND_2(region_set_map, RID, p_region, RID, p_map);
virtual RID region_get_map(RID p_region) const override;
- COMMAND_2(region_set_layers, RID, p_region, uint32_t, p_layers);
- virtual uint32_t region_get_layers(RID p_region) const override;
+ COMMAND_2(region_set_navigation_layers, RID, p_region, uint32_t, p_navigation_layers);
+ virtual uint32_t region_get_navigation_layers(RID p_region) const override;
COMMAND_2(region_set_transform, RID, p_region, Transform3D, p_transform);
COMMAND_2(region_set_navmesh, RID, p_region, Ref<NavigationMesh>, p_nav_mesh);
virtual void region_bake_navmesh(Ref<NavigationMesh> r_mesh, Node *p_node) const override;
diff --git a/modules/navigation/nav_map.cpp b/modules/navigation/nav_map.cpp
index 059dc989a8..49c12813b3 100644
--- a/modules/navigation/nav_map.cpp
+++ b/modules/navigation/nav_map.cpp
@@ -65,7 +65,7 @@ gd::PointKey NavMap::get_point_key(const Vector3 &p_pos) const {
return p;
}
-Vector<Vector3> NavMap::get_path(Vector3 p_origin, Vector3 p_destination, bool p_optimize, uint32_t p_layers) const {
+Vector<Vector3> NavMap::get_path(Vector3 p_origin, Vector3 p_destination, bool p_optimize, uint32_t p_navigation_layers) const {
// Find the start poly and the end poly on this map.
const gd::Polygon *begin_poly = nullptr;
const gd::Polygon *end_poly = nullptr;
@@ -78,7 +78,7 @@ Vector<Vector3> NavMap::get_path(Vector3 p_origin, Vector3 p_destination, bool p
const gd::Polygon &p = polygons[i];
// Only consider the polygon if it in a region with compatible layers.
- if ((p_layers & p.owner->get_layers()) == 0) {
+ if ((p_navigation_layers & p.owner->get_navigation_layers()) == 0) {
continue;
}
@@ -154,7 +154,7 @@ Vector<Vector3> NavMap::get_path(Vector3 p_origin, Vector3 p_destination, bool p
const gd::Edge::Connection &connection = edge.connections[connection_index];
// Only consider the connection to another polygon if this polygon is in a region with compatible layers.
- if ((p_layers & connection.polygon->owner->get_layers()) == 0) {
+ if ((p_navigation_layers & connection.polygon->owner->get_navigation_layers()) == 0) {
continue;
}
diff --git a/modules/navigation/nav_map.h b/modules/navigation/nav_map.h
index 20115dd1b4..2036dbecd7 100644
--- a/modules/navigation/nav_map.h
+++ b/modules/navigation/nav_map.h
@@ -105,7 +105,7 @@ public:
gd::PointKey get_point_key(const Vector3 &p_pos) const;
- Vector<Vector3> get_path(Vector3 p_origin, Vector3 p_destination, bool p_optimize, uint32_t p_layers = 1) const;
+ Vector<Vector3> get_path(Vector3 p_origin, Vector3 p_destination, bool p_optimize, uint32_t p_navigation_layers = 1) const;
Vector3 get_closest_point_to_segment(const Vector3 &p_from, const Vector3 &p_to, const bool p_use_collision) const;
Vector3 get_closest_point(const Vector3 &p_point) const;
Vector3 get_closest_point_normal(const Vector3 &p_point) const;
diff --git a/modules/navigation/nav_region.cpp b/modules/navigation/nav_region.cpp
index fea0ad519a..88740807eb 100644
--- a/modules/navigation/nav_region.cpp
+++ b/modules/navigation/nav_region.cpp
@@ -40,12 +40,12 @@ void NavRegion::set_map(NavMap *p_map) {
}
}
-void NavRegion::set_layers(uint32_t p_layers) {
- layers = p_layers;
+void NavRegion::set_navigation_layers(uint32_t p_navigation_layers) {
+ navigation_layers = p_navigation_layers;
}
-uint32_t NavRegion::get_layers() const {
- return layers;
+uint32_t NavRegion::get_navigation_layers() const {
+ return navigation_layers;
}
void NavRegion::set_transform(Transform3D p_transform) {
diff --git a/modules/navigation/nav_region.h b/modules/navigation/nav_region.h
index acde5de834..484856ae36 100644
--- a/modules/navigation/nav_region.h
+++ b/modules/navigation/nav_region.h
@@ -45,7 +45,7 @@ class NavRegion : public NavRid {
NavMap *map = nullptr;
Transform3D transform;
Ref<NavigationMesh> mesh;
- uint32_t layers = 1;
+ uint32_t navigation_layers = 1;
float enter_cost = 0.0;
float travel_cost = 1.0;
Vector<gd::Edge::Connection> connections;
@@ -73,8 +73,8 @@ public:
void set_travel_cost(float p_travel_cost) { travel_cost = MAX(p_travel_cost, 0.0); }
float get_travel_cost() const { return travel_cost; }
- void set_layers(uint32_t p_layers);
- uint32_t get_layers() const;
+ void set_navigation_layers(uint32_t p_navigation_layers);
+ uint32_t get_navigation_layers() const;
void set_transform(Transform3D transform);
const Transform3D &get_transform() const {
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/modules/noise/noise_texture.cpp b/modules/noise/noise_texture.cpp
index e9d16e548c..ca55d3b96d 100644
--- a/modules/noise/noise_texture.cpp
+++ b/modules/noise/noise_texture.cpp
@@ -81,8 +81,8 @@ void NoiseTexture::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_noise", "noise"), &NoiseTexture::set_noise);
ClassDB::bind_method(D_METHOD("get_noise"), &NoiseTexture::get_noise);
- ADD_PROPERTY(PropertyInfo(Variant::INT, "width", PROPERTY_HINT_RANGE, "1,2048,1,or_greater"), "set_width", "get_width");
- ADD_PROPERTY(PropertyInfo(Variant::INT, "height", PROPERTY_HINT_RANGE, "1,2048,1,or_greater"), "set_height", "get_height");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "width", PROPERTY_HINT_RANGE, "1,2048,1,or_greater,suffix:px"), "set_width", "get_width");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "height", PROPERTY_HINT_RANGE, "1,2048,1,or_greater,suffix:px"), "set_height", "get_height");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "invert"), "set_invert", "get_invert");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "in_3d_space"), "set_in_3d_space", "is_in_3d_space");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "generate_mipmaps"), "set_generate_mipmaps", "is_generating_mipmaps");
diff --git a/modules/text_server_adv/text_server_adv.cpp b/modules/text_server_adv/text_server_adv.cpp
index d3abef4c38..86687357d6 100644
--- a/modules/text_server_adv/text_server_adv.cpp
+++ b/modules/text_server_adv/text_server_adv.cpp
@@ -1288,7 +1288,16 @@ _FORCE_INLINE_ bool TextServerAdvanced::_ensure_cache_for_size(FontDataAdvanced
fargs.memory_size = p_font_data->data_size;
fargs.flags = FT_OPEN_MEMORY;
fargs.stream = &fd->stream;
- error = FT_Open_Face(ft_library, &fargs, 0, &fd->face);
+
+ int max_index = 0;
+ FT_Face tmp_face;
+ error = FT_Open_Face(ft_library, &fargs, -1, &tmp_face);
+ if (error == 0) {
+ max_index = tmp_face->num_faces - 1;
+ }
+ FT_Done_Face(tmp_face);
+
+ error = FT_Open_Face(ft_library, &fargs, CLAMP(p_font_data->face_index, 0, max_index), &fd->face);
if (error) {
FT_Done_Face(fd->face);
fd->face = nullptr;
@@ -1720,6 +1729,69 @@ void TextServerAdvanced::font_set_data_ptr(const RID &p_font_rid, const uint8_t
fd->data_size = p_data_size;
}
+void TextServerAdvanced::font_set_face_index(const RID &p_font_rid, int64_t p_face_index) {
+ ERR_FAIL_COND(p_face_index < 0);
+ ERR_FAIL_COND(p_face_index >= 0x7FFF);
+
+ FontDataAdvanced *fd = font_owner.get_or_null(p_font_rid);
+ ERR_FAIL_COND(!fd);
+
+ MutexLock lock(fd->mutex);
+ if (fd->face_index != p_face_index) {
+ fd->face_index = p_face_index;
+ _font_clear_cache(fd);
+ }
+}
+
+int64_t TextServerAdvanced::font_get_face_index(const RID &p_font_rid) const {
+ FontDataAdvanced *fd = font_owner.get_or_null(p_font_rid);
+ ERR_FAIL_COND_V(!fd, 0);
+
+ MutexLock lock(fd->mutex);
+ return fd->face_index;
+}
+
+int64_t TextServerAdvanced::font_get_face_count(const RID &p_font_rid) const {
+ FontDataAdvanced *fd = font_owner.get_or_null(p_font_rid);
+ ERR_FAIL_COND_V(!fd, 0);
+
+ MutexLock lock(fd->mutex);
+ int face_count = 0;
+
+ if (fd->data_ptr && (fd->data_size > 0)) {
+ // Init dynamic font.
+#ifdef MODULE_FREETYPE_ENABLED
+ int error = 0;
+ if (!ft_library) {
+ error = FT_Init_FreeType(&ft_library);
+ ERR_FAIL_COND_V_MSG(error != 0, false, "FreeType: Error initializing library: '" + String(FT_Error_String(error)) + "'.");
+ }
+
+ FT_StreamRec stream;
+ memset(&stream, 0, sizeof(FT_StreamRec));
+ stream.base = (unsigned char *)fd->data_ptr;
+ stream.size = fd->data_size;
+ stream.pos = 0;
+
+ FT_Open_Args fargs;
+ memset(&fargs, 0, sizeof(FT_Open_Args));
+ fargs.memory_base = (unsigned char *)fd->data_ptr;
+ fargs.memory_size = fd->data_size;
+ fargs.flags = FT_OPEN_MEMORY;
+ fargs.stream = &stream;
+
+ FT_Face tmp_face;
+ error = FT_Open_Face(ft_library, &fargs, -1, &tmp_face);
+ if (error == 0) {
+ face_count = tmp_face->num_faces;
+ }
+ FT_Done_Face(tmp_face);
+#endif
+ }
+
+ return face_count;
+}
+
void TextServerAdvanced::font_set_style(const RID &p_font_rid, int64_t /*FontStyle*/ p_style) {
FontDataAdvanced *fd = font_owner.get_or_null(p_font_rid);
ERR_FAIL_COND(!fd);
@@ -4780,6 +4852,9 @@ void TextServerAdvanced::_shape_run(ShapedTextDataAdvanced *p_sd, int64_t p_star
RID f = p_fonts[p_fb_index];
FontDataAdvanced *fd = font_owner.get_or_null(f);
+ ERR_FAIL_COND(!fd);
+ MutexLock lock(fd->mutex);
+
Vector2i fss = _get_size(fd, fs);
hb_font_t *hb_font = _font_get_hb_handle(f, fs);
double scale = font_get_scale(f, fs);
diff --git a/modules/text_server_adv/text_server_adv.h b/modules/text_server_adv/text_server_adv.h
index 552ec28ce4..e7690cb70d 100644
--- a/modules/text_server_adv/text_server_adv.h
+++ b/modules/text_server_adv/text_server_adv.h
@@ -247,6 +247,7 @@ class TextServerAdvanced : public TextServerExtension {
PackedByteArray data;
const uint8_t *data_ptr;
size_t data_size;
+ int face_index = 0;
mutable ThreadWorkPool work_pool;
~FontDataAdvanced() {
@@ -473,6 +474,11 @@ public:
virtual void font_set_data(const RID &p_font_rid, const PackedByteArray &p_data) override;
virtual void font_set_data_ptr(const RID &p_font_rid, const uint8_t *p_data_ptr, int64_t p_data_size) override;
+ virtual void font_set_face_index(const RID &p_font_rid, int64_t p_index) override;
+ virtual int64_t font_get_face_index(const RID &p_font_rid) const override;
+
+ virtual int64_t font_get_face_count(const RID &p_font_rid) const override;
+
virtual void font_set_style(const RID &p_font_rid, int64_t /*FontStyle*/ p_style) override;
virtual int64_t /*FontStyle*/ font_get_style(const RID &p_font_rid) const override;
diff --git a/modules/text_server_fb/text_server_fb.cpp b/modules/text_server_fb/text_server_fb.cpp
index 8c6c1d49d4..0bece4e7a7 100644
--- a/modules/text_server_fb/text_server_fb.cpp
+++ b/modules/text_server_fb/text_server_fb.cpp
@@ -733,7 +733,16 @@ _FORCE_INLINE_ bool TextServerFallback::_ensure_cache_for_size(FontDataFallback
fargs.memory_size = p_font_data->data_size;
fargs.flags = FT_OPEN_MEMORY;
fargs.stream = &fd->stream;
- error = FT_Open_Face(ft_library, &fargs, 0, &fd->face);
+
+ int max_index = 0;
+ FT_Face tmp_face;
+ error = FT_Open_Face(ft_library, &fargs, -1, &tmp_face);
+ if (error == 0) {
+ max_index = tmp_face->num_faces - 1;
+ }
+ FT_Done_Face(tmp_face);
+
+ error = FT_Open_Face(ft_library, &fargs, CLAMP(p_font_data->face_index, 0, max_index), &fd->face);
if (error) {
FT_Done_Face(fd->face);
fd->face = nullptr;
@@ -892,6 +901,69 @@ void TextServerFallback::font_set_style(const RID &p_font_rid, int64_t /*FontSty
fd->style_flags = p_style;
}
+void TextServerFallback::font_set_face_index(const RID &p_font_rid, int64_t p_face_index) {
+ ERR_FAIL_COND(p_face_index < 0);
+ ERR_FAIL_COND(p_face_index >= 0x7FFF);
+
+ FontDataFallback *fd = font_owner.get_or_null(p_font_rid);
+ ERR_FAIL_COND(!fd);
+
+ MutexLock lock(fd->mutex);
+ if (fd->face_index != p_face_index) {
+ fd->face_index = p_face_index;
+ _font_clear_cache(fd);
+ }
+}
+
+int64_t TextServerFallback::font_get_face_index(const RID &p_font_rid) const {
+ FontDataFallback *fd = font_owner.get_or_null(p_font_rid);
+ ERR_FAIL_COND_V(!fd, 0);
+
+ MutexLock lock(fd->mutex);
+ return fd->face_index;
+}
+
+int64_t TextServerFallback::font_get_face_count(const RID &p_font_rid) const {
+ FontDataFallback *fd = font_owner.get_or_null(p_font_rid);
+ ERR_FAIL_COND_V(!fd, 0);
+
+ MutexLock lock(fd->mutex);
+ int face_count = 0;
+
+ if (fd->data_ptr && (fd->data_size > 0)) {
+ // Init dynamic font.
+#ifdef MODULE_FREETYPE_ENABLED
+ int error = 0;
+ if (!ft_library) {
+ error = FT_Init_FreeType(&ft_library);
+ ERR_FAIL_COND_V_MSG(error != 0, false, "FreeType: Error initializing library: '" + String(FT_Error_String(error)) + "'.");
+ }
+
+ FT_StreamRec stream;
+ memset(&stream, 0, sizeof(FT_StreamRec));
+ stream.base = (unsigned char *)fd->data_ptr;
+ stream.size = fd->data_size;
+ stream.pos = 0;
+
+ FT_Open_Args fargs;
+ memset(&fargs, 0, sizeof(FT_Open_Args));
+ fargs.memory_base = (unsigned char *)fd->data_ptr;
+ fargs.memory_size = fd->data_size;
+ fargs.flags = FT_OPEN_MEMORY;
+ fargs.stream = &stream;
+
+ FT_Face tmp_face;
+ error = FT_Open_Face(ft_library, &fargs, -1, &tmp_face);
+ if (error == 0) {
+ face_count = tmp_face->num_faces;
+ }
+ FT_Done_Face(tmp_face);
+#endif
+ }
+
+ return face_count;
+}
+
int64_t /*FontStyle*/ TextServerFallback::font_get_style(const RID &p_font_rid) const {
FontDataFallback *fd = font_owner.get_or_null(p_font_rid);
ERR_FAIL_COND_V(!fd, 0);
diff --git a/modules/text_server_fb/text_server_fb.h b/modules/text_server_fb/text_server_fb.h
index 6456bc6723..e4c81aed5b 100644
--- a/modules/text_server_fb/text_server_fb.h
+++ b/modules/text_server_fb/text_server_fb.h
@@ -209,6 +209,7 @@ class TextServerFallback : public TextServerExtension {
PackedByteArray data;
const uint8_t *data_ptr;
size_t data_size;
+ int face_index = 0;
mutable ThreadWorkPool work_pool;
@@ -364,6 +365,11 @@ public:
virtual void font_set_data(const RID &p_font_rid, const PackedByteArray &p_data) override;
virtual void font_set_data_ptr(const RID &p_font_rid, const uint8_t *p_data_ptr, int64_t p_data_size) override;
+ virtual void font_set_face_index(const RID &p_font_rid, int64_t p_index) override;
+ virtual int64_t font_get_face_index(const RID &p_font_rid) const override;
+
+ virtual int64_t font_get_face_count(const RID &p_font_rid) const override;
+
virtual void font_set_style(const RID &p_font_rid, int64_t /*FontStyle*/ p_style) override;
virtual int64_t /*FontStyle*/ font_get_style(const RID &p_font_rid) const override;
diff --git a/modules/webrtc/doc_classes/WebRTCPeerConnection.xml b/modules/webrtc/doc_classes/WebRTCPeerConnection.xml
index b4d97077e3..fed67397d1 100644
--- a/modules/webrtc/doc_classes/WebRTCPeerConnection.xml
+++ b/modules/webrtc/doc_classes/WebRTCPeerConnection.xml
@@ -95,6 +95,13 @@
Call this method frequently (e.g. in [method Node._process] or [method Node._physics_process]) to properly receive signals.
</description>
</method>
+ <method name="set_default_extension" qualifiers="static">
+ <return type="void" />
+ <argument index="0" name="extension_class" type="StringName" />
+ <description>
+ Sets the [code]extension_class[/code] as the default [WebRTCPeerConnectionExtension] returned when creating a new [WebRTCPeerConnection].
+ </description>
+ </method>
<method name="set_local_description">
<return type="int" enum="Error" />
<argument index="0" name="type" type="String" />
diff --git a/modules/webrtc/doc_classes/WebRTCPeerConnectionExtension.xml b/modules/webrtc/doc_classes/WebRTCPeerConnectionExtension.xml
index e88acdc845..163d939ac1 100644
--- a/modules/webrtc/doc_classes/WebRTCPeerConnectionExtension.xml
+++ b/modules/webrtc/doc_classes/WebRTCPeerConnectionExtension.xml
@@ -62,10 +62,5 @@
<description>
</description>
</method>
- <method name="make_default">
- <return type="void" />
- <description>
- </description>
- </method>
</methods>
</class>
diff --git a/modules/webrtc/webrtc_peer_connection.cpp b/modules/webrtc/webrtc_peer_connection.cpp
index 7fdf26d3cd..75716017d7 100644
--- a/modules/webrtc/webrtc_peer_connection.cpp
+++ b/modules/webrtc/webrtc_peer_connection.cpp
@@ -32,13 +32,14 @@
#ifdef JAVASCRIPT_ENABLED
#include "webrtc_peer_connection_js.h"
-#else
-#include "webrtc_peer_connection_extension.h"
#endif
+#include "webrtc_peer_connection_extension.h"
+
StringName WebRTCPeerConnection::default_extension;
void WebRTCPeerConnection::set_default_extension(const StringName &p_extension) {
+ ERR_FAIL_COND_MSG(!ClassDB::is_parent_class(p_extension, WebRTCPeerConnectionExtension::get_class_static()), vformat("Can't make %s the default WebRTC extension since it does not extend WebRTCPeerConnectionExtension.", p_extension));
default_extension = p_extension;
}
@@ -56,6 +57,8 @@ WebRTCPeerConnection *WebRTCPeerConnection::create() {
}
void WebRTCPeerConnection::_bind_methods() {
+ ClassDB::bind_static_method(get_class_static(), D_METHOD("set_default_extension", "extension_class"), &WebRTCPeerConnectionExtension::set_default_extension);
+
ClassDB::bind_method(D_METHOD("initialize", "configuration"), &WebRTCPeerConnection::initialize, DEFVAL(Dictionary()));
ClassDB::bind_method(D_METHOD("create_data_channel", "label", "options"), &WebRTCPeerConnection::create_data_channel, DEFVAL(Dictionary()));
ClassDB::bind_method(D_METHOD("create_offer"), &WebRTCPeerConnection::create_offer);
diff --git a/modules/webrtc/webrtc_peer_connection_extension.cpp b/modules/webrtc/webrtc_peer_connection_extension.cpp
index 3bc7de217e..85c04b3b19 100644
--- a/modules/webrtc/webrtc_peer_connection_extension.cpp
+++ b/modules/webrtc/webrtc_peer_connection_extension.cpp
@@ -31,8 +31,6 @@
#include "webrtc_peer_connection_extension.h"
void WebRTCPeerConnectionExtension::_bind_methods() {
- ClassDB::bind_method(D_METHOD("make_default"), &WebRTCPeerConnectionExtension::make_default);
-
GDVIRTUAL_BIND(_get_connection_state);
GDVIRTUAL_BIND(_initialize, "p_config");
GDVIRTUAL_BIND(_create_data_channel, "p_label", "p_config");
@@ -44,11 +42,6 @@ void WebRTCPeerConnectionExtension::_bind_methods() {
GDVIRTUAL_BIND(_close);
}
-void WebRTCPeerConnectionExtension::make_default() {
- ERR_FAIL_COND_MSG(!_get_extension(), vformat("Can't make %s the default without extending it.", get_class()));
- WebRTCPeerConnection::set_default_extension(get_class());
-}
-
WebRTCPeerConnection::ConnectionState WebRTCPeerConnectionExtension::get_connection_state() const {
int state;
if (GDVIRTUAL_CALL(_get_connection_state, state)) {
diff --git a/modules/webrtc/webrtc_peer_connection_extension.h b/modules/webrtc/webrtc_peer_connection_extension.h
index 82e32b5602..bde19c173b 100644
--- a/modules/webrtc/webrtc_peer_connection_extension.h
+++ b/modules/webrtc/webrtc_peer_connection_extension.h
@@ -44,8 +44,6 @@ protected:
static void _bind_methods();
public:
- void make_default();
-
virtual ConnectionState get_connection_state() const override;
virtual Error initialize(Dictionary p_config = Dictionary()) override;
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/area_2d.cpp b/scene/2d/area_2d.cpp
index 02d9198e43..dfc1016c84 100644
--- a/scene/2d/area_2d.cpp
+++ b/scene/2d/area_2d.cpp
@@ -605,7 +605,7 @@ void Area2D::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::INT, "gravity_space_override", PROPERTY_HINT_ENUM, "Disabled,Combine,Combine-Replace,Replace,Replace-Combine", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_UPDATE_ALL_IF_MODIFIED), "set_gravity_space_override_mode", "get_gravity_space_override_mode");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "gravity_point", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_UPDATE_ALL_IF_MODIFIED), "set_gravity_is_point", "is_gravity_a_point");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "gravity_point_distance_scale", PROPERTY_HINT_RANGE, "0,1024,0.001,or_greater,exp"), "set_gravity_point_distance_scale", "get_gravity_point_distance_scale");
- ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "gravity_point_center"), "set_gravity_point_center", "get_gravity_point_center");
+ ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "gravity_point_center", PROPERTY_HINT_NONE, "suffix:px"), "set_gravity_point_center", "get_gravity_point_center");
ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "gravity_direction"), "set_gravity_direction", "get_gravity_direction");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "gravity", PROPERTY_HINT_RANGE, U"-4096,4096,0.001,or_lesser,or_greater,suffix:px/s\u00B2"), "set_gravity", "get_gravity");
diff --git a/scene/2d/back_buffer_copy.cpp b/scene/2d/back_buffer_copy.cpp
index c411aaf411..aa4ae01fd9 100644
--- a/scene/2d/back_buffer_copy.cpp
+++ b/scene/2d/back_buffer_copy.cpp
@@ -85,7 +85,7 @@ void BackBufferCopy::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_copy_mode"), &BackBufferCopy::get_copy_mode);
ADD_PROPERTY(PropertyInfo(Variant::INT, "copy_mode", PROPERTY_HINT_ENUM, "Disabled,Rect,Viewport"), "set_copy_mode", "get_copy_mode");
- ADD_PROPERTY(PropertyInfo(Variant::RECT2, "rect"), "set_rect", "get_rect");
+ ADD_PROPERTY(PropertyInfo(Variant::RECT2, "rect", PROPERTY_HINT_NONE, "suffix:px"), "set_rect", "get_rect");
BIND_ENUM_CONSTANT(COPY_MODE_DISABLED);
BIND_ENUM_CONSTANT(COPY_MODE_RECT);
diff --git a/scene/2d/camera_2d.cpp b/scene/2d/camera_2d.cpp
index f61dbc071d..2616d1f09e 100644
--- a/scene/2d/camera_2d.cpp
+++ b/scene/2d/camera_2d.cpp
@@ -729,24 +729,24 @@ void Camera2D::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_margin_drawing_enabled", "margin_drawing_enabled"), &Camera2D::set_margin_drawing_enabled);
ClassDB::bind_method(D_METHOD("is_margin_drawing_enabled"), &Camera2D::is_margin_drawing_enabled);
- ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "offset"), "set_offset", "get_offset");
+ ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "offset", PROPERTY_HINT_NONE, "suffix:px"), "set_offset", "get_offset");
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");
ADD_GROUP("Limit", "limit_");
- ADD_PROPERTYI(PropertyInfo(Variant::INT, "limit_left"), "set_limit", "get_limit", SIDE_LEFT);
- ADD_PROPERTYI(PropertyInfo(Variant::INT, "limit_top"), "set_limit", "get_limit", SIDE_TOP);
- ADD_PROPERTYI(PropertyInfo(Variant::INT, "limit_right"), "set_limit", "get_limit", SIDE_RIGHT);
- ADD_PROPERTYI(PropertyInfo(Variant::INT, "limit_bottom"), "set_limit", "get_limit", SIDE_BOTTOM);
+ ADD_PROPERTYI(PropertyInfo(Variant::INT, "limit_left", PROPERTY_HINT_NONE, "suffix:px"), "set_limit", "get_limit", SIDE_LEFT);
+ ADD_PROPERTYI(PropertyInfo(Variant::INT, "limit_top", PROPERTY_HINT_NONE, "suffix:px"), "set_limit", "get_limit", SIDE_TOP);
+ ADD_PROPERTYI(PropertyInfo(Variant::INT, "limit_right", PROPERTY_HINT_NONE, "suffix:px"), "set_limit", "get_limit", SIDE_RIGHT);
+ ADD_PROPERTYI(PropertyInfo(Variant::INT, "limit_bottom", PROPERTY_HINT_NONE, "suffix:px"), "set_limit", "get_limit", SIDE_BOTTOM);
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "limit_smoothed"), "set_limit_smoothing_enabled", "is_limit_smoothing_enabled");
ADD_GROUP("Smoothing", "smoothing_");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "smoothing_enabled"), "set_enable_follow_smoothing", "is_follow_smoothing_enabled");
- ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "smoothing_speed"), "set_follow_smoothing", "get_follow_smoothing");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "smoothing_speed", PROPERTY_HINT_NONE, "suffix:px/s"), "set_follow_smoothing", "get_follow_smoothing");
ADD_GROUP("Drag", "drag_");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "drag_horizontal_enabled"), "set_drag_horizontal_enabled", "is_drag_horizontal_enabled");
diff --git a/scene/2d/canvas_group.cpp b/scene/2d/canvas_group.cpp
index 37a858330c..bbf3fff0ad 100644
--- a/scene/2d/canvas_group.cpp
+++ b/scene/2d/canvas_group.cpp
@@ -75,8 +75,8 @@ void CanvasGroup::_bind_methods() {
ClassDB::bind_method(D_METHOD("is_using_mipmaps"), &CanvasGroup::is_using_mipmaps);
ADD_GROUP("Tweaks", "");
- ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "fit_margin", PROPERTY_HINT_RANGE, "0,1024,1.0,or_greater"), "set_fit_margin", "get_fit_margin");
- ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "clear_margin", PROPERTY_HINT_RANGE, "0,1024,1.0,or_greater"), "set_clear_margin", "get_clear_margin");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "fit_margin", PROPERTY_HINT_RANGE, "0,1024,1.0,or_greater,suffix:px"), "set_fit_margin", "get_fit_margin");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "clear_margin", PROPERTY_HINT_RANGE, "0,1024,1.0,or_greater,suffix:px"), "set_clear_margin", "get_clear_margin");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "use_mipmaps"), "set_use_mipmaps", "is_using_mipmaps");
}
diff --git a/scene/2d/collision_polygon_2d.cpp b/scene/2d/collision_polygon_2d.cpp
index 20840f5aea..8df29851e5 100644
--- a/scene/2d/collision_polygon_2d.cpp
+++ b/scene/2d/collision_polygon_2d.cpp
@@ -315,7 +315,7 @@ void CollisionPolygon2D::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::PACKED_VECTOR2_ARRAY, "polygon"), "set_polygon", "get_polygon");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "disabled"), "set_disabled", "is_disabled");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "one_way_collision"), "set_one_way_collision", "is_one_way_collision_enabled");
- ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "one_way_collision_margin", PROPERTY_HINT_RANGE, "0,128,0.1"), "set_one_way_collision_margin", "get_one_way_collision_margin");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "one_way_collision_margin", PROPERTY_HINT_RANGE, "0,128,0.1,suffix:px"), "set_one_way_collision_margin", "get_one_way_collision_margin");
BIND_ENUM_CONSTANT(BUILD_SOLIDS);
BIND_ENUM_CONSTANT(BUILD_SEGMENTS);
diff --git a/scene/2d/cpu_particles_2d.cpp b/scene/2d/cpu_particles_2d.cpp
index 07b58e9721..f9cf70a586 100644
--- a/scene/2d/cpu_particles_2d.cpp
+++ b/scene/2d/cpu_particles_2d.cpp
@@ -1364,7 +1364,7 @@ void CPUParticles2D::_bind_methods() {
ADD_GROUP("Emission Shape", "emission_");
ADD_PROPERTY(PropertyInfo(Variant::INT, "emission_shape", PROPERTY_HINT_ENUM, "Point,Sphere,Sphere Surface,Box,Points,Directed Points", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_UPDATE_ALL_IF_MODIFIED), "set_emission_shape", "get_emission_shape");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "emission_sphere_radius", PROPERTY_HINT_RANGE, "0.01,128,0.01,suffix:px"), "set_emission_sphere_radius", "get_emission_sphere_radius");
- ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "emission_rect_extents"), "set_emission_rect_extents", "get_emission_rect_extents");
+ ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "emission_rect_extents", PROPERTY_HINT_NONE, "suffix:px"), "set_emission_rect_extents", "get_emission_rect_extents");
ADD_PROPERTY(PropertyInfo(Variant::PACKED_VECTOR2_ARRAY, "emission_points"), "set_emission_points", "get_emission_points");
ADD_PROPERTY(PropertyInfo(Variant::PACKED_VECTOR2_ARRAY, "emission_normals"), "set_emission_normals", "get_emission_normals");
ADD_PROPERTY(PropertyInfo(Variant::PACKED_COLOR_ARRAY, "emission_colors"), "set_emission_colors", "get_emission_colors");
diff --git a/scene/2d/gpu_particles_2d.cpp b/scene/2d/gpu_particles_2d.cpp
index d1b5f16e08..6edd75e62a 100644
--- a/scene/2d/gpu_particles_2d.cpp
+++ b/scene/2d/gpu_particles_2d.cpp
@@ -617,12 +617,12 @@ void GPUParticles2D::_bind_methods() {
ADD_GROUP("Collision", "collision_");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "collision_base_size", PROPERTY_HINT_RANGE, "0,128,0.01,or_greater,suffix:px"), "set_collision_base_size", "get_collision_base_size");
ADD_GROUP("Drawing", "");
- ADD_PROPERTY(PropertyInfo(Variant::RECT2, "visibility_rect"), "set_visibility_rect", "get_visibility_rect");
+ ADD_PROPERTY(PropertyInfo(Variant::RECT2, "visibility_rect", PROPERTY_HINT_NONE, "suffix:px"), "set_visibility_rect", "get_visibility_rect");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "local_coords"), "set_use_local_coordinates", "get_use_local_coordinates");
ADD_PROPERTY(PropertyInfo(Variant::INT, "draw_order", PROPERTY_HINT_ENUM, "Index,Lifetime,Reverse Lifetime"), "set_draw_order", "get_draw_order");
ADD_GROUP("Trails", "trail_");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "trail_enabled"), "set_trail_enabled", "is_trail_enabled");
- ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "trail_length_secs", PROPERTY_HINT_RANGE, "0.01,10,0.01"), "set_trail_length", "get_trail_length");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "trail_length_secs", PROPERTY_HINT_RANGE, "0.01,10,0.01,suffix:s"), "set_trail_length", "get_trail_length");
ADD_PROPERTY(PropertyInfo(Variant::INT, "trail_sections", PROPERTY_HINT_RANGE, "2,128,1"), "set_trail_sections", "get_trail_sections");
ADD_PROPERTY(PropertyInfo(Variant::INT, "trail_section_subdivisions", PROPERTY_HINT_RANGE, "1,1024,1"), "set_trail_section_subdivisions", "get_trail_section_subdivisions");
ADD_GROUP("Process Material", "process_");
diff --git a/scene/2d/navigation_agent_2d.cpp b/scene/2d/navigation_agent_2d.cpp
index 80d60dca17..e2ab4f7538 100644
--- a/scene/2d/navigation_agent_2d.cpp
+++ b/scene/2d/navigation_agent_2d.cpp
@@ -61,8 +61,11 @@ void NavigationAgent2D::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_path_max_distance", "max_speed"), &NavigationAgent2D::set_path_max_distance);
ClassDB::bind_method(D_METHOD("get_path_max_distance"), &NavigationAgent2D::get_path_max_distance);
- ClassDB::bind_method(D_METHOD("set_navigable_layers", "navigable_layers"), &NavigationAgent2D::set_navigable_layers);
- ClassDB::bind_method(D_METHOD("get_navigable_layers"), &NavigationAgent2D::get_navigable_layers);
+ ClassDB::bind_method(D_METHOD("set_navigation_layers", "navigation_layers"), &NavigationAgent2D::set_navigation_layers);
+ ClassDB::bind_method(D_METHOD("get_navigation_layers"), &NavigationAgent2D::get_navigation_layers);
+
+ ClassDB::bind_method(D_METHOD("set_navigation_map", "navigation_map"), &NavigationAgent2D::set_navigation_map);
+ ClassDB::bind_method(D_METHOD("get_navigation_map"), &NavigationAgent2D::get_navigation_map);
ClassDB::bind_method(D_METHOD("set_target_location", "location"), &NavigationAgent2D::set_target_location);
ClassDB::bind_method(D_METHOD("get_target_location"), &NavigationAgent2D::get_target_location);
@@ -86,7 +89,7 @@ void NavigationAgent2D::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "max_speed", PROPERTY_HINT_RANGE, "0.1,100000,0.01,suffix:px/s"), "set_max_speed", "get_max_speed");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "path_max_distance", PROPERTY_HINT_RANGE, "10,100,1,suffix:px"), "set_path_max_distance", "get_path_max_distance");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "avoidance_enabled"), "set_avoidance_enabled", "get_avoidance_enabled");
- ADD_PROPERTY(PropertyInfo(Variant::INT, "navigable_layers", PROPERTY_HINT_LAYERS_2D_NAVIGATION), "set_navigable_layers", "get_navigable_layers");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "navigation_layers", PROPERTY_HINT_LAYERS_2D_NAVIGATION), "set_navigation_layers", "get_navigation_layers");
ADD_SIGNAL(MethodInfo("path_changed"));
ADD_SIGNAL(MethodInfo("target_reached"));
@@ -191,7 +194,11 @@ void NavigationAgent2D::set_agent_parent(Node *p_agent_parent) {
if (Object::cast_to<Node2D>(p_agent_parent) != nullptr) {
// place agent on navigation map first or else the RVO agent callback creation fails silently later
agent_parent = Object::cast_to<Node2D>(p_agent_parent);
- NavigationServer2D::get_singleton()->agent_set_map(get_rid(), agent_parent->get_world_2d()->get_navigation_map());
+ if (map_override.is_valid()) {
+ NavigationServer2D::get_singleton()->agent_set_map(get_rid(), map_override);
+ } else {
+ NavigationServer2D::get_singleton()->agent_set_map(get_rid(), agent_parent->get_world_2d()->get_navigation_map());
+ }
// create new avoidance callback if enabled
set_avoidance_enabled(avoidance_enabled);
} else {
@@ -200,16 +207,31 @@ void NavigationAgent2D::set_agent_parent(Node *p_agent_parent) {
}
}
-void NavigationAgent2D::set_navigable_layers(uint32_t p_layers) {
- bool layers_changed = navigable_layers != p_layers;
- navigable_layers = p_layers;
- if (layers_changed) {
+void NavigationAgent2D::set_navigation_layers(uint32_t p_navigation_layers) {
+ bool navigation_layers_changed = navigation_layers != p_navigation_layers;
+ navigation_layers = p_navigation_layers;
+ if (navigation_layers_changed) {
_request_repath();
}
}
-uint32_t NavigationAgent2D::get_navigable_layers() const {
- return navigable_layers;
+uint32_t NavigationAgent2D::get_navigation_layers() const {
+ return navigation_layers;
+}
+
+void NavigationAgent2D::set_navigation_map(RID p_navigation_map) {
+ map_override = p_navigation_map;
+ NavigationServer2D::get_singleton()->agent_set_map(agent, map_override);
+ _request_repath();
+}
+
+RID NavigationAgent2D::get_navigation_map() const {
+ if (map_override.is_valid()) {
+ return map_override;
+ } else if (agent_parent != nullptr) {
+ return agent_parent->get_world_2d()->get_navigation_map();
+ }
+ return RID();
}
void NavigationAgent2D::set_target_desired_distance(real_t p_dd) {
@@ -360,7 +382,11 @@ void NavigationAgent2D::update_navigation() {
}
if (reload_path) {
- navigation_path = NavigationServer2D::get_singleton()->map_get_path(agent_parent->get_world_2d()->get_navigation_map(), o, target_location, true, navigable_layers);
+ if (map_override.is_valid()) {
+ navigation_path = NavigationServer2D::get_singleton()->map_get_path(map_override, o, target_location, true, navigation_layers);
+ } else {
+ navigation_path = NavigationServer2D::get_singleton()->map_get_path(agent_parent->get_world_2d()->get_navigation_map(), o, target_location, true, navigation_layers);
+ }
navigation_finished = false;
nav_path_index = 0;
emit_signal(SNAME("path_changed"));
diff --git a/scene/2d/navigation_agent_2d.h b/scene/2d/navigation_agent_2d.h
index c9983119d0..0e494a0512 100644
--- a/scene/2d/navigation_agent_2d.h
+++ b/scene/2d/navigation_agent_2d.h
@@ -42,9 +42,10 @@ class NavigationAgent2D : public Node {
RID agent;
RID map_before_pause;
+ RID map_override;
bool avoidance_enabled = false;
- uint32_t navigable_layers = 1;
+ uint32_t navigation_layers = 1;
real_t target_desired_distance = 1.0;
real_t radius = 0.0;
@@ -84,8 +85,11 @@ public:
void set_agent_parent(Node *p_agent_parent);
- void set_navigable_layers(uint32_t p_layers);
- uint32_t get_navigable_layers() const;
+ void set_navigation_layers(uint32_t p_navigation_layers);
+ uint32_t get_navigation_layers() const;
+
+ void set_navigation_map(RID p_navigation_map);
+ RID get_navigation_map() const;
void set_target_desired_distance(real_t p_dd);
real_t get_target_desired_distance() const {
diff --git a/scene/2d/navigation_region_2d.cpp b/scene/2d/navigation_region_2d.cpp
index 6f3222f27e..d611e524a6 100644
--- a/scene/2d/navigation_region_2d.cpp
+++ b/scene/2d/navigation_region_2d.cpp
@@ -380,12 +380,12 @@ bool NavigationRegion2D::is_enabled() const {
return enabled;
}
-void NavigationRegion2D::set_layers(uint32_t p_layers) {
- NavigationServer2D::get_singleton()->region_set_layers(region, p_layers);
+void NavigationRegion2D::set_navigation_layers(uint32_t p_navigation_layers) {
+ NavigationServer2D::get_singleton()->region_set_navigation_layers(region, p_navigation_layers);
}
-uint32_t NavigationRegion2D::get_layers() const {
- return NavigationServer2D::get_singleton()->region_get_layers(region);
+uint32_t NavigationRegion2D::get_navigation_layers() const {
+ return NavigationServer2D::get_singleton()->region_get_navigation_layers(region);
}
void NavigationRegion2D::set_enter_cost(real_t p_enter_cost) {
@@ -559,8 +559,8 @@ void NavigationRegion2D::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_enabled", "enabled"), &NavigationRegion2D::set_enabled);
ClassDB::bind_method(D_METHOD("is_enabled"), &NavigationRegion2D::is_enabled);
- ClassDB::bind_method(D_METHOD("set_layers", "layers"), &NavigationRegion2D::set_layers);
- ClassDB::bind_method(D_METHOD("get_layers"), &NavigationRegion2D::get_layers);
+ ClassDB::bind_method(D_METHOD("set_navigation_layers", "navigation_layers"), &NavigationRegion2D::set_navigation_layers);
+ ClassDB::bind_method(D_METHOD("get_navigation_layers"), &NavigationRegion2D::get_navigation_layers);
ClassDB::bind_method(D_METHOD("get_region_rid"), &NavigationRegion2D::get_region_rid);
@@ -574,7 +574,7 @@ void NavigationRegion2D::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "navpoly", PROPERTY_HINT_RESOURCE_TYPE, "NavigationPolygon"), "set_navigation_polygon", "get_navigation_polygon");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "enabled"), "set_enabled", "is_enabled");
- ADD_PROPERTY(PropertyInfo(Variant::INT, "layers", PROPERTY_HINT_LAYERS_2D_NAVIGATION), "set_layers", "get_layers");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "navigation_layers", PROPERTY_HINT_LAYERS_2D_NAVIGATION), "set_navigation_layers", "get_navigation_layers");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "enter_cost"), "set_enter_cost", "get_enter_cost");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "travel_cost"), "set_travel_cost", "get_travel_cost");
}
diff --git a/scene/2d/navigation_region_2d.h b/scene/2d/navigation_region_2d.h
index 31574749f7..000cb32f95 100644
--- a/scene/2d/navigation_region_2d.h
+++ b/scene/2d/navigation_region_2d.h
@@ -117,8 +117,8 @@ public:
void set_enabled(bool p_enabled);
bool is_enabled() const;
- void set_layers(uint32_t p_layers);
- uint32_t get_layers() const;
+ void set_navigation_layers(uint32_t p_navigation_layers);
+ uint32_t get_navigation_layers() const;
RID get_region_rid() const;
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/physics_body_2d.cpp b/scene/2d/physics_body_2d.cpp
index e7ac6432c6..e60a5ed034 100644
--- a/scene/2d/physics_body_2d.cpp
+++ b/scene/2d/physics_body_2d.cpp
@@ -222,8 +222,8 @@ void StaticBody2D::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_physics_material_override"), &StaticBody2D::get_physics_material_override);
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "physics_material_override", PROPERTY_HINT_RESOURCE_TYPE, "PhysicsMaterial"), "set_physics_material_override", "get_physics_material_override");
- ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "constant_linear_velocity"), "set_constant_linear_velocity", "get_constant_linear_velocity");
- ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "constant_angular_velocity"), "set_constant_angular_velocity", "get_constant_angular_velocity");
+ ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "constant_linear_velocity", PROPERTY_HINT_NONE, "suffix:px/s"), "set_constant_linear_velocity", "get_constant_linear_velocity");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "constant_angular_velocity", PROPERTY_HINT_NONE, U"radians,suffix:\u00B0/s"), "set_constant_angular_velocity", "get_constant_angular_velocity");
}
StaticBody2D::StaticBody2D(PhysicsServer2D::BodyMode p_mode) :
@@ -1761,7 +1761,7 @@ void CharacterBody2D::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "floor_constant_speed"), "set_floor_constant_speed_enabled", "is_floor_constant_speed_enabled");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "floor_block_on_wall"), "set_floor_block_on_wall_enabled", "is_floor_block_on_wall_enabled");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "floor_max_angle", PROPERTY_HINT_RANGE, "0,180,0.1,radians"), "set_floor_max_angle", "get_floor_max_angle");
- ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "floor_snap_length", PROPERTY_HINT_RANGE, "0,32,0.1,or_greater"), "set_floor_snap_length", "get_floor_snap_length");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "floor_snap_length", PROPERTY_HINT_RANGE, "0,32,0.1,or_greater,suffix:px"), "set_floor_snap_length", "get_floor_snap_length");
ADD_GROUP("Moving Platform", "moving_platform");
ADD_PROPERTY(PropertyInfo(Variant::INT, "moving_platform_apply_velocity_on_leave", PROPERTY_HINT_ENUM, "Always,Upward Only,Never", PROPERTY_USAGE_DEFAULT), "set_moving_platform_apply_velocity_on_leave", "get_moving_platform_apply_velocity_on_leave");
ADD_PROPERTY(PropertyInfo(Variant::INT, "moving_platform_floor_layers", PROPERTY_HINT_LAYERS_2D_PHYSICS), "set_moving_platform_floor_layers", "get_moving_platform_floor_layers");
diff --git a/scene/2d/polygon_2d.cpp b/scene/2d/polygon_2d.cpp
index 4752d3148b..ba62941d3a 100644
--- a/scene/2d/polygon_2d.cpp
+++ b/scene/2d/polygon_2d.cpp
@@ -635,18 +635,19 @@ 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");
ADD_GROUP("Invert", "invert_");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "invert_enable"), "set_invert", "get_invert");
- ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "invert_border", PROPERTY_HINT_RANGE, "0.1,16384,0.1"), "set_invert_border", "get_invert_border");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "invert_border", PROPERTY_HINT_RANGE, "0.1,16384,0.1,suffix:px"), "set_invert_border", "get_invert_border");
ADD_GROUP("Data", "");
ADD_PROPERTY(PropertyInfo(Variant::PACKED_VECTOR2_ARRAY, "polygon"), "set_polygon", "get_polygon");
diff --git a/scene/2d/shape_cast_2d.cpp b/scene/2d/shape_cast_2d.cpp
index a2f4b16ed3..ae810156a2 100644
--- a/scene/2d/shape_cast_2d.cpp
+++ b/scene/2d/shape_cast_2d.cpp
@@ -444,8 +444,8 @@ void ShapeCast2D::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "enabled"), "set_enabled", "is_enabled");
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "shape", PROPERTY_HINT_RESOURCE_TYPE, "Shape2D"), "set_shape", "get_shape");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "exclude_parent"), "set_exclude_parent_body", "get_exclude_parent_body");
- ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "target_position"), "set_target_position", "get_target_position");
- ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "margin", PROPERTY_HINT_RANGE, "0,100,0.01"), "set_margin", "get_margin");
+ ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "target_position", PROPERTY_HINT_NONE, "suffix:px"), "set_target_position", "get_target_position");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "margin", PROPERTY_HINT_RANGE, "0,100,0.01,suffix:px"), "set_margin", "get_margin");
ADD_PROPERTY(PropertyInfo(Variant::INT, "max_results"), "set_max_results", "get_max_results");
ADD_PROPERTY(PropertyInfo(Variant::INT, "collision_mask", PROPERTY_HINT_LAYERS_2D_PHYSICS), "set_collision_mask", "get_collision_mask");
ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "collision_result", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR), "", "_get_collision_result");
diff --git a/scene/2d/tile_map.cpp b/scene/2d/tile_map.cpp
index c4b923ff34..6d04dcdc71 100644
--- a/scene/2d/tile_map.cpp
+++ b/scene/2d/tile_map.cpp
@@ -36,43 +36,34 @@
HashMap<Vector2i, TileSet::CellNeighbor> TileMap::TerrainConstraint::get_overlapping_coords_and_peering_bits() const {
HashMap<Vector2i, TileSet::CellNeighbor> output;
+
+ ERR_FAIL_COND_V(is_center_bit(), output);
+
Ref<TileSet> tile_set = tile_map->get_tileset();
ERR_FAIL_COND_V(!tile_set.is_valid(), output);
TileSet::TileShape shape = tile_set->get_tile_shape();
if (shape == TileSet::TILE_SHAPE_SQUARE) {
switch (bit) {
- case 0:
+ case 1:
output[base_cell_coords] = TileSet::CELL_NEIGHBOR_RIGHT_SIDE;
output[tile_map->get_neighbor_cell(base_cell_coords, TileSet::CELL_NEIGHBOR_RIGHT_SIDE)] = TileSet::CELL_NEIGHBOR_LEFT_SIDE;
break;
- case 1:
+ case 2:
output[base_cell_coords] = TileSet::CELL_NEIGHBOR_BOTTOM_RIGHT_CORNER;
output[tile_map->get_neighbor_cell(base_cell_coords, TileSet::CELL_NEIGHBOR_RIGHT_SIDE)] = TileSet::CELL_NEIGHBOR_BOTTOM_LEFT_CORNER;
output[tile_map->get_neighbor_cell(base_cell_coords, TileSet::CELL_NEIGHBOR_BOTTOM_RIGHT_CORNER)] = TileSet::CELL_NEIGHBOR_TOP_LEFT_CORNER;
output[tile_map->get_neighbor_cell(base_cell_coords, TileSet::CELL_NEIGHBOR_BOTTOM_SIDE)] = TileSet::CELL_NEIGHBOR_TOP_RIGHT_CORNER;
break;
- case 2:
+ case 3:
output[base_cell_coords] = TileSet::CELL_NEIGHBOR_BOTTOM_SIDE;
output[tile_map->get_neighbor_cell(base_cell_coords, TileSet::CELL_NEIGHBOR_BOTTOM_SIDE)] = TileSet::CELL_NEIGHBOR_TOP_SIDE;
break;
- case 3:
- output[base_cell_coords] = TileSet::CELL_NEIGHBOR_BOTTOM_LEFT_CORNER;
- output[tile_map->get_neighbor_cell(base_cell_coords, TileSet::CELL_NEIGHBOR_BOTTOM_SIDE)] = TileSet::CELL_NEIGHBOR_TOP_LEFT_CORNER;
- output[tile_map->get_neighbor_cell(base_cell_coords, TileSet::CELL_NEIGHBOR_BOTTOM_LEFT_CORNER)] = TileSet::CELL_NEIGHBOR_TOP_RIGHT_CORNER;
- output[tile_map->get_neighbor_cell(base_cell_coords, TileSet::CELL_NEIGHBOR_LEFT_SIDE)] = TileSet::CELL_NEIGHBOR_BOTTOM_RIGHT_CORNER;
- break;
default:
ERR_FAIL_V(output);
}
} else if (shape == TileSet::TILE_SHAPE_ISOMETRIC) {
switch (bit) {
- case 0:
- output[base_cell_coords] = TileSet::CELL_NEIGHBOR_RIGHT_CORNER;
- output[tile_map->get_neighbor_cell(base_cell_coords, TileSet::CELL_NEIGHBOR_TOP_RIGHT_SIDE)] = TileSet::CELL_NEIGHBOR_BOTTOM_CORNER;
- output[tile_map->get_neighbor_cell(base_cell_coords, TileSet::CELL_NEIGHBOR_RIGHT_CORNER)] = TileSet::CELL_NEIGHBOR_LEFT_CORNER;
- output[tile_map->get_neighbor_cell(base_cell_coords, TileSet::CELL_NEIGHBOR_BOTTOM_RIGHT_SIDE)] = TileSet::CELL_NEIGHBOR_TOP_CORNER;
- break;
case 1:
output[base_cell_coords] = TileSet::CELL_NEIGHBOR_BOTTOM_RIGHT_SIDE;
output[tile_map->get_neighbor_cell(base_cell_coords, TileSet::CELL_NEIGHBOR_BOTTOM_RIGHT_SIDE)] = TileSet::CELL_NEIGHBOR_TOP_LEFT_SIDE;
@@ -95,25 +86,25 @@ HashMap<Vector2i, TileSet::CellNeighbor> TileMap::TerrainConstraint::get_overlap
TileSet::TileOffsetAxis offset_axis = tile_set->get_tile_offset_axis();
if (offset_axis == TileSet::TILE_OFFSET_AXIS_HORIZONTAL) {
switch (bit) {
- case 0:
+ case 1:
output[base_cell_coords] = TileSet::CELL_NEIGHBOR_RIGHT_SIDE;
output[tile_map->get_neighbor_cell(base_cell_coords, TileSet::CELL_NEIGHBOR_RIGHT_SIDE)] = TileSet::CELL_NEIGHBOR_LEFT_SIDE;
break;
- case 1:
+ case 2:
output[base_cell_coords] = TileSet::CELL_NEIGHBOR_BOTTOM_RIGHT_CORNER;
output[tile_map->get_neighbor_cell(base_cell_coords, TileSet::CELL_NEIGHBOR_RIGHT_SIDE)] = TileSet::CELL_NEIGHBOR_BOTTOM_LEFT_CORNER;
output[tile_map->get_neighbor_cell(base_cell_coords, TileSet::CELL_NEIGHBOR_BOTTOM_RIGHT_SIDE)] = TileSet::CELL_NEIGHBOR_TOP_CORNER;
break;
- case 2:
+ case 3:
output[base_cell_coords] = TileSet::CELL_NEIGHBOR_BOTTOM_RIGHT_SIDE;
output[tile_map->get_neighbor_cell(base_cell_coords, TileSet::CELL_NEIGHBOR_BOTTOM_RIGHT_SIDE)] = TileSet::CELL_NEIGHBOR_TOP_LEFT_SIDE;
break;
- case 3:
+ case 4:
output[base_cell_coords] = TileSet::CELL_NEIGHBOR_BOTTOM_CORNER;
output[tile_map->get_neighbor_cell(base_cell_coords, TileSet::CELL_NEIGHBOR_BOTTOM_RIGHT_SIDE)] = TileSet::CELL_NEIGHBOR_TOP_LEFT_CORNER;
output[tile_map->get_neighbor_cell(base_cell_coords, TileSet::CELL_NEIGHBOR_BOTTOM_LEFT_SIDE)] = TileSet::CELL_NEIGHBOR_TOP_RIGHT_CORNER;
break;
- case 4:
+ case 5:
output[base_cell_coords] = TileSet::CELL_NEIGHBOR_BOTTOM_LEFT_SIDE;
output[tile_map->get_neighbor_cell(base_cell_coords, TileSet::CELL_NEIGHBOR_BOTTOM_LEFT_SIDE)] = TileSet::CELL_NEIGHBOR_TOP_RIGHT_SIDE;
break;
@@ -122,25 +113,25 @@ HashMap<Vector2i, TileSet::CellNeighbor> TileMap::TerrainConstraint::get_overlap
}
} else {
switch (bit) {
- case 0:
+ case 1:
output[base_cell_coords] = TileSet::CELL_NEIGHBOR_RIGHT_CORNER;
output[tile_map->get_neighbor_cell(base_cell_coords, TileSet::CELL_NEIGHBOR_TOP_RIGHT_SIDE)] = TileSet::CELL_NEIGHBOR_BOTTOM_LEFT_CORNER;
output[tile_map->get_neighbor_cell(base_cell_coords, TileSet::CELL_NEIGHBOR_BOTTOM_RIGHT_SIDE)] = TileSet::CELL_NEIGHBOR_TOP_LEFT_CORNER;
break;
- case 1:
+ case 2:
output[base_cell_coords] = TileSet::CELL_NEIGHBOR_BOTTOM_RIGHT_SIDE;
output[tile_map->get_neighbor_cell(base_cell_coords, TileSet::CELL_NEIGHBOR_BOTTOM_RIGHT_SIDE)] = TileSet::CELL_NEIGHBOR_TOP_LEFT_SIDE;
break;
- case 2:
+ case 3:
output[base_cell_coords] = TileSet::CELL_NEIGHBOR_BOTTOM_RIGHT_CORNER;
output[tile_map->get_neighbor_cell(base_cell_coords, TileSet::CELL_NEIGHBOR_BOTTOM_RIGHT_SIDE)] = TileSet::CELL_NEIGHBOR_LEFT_CORNER;
output[tile_map->get_neighbor_cell(base_cell_coords, TileSet::CELL_NEIGHBOR_BOTTOM_SIDE)] = TileSet::CELL_NEIGHBOR_TOP_LEFT_CORNER;
break;
- case 3:
+ case 4:
output[base_cell_coords] = TileSet::CELL_NEIGHBOR_BOTTOM_SIDE;
output[tile_map->get_neighbor_cell(base_cell_coords, TileSet::CELL_NEIGHBOR_BOTTOM_SIDE)] = TileSet::CELL_NEIGHBOR_TOP_SIDE;
break;
- case 4:
+ case 5:
output[base_cell_coords] = TileSet::CELL_NEIGHBOR_BOTTOM_LEFT_SIDE;
output[tile_map->get_neighbor_cell(base_cell_coords, TileSet::CELL_NEIGHBOR_BOTTOM_LEFT_SIDE)] = TileSet::CELL_NEIGHBOR_TOP_RIGHT_SIDE;
break;
@@ -152,6 +143,17 @@ HashMap<Vector2i, TileSet::CellNeighbor> TileMap::TerrainConstraint::get_overlap
return output;
}
+TileMap::TerrainConstraint::TerrainConstraint(const TileMap *p_tile_map, const Vector2i &p_position, int p_terrain) {
+ tile_map = p_tile_map;
+
+ Ref<TileSet> tile_set = tile_map->get_tileset();
+ ERR_FAIL_COND(!tile_set.is_valid());
+
+ bit = 0;
+ base_cell_coords = p_position;
+ terrain = p_terrain;
+}
+
TileMap::TerrainConstraint::TerrainConstraint(const TileMap *p_tile_map, const Vector2i &p_position, const TileSet::CellNeighbor &p_bit, int p_terrain) {
// The way we build the constraint make it easy to detect conflicting constraints.
tile_map = p_tile_map;
@@ -163,35 +165,35 @@ TileMap::TerrainConstraint::TerrainConstraint(const TileMap *p_tile_map, const V
if (shape == TileSet::TILE_SHAPE_SQUARE) {
switch (p_bit) {
case TileSet::CELL_NEIGHBOR_RIGHT_SIDE:
- bit = 0;
+ bit = 1;
base_cell_coords = p_position;
break;
case TileSet::CELL_NEIGHBOR_BOTTOM_RIGHT_CORNER:
- bit = 1;
+ bit = 2;
base_cell_coords = p_position;
break;
case TileSet::CELL_NEIGHBOR_BOTTOM_SIDE:
- bit = 2;
+ bit = 3;
base_cell_coords = p_position;
break;
case TileSet::CELL_NEIGHBOR_BOTTOM_LEFT_CORNER:
- bit = 1;
+ bit = 2;
base_cell_coords = p_tile_map->get_neighbor_cell(p_position, TileSet::CELL_NEIGHBOR_LEFT_SIDE);
break;
case TileSet::CELL_NEIGHBOR_LEFT_SIDE:
- bit = 0;
+ bit = 1;
base_cell_coords = p_tile_map->get_neighbor_cell(p_position, TileSet::CELL_NEIGHBOR_LEFT_SIDE);
break;
case TileSet::CELL_NEIGHBOR_TOP_LEFT_CORNER:
- bit = 1;
+ bit = 2;
base_cell_coords = p_tile_map->get_neighbor_cell(p_position, TileSet::CELL_NEIGHBOR_TOP_LEFT_CORNER);
break;
case TileSet::CELL_NEIGHBOR_TOP_SIDE:
- bit = 2;
+ bit = 3;
base_cell_coords = p_tile_map->get_neighbor_cell(p_position, TileSet::CELL_NEIGHBOR_TOP_SIDE);
break;
case TileSet::CELL_NEIGHBOR_TOP_RIGHT_CORNER:
- bit = 1;
+ bit = 2;
base_cell_coords = p_tile_map->get_neighbor_cell(p_position, TileSet::CELL_NEIGHBOR_TOP_SIDE);
break;
default:
@@ -201,35 +203,35 @@ TileMap::TerrainConstraint::TerrainConstraint(const TileMap *p_tile_map, const V
} else if (shape == TileSet::TILE_SHAPE_ISOMETRIC) {
switch (p_bit) {
case TileSet::CELL_NEIGHBOR_RIGHT_CORNER:
- bit = 1;
+ bit = 2;
base_cell_coords = p_tile_map->get_neighbor_cell(p_position, TileSet::CELL_NEIGHBOR_TOP_RIGHT_SIDE);
break;
case TileSet::CELL_NEIGHBOR_BOTTOM_RIGHT_SIDE:
- bit = 0;
+ bit = 1;
base_cell_coords = p_position;
break;
case TileSet::CELL_NEIGHBOR_BOTTOM_CORNER:
- bit = 1;
+ bit = 2;
base_cell_coords = p_position;
break;
case TileSet::CELL_NEIGHBOR_BOTTOM_LEFT_SIDE:
- bit = 2;
+ bit = 3;
base_cell_coords = p_position;
break;
case TileSet::CELL_NEIGHBOR_LEFT_CORNER:
- bit = 1;
+ bit = 2;
base_cell_coords = p_tile_map->get_neighbor_cell(p_position, TileSet::CELL_NEIGHBOR_TOP_LEFT_SIDE);
break;
case TileSet::CELL_NEIGHBOR_TOP_LEFT_SIDE:
- bit = 0;
+ bit = 1;
base_cell_coords = p_tile_map->get_neighbor_cell(p_position, TileSet::CELL_NEIGHBOR_TOP_LEFT_SIDE);
break;
case TileSet::CELL_NEIGHBOR_TOP_CORNER:
- bit = 1;
+ bit = 2;
base_cell_coords = p_tile_map->get_neighbor_cell(p_position, TileSet::CELL_NEIGHBOR_TOP_CORNER);
break;
case TileSet::CELL_NEIGHBOR_TOP_RIGHT_SIDE:
- bit = 2;
+ bit = 3;
base_cell_coords = p_tile_map->get_neighbor_cell(p_position, TileSet::CELL_NEIGHBOR_TOP_RIGHT_SIDE);
break;
default:
@@ -242,51 +244,51 @@ TileMap::TerrainConstraint::TerrainConstraint(const TileMap *p_tile_map, const V
if (offset_axis == TileSet::TILE_OFFSET_AXIS_HORIZONTAL) {
switch (p_bit) {
case TileSet::CELL_NEIGHBOR_RIGHT_SIDE:
- bit = 0;
+ bit = 1;
base_cell_coords = p_position;
break;
case TileSet::CELL_NEIGHBOR_BOTTOM_RIGHT_CORNER:
- bit = 1;
+ bit = 2;
base_cell_coords = p_position;
break;
case TileSet::CELL_NEIGHBOR_BOTTOM_RIGHT_SIDE:
- bit = 2;
+ bit = 3;
base_cell_coords = p_position;
break;
case TileSet::CELL_NEIGHBOR_BOTTOM_CORNER:
- bit = 3;
+ bit = 4;
base_cell_coords = p_position;
break;
case TileSet::CELL_NEIGHBOR_BOTTOM_LEFT_SIDE:
- bit = 4;
+ bit = 5;
base_cell_coords = p_position;
break;
case TileSet::CELL_NEIGHBOR_BOTTOM_LEFT_CORNER:
- bit = 1;
+ bit = 2;
base_cell_coords = p_tile_map->get_neighbor_cell(p_position, TileSet::CELL_NEIGHBOR_LEFT_SIDE);
break;
case TileSet::CELL_NEIGHBOR_LEFT_SIDE:
- bit = 0;
+ bit = 1;
base_cell_coords = p_tile_map->get_neighbor_cell(p_position, TileSet::CELL_NEIGHBOR_LEFT_SIDE);
break;
case TileSet::CELL_NEIGHBOR_TOP_LEFT_CORNER:
- bit = 3;
+ bit = 4;
base_cell_coords = p_tile_map->get_neighbor_cell(p_position, TileSet::CELL_NEIGHBOR_TOP_LEFT_SIDE);
break;
case TileSet::CELL_NEIGHBOR_TOP_LEFT_SIDE:
- bit = 2;
+ bit = 3;
base_cell_coords = p_tile_map->get_neighbor_cell(p_position, TileSet::CELL_NEIGHBOR_TOP_LEFT_SIDE);
break;
case TileSet::CELL_NEIGHBOR_TOP_CORNER:
- bit = 1;
+ bit = 2;
base_cell_coords = p_tile_map->get_neighbor_cell(p_position, TileSet::CELL_NEIGHBOR_TOP_LEFT_SIDE);
break;
case TileSet::CELL_NEIGHBOR_TOP_RIGHT_SIDE:
- bit = 4;
+ bit = 5;
base_cell_coords = p_tile_map->get_neighbor_cell(p_position, TileSet::CELL_NEIGHBOR_TOP_RIGHT_SIDE);
break;
case TileSet::CELL_NEIGHBOR_TOP_RIGHT_CORNER:
- bit = 3;
+ bit = 4;
base_cell_coords = p_tile_map->get_neighbor_cell(p_position, TileSet::CELL_NEIGHBOR_TOP_RIGHT_SIDE);
break;
default:
@@ -296,51 +298,51 @@ TileMap::TerrainConstraint::TerrainConstraint(const TileMap *p_tile_map, const V
} else {
switch (p_bit) {
case TileSet::CELL_NEIGHBOR_RIGHT_CORNER:
- bit = 0;
+ bit = 1;
base_cell_coords = p_position;
break;
case TileSet::CELL_NEIGHBOR_BOTTOM_RIGHT_SIDE:
- bit = 1;
+ bit = 2;
base_cell_coords = p_position;
break;
case TileSet::CELL_NEIGHBOR_BOTTOM_RIGHT_CORNER:
- bit = 2;
+ bit = 3;
base_cell_coords = p_position;
break;
case TileSet::CELL_NEIGHBOR_BOTTOM_SIDE:
- bit = 3;
+ bit = 4;
base_cell_coords = p_position;
break;
case TileSet::CELL_NEIGHBOR_BOTTOM_LEFT_CORNER:
- bit = 0;
+ bit = 1;
base_cell_coords = p_tile_map->get_neighbor_cell(p_position, TileSet::CELL_NEIGHBOR_BOTTOM_LEFT_SIDE);
break;
case TileSet::CELL_NEIGHBOR_BOTTOM_LEFT_SIDE:
- bit = 4;
+ bit = 5;
base_cell_coords = p_position;
break;
case TileSet::CELL_NEIGHBOR_LEFT_CORNER:
- bit = 2;
+ bit = 3;
base_cell_coords = p_tile_map->get_neighbor_cell(p_position, TileSet::CELL_NEIGHBOR_TOP_LEFT_SIDE);
break;
case TileSet::CELL_NEIGHBOR_TOP_LEFT_SIDE:
- bit = 1;
+ bit = 2;
base_cell_coords = p_tile_map->get_neighbor_cell(p_position, TileSet::CELL_NEIGHBOR_TOP_LEFT_SIDE);
break;
case TileSet::CELL_NEIGHBOR_TOP_LEFT_CORNER:
- bit = 0;
+ bit = 1;
base_cell_coords = p_tile_map->get_neighbor_cell(p_position, TileSet::CELL_NEIGHBOR_TOP_LEFT_SIDE);
break;
case TileSet::CELL_NEIGHBOR_TOP_SIDE:
- bit = 3;
+ bit = 4;
base_cell_coords = p_tile_map->get_neighbor_cell(p_position, TileSet::CELL_NEIGHBOR_TOP_SIDE);
break;
case TileSet::CELL_NEIGHBOR_TOP_RIGHT_CORNER:
- bit = 2;
+ bit = 3;
base_cell_coords = p_tile_map->get_neighbor_cell(p_position, TileSet::CELL_NEIGHBOR_TOP_SIDE);
break;
case TileSet::CELL_NEIGHBOR_TOP_RIGHT_SIDE:
- bit = 4;
+ bit = 5;
base_cell_coords = p_tile_map->get_neighbor_cell(p_position, TileSet::CELL_NEIGHBOR_TOP_RIGHT_SIDE);
break;
default:
@@ -2149,37 +2151,75 @@ void TileMap::set_pattern(int p_layer, Vector2i p_position, const Ref<TileMapPat
}
}
-RBSet<TileSet::TerrainsPattern> TileMap::_get_valid_terrains_patterns_for_constraints(int p_terrain_set, const Vector2i &p_position, RBSet<TerrainConstraint> p_constraints) {
+TileSet::TerrainsPattern TileMap::_get_best_terrain_pattern_for_constraints(int p_terrain_set, const Vector2i &p_position, RBSet<TerrainConstraint> p_constraints) {
if (!tile_set.is_valid()) {
- return RBSet<TileSet::TerrainsPattern>();
+ return TileSet::TerrainsPattern();
}
// Returns all tiles compatible with the given constraints.
- RBSet<TileSet::TerrainsPattern> compatible_terrain_tile_patterns;
- for (TileSet::TerrainsPattern &terrain_pattern : tile_set->get_terrains_pattern_set(p_terrain_set)) {
- int valid = true;
+ RBMap<TileSet::TerrainsPattern, int> terrain_pattern_score;
+ RBSet<TileSet::TerrainsPattern> pattern_set = tile_set->get_terrains_pattern_set(p_terrain_set);
+ ERR_FAIL_COND_V(pattern_set.is_empty(), TileSet::TerrainsPattern());
+ for (TileSet::TerrainsPattern &terrain_pattern : pattern_set) {
+ int score = 0;
+
+ // Check the center bit constraint
+ TerrainConstraint terrain_constraint = TerrainConstraint(this, p_position, terrain_pattern.get_terrain());
+ RBSet<TerrainConstraint>::Element *in_set_constraint_element = p_constraints.find(terrain_constraint);
+ if (in_set_constraint_element && in_set_constraint_element->get().get_terrain() != terrain_constraint.get_terrain()) {
+ score += in_set_constraint_element->get().get_priority();
+ }
+
+ // Check the surrounding bits
for (int i = 0; i < TileSet::CELL_NEIGHBOR_MAX; i++) {
TileSet::CellNeighbor bit = TileSet::CellNeighbor(i);
- if (tile_set->is_valid_peering_bit_terrain(p_terrain_set, bit)) {
+ if (tile_set->is_valid_terrain_peering_bit(p_terrain_set, bit)) {
// Check if the bit is compatible with the constraints.
- TerrainConstraint terrain_bit_constraint = TerrainConstraint(this, p_position, bit, terrain_pattern.get_terrain(bit));
- RBSet<TerrainConstraint>::Element *in_set_constraint_element = p_constraints.find(terrain_bit_constraint);
+ TerrainConstraint terrain_bit_constraint = TerrainConstraint(this, p_position, bit, terrain_pattern.get_terrain_peering_bit(bit));
+ in_set_constraint_element = p_constraints.find(terrain_bit_constraint);
if (in_set_constraint_element && in_set_constraint_element->get().get_terrain() != terrain_bit_constraint.get_terrain()) {
- valid = false;
- break;
+ score += in_set_constraint_element->get().get_priority();
}
}
}
- if (valid) {
- compatible_terrain_tile_patterns.insert(terrain_pattern);
+ terrain_pattern_score[terrain_pattern] = score;
+ }
+
+ // Compute the minimum score
+ TileSet::TerrainsPattern min_score_pattern;
+ int min_score = INT32_MAX;
+ for (KeyValue<TileSet::TerrainsPattern, int> E : terrain_pattern_score) {
+ if (E.value < min_score) {
+ min_score_pattern = E.key;
+ min_score = E.value;
}
}
- return compatible_terrain_tile_patterns;
+ return min_score_pattern;
}
-RBSet<TileMap::TerrainConstraint> TileMap::get_terrain_constraints_from_removed_cells_list(int p_layer, const RBSet<Vector2i> &p_to_replace, int p_terrain_set, bool p_ignore_empty_terrains) const {
+RBSet<TileMap::TerrainConstraint> TileMap::_get_terrain_constraints_from_added_pattern(Vector2i p_position, int p_terrain_set, TileSet::TerrainsPattern p_terrains_pattern) const {
+ if (!tile_set.is_valid()) {
+ return RBSet<TerrainConstraint>();
+ }
+
+ // Compute the constraints needed from the surrounding tiles.
+ RBSet<TerrainConstraint> output;
+ output.insert(TerrainConstraint(this, p_position, p_terrains_pattern.get_terrain()));
+
+ for (uint32_t i = 0; i < TileSet::CELL_NEIGHBOR_MAX; i++) {
+ TileSet::CellNeighbor side = TileSet::CellNeighbor(i);
+ if (tile_set->is_valid_terrain_peering_bit(p_terrain_set, side)) {
+ TerrainConstraint c = TerrainConstraint(this, p_position, side, p_terrains_pattern.get_terrain_peering_bit(side));
+ output.insert(c);
+ }
+ }
+
+ return output;
+}
+
+RBSet<TileMap::TerrainConstraint> TileMap::_get_terrain_constraints_from_cells_list(int p_layer, const RBSet<Vector2i> &p_cell_list, int p_terrain_set, bool p_ignore_empty_terrains) const {
if (!tile_set.is_valid()) {
return RBSet<TerrainConstraint>();
}
@@ -2187,12 +2227,12 @@ RBSet<TileMap::TerrainConstraint> TileMap::get_terrain_constraints_from_removed_
ERR_FAIL_INDEX_V(p_terrain_set, tile_set->get_terrain_sets_count(), RBSet<TerrainConstraint>());
ERR_FAIL_INDEX_V(p_layer, (int)layers.size(), RBSet<TerrainConstraint>());
- // Build a set of dummy constraints get the constrained points.
+ // Build a set of dummy constraints to get the constrained points.
RBSet<TerrainConstraint> dummy_constraints;
- for (const Vector2i &E : p_to_replace) {
+ for (const Vector2i &E : p_cell_list) {
for (int i = 0; i < TileSet::CELL_NEIGHBOR_MAX; i++) { // Iterates over sides.
TileSet::CellNeighbor bit = TileSet::CellNeighbor(i);
- if (tile_set->is_valid_peering_bit_terrain(p_terrain_set, bit)) {
+ if (tile_set->is_valid_terrain_peering_bit(p_terrain_set, bit)) {
dummy_constraints.insert(TerrainConstraint(this, E, bit, -1));
}
}
@@ -2200,35 +2240,31 @@ RBSet<TileMap::TerrainConstraint> TileMap::get_terrain_constraints_from_removed_
// For each constrained point, we get all overlapping tiles, and select the most adequate terrain for it.
RBSet<TerrainConstraint> constraints;
- for (const TerrainConstraint &E : dummy_constraints) {
- TerrainConstraint c = E;
-
+ for (const TerrainConstraint &E_constraint : dummy_constraints) {
HashMap<int, int> terrain_count;
// Count the number of occurrences per terrain.
- HashMap<Vector2i, TileSet::CellNeighbor> overlapping_terrain_bits = c.get_overlapping_coords_and_peering_bits();
+ HashMap<Vector2i, TileSet::CellNeighbor> overlapping_terrain_bits = E_constraint.get_overlapping_coords_and_peering_bits();
for (const KeyValue<Vector2i, TileSet::CellNeighbor> &E_overlapping : overlapping_terrain_bits) {
- if (!p_to_replace.has(E_overlapping.key)) {
- TileData *neighbor_tile_data = nullptr;
- TileMapCell neighbor_cell = get_cell(p_layer, E_overlapping.key);
- if (neighbor_cell.source_id != TileSet::INVALID_SOURCE) {
- Ref<TileSetSource> source = tile_set->get_source(neighbor_cell.source_id);
- Ref<TileSetAtlasSource> atlas_source = source;
- if (atlas_source.is_valid()) {
- TileData *tile_data = atlas_source->get_tile_data(neighbor_cell.get_atlas_coords(), neighbor_cell.alternative_tile);
- if (tile_data && tile_data->get_terrain_set() == p_terrain_set) {
- neighbor_tile_data = tile_data;
- }
+ TileData *neighbor_tile_data = nullptr;
+ TileMapCell neighbor_cell = get_cell(p_layer, E_overlapping.key);
+ if (neighbor_cell.source_id != TileSet::INVALID_SOURCE) {
+ Ref<TileSetSource> source = tile_set->get_source(neighbor_cell.source_id);
+ Ref<TileSetAtlasSource> atlas_source = source;
+ if (atlas_source.is_valid()) {
+ TileData *tile_data = atlas_source->get_tile_data(neighbor_cell.get_atlas_coords(), neighbor_cell.alternative_tile);
+ if (tile_data && tile_data->get_terrain_set() == p_terrain_set) {
+ neighbor_tile_data = tile_data;
}
}
+ }
- int terrain = neighbor_tile_data ? neighbor_tile_data->get_peering_bit_terrain(TileSet::CellNeighbor(E_overlapping.value)) : -1;
- if (!p_ignore_empty_terrains || terrain >= 0) {
- if (!terrain_count.has(terrain)) {
- terrain_count[terrain] = 0;
- }
- terrain_count[terrain] += 1;
+ int terrain = neighbor_tile_data ? neighbor_tile_data->get_terrain_peering_bit(TileSet::CellNeighbor(E_overlapping.value)) : -1;
+ if (!p_ignore_empty_terrains || terrain >= 0) {
+ if (!terrain_count.has(terrain)) {
+ terrain_count[terrain] = 0;
}
+ terrain_count[terrain] += 1;
}
}
@@ -2244,33 +2280,34 @@ RBSet<TileMap::TerrainConstraint> TileMap::get_terrain_constraints_from_removed_
// Set the adequate terrain.
if (max > 0) {
+ TerrainConstraint c = E_constraint;
c.set_terrain(max_terrain);
constraints.insert(c);
}
}
- return constraints;
-}
-
-RBSet<TileMap::TerrainConstraint> TileMap::get_terrain_constraints_from_added_tile(Vector2i p_position, int p_terrain_set, TileSet::TerrainsPattern p_terrains_pattern) const {
- if (!tile_set.is_valid()) {
- return RBSet<TerrainConstraint>();
- }
+ // Add the centers as constraints
+ for (Vector2i E_coords : p_cell_list) {
+ TileData *tile_data = nullptr;
+ TileMapCell cell = get_cell(p_layer, E_coords);
+ if (cell.source_id != TileSet::INVALID_SOURCE) {
+ Ref<TileSetSource> source = tile_set->get_source(cell.source_id);
+ Ref<TileSetAtlasSource> atlas_source = source;
+ if (atlas_source.is_valid()) {
+ tile_data = atlas_source->get_tile_data(cell.get_atlas_coords(), cell.alternative_tile);
+ }
+ }
- // Compute the constraints needed from the surrounding tiles.
- RBSet<TerrainConstraint> output;
- for (uint32_t i = 0; i < TileSet::CELL_NEIGHBOR_MAX; i++) {
- TileSet::CellNeighbor side = TileSet::CellNeighbor(i);
- if (tile_set->is_valid_peering_bit_terrain(p_terrain_set, side)) {
- TerrainConstraint c = TerrainConstraint(this, p_position, side, p_terrains_pattern.get_terrain(side));
- output.insert(c);
+ int terrain = (tile_data && tile_data->get_terrain_set() == p_terrain_set) ? tile_data->get_terrain() : -1;
+ if (!p_ignore_empty_terrains || terrain >= 0) {
+ constraints.insert(TerrainConstraint(this, E_coords, terrain));
}
}
- return output;
+ return constraints;
}
-HashMap<Vector2i, TileSet::TerrainsPattern> TileMap::terrain_wave_function_collapse(const RBSet<Vector2i> &p_to_replace, int p_terrain_set, const RBSet<TerrainConstraint> p_constraints) {
+HashMap<Vector2i, TileSet::TerrainsPattern> TileMap::terrain_fill_constraints(const Vector<Vector2i> &p_to_replace, int p_terrain_set, const RBSet<TerrainConstraint> p_constraints) {
if (!tile_set.is_valid()) {
return HashMap<Vector2i, TileSet::TerrainsPattern>();
}
@@ -2278,110 +2315,287 @@ HashMap<Vector2i, TileSet::TerrainsPattern> TileMap::terrain_wave_function_colla
// Copy the constraints set.
RBSet<TerrainConstraint> constraints = p_constraints;
- // Compute all acceptable patterns for each cell.
- HashMap<Vector2i, RBSet<TileSet::TerrainsPattern>> per_cell_acceptable_tiles;
- for (Vector2i cell : p_to_replace) {
- per_cell_acceptable_tiles[cell] = _get_valid_terrains_patterns_for_constraints(p_terrain_set, cell, constraints);
- }
-
// Output map.
HashMap<Vector2i, TileSet::TerrainsPattern> output;
// Add all positions to a set.
- RBSet<Vector2i> to_replace = RBSet<Vector2i>(p_to_replace);
- while (!to_replace.is_empty()) {
- // Compute the minimum number of tile possibilities for each cell.
- int min_nb_possibilities = 100000000;
- for (const KeyValue<Vector2i, RBSet<TileSet::TerrainsPattern>> &E : per_cell_acceptable_tiles) {
- min_nb_possibilities = MIN(min_nb_possibilities, E.value.size());
- }
-
- // Get the set of possible cells to fill, out of the most constrained ones.
- LocalVector<Vector2i> to_choose_from;
- for (const KeyValue<Vector2i, RBSet<TileSet::TerrainsPattern>> &E : per_cell_acceptable_tiles) {
- if (E.value.size() == min_nb_possibilities) {
- to_choose_from.push_back(E.key);
- }
- }
-
- // Randomly a cell to fill out of the most constrained.
- Vector2i selected_cell_to_replace = to_choose_from[Math::random(0, to_choose_from.size() - 1)];
-
- // Get the list of acceptable patterns for the given cell.
- RBSet<TileSet::TerrainsPattern> valid_tiles = per_cell_acceptable_tiles[selected_cell_to_replace];
- if (valid_tiles.is_empty()) {
- break; // No possibilities :/
- }
-
- // Out of the possible patterns, prioritize the one which have the least amount of different terrains.
- LocalVector<TileSet::TerrainsPattern> valid_tiles_with_least_amount_of_terrains;
- int min_terrain_count = 10000;
- LocalVector<int> terrains_counts;
- int pattern_index = 0;
- for (const TileSet::TerrainsPattern &pattern : valid_tiles) {
- RBSet<int> terrains;
- for (int i = 0; i < TileSet::CELL_NEIGHBOR_MAX; i++) {
- TileSet::CellNeighbor side = TileSet::CellNeighbor(i);
- if (tile_set->is_valid_peering_bit_terrain(p_terrain_set, side)) {
- terrains.insert(pattern.get_terrain(side));
+ for (int i = 0; i < p_to_replace.size(); i++) {
+ const Vector2i &coords = p_to_replace[i];
+
+ // Select the best pattern for the given constraints
+ TileSet::TerrainsPattern pattern = _get_best_terrain_pattern_for_constraints(p_terrain_set, coords, constraints);
+
+ // Update the constraint set with the new ones
+ RBSet<TerrainConstraint> new_constraints = _get_terrain_constraints_from_added_pattern(coords, p_terrain_set, pattern);
+ for (const TerrainConstraint &E_constraint : new_constraints) {
+ if (constraints.has(E_constraint)) {
+ constraints.erase(E_constraint);
+ }
+ TerrainConstraint c = E_constraint;
+ c.set_priority(5);
+ constraints.insert(c);
+ }
+
+ output[coords] = pattern;
+ }
+ return output;
+}
+
+HashMap<Vector2i, TileSet::TerrainsPattern> TileMap::terrain_fill_connect(int p_layer, const Vector<Vector2i> &p_coords_array, int p_terrain_set, int p_terrain, bool p_ignore_empty_terrains) {
+ HashMap<Vector2i, TileSet::TerrainsPattern> output;
+ ERR_FAIL_COND_V(!tile_set.is_valid(), output);
+ ERR_FAIL_INDEX_V(p_terrain_set, tile_set->get_terrain_sets_count(), output);
+
+ // Build list and set of tiles that can be modified (painted and their surroundings)
+ Vector<Vector2i> can_modify_list;
+ RBSet<Vector2i> can_modify_set;
+ RBSet<Vector2i> painted_set;
+ for (int i = p_coords_array.size() - 1; i >= 0; i--) {
+ const Vector2i &coords = p_coords_array[i];
+ can_modify_list.push_back(coords);
+ can_modify_set.insert(coords);
+ painted_set.insert(coords);
+ }
+ for (Vector2i coords : p_coords_array) {
+ // Find the adequate neighbor
+ for (int j = 0; j < TileSet::CELL_NEIGHBOR_MAX; j++) {
+ TileSet::CellNeighbor bit = TileSet::CellNeighbor(j);
+ if (tile_set->is_valid_terrain_peering_bit(p_terrain_set, bit)) {
+ Vector2i neighbor = get_neighbor_cell(coords, bit);
+ if (!can_modify_set.has(neighbor)) {
+ can_modify_list.push_back(neighbor);
+ can_modify_set.insert(neighbor);
}
}
- min_terrain_count = MIN(min_terrain_count, terrains.size());
- terrains_counts.push_back(terrains.size());
- pattern_index++;
}
- pattern_index = 0;
- for (const TileSet::TerrainsPattern &pattern : valid_tiles) {
- if (terrains_counts[pattern_index] == min_terrain_count) {
- valid_tiles_with_least_amount_of_terrains.push_back(pattern);
+ }
+
+ // Build a set, out of the possibly modified tiles, of the one with a center bit that is set (or will be) to the painted terrain
+ RBSet<Vector2i> cells_with_terrain_center_bit;
+ for (Vector2i coords : can_modify_set) {
+ bool connect = false;
+ if (painted_set.has(coords)) {
+ connect = true;
+ } else {
+ // Get the center bit of the cell
+ TileData *tile_data = nullptr;
+ TileMapCell cell = get_cell(p_layer, coords);
+ if (cell.source_id != TileSet::INVALID_SOURCE) {
+ Ref<TileSetSource> source = tile_set->get_source(cell.source_id);
+ Ref<TileSetAtlasSource> atlas_source = source;
+ if (atlas_source.is_valid()) {
+ tile_data = atlas_source->get_tile_data(cell.get_atlas_coords(), cell.alternative_tile);
+ }
+ }
+
+ if (tile_data && tile_data->get_terrain_set() == p_terrain_set && tile_data->get_terrain() == p_terrain) {
+ connect = true;
+ }
+ }
+ if (connect) {
+ cells_with_terrain_center_bit.insert(coords);
+ }
+ }
+
+ RBSet<TerrainConstraint> constraints;
+
+ // Add new constraints from the path drawn.
+ for (Vector2i coords : p_coords_array) {
+ // Constraints on the center bit.
+ TerrainConstraint c = TerrainConstraint(this, coords, p_terrain);
+ c.set_priority(10);
+ constraints.insert(c);
+
+ // Constraints on the connecting bits.
+ for (int j = 0; j < TileSet::CELL_NEIGHBOR_MAX; j++) {
+ TileSet::CellNeighbor bit = TileSet::CellNeighbor(j);
+ if (tile_set->is_valid_terrain_peering_bit(p_terrain_set, bit)) {
+ c = TerrainConstraint(this, coords, bit, p_terrain);
+ c.set_priority(10);
+ if ((int(bit) % 2) == 0) {
+ // Side peering bits: add the constraint if the center is of the same terrain
+ Vector2i neighbor = get_neighbor_cell(coords, bit);
+ if (cells_with_terrain_center_bit.has(neighbor)) {
+ constraints.insert(c);
+ }
+ } else {
+ // Corner peering bits: add the constraint if all tiles on the constraint has the same center bit
+ HashMap<Vector2i, TileSet::CellNeighbor> overlapping_terrain_bits = c.get_overlapping_coords_and_peering_bits();
+ bool valid = true;
+ for (KeyValue<Vector2i, TileSet::CellNeighbor> kv : overlapping_terrain_bits) {
+ if (!cells_with_terrain_center_bit.has(kv.key)) {
+ valid = false;
+ break;
+ }
+ }
+ if (valid) {
+ constraints.insert(c);
+ }
+ }
}
- pattern_index++;
}
+ }
- // Randomly select a pattern out of the remaining ones.
- TileSet::TerrainsPattern selected_terrain_tile_pattern = valid_tiles_with_least_amount_of_terrains[Math::random(0, valid_tiles_with_least_amount_of_terrains.size() - 1)];
+ // Fills in the constraint list from existing tiles.
+ for (TerrainConstraint c : _get_terrain_constraints_from_cells_list(p_layer, can_modify_set, p_terrain_set, p_ignore_empty_terrains)) {
+ constraints.insert(c);
+ }
- // Set the selected cell into the output.
- output[selected_cell_to_replace] = selected_terrain_tile_pattern;
- to_replace.erase(selected_cell_to_replace);
- per_cell_acceptable_tiles.erase(selected_cell_to_replace);
+ // Fill the terrains.
+ output = terrain_fill_constraints(can_modify_list, p_terrain_set, constraints);
+ return output;
+}
- // Add the new constraints from the added tiles.
- RBSet<TerrainConstraint> new_constraints = get_terrain_constraints_from_added_tile(selected_cell_to_replace, p_terrain_set, selected_terrain_tile_pattern);
- for (const TerrainConstraint &E_constraint : new_constraints) {
- constraints.insert(E_constraint);
+HashMap<Vector2i, TileSet::TerrainsPattern> TileMap::terrain_fill_path(int p_layer, const Vector<Vector2i> &p_path, int p_terrain_set, int p_terrain, bool p_ignore_empty_terrains) {
+ HashMap<Vector2i, TileSet::TerrainsPattern> output;
+ ERR_FAIL_COND_V(!tile_set.is_valid(), output);
+ ERR_FAIL_INDEX_V(p_terrain_set, tile_set->get_terrain_sets_count(), output);
+
+ // Make sure the path is correct and build the peering bit list while doing it.
+ Vector<TileSet::CellNeighbor> neighbor_list;
+ for (int i = 0; i < p_path.size() - 1; i++) {
+ // Find the adequate neighbor
+ TileSet::CellNeighbor found_bit = TileSet::CELL_NEIGHBOR_MAX;
+ for (int j = 0; j < TileSet::CELL_NEIGHBOR_MAX; j++) {
+ TileSet::CellNeighbor bit = TileSet::CellNeighbor(j);
+ if (tile_set->is_valid_terrain_peering_bit(p_terrain_set, bit)) {
+ if (get_neighbor_cell(p_path[i], bit) == p_path[i + 1]) {
+ found_bit = bit;
+ break;
+ }
+ }
}
+ ERR_FAIL_COND_V_MSG(found_bit == TileSet::CELL_NEIGHBOR_MAX, output, vformat("Invalid terrain path, %s is not a neighbouring tile of %s", p_path[i + 1], p_path[i]));
+ neighbor_list.push_back(found_bit);
+ }
+
+ // Build list and set of tiles that can be modified (painted and their surroundings)
+ Vector<Vector2i> can_modify_list;
+ RBSet<Vector2i> can_modify_set;
+ for (int i = p_path.size() - 1; i >= 0; i--) {
+ const Vector2i &coords = p_path[i];
+ can_modify_list.push_back(coords);
+ can_modify_set.insert(coords);
+ }
+ for (Vector2i coords : p_path) {
+ // Find the adequate neighbor
+ for (int j = 0; j < TileSet::CELL_NEIGHBOR_MAX; j++) {
+ TileSet::CellNeighbor bit = TileSet::CellNeighbor(j);
+ if (tile_set->is_valid_terrain_peering_bit(p_terrain_set, bit)) {
+ Vector2i neighbor = get_neighbor_cell(coords, bit);
+ if (!can_modify_set.has(neighbor)) {
+ can_modify_list.push_back(neighbor);
+ can_modify_set.insert(neighbor);
+ }
+ }
+ }
+ }
+
+ RBSet<TerrainConstraint> constraints;
+
+ // Add new constraints from the path drawn.
+ for (Vector2i coords : p_path) {
+ // Constraints on the center bit
+ TerrainConstraint c = TerrainConstraint(this, coords, p_terrain);
+ c.set_priority(10);
+ constraints.insert(c);
+ }
+ for (int i = 0; i < p_path.size() - 1; i++) {
+ // Constraints on the peering bits.
+ TerrainConstraint c = TerrainConstraint(this, p_path[i], neighbor_list[i], p_terrain);
+ c.set_priority(10);
+ constraints.insert(c);
+ }
+
+ // Fills in the constraint list from existing tiles.
+ for (TerrainConstraint c : _get_terrain_constraints_from_cells_list(p_layer, can_modify_set, p_terrain_set, p_ignore_empty_terrains)) {
+ constraints.insert(c);
+ }
+
+ // Fill the terrains.
+ output = terrain_fill_constraints(can_modify_list, p_terrain_set, constraints);
+ return output;
+}
- // Compute valid tiles again for neighbors.
- for (uint32_t i = 0; i < TileSet::CELL_NEIGHBOR_MAX; i++) {
- TileSet::CellNeighbor side = TileSet::CellNeighbor(i);
- if (is_existing_neighbor(side)) {
- Vector2i neighbor = get_neighbor_cell(selected_cell_to_replace, side);
- if (to_replace.has(neighbor)) {
- per_cell_acceptable_tiles[neighbor] = _get_valid_terrains_patterns_for_constraints(p_terrain_set, neighbor, constraints);
+HashMap<Vector2i, TileSet::TerrainsPattern> TileMap::terrain_fill_pattern(int p_layer, const Vector<Vector2i> &p_coords_array, int p_terrain_set, TileSet::TerrainsPattern p_terrains_pattern, bool p_ignore_empty_terrains) {
+ HashMap<Vector2i, TileSet::TerrainsPattern> output;
+ ERR_FAIL_COND_V(!tile_set.is_valid(), output);
+ ERR_FAIL_INDEX_V(p_terrain_set, tile_set->get_terrain_sets_count(), output);
+
+ // Build list and set of tiles that can be modified (painted and their surroundings).
+ Vector<Vector2i> can_modify_list;
+ RBSet<Vector2i> can_modify_set;
+ for (int i = p_coords_array.size() - 1; i >= 0; i--) {
+ const Vector2i &coords = p_coords_array[i];
+ can_modify_list.push_back(coords);
+ can_modify_set.insert(coords);
+ }
+ for (Vector2i coords : p_coords_array) {
+ // Find the adequate neighbor
+ for (int j = 0; j < TileSet::CELL_NEIGHBOR_MAX; j++) {
+ TileSet::CellNeighbor bit = TileSet::CellNeighbor(j);
+ if (tile_set->is_valid_terrain_peering_bit(p_terrain_set, bit)) {
+ Vector2i neighbor = get_neighbor_cell(coords, bit);
+ if (!can_modify_set.has(neighbor)) {
+ can_modify_list.push_back(neighbor);
+ can_modify_set.insert(neighbor);
}
}
}
}
+
+ // Add constraint by the new ones.
+ RBSet<TerrainConstraint> constraints;
+
+ // Add new constraints from the path drawn.
+ for (Vector2i coords : p_coords_array) {
+ // Constraints on the center bit
+ RBSet<TerrainConstraint> added_constraints = _get_terrain_constraints_from_added_pattern(coords, p_terrain_set, p_terrains_pattern);
+ for (TerrainConstraint c : added_constraints) {
+ c.set_priority(10);
+ constraints.insert(c);
+ }
+ }
+
+ // Fills in the constraint list from modified tiles border.
+ for (TerrainConstraint c : _get_terrain_constraints_from_cells_list(p_layer, can_modify_set, p_terrain_set, p_ignore_empty_terrains)) {
+ constraints.insert(c);
+ }
+
+ // Fill the terrains.
+ output = terrain_fill_constraints(can_modify_list, p_terrain_set, constraints);
return output;
}
-void TileMap::set_cells_from_surrounding_terrains(int p_layer, TypedArray<Vector2i> p_coords_array, int p_terrain_set, bool p_ignore_empty_terrains) {
+void TileMap::set_cells_terrain_connect(int p_layer, TypedArray<Vector2i> p_cells, int p_terrain_set, int p_terrain, bool p_ignore_empty_terrains) {
ERR_FAIL_COND(!tile_set.is_valid());
ERR_FAIL_INDEX(p_layer, (int)layers.size());
ERR_FAIL_INDEX(p_terrain_set, tile_set->get_terrain_sets_count());
- RBSet<Vector2i> coords_set;
- for (int i = 0; i < p_coords_array.size(); i++) {
- coords_set.insert(p_coords_array[i]);
+ Vector<Vector2i> vector_cells;
+ for (int i = 0; i < p_cells.size(); i++) {
+ vector_cells.push_back(p_cells[i]);
}
+ HashMap<Vector2i, TileSet::TerrainsPattern> terrain_fill_output = terrain_fill_connect(p_layer, vector_cells, p_terrain_set, p_terrain, p_ignore_empty_terrains);
+ for (const KeyValue<Vector2i, TileSet::TerrainsPattern> &E : terrain_fill_output) {
+ TileMapCell c = tile_set->get_random_tile_from_terrains_pattern(p_terrain_set, E.value);
+ set_cell(p_layer, E.key, c.source_id, c.get_atlas_coords(), c.alternative_tile);
+ }
+}
- RBSet<TileMap::TerrainConstraint> constraints = get_terrain_constraints_from_removed_cells_list(p_layer, coords_set, p_terrain_set, p_ignore_empty_terrains);
+void TileMap::set_cells_terrain_path(int p_layer, TypedArray<Vector2i> p_path, int p_terrain_set, int p_terrain, bool p_ignore_empty_terrains) {
+ ERR_FAIL_COND(!tile_set.is_valid());
+ ERR_FAIL_INDEX(p_layer, (int)layers.size());
+ ERR_FAIL_INDEX(p_terrain_set, tile_set->get_terrain_sets_count());
- HashMap<Vector2i, TileSet::TerrainsPattern> wfc_output = terrain_wave_function_collapse(coords_set, p_terrain_set, constraints);
- for (const KeyValue<Vector2i, TileSet::TerrainsPattern> &kv : wfc_output) {
- TileMapCell cell = tile_set->get_random_tile_from_terrains_pattern(p_terrain_set, kv.value);
- set_cell(p_layer, kv.key, cell.source_id, cell.get_atlas_coords(), cell.alternative_tile);
+ Vector<Vector2i> vector_path;
+ for (int i = 0; i < p_path.size(); i++) {
+ vector_path.push_back(p_path[i]);
+ }
+ HashMap<Vector2i, TileSet::TerrainsPattern> terrain_fill_output = terrain_fill_path(p_layer, vector_path, p_terrain_set, p_terrain, p_ignore_empty_terrains);
+ for (const KeyValue<Vector2i, TileSet::TerrainsPattern> &E : terrain_fill_output) {
+ TileMapCell c = tile_set->get_random_tile_from_terrains_pattern(p_terrain_set, E.value);
+ set_cell(p_layer, E.key, c.source_id, c.get_atlas_coords(), c.alternative_tile);
}
}
@@ -2729,7 +2943,7 @@ void TileMap::_get_property_list(List<PropertyInfo> *p_list) const {
p_list->push_back(PropertyInfo(Variant::BOOL, vformat("layer_%d/enabled", i), PROPERTY_HINT_NONE));
p_list->push_back(PropertyInfo(Variant::COLOR, vformat("layer_%d/modulate", i), PROPERTY_HINT_NONE));
p_list->push_back(PropertyInfo(Variant::BOOL, vformat("layer_%d/y_sort_enabled", i), PROPERTY_HINT_NONE));
- p_list->push_back(PropertyInfo(Variant::INT, vformat("layer_%d/y_sort_origin", i), PROPERTY_HINT_NONE));
+ p_list->push_back(PropertyInfo(Variant::INT, vformat("layer_%d/y_sort_origin", i), PROPERTY_HINT_NONE, "suffix:px"));
p_list->push_back(PropertyInfo(Variant::INT, vformat("layer_%d/z_index", i), PROPERTY_HINT_NONE));
p_list->push_back(PropertyInfo(Variant::OBJECT, vformat("layer_%d/tile_data", i), PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR));
}
@@ -3640,7 +3854,8 @@ void TileMap::_bind_methods() {
ClassDB::bind_method(D_METHOD("map_pattern", "position_in_tilemap", "coords_in_pattern", "pattern"), &TileMap::map_pattern);
ClassDB::bind_method(D_METHOD("set_pattern", "layer", "position", "pattern"), &TileMap::set_pattern);
- ClassDB::bind_method(D_METHOD("set_cells_from_surrounding_terrains", "layer", "cells", "terrain_set", "ignore_empty_terrains"), &TileMap::set_cells_from_surrounding_terrains, DEFVAL(true));
+ ClassDB::bind_method(D_METHOD("set_cells_terrain_connect", "layer", "cells", "terrain_set", "terrain", "ignore_empty_terrains"), &TileMap::set_cells_terrain_connect, DEFVAL(true));
+ ClassDB::bind_method(D_METHOD("set_cells_terrain_path", "layer", "path", "terrain_set", "terrain", "ignore_empty_terrains"), &TileMap::set_cells_terrain_path, DEFVAL(true));
ClassDB::bind_method(D_METHOD("fix_invalid_tiles"), &TileMap::fix_invalid_tiles);
ClassDB::bind_method(D_METHOD("clear_layer", "layer"), &TileMap::clear_layer);
diff --git a/scene/2d/tile_map.h b/scene/2d/tile_map.h
index 02a2b3a1c6..0ac94b9d45 100644
--- a/scene/2d/tile_map.h
+++ b/scene/2d/tile_map.h
@@ -119,6 +119,8 @@ public:
int bit = -1;
int terrain = -1;
+ int priority = 1;
+
public:
bool operator<(const TerrainConstraint &p_other) const {
if (base_cell_coords == p_other.base_cell_coords) {
@@ -128,13 +130,17 @@ public:
}
String to_string() const {
- return vformat("Constraint {pos:%s, bit:%d, terrain:%d}", base_cell_coords, bit, terrain);
+ return vformat("Constraint {pos:%s, bit:%d, terrain:%d, priotity:%d}", base_cell_coords, bit, terrain, priority);
}
Vector2i get_base_cell_coords() const {
return base_cell_coords;
}
+ bool is_center_bit() const {
+ return bit == 0;
+ }
+
HashMap<Vector2i, TileSet::CellNeighbor> get_overlapping_coords_and_peering_bits() const;
void set_terrain(int p_terrain) {
@@ -145,8 +151,17 @@ public:
return terrain;
}
- TerrainConstraint(const TileMap *p_tile_map, const Vector2i &p_position, const TileSet::CellNeighbor &p_bit, int p_terrain);
- TerrainConstraint() {}
+ void set_priority(int p_priority) {
+ priority = p_priority;
+ }
+
+ int get_priority() {
+ return priority;
+ }
+
+ TerrainConstraint(const TileMap *p_tile_map, const Vector2i &p_position, int p_terrain); // For the center terrain bit
+ TerrainConstraint(const TileMap *p_tile_map, const Vector2i &p_position, const TileSet::CellNeighbor &p_bit, int p_terrain); // For peering bits
+ TerrainConstraint(){};
};
enum VisibilityMode {
@@ -251,7 +266,9 @@ private:
void _scenes_draw_quadrant_debug(TileMapQuadrant *p_quadrant);
// Terrains.
- RBSet<TileSet::TerrainsPattern> _get_valid_terrains_patterns_for_constraints(int p_terrain_set, const Vector2i &p_position, RBSet<TerrainConstraint> p_constraints);
+ TileSet::TerrainsPattern _get_best_terrain_pattern_for_constraints(int p_terrain_set, const Vector2i &p_position, RBSet<TerrainConstraint> p_constraints);
+ RBSet<TerrainConstraint> _get_terrain_constraints_from_added_pattern(Vector2i p_position, int p_terrain_set, TileSet::TerrainsPattern p_terrains_pattern) const;
+ RBSet<TerrainConstraint> _get_terrain_constraints_from_cells_list(int p_layer, const RBSet<Vector2i> &p_on_map, int p_terrain_set, bool p_ignore_empty_terrains) const;
// Set and get tiles from data arrays.
void _set_tile_data(int p_layer, const Vector<int> &p_data);
@@ -333,10 +350,13 @@ public:
void set_pattern(int p_layer, Vector2i p_position, const Ref<TileMapPattern> p_pattern);
// Terrains.
- RBSet<TerrainConstraint> get_terrain_constraints_from_removed_cells_list(int p_layer, const RBSet<Vector2i> &p_to_replace, int p_terrain_set, bool p_ignore_empty_terrains = true) const; // Not exposed.
- RBSet<TerrainConstraint> get_terrain_constraints_from_added_tile(Vector2i p_position, int p_terrain_set, TileSet::TerrainsPattern p_terrains_pattern) const; // Not exposed.
- HashMap<Vector2i, TileSet::TerrainsPattern> terrain_wave_function_collapse(const RBSet<Vector2i> &p_to_replace, int p_terrain_set, const RBSet<TerrainConstraint> p_constraints); // Not exposed.
- void set_cells_from_surrounding_terrains(int p_layer, TypedArray<Vector2i> p_coords_array, int p_terrain_set, bool p_ignore_empty_terrains = true);
+ HashMap<Vector2i, TileSet::TerrainsPattern> terrain_fill_constraints(const Vector<Vector2i> &p_to_replace, int p_terrain_set, const RBSet<TerrainConstraint> p_constraints); // Not exposed.
+ HashMap<Vector2i, TileSet::TerrainsPattern> terrain_fill_connect(int p_layer, const Vector<Vector2i> &p_coords_array, int p_terrain_set, int p_terrain, bool p_ignore_empty_terrains = true); // Not exposed.
+ HashMap<Vector2i, TileSet::TerrainsPattern> terrain_fill_path(int p_layer, const Vector<Vector2i> &p_coords_array, int p_terrain_set, int p_terrain, bool p_ignore_empty_terrains = true); // Not exposed.
+ HashMap<Vector2i, TileSet::TerrainsPattern> terrain_fill_pattern(int p_layer, const Vector<Vector2i> &p_coords_array, int p_terrain_set, TileSet::TerrainsPattern p_terrains_pattern, bool p_ignore_empty_terrains = true); // Not exposed.
+
+ void set_cells_terrain_connect(int p_layer, TypedArray<Vector2i> p_cells, int p_terrain_set, int p_terrain, bool p_ignore_empty_terrains = true);
+ void set_cells_terrain_path(int p_layer, TypedArray<Vector2i> p_path, int p_terrain_set, int p_terrain, bool p_ignore_empty_terrains = true);
// Not exposed to users
TileMapCell get_cell(int p_layer, const Vector2i &p_coords, bool p_use_proxies = false) const;
@@ -365,7 +385,7 @@ public:
// For finding tiles from collision.
Vector2i get_coords_for_body_rid(RID p_physics_body);
- // Fixing a nclearing methods.
+ // Fixing and clearing methods.
void fix_invalid_tiles();
// Clears tiles from a given layer
diff --git a/scene/3d/area_3d.cpp b/scene/3d/area_3d.cpp
index c8c8c6a4e5..fb0c59daa1 100644
--- a/scene/3d/area_3d.cpp
+++ b/scene/3d/area_3d.cpp
@@ -728,7 +728,7 @@ void Area3D::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::INT, "gravity_space_override", PROPERTY_HINT_ENUM, "Disabled,Combine,Combine-Replace,Replace,Replace-Combine", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_UPDATE_ALL_IF_MODIFIED), "set_gravity_space_override_mode", "get_gravity_space_override_mode");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "gravity_point", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_UPDATE_ALL_IF_MODIFIED), "set_gravity_is_point", "is_gravity_a_point");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "gravity_point_distance_scale", PROPERTY_HINT_RANGE, "0,1024,0.001,or_greater,exp"), "set_gravity_point_distance_scale", "get_gravity_point_distance_scale");
- ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "gravity_point_center"), "set_gravity_point_center", "get_gravity_point_center");
+ ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "gravity_point_center", PROPERTY_HINT_NONE, "suffix:m"), "set_gravity_point_center", "get_gravity_point_center");
ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "gravity_direction"), "set_gravity_direction", "get_gravity_direction");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "gravity", PROPERTY_HINT_RANGE, U"-32,32,0.001,or_lesser,or_greater,suffix:m/s\u00B2"), "set_gravity", "get_gravity");
diff --git a/scene/3d/fog_volume.cpp b/scene/3d/fog_volume.cpp
index 8fbadb4b7b..1b329143b6 100644
--- a/scene/3d/fog_volume.cpp
+++ b/scene/3d/fog_volume.cpp
@@ -40,7 +40,7 @@ void FogVolume::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_material", "material"), &FogVolume::set_material);
ClassDB::bind_method(D_METHOD("get_material"), &FogVolume::get_material);
- ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "extents", PROPERTY_HINT_RANGE, "0.01,1024,0.01,or_greater"), "set_extents", "get_extents");
+ ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "extents", PROPERTY_HINT_RANGE, "0.01,1024,0.01,or_greater,suffix:m"), "set_extents", "get_extents");
ADD_PROPERTY(PropertyInfo(Variant::INT, "shape", PROPERTY_HINT_ENUM, "Ellipsoid (Local),Cone (Local),Cylinder (Local),Box (Local),World (Global)"), "set_shape", "get_shape");
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "material", PROPERTY_HINT_RESOURCE_TYPE, "FogMaterial,ShaderMaterial"), "set_material", "get_material");
}
diff --git a/scene/3d/gpu_particles_3d.cpp b/scene/3d/gpu_particles_3d.cpp
index 8008512546..d18c452ca7 100644
--- a/scene/3d/gpu_particles_3d.cpp
+++ b/scene/3d/gpu_particles_3d.cpp
@@ -579,7 +579,7 @@ void GPUParticles3D::_bind_methods() {
ADD_GROUP("Collision", "collision_");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "collision_base_size", PROPERTY_HINT_RANGE, "0,128,0.01,or_greater,suffix:m"), "set_collision_base_size", "get_collision_base_size");
ADD_GROUP("Drawing", "");
- ADD_PROPERTY(PropertyInfo(Variant::AABB, "visibility_aabb"), "set_visibility_aabb", "get_visibility_aabb");
+ ADD_PROPERTY(PropertyInfo(Variant::AABB, "visibility_aabb", PROPERTY_HINT_NONE, "suffix:m"), "set_visibility_aabb", "get_visibility_aabb");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "local_coords"), "set_use_local_coordinates", "get_use_local_coordinates");
ADD_PROPERTY(PropertyInfo(Variant::INT, "draw_order", PROPERTY_HINT_ENUM, "Index,Lifetime,Reverse Lifetime,View Depth"), "set_draw_order", "get_draw_order");
ADD_PROPERTY(PropertyInfo(Variant::INT, "transform_align", PROPERTY_HINT_ENUM, "Disabled,Z-Billboard,Y to Velocity,Z-Billboard + Y to Velocity"), "set_transform_align", "get_transform_align");
diff --git a/scene/3d/gpu_particles_collision_3d.cpp b/scene/3d/gpu_particles_collision_3d.cpp
index c1c5a2a631..da0789ccd5 100644
--- a/scene/3d/gpu_particles_collision_3d.cpp
+++ b/scene/3d/gpu_particles_collision_3d.cpp
@@ -516,7 +516,7 @@ void GPUParticlesCollisionSDF3D::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "extents", PROPERTY_HINT_RANGE, "0.01,1024,0.01,or_greater,suffix:m"), "set_extents", "get_extents");
ADD_PROPERTY(PropertyInfo(Variant::INT, "resolution", PROPERTY_HINT_ENUM, "16,32,64,128,256,512,suffix:px"), "set_resolution", "get_resolution");
- ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "thickness", PROPERTY_HINT_RANGE, "0.0,2.0,0.01"), "set_thickness", "get_thickness");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "thickness", PROPERTY_HINT_RANGE, "0.0,2.0,0.01,suffix:m"), "set_thickness", "get_thickness");
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "texture", PROPERTY_HINT_RESOURCE_TYPE, "Texture3D"), "set_texture", "get_texture");
BIND_ENUM_CONSTANT(RESOLUTION_16);
diff --git a/scene/3d/joint_3d.cpp b/scene/3d/joint_3d.cpp
index b6fc83e599..0b824ef28b 100644
--- a/scene/3d/joint_3d.cpp
+++ b/scene/3d/joint_3d.cpp
@@ -331,7 +331,7 @@ void HingeJoint3D::_bind_methods() {
ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "angular_limit/relaxation", PROPERTY_HINT_RANGE, "0.01,16,0.01"), "set_param", "get_param", PARAM_LIMIT_RELAXATION);
ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "motor/enable"), "set_flag", "get_flag", FLAG_ENABLE_MOTOR);
- ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "motor/target_velocity", PROPERTY_HINT_RANGE, "-200,200,0.01,or_greater,or_lesser"), "set_param", "get_param", PARAM_MOTOR_TARGET_VELOCITY);
+ ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "motor/target_velocity", PROPERTY_HINT_RANGE, "-200,200,0.01,or_greater,or_lesser,suffix:m/s"), "set_param", "get_param", PARAM_MOTOR_TARGET_VELOCITY);
ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "motor/max_impulse", PROPERTY_HINT_RANGE, "0.01,1024,0.01"), "set_param", "get_param", PARAM_MOTOR_MAX_IMPULSE);
BIND_ENUM_CONSTANT(PARAM_BIAS);
@@ -448,8 +448,8 @@ void SliderJoint3D::_bind_methods() {
ClassDB::bind_method(D_METHOD("_set_lower_limit_angular", "lower_limit_angular"), &SliderJoint3D::_set_lower_limit_angular);
ClassDB::bind_method(D_METHOD("_get_lower_limit_angular"), &SliderJoint3D::_get_lower_limit_angular);
- ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "linear_limit/upper_distance", PROPERTY_HINT_RANGE, "-1024,1024,0.01"), "set_param", "get_param", PARAM_LINEAR_LIMIT_UPPER);
- ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "linear_limit/lower_distance", PROPERTY_HINT_RANGE, "-1024,1024,0.01"), "set_param", "get_param", PARAM_LINEAR_LIMIT_LOWER);
+ ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "linear_limit/upper_distance", PROPERTY_HINT_RANGE, "-1024,1024,0.01,suffix:m"), "set_param", "get_param", PARAM_LINEAR_LIMIT_UPPER);
+ ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "linear_limit/lower_distance", PROPERTY_HINT_RANGE, "-1024,1024,0.01,suffix:m"), "set_param", "get_param", PARAM_LINEAR_LIMIT_LOWER);
ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "linear_limit/softness", PROPERTY_HINT_RANGE, "0.01,16.0,0.01"), "set_param", "get_param", PARAM_LINEAR_LIMIT_SOFTNESS);
ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "linear_limit/restitution", PROPERTY_HINT_RANGE, "0.01,16.0,0.01"), "set_param", "get_param", PARAM_LINEAR_LIMIT_RESTITUTION);
ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "linear_limit/damping", PROPERTY_HINT_RANGE, "0,16.0,0.01"), "set_param", "get_param", PARAM_LINEAR_LIMIT_DAMPING);
@@ -737,15 +737,18 @@ void Generic6DOFJoint3D::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_flag_z", "flag", "value"), &Generic6DOFJoint3D::set_flag_z);
ClassDB::bind_method(D_METHOD("get_flag_z", "flag"), &Generic6DOFJoint3D::get_flag_z);
+ // X
ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "linear_limit_x/enabled"), "set_flag_x", "get_flag_x", FLAG_ENABLE_LINEAR_LIMIT);
- ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "linear_limit_x/upper_distance"), "set_param_x", "get_param_x", PARAM_LINEAR_UPPER_LIMIT);
- ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "linear_limit_x/lower_distance"), "set_param_x", "get_param_x", PARAM_LINEAR_LOWER_LIMIT);
+ ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "linear_limit_x/upper_distance", PROPERTY_HINT_NONE, "suffix:m"), "set_param_x", "get_param_x", PARAM_LINEAR_UPPER_LIMIT);
+ ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "linear_limit_x/lower_distance", PROPERTY_HINT_NONE, "suffix:m"), "set_param_x", "get_param_x", PARAM_LINEAR_LOWER_LIMIT);
ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "linear_limit_x/softness", PROPERTY_HINT_RANGE, "0.01,16,0.01"), "set_param_x", "get_param_x", PARAM_LINEAR_LIMIT_SOFTNESS);
ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "linear_limit_x/restitution", PROPERTY_HINT_RANGE, "0.01,16,0.01"), "set_param_x", "get_param_x", PARAM_LINEAR_RESTITUTION);
ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "linear_limit_x/damping", PROPERTY_HINT_RANGE, "0.01,16,0.01"), "set_param_x", "get_param_x", PARAM_LINEAR_DAMPING);
+
ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "linear_motor_x/enabled"), "set_flag_x", "get_flag_x", FLAG_ENABLE_LINEAR_MOTOR);
- ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "linear_motor_x/target_velocity"), "set_param_x", "get_param_x", PARAM_LINEAR_MOTOR_TARGET_VELOCITY);
+ ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "linear_motor_x/target_velocity", PROPERTY_HINT_NONE, "suffix:m/s"), "set_param_x", "get_param_x", PARAM_LINEAR_MOTOR_TARGET_VELOCITY);
ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "linear_motor_x/force_limit"), "set_param_x", "get_param_x", PARAM_LINEAR_MOTOR_FORCE_LIMIT);
+
ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "linear_spring_x/enabled"), "set_flag_x", "get_flag_x", FLAG_ENABLE_LINEAR_SPRING);
ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "linear_spring_x/stiffness"), "set_param_x", "get_param_x", PARAM_LINEAR_SPRING_STIFFNESS);
ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "linear_spring_x/damping"), "set_param_x", "get_param_x", PARAM_LINEAR_SPRING_DAMPING);
@@ -759,56 +762,69 @@ void Generic6DOFJoint3D::_bind_methods() {
ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "angular_limit_x/damping", PROPERTY_HINT_RANGE, "0.01,16,0.01"), "set_param_x", "get_param_x", PARAM_ANGULAR_DAMPING);
ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "angular_limit_x/force_limit"), "set_param_x", "get_param_x", PARAM_ANGULAR_FORCE_LIMIT);
ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "angular_limit_x/erp"), "set_param_x", "get_param_x", PARAM_ANGULAR_ERP);
+
ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "angular_motor_x/enabled"), "set_flag_x", "get_flag_x", FLAG_ENABLE_MOTOR);
ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "angular_motor_x/target_velocity"), "set_param_x", "get_param_x", PARAM_ANGULAR_MOTOR_TARGET_VELOCITY);
ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "angular_motor_x/force_limit"), "set_param_x", "get_param_x", PARAM_ANGULAR_MOTOR_FORCE_LIMIT);
+
ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "angular_spring_x/enabled"), "set_flag_x", "get_flag_x", FLAG_ENABLE_ANGULAR_SPRING);
ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "angular_spring_x/stiffness"), "set_param_x", "get_param_x", PARAM_ANGULAR_SPRING_STIFFNESS);
ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "angular_spring_x/damping"), "set_param_x", "get_param_x", PARAM_ANGULAR_SPRING_DAMPING);
ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "angular_spring_x/equilibrium_point"), "set_param_x", "get_param_x", PARAM_ANGULAR_SPRING_EQUILIBRIUM_POINT);
+ // Y
ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "linear_limit_y/enabled"), "set_flag_y", "get_flag_y", FLAG_ENABLE_LINEAR_LIMIT);
- ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "linear_limit_y/upper_distance"), "set_param_y", "get_param_y", PARAM_LINEAR_UPPER_LIMIT);
- ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "linear_limit_y/lower_distance"), "set_param_y", "get_param_y", PARAM_LINEAR_LOWER_LIMIT);
+ ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "linear_limit_y/upper_distance", PROPERTY_HINT_NONE, "suffix:m"), "set_param_y", "get_param_y", PARAM_LINEAR_UPPER_LIMIT);
+ ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "linear_limit_y/lower_distance", PROPERTY_HINT_NONE, "suffix:m"), "set_param_y", "get_param_y", PARAM_LINEAR_LOWER_LIMIT);
ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "linear_limit_y/softness", PROPERTY_HINT_RANGE, "0.01,16,0.01"), "set_param_y", "get_param_y", PARAM_LINEAR_LIMIT_SOFTNESS);
ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "linear_limit_y/restitution", PROPERTY_HINT_RANGE, "0.01,16,0.01"), "set_param_y", "get_param_y", PARAM_LINEAR_RESTITUTION);
ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "linear_limit_y/damping", PROPERTY_HINT_RANGE, "0.01,16,0.01"), "set_param_y", "get_param_y", PARAM_LINEAR_DAMPING);
+
ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "linear_motor_y/enabled"), "set_flag_y", "get_flag_y", FLAG_ENABLE_LINEAR_MOTOR);
- ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "linear_motor_y/target_velocity"), "set_param_y", "get_param_y", PARAM_LINEAR_MOTOR_TARGET_VELOCITY);
+ ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "linear_motor_y/target_velocity", PROPERTY_HINT_NONE, "suffix:m/s"), "set_param_y", "get_param_y", PARAM_LINEAR_MOTOR_TARGET_VELOCITY);
ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "linear_motor_y/force_limit"), "set_param_y", "get_param_y", PARAM_LINEAR_MOTOR_FORCE_LIMIT);
+
ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "linear_spring_y/enabled"), "set_flag_y", "get_flag_y", FLAG_ENABLE_LINEAR_SPRING);
ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "linear_spring_y/stiffness"), "set_param_y", "get_param_y", PARAM_LINEAR_SPRING_STIFFNESS);
ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "linear_spring_y/damping"), "set_param_y", "get_param_y", PARAM_LINEAR_SPRING_DAMPING);
ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "linear_spring_y/equilibrium_point"), "set_param_y", "get_param_y", PARAM_LINEAR_SPRING_EQUILIBRIUM_POINT);
+
ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "angular_limit_y/enabled"), "set_flag_y", "get_flag_y", FLAG_ENABLE_ANGULAR_LIMIT);
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "angular_limit_y/upper_angle", PROPERTY_HINT_RANGE, "-180,180,0.01"), "_set_angular_hi_limit_y", "_get_angular_hi_limit_y");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "angular_limit_y/lower_angle", PROPERTY_HINT_RANGE, "-180,180,0.01"), "_set_angular_lo_limit_y", "_get_angular_lo_limit_y");
+
ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "angular_limit_y/softness", PROPERTY_HINT_RANGE, "0.01,16,0.01"), "set_param_y", "get_param_y", PARAM_ANGULAR_LIMIT_SOFTNESS);
ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "angular_limit_y/restitution", PROPERTY_HINT_RANGE, "0.01,16,0.01"), "set_param_y", "get_param_y", PARAM_ANGULAR_RESTITUTION);
ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "angular_limit_y/damping", PROPERTY_HINT_RANGE, "0.01,16,0.01"), "set_param_y", "get_param_y", PARAM_ANGULAR_DAMPING);
ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "angular_limit_y/force_limit"), "set_param_y", "get_param_y", PARAM_ANGULAR_FORCE_LIMIT);
ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "angular_limit_y/erp"), "set_param_y", "get_param_y", PARAM_ANGULAR_ERP);
+
ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "angular_motor_y/enabled"), "set_flag_y", "get_flag_y", FLAG_ENABLE_MOTOR);
ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "angular_motor_y/target_velocity"), "set_param_y", "get_param_y", PARAM_ANGULAR_MOTOR_TARGET_VELOCITY);
ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "angular_motor_y/force_limit"), "set_param_y", "get_param_y", PARAM_ANGULAR_MOTOR_FORCE_LIMIT);
+
ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "angular_spring_y/enabled"), "set_flag_y", "get_flag_y", FLAG_ENABLE_ANGULAR_SPRING);
ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "angular_spring_y/stiffness"), "set_param_y", "get_param_y", PARAM_ANGULAR_SPRING_STIFFNESS);
ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "angular_spring_y/damping"), "set_param_y", "get_param_y", PARAM_ANGULAR_SPRING_DAMPING);
ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "angular_spring_y/equilibrium_point"), "set_param_y", "get_param_y", PARAM_ANGULAR_SPRING_EQUILIBRIUM_POINT);
+ // Z
ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "linear_limit_z/enabled"), "set_flag_z", "get_flag_z", FLAG_ENABLE_LINEAR_LIMIT);
- ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "linear_limit_z/upper_distance"), "set_param_z", "get_param_z", PARAM_LINEAR_UPPER_LIMIT);
- ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "linear_limit_z/lower_distance"), "set_param_z", "get_param_z", PARAM_LINEAR_LOWER_LIMIT);
+ ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "linear_limit_z/upper_distance", PROPERTY_HINT_NONE, "suffix:m"), "set_param_z", "get_param_z", PARAM_LINEAR_UPPER_LIMIT);
+ ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "linear_limit_z/lower_distance", PROPERTY_HINT_NONE, "suffix:m"), "set_param_z", "get_param_z", PARAM_LINEAR_LOWER_LIMIT);
ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "linear_limit_z/softness", PROPERTY_HINT_RANGE, "0.01,16,0.01"), "set_param_z", "get_param_z", PARAM_LINEAR_LIMIT_SOFTNESS);
ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "linear_limit_z/restitution", PROPERTY_HINT_RANGE, "0.01,16,0.01"), "set_param_z", "get_param_z", PARAM_LINEAR_RESTITUTION);
ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "linear_limit_z/damping", PROPERTY_HINT_RANGE, "0.01,16,0.01"), "set_param_z", "get_param_z", PARAM_LINEAR_DAMPING);
+
ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "linear_motor_z/enabled"), "set_flag_z", "get_flag_z", FLAG_ENABLE_LINEAR_MOTOR);
- ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "linear_motor_z/target_velocity"), "set_param_z", "get_param_z", PARAM_LINEAR_MOTOR_TARGET_VELOCITY);
+ ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "linear_motor_z/target_velocity", PROPERTY_HINT_NONE, "suffix:m/s"), "set_param_z", "get_param_z", PARAM_LINEAR_MOTOR_TARGET_VELOCITY);
ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "linear_motor_z/force_limit"), "set_param_z", "get_param_z", PARAM_LINEAR_MOTOR_FORCE_LIMIT);
+
ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "linear_spring_z/enabled"), "set_flag_z", "get_flag_z", FLAG_ENABLE_LINEAR_SPRING);
ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "linear_spring_z/stiffness"), "set_param_z", "get_param_z", PARAM_LINEAR_SPRING_STIFFNESS);
ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "linear_spring_z/damping"), "set_param_z", "get_param_z", PARAM_LINEAR_SPRING_DAMPING);
ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "linear_spring_z/equilibrium_point"), "set_param_z", "get_param_z", PARAM_LINEAR_SPRING_EQUILIBRIUM_POINT);
+
ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "angular_limit_z/enabled"), "set_flag_z", "get_flag_z", FLAG_ENABLE_ANGULAR_LIMIT);
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "angular_limit_z/upper_angle", PROPERTY_HINT_RANGE, "-180,180,0.01"), "_set_angular_hi_limit_z", "_get_angular_hi_limit_z");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "angular_limit_z/lower_angle", PROPERTY_HINT_RANGE, "-180,180,0.01"), "_set_angular_lo_limit_z", "_get_angular_lo_limit_z");
@@ -817,9 +833,11 @@ void Generic6DOFJoint3D::_bind_methods() {
ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "angular_limit_z/damping", PROPERTY_HINT_RANGE, "0.01,16,0.01"), "set_param_z", "get_param_z", PARAM_ANGULAR_DAMPING);
ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "angular_limit_z/force_limit"), "set_param_z", "get_param_z", PARAM_ANGULAR_FORCE_LIMIT);
ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "angular_limit_z/erp"), "set_param_z", "get_param_z", PARAM_ANGULAR_ERP);
+
ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "angular_motor_z/enabled"), "set_flag_z", "get_flag_z", FLAG_ENABLE_MOTOR);
ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "angular_motor_z/target_velocity"), "set_param_z", "get_param_z", PARAM_ANGULAR_MOTOR_TARGET_VELOCITY);
ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "angular_motor_z/force_limit"), "set_param_z", "get_param_z", PARAM_ANGULAR_MOTOR_FORCE_LIMIT);
+
ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "angular_spring_z/enabled"), "set_flag_z", "get_flag_z", FLAG_ENABLE_ANGULAR_SPRING);
ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "angular_spring_z/stiffness"), "set_param_z", "get_param_z", PARAM_ANGULAR_SPRING_STIFFNESS);
ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "angular_spring_z/damping"), "set_param_z", "get_param_z", PARAM_ANGULAR_SPRING_DAMPING);
diff --git a/scene/3d/label_3d.cpp b/scene/3d/label_3d.cpp
index 78da22a0c3..d95cf15bfa 100644
--- a/scene/3d/label_3d.cpp
+++ b/scene/3d/label_3d.cpp
@@ -120,8 +120,8 @@ void Label3D::_bind_methods() {
ClassDB::bind_method(D_METHOD("_font_changed"), &Label3D::_font_changed);
ClassDB::bind_method(D_METHOD("_im_update"), &Label3D::_im_update);
- ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "pixel_size", PROPERTY_HINT_RANGE, "0.0001,128,0.0001"), "set_pixel_size", "get_pixel_size");
- ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "offset"), "set_offset", "get_offset");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "pixel_size", PROPERTY_HINT_RANGE, "0.0001,128,0.0001,suffix:m"), "set_pixel_size", "get_pixel_size");
+ ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "offset", PROPERTY_HINT_NONE, "suffix:px"), "set_offset", "get_offset");
ADD_GROUP("Flags", "");
ADD_PROPERTY(PropertyInfo(Variant::INT, "billboard", PROPERTY_HINT_ENUM, "Disabled,Enabled,Y-Billboard"), "set_billboard_mode", "get_billboard_mode");
@@ -140,14 +140,14 @@ void Label3D::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::COLOR, "outline_modulate"), "set_outline_modulate", "get_outline_modulate");
ADD_PROPERTY(PropertyInfo(Variant::STRING, "text", PROPERTY_HINT_MULTILINE_TEXT, ""), "set_text", "get_text");
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "font", PROPERTY_HINT_RESOURCE_TYPE, "Font"), "set_font", "get_font");
- ADD_PROPERTY(PropertyInfo(Variant::INT, "font_size", PROPERTY_HINT_RANGE, "1,127,1"), "set_font_size", "get_font_size");
- ADD_PROPERTY(PropertyInfo(Variant::INT, "outline_size", PROPERTY_HINT_RANGE, "0,127,1"), "set_outline_size", "get_outline_size");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "font_size", PROPERTY_HINT_RANGE, "1,127,1,suffix:px"), "set_font_size", "get_font_size");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "outline_size", PROPERTY_HINT_RANGE, "0,127,1,suffix:px"), "set_outline_size", "get_outline_size");
ADD_PROPERTY(PropertyInfo(Variant::INT, "horizontal_alignment", PROPERTY_HINT_ENUM, "Left,Center,Right,Fill"), "set_horizontal_alignment", "get_horizontal_alignment");
ADD_PROPERTY(PropertyInfo(Variant::INT, "vertical_alignment", PROPERTY_HINT_ENUM, "Top,Center,Bottom"), "set_vertical_alignment", "get_vertical_alignment");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "uppercase"), "set_uppercase", "is_uppercase");
- ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "line_spacing"), "set_line_spacing", "get_line_spacing");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "line_spacing", PROPERTY_HINT_NONE, "suffix:px"), "set_line_spacing", "get_line_spacing");
ADD_PROPERTY(PropertyInfo(Variant::INT, "autowrap_mode", PROPERTY_HINT_ENUM, "Off,Arbitrary,Word,Word (Smart)"), "set_autowrap_mode", "get_autowrap_mode");
- ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "width"), "set_width", "get_width");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "width", PROPERTY_HINT_NONE, "suffix:px"), "set_width", "get_width");
ADD_PROPERTY(PropertyInfo(Variant::INT, "structured_text_bidi_override", PROPERTY_HINT_ENUM, "Default,URI,File,Email,List,None,Custom"), "set_structured_text_bidi_override", "get_structured_text_bidi_override");
ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "structured_text_bidi_override_options"), "set_structured_text_bidi_override_options", "get_structured_text_bidi_override_options");
diff --git a/scene/3d/light_3d.cpp b/scene/3d/light_3d.cpp
index 2568defe0f..d80c10d63a 100644
--- a/scene/3d/light_3d.cpp
+++ b/scene/3d/light_3d.cpp
@@ -277,13 +277,13 @@ void Light3D::_bind_methods() {
ADD_GROUP("Light", "light_");
ADD_PROPERTY(PropertyInfo(Variant::COLOR, "light_color", PROPERTY_HINT_COLOR_NO_ALPHA), "set_color", "get_color");
- ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "light_energy", PROPERTY_HINT_RANGE, "0,16,0.01,or_greater"), "set_param", "get_param", PARAM_ENERGY);
- ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "light_indirect_energy", PROPERTY_HINT_RANGE, "0,16,0.01,or_greater"), "set_param", "get_param", PARAM_INDIRECT_ENERGY);
+ ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "light_energy", PROPERTY_HINT_RANGE, "0,16,0.001,or_greater"), "set_param", "get_param", PARAM_ENERGY);
+ ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "light_indirect_energy", PROPERTY_HINT_RANGE, "0,16,0.001,or_greater"), "set_param", "get_param", PARAM_INDIRECT_ENERGY);
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "light_projector", PROPERTY_HINT_RESOURCE_TYPE, "Texture2D"), "set_projector", "get_projector");
- ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "light_size", PROPERTY_HINT_RANGE, "0,1,0.01,or_greater"), "set_param", "get_param", PARAM_SIZE);
+ ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "light_size", PROPERTY_HINT_RANGE, "0,1,0.001,or_greater,suffix:m"), "set_param", "get_param", PARAM_SIZE);
ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "light_angular_distance", PROPERTY_HINT_RANGE, "0,90,0.01,radians"), "set_param", "get_param", PARAM_SIZE);
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "light_negative"), "set_negative", "is_negative");
- ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "light_specular", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_param", "get_param", PARAM_SPECULAR);
+ ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "light_specular", PROPERTY_HINT_RANGE, "0,16,0.001,or_greater"), "set_param", "get_param", PARAM_SPECULAR);
ADD_PROPERTY(PropertyInfo(Variant::INT, "light_bake_mode", PROPERTY_HINT_ENUM, "Disabled,Static (VoxelGI/SDFGI/LightmapGI),Dynamic (VoxelGI/SDFGI only)"), "set_bake_mode", "get_bake_mode");
ADD_PROPERTY(PropertyInfo(Variant::INT, "light_cull_mask", PROPERTY_HINT_LAYERS_3D_RENDER), "set_cull_mask", "get_cull_mask");
ADD_GROUP("Shadow", "shadow_");
@@ -291,14 +291,13 @@ void Light3D::_bind_methods() {
ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "shadow_bias", PROPERTY_HINT_RANGE, "0,10,0.001"), "set_param", "get_param", PARAM_SHADOW_BIAS);
ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "shadow_normal_bias", PROPERTY_HINT_RANGE, "0,10,0.001"), "set_param", "get_param", PARAM_SHADOW_NORMAL_BIAS);
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "shadow_reverse_cull_face"), "set_shadow_reverse_cull_face", "get_shadow_reverse_cull_face");
- ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "shadow_transmittance_bias", PROPERTY_HINT_RANGE, "-16,16,0.01"), "set_param", "get_param", PARAM_TRANSMITTANCE_BIAS);
- ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "shadow_fog_fade", PROPERTY_HINT_RANGE, "0.01,10,0.01"), "set_param", "get_param", PARAM_SHADOW_VOLUMETRIC_FOG_FADE);
- ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "shadow_blur", PROPERTY_HINT_RANGE, "0.1,8,0.01"), "set_param", "get_param", PARAM_SHADOW_BLUR);
- ADD_GROUP("Distance Fade", "distance_fade_");
+ ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "shadow_transmittance_bias", PROPERTY_HINT_RANGE, "-16,16,0.001"), "set_param", "get_param", PARAM_TRANSMITTANCE_BIAS);
+ ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "shadow_fog_fade", PROPERTY_HINT_RANGE, "0.001,10,0.001"), "set_param", "get_param", PARAM_SHADOW_VOLUMETRIC_FOG_FADE);
+ ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "shadow_blur", PROPERTY_HINT_RANGE, "0,10,0.001"), "set_param", "get_param", PARAM_SHADOW_BLUR);
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "distance_fade_enabled"), "set_enable_distance_fade", "is_distance_fade_enabled");
- ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "distance_fade_begin", PROPERTY_HINT_RANGE, "0.0,4096.0,0.01,or_greater"), "set_distance_fade_begin", "get_distance_fade_begin");
- ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "distance_fade_shadow", PROPERTY_HINT_RANGE, "0.0,4096.0,0.01,or_greater"), "set_distance_fade_shadow", "get_distance_fade_shadow");
- ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "distance_fade_length", PROPERTY_HINT_RANGE, "0.0,4096.0,0.01,or_greater"), "set_distance_fade_length", "get_distance_fade_length");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "distance_fade_begin", PROPERTY_HINT_RANGE, "0.0,4096.0,0.01,or_greater,suffix:m"), "set_distance_fade_begin", "get_distance_fade_begin");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "distance_fade_shadow", PROPERTY_HINT_RANGE, "0.0,4096.0,0.01,or_greater,suffix:m"), "set_distance_fade_shadow", "get_distance_fade_shadow");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "distance_fade_length", PROPERTY_HINT_RANGE, "0.0,4096.0,0.01,or_greater,suffix:m"), "set_distance_fade_length", "get_distance_fade_length");
ADD_GROUP("Editor", "");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "editor_only"), "set_editor_only", "is_editor_only");
ADD_GROUP("", "");
@@ -458,7 +457,7 @@ void DirectionalLight3D::_bind_methods() {
ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "directional_shadow_split_2", PROPERTY_HINT_RANGE, "0,1,0.001"), "set_param", "get_param", PARAM_SHADOW_SPLIT_2_OFFSET);
ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "directional_shadow_split_3", PROPERTY_HINT_RANGE, "0,1,0.001"), "set_param", "get_param", PARAM_SHADOW_SPLIT_3_OFFSET);
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "directional_shadow_blend_splits"), "set_blend_splits", "is_blend_splits_enabled");
- ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "directional_shadow_fade_start", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_param", "get_param", PARAM_SHADOW_FADE_START);
+ ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "directional_shadow_fade_start", PROPERTY_HINT_RANGE, "0,1,0.001"), "set_param", "get_param", PARAM_SHADOW_FADE_START);
ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "directional_shadow_max_distance", PROPERTY_HINT_RANGE, "0,8192,0.1,or_greater,exp"), "set_param", "get_param", PARAM_SHADOW_MAX_DISTANCE);
ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "directional_shadow_pancake_size", PROPERTY_HINT_RANGE, "0,1024,0.1,or_greater,exp"), "set_param", "get_param", PARAM_SHADOW_PANCAKE_SIZE);
@@ -508,7 +507,7 @@ void OmniLight3D::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_shadow_mode"), &OmniLight3D::get_shadow_mode);
ADD_GROUP("Omni", "omni_");
- ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "omni_range", PROPERTY_HINT_RANGE, "0,4096,0.1,or_greater,exp"), "set_param", "get_param", PARAM_RANGE);
+ ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "omni_range", PROPERTY_HINT_RANGE, "0,4096,0.001,or_greater,exp"), "set_param", "get_param", PARAM_RANGE);
ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "omni_attenuation", PROPERTY_HINT_EXP_EASING, "attenuation"), "set_param", "get_param", PARAM_ATTENUATION);
ADD_PROPERTY(PropertyInfo(Variant::INT, "omni_shadow_mode", PROPERTY_HINT_ENUM, "Dual Paraboloid,Cube"), "set_shadow_mode", "get_shadow_mode");
@@ -539,8 +538,8 @@ TypedArray<String> SpotLight3D::get_configuration_warnings() const {
void SpotLight3D::_bind_methods() {
ADD_GROUP("Spot", "spot_");
- ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "spot_range", PROPERTY_HINT_RANGE, "0,4096,0.1,or_greater,exp,suffix:m"), "set_param", "get_param", PARAM_RANGE);
+ ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "spot_range", PROPERTY_HINT_RANGE, "0,4096,0.001,or_greater,exp,suffix:m"), "set_param", "get_param", PARAM_RANGE);
ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "spot_attenuation", PROPERTY_HINT_EXP_EASING, "attenuation"), "set_param", "get_param", PARAM_ATTENUATION);
- ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "spot_angle", PROPERTY_HINT_RANGE, "0,180,0.1,degrees"), "set_param", "get_param", PARAM_SPOT_ANGLE);
+ ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "spot_angle", PROPERTY_HINT_RANGE, "0,180,0.01,degrees"), "set_param", "get_param", PARAM_SPOT_ANGLE);
ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "spot_angle_attenuation", PROPERTY_HINT_EXP_EASING, "attenuation"), "set_param", "get_param", PARAM_SPOT_ATTENUATION);
}
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/navigation_agent_3d.cpp b/scene/3d/navigation_agent_3d.cpp
index 947d6012d5..09d75dd284 100644
--- a/scene/3d/navigation_agent_3d.cpp
+++ b/scene/3d/navigation_agent_3d.cpp
@@ -65,8 +65,11 @@ void NavigationAgent3D::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_path_max_distance", "max_speed"), &NavigationAgent3D::set_path_max_distance);
ClassDB::bind_method(D_METHOD("get_path_max_distance"), &NavigationAgent3D::get_path_max_distance);
- ClassDB::bind_method(D_METHOD("set_navigable_layers", "navigable_layers"), &NavigationAgent3D::set_navigable_layers);
- ClassDB::bind_method(D_METHOD("get_navigable_layers"), &NavigationAgent3D::get_navigable_layers);
+ ClassDB::bind_method(D_METHOD("set_navigation_layers", "navigation_layers"), &NavigationAgent3D::set_navigation_layers);
+ ClassDB::bind_method(D_METHOD("get_navigation_layers"), &NavigationAgent3D::get_navigation_layers);
+
+ ClassDB::bind_method(D_METHOD("set_navigation_map", "navigation_map"), &NavigationAgent3D::set_navigation_map);
+ ClassDB::bind_method(D_METHOD("get_navigation_map"), &NavigationAgent3D::get_navigation_map);
ClassDB::bind_method(D_METHOD("set_target_location", "location"), &NavigationAgent3D::set_target_location);
ClassDB::bind_method(D_METHOD("get_target_location"), &NavigationAgent3D::get_target_location);
@@ -92,7 +95,7 @@ void NavigationAgent3D::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "path_max_distance", PROPERTY_HINT_RANGE, "0.01,100,0.1,suffix:m"), "set_path_max_distance", "get_path_max_distance");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "ignore_y"), "set_ignore_y", "get_ignore_y");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "avoidance_enabled"), "set_avoidance_enabled", "get_avoidance_enabled");
- ADD_PROPERTY(PropertyInfo(Variant::INT, "navigable_layers", PROPERTY_HINT_LAYERS_3D_NAVIGATION), "set_navigable_layers", "get_navigable_layers");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "navigation_layers", PROPERTY_HINT_LAYERS_3D_NAVIGATION), "set_navigation_layers", "get_navigation_layers");
ADD_SIGNAL(MethodInfo("path_changed"));
ADD_SIGNAL(MethodInfo("target_reached"));
@@ -198,7 +201,11 @@ void NavigationAgent3D::set_agent_parent(Node *p_agent_parent) {
if (Object::cast_to<Node3D>(p_agent_parent) != nullptr) {
// place agent on navigation map first or else the RVO agent callback creation fails silently later
agent_parent = Object::cast_to<Node3D>(p_agent_parent);
- NavigationServer3D::get_singleton()->agent_set_map(get_rid(), agent_parent->get_world_3d()->get_navigation_map());
+ if (map_override.is_valid()) {
+ NavigationServer3D::get_singleton()->agent_set_map(get_rid(), map_override);
+ } else {
+ NavigationServer3D::get_singleton()->agent_set_map(get_rid(), agent_parent->get_world_3d()->get_navigation_map());
+ }
// create new avoidance callback if enabled
set_avoidance_enabled(avoidance_enabled);
} else {
@@ -207,16 +214,31 @@ void NavigationAgent3D::set_agent_parent(Node *p_agent_parent) {
}
}
-void NavigationAgent3D::set_navigable_layers(uint32_t p_layers) {
- bool layers_changed = navigable_layers != p_layers;
- navigable_layers = p_layers;
- if (layers_changed) {
+void NavigationAgent3D::set_navigation_layers(uint32_t p_navigation_layers) {
+ bool navigation_layers_changed = navigation_layers != p_navigation_layers;
+ navigation_layers = p_navigation_layers;
+ if (navigation_layers_changed) {
_request_repath();
}
}
-uint32_t NavigationAgent3D::get_navigable_layers() const {
- return navigable_layers;
+uint32_t NavigationAgent3D::get_navigation_layers() const {
+ return navigation_layers;
+}
+
+void NavigationAgent3D::set_navigation_map(RID p_navigation_map) {
+ map_override = p_navigation_map;
+ NavigationServer3D::get_singleton()->agent_set_map(agent, map_override);
+ _request_repath();
+}
+
+RID NavigationAgent3D::get_navigation_map() const {
+ if (map_override.is_valid()) {
+ return map_override;
+ } else if (agent_parent != nullptr) {
+ return agent_parent->get_world_3d()->get_navigation_map();
+ }
+ return RID();
}
void NavigationAgent3D::set_target_desired_distance(real_t p_dd) {
@@ -377,7 +399,11 @@ void NavigationAgent3D::update_navigation() {
}
if (reload_path) {
- navigation_path = NavigationServer3D::get_singleton()->map_get_path(agent_parent->get_world_3d()->get_navigation_map(), o, target_location, true, navigable_layers);
+ if (map_override.is_valid()) {
+ navigation_path = NavigationServer3D::get_singleton()->map_get_path(map_override, o, target_location, true, navigation_layers);
+ } else {
+ navigation_path = NavigationServer3D::get_singleton()->map_get_path(agent_parent->get_world_3d()->get_navigation_map(), o, target_location, true, navigation_layers);
+ }
navigation_finished = false;
nav_path_index = 0;
emit_signal(SNAME("path_changed"));
diff --git a/scene/3d/navigation_agent_3d.h b/scene/3d/navigation_agent_3d.h
index 633bf091d1..d0eaead3f1 100644
--- a/scene/3d/navigation_agent_3d.h
+++ b/scene/3d/navigation_agent_3d.h
@@ -42,9 +42,10 @@ class NavigationAgent3D : public Node {
RID agent;
RID map_before_pause;
+ RID map_override;
bool avoidance_enabled = false;
- uint32_t navigable_layers = 1;
+ uint32_t navigation_layers = 1;
real_t target_desired_distance = 1.0;
real_t radius = 0.0;
@@ -86,8 +87,11 @@ public:
void set_agent_parent(Node *p_agent_parent);
- void set_navigable_layers(uint32_t p_layers);
- uint32_t get_navigable_layers() const;
+ void set_navigation_layers(uint32_t p_navigation_layers);
+ uint32_t get_navigation_layers() const;
+
+ void set_navigation_map(RID p_navigation_map);
+ RID get_navigation_map() const;
void set_target_desired_distance(real_t p_dd);
real_t get_target_desired_distance() const {
diff --git a/scene/3d/navigation_region_3d.cpp b/scene/3d/navigation_region_3d.cpp
index dda1382814..7ef16fbc0a 100644
--- a/scene/3d/navigation_region_3d.cpp
+++ b/scene/3d/navigation_region_3d.cpp
@@ -65,12 +65,12 @@ bool NavigationRegion3D::is_enabled() const {
return enabled;
}
-void NavigationRegion3D::set_layers(uint32_t p_layers) {
- NavigationServer3D::get_singleton()->region_set_layers(region, p_layers);
+void NavigationRegion3D::set_navigation_layers(uint32_t p_navigation_layers) {
+ NavigationServer3D::get_singleton()->region_set_navigation_layers(region, p_navigation_layers);
}
-uint32_t NavigationRegion3D::get_layers() const {
- return NavigationServer3D::get_singleton()->region_get_layers(region);
+uint32_t NavigationRegion3D::get_navigation_layers() const {
+ return NavigationServer3D::get_singleton()->region_get_navigation_layers(region);
}
void NavigationRegion3D::set_enter_cost(real_t p_enter_cost) {
@@ -239,8 +239,8 @@ void NavigationRegion3D::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_enabled", "enabled"), &NavigationRegion3D::set_enabled);
ClassDB::bind_method(D_METHOD("is_enabled"), &NavigationRegion3D::is_enabled);
- ClassDB::bind_method(D_METHOD("set_layers", "layers"), &NavigationRegion3D::set_layers);
- ClassDB::bind_method(D_METHOD("get_layers"), &NavigationRegion3D::get_layers);
+ ClassDB::bind_method(D_METHOD("set_navigation_layers", "navigation_layers"), &NavigationRegion3D::set_navigation_layers);
+ ClassDB::bind_method(D_METHOD("get_navigation_layers"), &NavigationRegion3D::get_navigation_layers);
ClassDB::bind_method(D_METHOD("get_region_rid"), &NavigationRegion3D::get_region_rid);
@@ -255,7 +255,7 @@ void NavigationRegion3D::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "navmesh", PROPERTY_HINT_RESOURCE_TYPE, "NavigationMesh"), "set_navigation_mesh", "get_navigation_mesh");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "enabled"), "set_enabled", "is_enabled");
- ADD_PROPERTY(PropertyInfo(Variant::INT, "layers", PROPERTY_HINT_LAYERS_3D_NAVIGATION), "set_layers", "get_layers");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "navigation_layers", PROPERTY_HINT_LAYERS_3D_NAVIGATION), "set_navigation_layers", "get_navigation_layers");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "enter_cost"), "set_enter_cost", "get_enter_cost");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "travel_cost"), "set_travel_cost", "get_travel_cost");
diff --git a/scene/3d/navigation_region_3d.h b/scene/3d/navigation_region_3d.h
index 042684c5b7..92474d1429 100644
--- a/scene/3d/navigation_region_3d.h
+++ b/scene/3d/navigation_region_3d.h
@@ -57,8 +57,8 @@ public:
void set_enabled(bool p_enabled);
bool is_enabled() const;
- void set_layers(uint32_t p_layers);
- uint32_t get_layers() const;
+ void set_navigation_layers(uint32_t p_navigation_layers);
+ uint32_t get_navigation_layers() const;
RID get_region_rid() const;
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/3d/occluder_instance_3d.cpp b/scene/3d/occluder_instance_3d.cpp
index f848eaab2e..66d0a8c4e2 100644
--- a/scene/3d/occluder_instance_3d.cpp
+++ b/scene/3d/occluder_instance_3d.cpp
@@ -219,7 +219,7 @@ void QuadOccluder3D::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_size", "size"), &QuadOccluder3D::set_size);
ClassDB::bind_method(D_METHOD("get_size"), &QuadOccluder3D::get_size);
- ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "size"), "set_size", "get_size");
+ ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "size", PROPERTY_HINT_NONE, "suffix:m"), "set_size", "get_size");
}
QuadOccluder3D::QuadOccluder3D() {
@@ -285,7 +285,7 @@ void BoxOccluder3D::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_size", "size"), &BoxOccluder3D::set_size);
ClassDB::bind_method(D_METHOD("get_size"), &BoxOccluder3D::get_size);
- ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "size"), "set_size", "get_size");
+ ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "size", PROPERTY_HINT_NONE, "suffix:m"), "set_size", "get_size");
}
BoxOccluder3D::BoxOccluder3D() {
@@ -354,7 +354,7 @@ void SphereOccluder3D::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_radius", "radius"), &SphereOccluder3D::set_radius);
ClassDB::bind_method(D_METHOD("get_radius"), &SphereOccluder3D::get_radius);
- ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "radius"), "set_radius", "get_radius");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "radius", PROPERTY_HINT_NONE, "suffix:m"), "set_radius", "get_radius");
}
SphereOccluder3D::SphereOccluder3D() {
@@ -736,7 +736,7 @@ void OccluderInstance3D::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "occluder", PROPERTY_HINT_RESOURCE_TYPE, "Occluder3D"), "set_occluder", "get_occluder");
ADD_GROUP("Bake", "bake_");
ADD_PROPERTY(PropertyInfo(Variant::INT, "bake_mask", PROPERTY_HINT_LAYERS_3D_RENDER), "set_bake_mask", "get_bake_mask");
- ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "bake_simplification_distance", PROPERTY_HINT_RANGE, "0.0,2.0,0.01"), "set_bake_simplification_distance", "get_bake_simplification_distance");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "bake_simplification_distance", PROPERTY_HINT_RANGE, "0.0,2.0,0.01,suffix:m"), "set_bake_simplification_distance", "get_bake_simplification_distance");
}
OccluderInstance3D::OccluderInstance3D() {
diff --git a/scene/3d/physics_body_3d.cpp b/scene/3d/physics_body_3d.cpp
index 982254c94d..30f7a025fa 100644
--- a/scene/3d/physics_body_3d.cpp
+++ b/scene/3d/physics_body_3d.cpp
@@ -261,8 +261,8 @@ void StaticBody3D::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_physics_material_override"), &StaticBody3D::get_physics_material_override);
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "physics_material_override", PROPERTY_HINT_RESOURCE_TYPE, "PhysicsMaterial"), "set_physics_material_override", "get_physics_material_override");
- ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "constant_linear_velocity"), "set_constant_linear_velocity", "get_constant_linear_velocity");
- ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "constant_angular_velocity"), "set_constant_angular_velocity", "get_constant_angular_velocity");
+ ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "constant_linear_velocity", PROPERTY_HINT_NONE, "suffix:m/s"), "set_constant_linear_velocity", "get_constant_linear_velocity");
+ ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "constant_angular_velocity", PROPERTY_HINT_NONE, U"radians,suffix:\u00B0/s"), "set_constant_angular_velocity", "get_constant_angular_velocity");
}
StaticBody3D::StaticBody3D(PhysicsServer3D::BodyMode p_mode) :
@@ -1101,7 +1101,7 @@ void RigidDynamicBody3D::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::INT, "linear_damp_mode", PROPERTY_HINT_ENUM, "Combine,Replace"), "set_linear_damp_mode", "get_linear_damp_mode");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "linear_damp", PROPERTY_HINT_RANGE, "0,100,0.001,or_greater"), "set_linear_damp", "get_linear_damp");
ADD_GROUP("Angular", "angular_");
- ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "angular_velocity", PROPERTY_HINT_NONE, "suffix:rad/s"), "set_angular_velocity", "get_angular_velocity");
+ ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "angular_velocity", PROPERTY_HINT_NONE, U"radians,suffix:\u00B0/s"), "set_angular_velocity", "get_angular_velocity");
ADD_PROPERTY(PropertyInfo(Variant::INT, "angular_damp_mode", PROPERTY_HINT_ENUM, "Combine,Replace"), "set_angular_damp_mode", "get_angular_damp_mode");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "angular_damp", PROPERTY_HINT_RANGE, "0,100,0.001,or_greater"), "set_angular_damp", "get_angular_damp");
ADD_GROUP("Constant Forces", "constant_");
@@ -2007,7 +2007,7 @@ void CharacterBody3D::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "floor_constant_speed"), "set_floor_constant_speed_enabled", "is_floor_constant_speed_enabled");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "floor_block_on_wall"), "set_floor_block_on_wall_enabled", "is_floor_block_on_wall_enabled");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "floor_max_angle", PROPERTY_HINT_RANGE, "0,180,0.1,radians"), "set_floor_max_angle", "get_floor_max_angle");
- ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "floor_snap_length", PROPERTY_HINT_RANGE, "0,1,0.01,or_greater"), "set_floor_snap_length", "get_floor_snap_length");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "floor_snap_length", PROPERTY_HINT_RANGE, "0,1,0.01,or_greater,suffix:m"), "set_floor_snap_length", "get_floor_snap_length");
ADD_GROUP("Moving Platform", "moving_platform");
ADD_PROPERTY(PropertyInfo(Variant::INT, "moving_platform_apply_velocity_on_leave", PROPERTY_HINT_ENUM, "Always,Upward Only,Never", PROPERTY_USAGE_DEFAULT), "set_moving_platform_apply_velocity_on_leave", "get_moving_platform_apply_velocity_on_leave");
ADD_PROPERTY(PropertyInfo(Variant::INT, "moving_platform_floor_layers", PROPERTY_HINT_LAYERS_2D_PHYSICS), "set_moving_platform_floor_layers", "get_moving_platform_floor_layers");
@@ -2998,8 +2998,8 @@ void PhysicalBone3D::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "linear_damp", PROPERTY_HINT_RANGE, "0,100,0.001,or_greater"), "set_linear_damp", "get_linear_damp");
ADD_PROPERTY(PropertyInfo(Variant::INT, "angular_damp_mode", PROPERTY_HINT_ENUM, "Combine,Replace"), "set_angular_damp_mode", "get_angular_damp_mode");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "angular_damp", PROPERTY_HINT_RANGE, "0,100,0.001,or_greater"), "set_angular_damp", "get_angular_damp");
- ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "linear_velocity"), "set_linear_velocity", "get_linear_velocity");
- ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "angular_velocity"), "set_angular_velocity", "get_angular_velocity");
+ ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "linear_velocity", PROPERTY_HINT_NONE, "suffix:m/s"), "set_linear_velocity", "get_linear_velocity");
+ ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "angular_velocity", PROPERTY_HINT_NONE, U"radians,suffix:\u00B0/s"), "set_angular_velocity", "get_angular_velocity");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "can_sleep"), "set_can_sleep", "is_able_to_sleep");
BIND_ENUM_CONSTANT(DAMP_MODE_COMBINE);
diff --git a/scene/3d/skeleton_ik_3d.cpp b/scene/3d/skeleton_ik_3d.cpp
index 55bbba26c3..2182c5ba11 100644
--- a/scene/3d/skeleton_ik_3d.cpp
+++ b/scene/3d/skeleton_ik_3d.cpp
@@ -396,7 +396,7 @@ void SkeletonIK3D::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "use_magnet"), "set_use_magnet", "is_using_magnet");
ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "magnet", PROPERTY_HINT_NONE, "suffix:m"), "set_magnet_position", "get_magnet_position");
ADD_PROPERTY(PropertyInfo(Variant::NODE_PATH, "target_node"), "set_target_node", "get_target_node");
- ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "min_distance"), "set_min_distance", "get_min_distance");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "min_distance", PROPERTY_HINT_NONE, "suffix:m"), "set_min_distance", "get_min_distance");
ADD_PROPERTY(PropertyInfo(Variant::INT, "max_iterations"), "set_max_iterations", "get_max_iterations");
}
diff --git a/scene/3d/sprite_3d.cpp b/scene/3d/sprite_3d.cpp
index 8cb5081047..55b55d924c 100644
--- a/scene/3d/sprite_3d.cpp
+++ b/scene/3d/sprite_3d.cpp
@@ -333,11 +333,11 @@ void SpriteBase3D::_bind_methods() {
ClassDB::bind_method(D_METHOD("_im_update"), &SpriteBase3D::_im_update);
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "centered"), "set_centered", "is_centered");
- ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "offset"), "set_offset", "get_offset");
+ ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "offset", PROPERTY_HINT_NONE, "suffix:px"), "set_offset", "get_offset");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "flip_h"), "set_flip_h", "is_flipped_h");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "flip_v"), "set_flip_v", "is_flipped_v");
ADD_PROPERTY(PropertyInfo(Variant::COLOR, "modulate"), "set_modulate", "get_modulate");
- ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "pixel_size", PROPERTY_HINT_RANGE, "0.0001,128,0.0001"), "set_pixel_size", "get_pixel_size");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "pixel_size", PROPERTY_HINT_RANGE, "0.0001,128,0.0001,suffix:m"), "set_pixel_size", "get_pixel_size");
ADD_PROPERTY(PropertyInfo(Variant::INT, "axis", PROPERTY_HINT_ENUM, "X-Axis,Y-Axis,Z-Axis"), "set_axis", "get_axis");
ADD_GROUP("Flags", "");
ADD_PROPERTY(PropertyInfo(Variant::INT, "billboard", PROPERTY_HINT_ENUM, "Disabled,Enabled,Y-Billboard"), "set_billboard_mode", "get_billboard_mode");
@@ -792,10 +792,10 @@ void Sprite3D::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::INT, "hframes", PROPERTY_HINT_RANGE, "1,16384,1"), "set_hframes", "get_hframes");
ADD_PROPERTY(PropertyInfo(Variant::INT, "vframes", PROPERTY_HINT_RANGE, "1,16384,1"), "set_vframes", "get_vframes");
ADD_PROPERTY(PropertyInfo(Variant::INT, "frame"), "set_frame", "get_frame");
- ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "frame_coords", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_EDITOR), "set_frame_coords", "get_frame_coords");
+ ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "frame_coords", PROPERTY_HINT_NONE, "suffix:px", PROPERTY_USAGE_EDITOR), "set_frame_coords", "get_frame_coords");
ADD_GROUP("Region", "region_");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "region_enabled"), "set_region_enabled", "is_region_enabled");
- ADD_PROPERTY(PropertyInfo(Variant::RECT2, "region_rect"), "set_region_rect", "get_region_rect");
+ ADD_PROPERTY(PropertyInfo(Variant::RECT2, "region_rect", PROPERTY_HINT_NONE, "suffix:px"), "set_region_rect", "get_region_rect");
ADD_SIGNAL(MethodInfo("frame_changed"));
ADD_SIGNAL(MethodInfo("texture_changed"));
diff --git a/scene/3d/visual_instance_3d.cpp b/scene/3d/visual_instance_3d.cpp
index e40c8bfa2b..6df50bc491 100644
--- a/scene/3d/visual_instance_3d.cpp
+++ b/scene/3d/visual_instance_3d.cpp
@@ -466,10 +466,10 @@ void GeometryInstance3D::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::INT, "gi_lightmap_scale", PROPERTY_HINT_ENUM, String::utf8("1×,2×,4×,8×")), "set_lightmap_scale", "get_lightmap_scale");
ADD_GROUP("Visibility Range", "visibility_range_");
- ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "visibility_range_begin", PROPERTY_HINT_RANGE, "0.0,4096.0,0.01"), "set_visibility_range_begin", "get_visibility_range_begin");
- ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "visibility_range_begin_margin", PROPERTY_HINT_RANGE, "0.0,4096.0,0.01"), "set_visibility_range_begin_margin", "get_visibility_range_begin_margin");
- ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "visibility_range_end", PROPERTY_HINT_RANGE, "0.0,4096.0,0.01"), "set_visibility_range_end", "get_visibility_range_end");
- ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "visibility_range_end_margin", PROPERTY_HINT_RANGE, "0.0,4096.0,0.01"), "set_visibility_range_end_margin", "get_visibility_range_end_margin");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "visibility_range_begin", PROPERTY_HINT_RANGE, "0.0,4096.0,0.01,suffix:m"), "set_visibility_range_begin", "get_visibility_range_begin");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "visibility_range_begin_margin", PROPERTY_HINT_RANGE, "0.0,4096.0,0.01,suffix:m"), "set_visibility_range_begin_margin", "get_visibility_range_begin_margin");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "visibility_range_end", PROPERTY_HINT_RANGE, "0.0,4096.0,0.01,suffix:m"), "set_visibility_range_end", "get_visibility_range_end");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "visibility_range_end_margin", PROPERTY_HINT_RANGE, "0.0,4096.0,0.01,suffix:m"), "set_visibility_range_end_margin", "get_visibility_range_end_margin");
ADD_PROPERTY(PropertyInfo(Variant::INT, "visibility_range_fade_mode", PROPERTY_HINT_ENUM, "Disabled,Self,Dependencies"), "set_visibility_range_fade_mode", "get_visibility_range_fade_mode");
//ADD_SIGNAL( MethodInfo("visibility_changed"));
diff --git a/scene/3d/voxel_gi.cpp b/scene/3d/voxel_gi.cpp
index 29e495ce1b..d81b59b3fc 100644
--- a/scene/3d/voxel_gi.cpp
+++ b/scene/3d/voxel_gi.cpp
@@ -476,7 +476,7 @@ void VoxelGI::_bind_methods() {
ClassDB::set_method_flags(get_class_static(), _scs_create("debug_bake"), METHOD_FLAGS_DEFAULT | METHOD_FLAG_EDITOR);
ADD_PROPERTY(PropertyInfo(Variant::INT, "subdiv", PROPERTY_HINT_ENUM, "64,128,256,512"), "set_subdiv", "get_subdiv");
- ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "extents"), "set_extents", "get_extents");
+ ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "extents", PROPERTY_HINT_NONE, "suffix:m"), "set_extents", "get_extents");
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "data", PROPERTY_HINT_RESOURCE_TYPE, "VoxelGIData", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_DO_NOT_SHARE_ON_DUPLICATE), "set_probe_data", "get_probe_data");
BIND_ENUM_CONSTANT(SUBDIV_64);
diff --git a/scene/animation/animation_blend_tree.cpp b/scene/animation/animation_blend_tree.cpp
index 17a99ed034..1d537837bd 100644
--- a/scene/animation/animation_blend_tree.cpp
+++ b/scene/animation/animation_blend_tree.cpp
@@ -375,14 +375,14 @@ void AnimationNodeOneShot::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::INT, "mix_mode", PROPERTY_HINT_ENUM, "Blend,Add"), "set_mix_mode", "get_mix_mode");
- ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "fadein_time", PROPERTY_HINT_RANGE, "0,60,0.01,or_greater"), "set_fadein_time", "get_fadein_time");
- ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "fadeout_time", PROPERTY_HINT_RANGE, "0,60,0.01,or_greater"), "set_fadeout_time", "get_fadeout_time");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "fadein_time", PROPERTY_HINT_RANGE, "0,60,0.01,or_greater,suffix:s"), "set_fadein_time", "get_fadein_time");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "fadeout_time", PROPERTY_HINT_RANGE, "0,60,0.01,or_greater,suffix:s"), "set_fadeout_time", "get_fadeout_time");
ADD_GROUP("Auto Restart", "autorestart_");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "autorestart"), "set_autorestart", "has_autorestart");
- ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "autorestart_delay", PROPERTY_HINT_RANGE, "0,60,0.01,or_greater"), "set_autorestart_delay", "get_autorestart_delay");
- ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "autorestart_random_delay", PROPERTY_HINT_RANGE, "0,60,0.01,or_greater"), "set_autorestart_random_delay", "get_autorestart_random_delay");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "autorestart_delay", PROPERTY_HINT_RANGE, "0,60,0.01,or_greater,suffix:s"), "set_autorestart_delay", "get_autorestart_delay");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "autorestart_random_delay", PROPERTY_HINT_RANGE, "0,60,0.01,or_greater,suffix:s"), "set_autorestart_random_delay", "get_autorestart_random_delay");
ADD_GROUP("", "");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "sync"), "set_use_sync", "is_using_sync");
@@ -825,7 +825,7 @@ void AnimationNodeTransition::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_cross_fade_time"), &AnimationNodeTransition::get_cross_fade_time);
ADD_PROPERTY(PropertyInfo(Variant::INT, "input_count", PROPERTY_HINT_RANGE, "0,64,1", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_UPDATE_ALL_IF_MODIFIED), "set_enabled_inputs", "get_enabled_inputs");
- ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "xfade_time", PROPERTY_HINT_RANGE, "0,120,0.01"), "set_cross_fade_time", "get_cross_fade_time");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "xfade_time", PROPERTY_HINT_RANGE, "0,120,0.01,suffix:s"), "set_cross_fade_time", "get_cross_fade_time");
for (int i = 0; i < MAX_INPUTS; i++) {
ADD_PROPERTYI(PropertyInfo(Variant::STRING, "input_" + itos(i) + "/name", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_INTERNAL), "set_input_caption", "get_input_caption", i);
diff --git a/scene/animation/animation_node_state_machine.cpp b/scene/animation/animation_node_state_machine.cpp
index fcc4548929..2c7d021427 100644
--- a/scene/animation/animation_node_state_machine.cpp
+++ b/scene/animation/animation_node_state_machine.cpp
@@ -118,7 +118,7 @@ void AnimationNodeStateMachineTransition::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::INT, "switch_mode", PROPERTY_HINT_ENUM, "Immediate,Sync,At End"), "set_switch_mode", "get_switch_mode");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "auto_advance"), "set_auto_advance", "has_auto_advance");
ADD_PROPERTY(PropertyInfo(Variant::STRING_NAME, "advance_condition"), "set_advance_condition", "get_advance_condition");
- ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "xfade_time", PROPERTY_HINT_RANGE, "0,240,0.01"), "set_xfade_time", "get_xfade_time");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "xfade_time", PROPERTY_HINT_RANGE, "0,240,0.01,suffix:s"), "set_xfade_time", "get_xfade_time");
ADD_PROPERTY(PropertyInfo(Variant::INT, "priority", PROPERTY_HINT_RANGE, "0,32,1"), "set_priority", "get_priority");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "disabled"), "set_disabled", "is_disabled");
diff --git a/scene/animation/animation_player.cpp b/scene/animation/animation_player.cpp
index 921b59748c..8edfaa5853 100644
--- a/scene/animation/animation_player.cpp
+++ b/scene/animation/animation_player.cpp
@@ -2095,7 +2095,7 @@ void AnimationPlayer::_bind_methods() {
ADD_GROUP("Playback Options", "playback_");
ADD_PROPERTY(PropertyInfo(Variant::INT, "playback_process_mode", PROPERTY_HINT_ENUM, "Physics,Idle,Manual"), "set_process_callback", "get_process_callback");
- ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "playback_default_blend_time", PROPERTY_HINT_RANGE, "0,4096,0.01"), "set_default_blend_time", "get_default_blend_time");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "playback_default_blend_time", PROPERTY_HINT_RANGE, "0,4096,0.01,suffix:s"), "set_default_blend_time", "get_default_blend_time");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "playback_active", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NONE), "set_active", "is_active");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "playback_speed", PROPERTY_HINT_RANGE, "-64,64,0.01"), "set_speed_scale", "get_speed_scale");
ADD_PROPERTY(PropertyInfo(Variant::INT, "method_call_mode", PROPERTY_HINT_ENUM, "Deferred,Immediate"), "set_method_call_mode", "get_method_call_mode");
diff --git a/scene/animation/root_motion_view.cpp b/scene/animation/root_motion_view.cpp
index 3192f5f7cd..47f08219a9 100644
--- a/scene/animation/root_motion_view.cpp
+++ b/scene/animation/root_motion_view.cpp
@@ -183,8 +183,8 @@ void RootMotionView::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::NODE_PATH, "animation_path", PROPERTY_HINT_NODE_PATH_VALID_TYPES, "AnimationTree"), "set_animation_path", "get_animation_path");
ADD_PROPERTY(PropertyInfo(Variant::COLOR, "color"), "set_color", "get_color");
- ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "cell_size", PROPERTY_HINT_RANGE, "0.1,16,0.01,or_greater"), "set_cell_size", "get_cell_size");
- ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "radius", PROPERTY_HINT_RANGE, "0.1,16,0.01,or_greater"), "set_radius", "get_radius");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "cell_size", PROPERTY_HINT_RANGE, "0.1,16,0.01,or_greater,suffix:m"), "set_cell_size", "get_cell_size");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "radius", PROPERTY_HINT_RANGE, "0.1,16,0.01,or_greater,suffix:m"), "set_radius", "get_radius");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "zero_y"), "set_zero_y", "get_zero_y");
}
diff --git a/scene/gui/button.cpp b/scene/gui/button.cpp
index c54897035a..0d21d82896 100644
--- a/scene/gui/button.cpp
+++ b/scene/gui/button.cpp
@@ -35,7 +35,7 @@
Size2 Button::get_minimum_size() const {
Size2 minsize = text_buf->get_size();
- if (clip_text) {
+ if (clip_text || overrun_behavior != TextParagraph::OVERRUN_NO_TRIMMING) {
minsize.width = 0;
}
@@ -292,9 +292,9 @@ void Button::_notification(int p_what) {
icon_ofs.x = 0.0;
}
int text_clip = size.width - style->get_minimum_size().width - icon_ofs.width;
- text_buf->set_width(clip_text ? text_clip : -1);
+ text_buf->set_width((clip_text || overrun_behavior != TextParagraph::OVERRUN_NO_TRIMMING) ? text_clip : -1);
- int text_width = MAX(1, clip_text ? MIN(text_clip, text_buf->get_size().x) : text_buf->get_size().x);
+ int text_width = MAX(1, (clip_text || overrun_behavior != TextParagraph::OVERRUN_NO_TRIMMING) ? MIN(text_clip, text_buf->get_size().x) : text_buf->get_size().x);
if (_internal_margin[SIDE_LEFT] > 0) {
text_clip -= _internal_margin[SIDE_LEFT] + get_theme_constant(SNAME("h_separation"));
@@ -364,6 +364,21 @@ void Button::_shape() {
text_buf->set_direction((TextServer::Direction)text_direction);
}
text_buf->add_string(xl_text, font, font_size, opentype_features, (!language.is_empty()) ? language : TranslationServer::get_singleton()->get_tool_locale());
+ text_buf->set_text_overrun_behavior(overrun_behavior);
+}
+
+void Button::set_text_overrun_behavior(TextParagraph::OverrunBehavior p_behavior) {
+ if (overrun_behavior != p_behavior) {
+ overrun_behavior = p_behavior;
+ _shape();
+
+ update();
+ update_minimum_size();
+ }
+}
+
+TextParagraph::OverrunBehavior Button::get_text_overrun_behavior() const {
+ return overrun_behavior;
}
void Button::set_text(const String &p_text) {
@@ -550,6 +565,8 @@ void Button::_get_property_list(List<PropertyInfo> *p_list) const {
void Button::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_text", "text"), &Button::set_text);
ClassDB::bind_method(D_METHOD("get_text"), &Button::get_text);
+ ClassDB::bind_method(D_METHOD("set_text_overrun_behavior", "overrun_behavior"), &Button::set_text_overrun_behavior);
+ ClassDB::bind_method(D_METHOD("get_text_overrun_behavior"), &Button::get_text_overrun_behavior);
ClassDB::bind_method(D_METHOD("set_text_direction", "direction"), &Button::set_text_direction);
ClassDB::bind_method(D_METHOD("get_text_direction"), &Button::get_text_direction);
ClassDB::bind_method(D_METHOD("set_opentype_feature", "tag", "value"), &Button::set_opentype_feature);
@@ -577,6 +594,7 @@ void Button::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "flat"), "set_flat", "is_flat");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "clip_text"), "set_clip_text", "get_clip_text");
ADD_PROPERTY(PropertyInfo(Variant::INT, "alignment", PROPERTY_HINT_ENUM, "Left,Center,Right"), "set_text_alignment", "get_text_alignment");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "text_overrun_behavior", PROPERTY_HINT_ENUM, "Trim Nothing,Trim Characters,Trim Words,Ellipsis,Word Ellipsis"), "set_text_overrun_behavior", "get_text_overrun_behavior");
ADD_PROPERTY(PropertyInfo(Variant::INT, "icon_alignment", PROPERTY_HINT_ENUM, "Left,Center,Right"), "set_icon_alignment", "get_icon_alignment");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "expand_icon"), "set_expand_icon", "is_expand_icon");
}
diff --git a/scene/gui/button.h b/scene/gui/button.h
index 1abf86c986..175785a35c 100644
--- a/scene/gui/button.h
+++ b/scene/gui/button.h
@@ -46,6 +46,7 @@ private:
Dictionary opentype_features;
String language;
TextDirection text_direction = TEXT_DIRECTION_AUTO;
+ TextParagraph::OverrunBehavior overrun_behavior = TextParagraph::OVERRUN_NO_TRIMMING;
Ref<Texture2D> icon;
bool expand_icon = false;
@@ -71,6 +72,9 @@ public:
void set_text(const String &p_text);
String get_text() const;
+ void set_text_overrun_behavior(TextParagraph::OverrunBehavior p_behavior);
+ TextParagraph::OverrunBehavior get_text_overrun_behavior() const;
+
void set_text_direction(TextDirection p_text_direction);
TextDirection get_text_direction() const;
diff --git a/scene/gui/control.cpp b/scene/gui/control.cpp
index db78b4adb6..5ddc38a0b9 100644
--- a/scene/gui/control.cpp
+++ b/scene/gui/control.cpp
@@ -414,7 +414,7 @@ void Control::_get_property_list(List<PropertyInfo> *p_list) const {
usage |= PROPERTY_USAGE_STORAGE | PROPERTY_USAGE_CHECKED;
}
- p_list->push_back(PropertyInfo(Variant::INT, "theme_override_font_sizes/" + E, PROPERTY_HINT_RANGE, "1,256,1,or_greater", usage));
+ p_list->push_back(PropertyInfo(Variant::INT, "theme_override_font_sizes/" + E, PROPERTY_HINT_RANGE, "1,256,1,or_greater,suffix:px", usage));
}
}
{
@@ -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/gui/graph_edit.cpp b/scene/gui/graph_edit.cpp
index 8ad55fc6ef..c219eafbf7 100644
--- a/scene/gui/graph_edit.cpp
+++ b/scene/gui/graph_edit.cpp
@@ -2317,14 +2317,14 @@ void GraphEdit::_bind_methods() {
GDVIRTUAL_BIND(_get_connection_line, "from", "to")
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "right_disconnects"), "set_right_disconnects", "is_right_disconnects_enabled");
- ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "scroll_offset"), "set_scroll_ofs", "get_scroll_ofs");
- ADD_PROPERTY(PropertyInfo(Variant::INT, "snap_distance"), "set_snap", "get_snap");
+ ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "scroll_offset", PROPERTY_HINT_NONE, "suffix:px"), "set_scroll_ofs", "get_scroll_ofs");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "snap_distance", PROPERTY_HINT_NONE, "suffix:px"), "set_snap", "get_snap");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "use_snap"), "set_use_snap", "is_using_snap");
ADD_PROPERTY(PropertyInfo(Variant::INT, "panning_scheme", PROPERTY_HINT_ENUM, "Scroll Zooms,Scroll Pans"), "set_panning_scheme", "get_panning_scheme");
ADD_GROUP("Connection Lines", "connection_lines");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "connection_lines_curvature"), "set_connection_lines_curvature", "get_connection_lines_curvature");
- ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "connection_lines_thickness"), "set_connection_lines_thickness", "get_connection_lines_thickness");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "connection_lines_thickness", PROPERTY_HINT_NONE, "suffix:px"), "set_connection_lines_thickness", "get_connection_lines_thickness");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "connection_lines_antialiased"), "set_connection_lines_antialiased", "is_connection_lines_antialiased");
ADD_GROUP("Zoom", "");
@@ -2336,7 +2336,7 @@ void GraphEdit::_bind_methods() {
ADD_GROUP("Minimap", "minimap");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "minimap_enabled"), "set_minimap_enabled", "is_minimap_enabled");
- ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "minimap_size"), "set_minimap_size", "get_minimap_size");
+ ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "minimap_size", PROPERTY_HINT_NONE, "suffix:px"), "set_minimap_size", "get_minimap_size");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "minimap_opacity"), "set_minimap_opacity", "get_minimap_opacity");
ADD_SIGNAL(MethodInfo("connection_request", PropertyInfo(Variant::STRING_NAME, "from"), PropertyInfo(Variant::INT, "from_slot"), PropertyInfo(Variant::STRING_NAME, "to"), PropertyInfo(Variant::INT, "to_slot")));
diff --git a/scene/gui/graph_node.cpp b/scene/gui/graph_node.cpp
index 5cb28a30e8..87706cd0d7 100644
--- a/scene/gui/graph_node.cpp
+++ b/scene/gui/graph_node.cpp
@@ -1107,7 +1107,7 @@ void GraphNode::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::STRING, "title"), "set_title", "get_title");
ADD_PROPERTY(PropertyInfo(Variant::INT, "text_direction", PROPERTY_HINT_ENUM, "Auto,Left-to-Right,Right-to-Left,Inherited"), "set_text_direction", "get_text_direction");
ADD_PROPERTY(PropertyInfo(Variant::STRING, "language", PROPERTY_HINT_LOCALE_ID, ""), "set_language", "get_language");
- ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "position_offset"), "set_position_offset", "get_position_offset");
+ ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "position_offset", PROPERTY_HINT_NONE, "suffix:px"), "set_position_offset", "get_position_offset");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "show_close"), "set_show_close_button", "is_close_button_visible");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "resizable"), "set_resizable", "is_resizable");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "selected"), "set_selected", "is_selected");
diff --git a/scene/gui/item_list.cpp b/scene/gui/item_list.cpp
index 8b22f3722a..0c95dabfb5 100644
--- a/scene/gui/item_list.cpp
+++ b/scene/gui/item_list.cpp
@@ -1763,11 +1763,11 @@ void ItemList::_bind_methods() {
ADD_GROUP("Columns", "");
ADD_PROPERTY(PropertyInfo(Variant::INT, "max_columns", PROPERTY_HINT_RANGE, "0,10,1,or_greater"), "set_max_columns", "get_max_columns");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "same_column_width"), "set_same_column_width", "is_same_column_width");
- ADD_PROPERTY(PropertyInfo(Variant::INT, "fixed_column_width", PROPERTY_HINT_RANGE, "0,100,1,or_greater"), "set_fixed_column_width", "get_fixed_column_width");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "fixed_column_width", PROPERTY_HINT_RANGE, "0,100,1,or_greater,suffix:px"), "set_fixed_column_width", "get_fixed_column_width");
ADD_GROUP("Icon", "");
ADD_PROPERTY(PropertyInfo(Variant::INT, "icon_mode", PROPERTY_HINT_ENUM, "Top,Left"), "set_icon_mode", "get_icon_mode");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "icon_scale"), "set_icon_scale", "get_icon_scale");
- ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "fixed_icon_size"), "set_fixed_icon_size", "get_fixed_icon_size");
+ ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "fixed_icon_size", PROPERTY_HINT_NONE, "suffix:px"), "set_fixed_icon_size", "get_fixed_icon_size");
BIND_ENUM_CONSTANT(ICON_MODE_TOP);
BIND_ENUM_CONSTANT(ICON_MODE_LEFT);
diff --git a/scene/gui/nine_patch_rect.cpp b/scene/gui/nine_patch_rect.cpp
index 4f34ece86f..8fee10b19a 100644
--- a/scene/gui/nine_patch_rect.cpp
+++ b/scene/gui/nine_patch_rect.cpp
@@ -73,13 +73,13 @@ void NinePatchRect::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "texture", PROPERTY_HINT_RESOURCE_TYPE, "Texture2D"), "set_texture", "get_texture");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "draw_center"), "set_draw_center", "is_draw_center_enabled");
- ADD_PROPERTY(PropertyInfo(Variant::RECT2, "region_rect"), "set_region_rect", "get_region_rect");
+ ADD_PROPERTY(PropertyInfo(Variant::RECT2, "region_rect", PROPERTY_HINT_NONE, "suffix:px"), "set_region_rect", "get_region_rect");
ADD_GROUP("Patch Margin", "patch_margin_");
- ADD_PROPERTYI(PropertyInfo(Variant::INT, "patch_margin_left", PROPERTY_HINT_RANGE, "0,16384,1"), "set_patch_margin", "get_patch_margin", SIDE_LEFT);
- ADD_PROPERTYI(PropertyInfo(Variant::INT, "patch_margin_top", PROPERTY_HINT_RANGE, "0,16384,1"), "set_patch_margin", "get_patch_margin", SIDE_TOP);
- ADD_PROPERTYI(PropertyInfo(Variant::INT, "patch_margin_right", PROPERTY_HINT_RANGE, "0,16384,1"), "set_patch_margin", "get_patch_margin", SIDE_RIGHT);
- ADD_PROPERTYI(PropertyInfo(Variant::INT, "patch_margin_bottom", PROPERTY_HINT_RANGE, "0,16384,1"), "set_patch_margin", "get_patch_margin", SIDE_BOTTOM);
+ ADD_PROPERTYI(PropertyInfo(Variant::INT, "patch_margin_left", PROPERTY_HINT_RANGE, "0,16384,1,suffix:px"), "set_patch_margin", "get_patch_margin", SIDE_LEFT);
+ ADD_PROPERTYI(PropertyInfo(Variant::INT, "patch_margin_top", PROPERTY_HINT_RANGE, "0,16384,1,suffix:px"), "set_patch_margin", "get_patch_margin", SIDE_TOP);
+ ADD_PROPERTYI(PropertyInfo(Variant::INT, "patch_margin_right", PROPERTY_HINT_RANGE, "0,16384,1,suffix:px"), "set_patch_margin", "get_patch_margin", SIDE_RIGHT);
+ ADD_PROPERTYI(PropertyInfo(Variant::INT, "patch_margin_bottom", PROPERTY_HINT_RANGE, "0,16384,1,suffix:px"), "set_patch_margin", "get_patch_margin", SIDE_BOTTOM);
ADD_GROUP("Axis Stretch", "axis_stretch_");
ADD_PROPERTY(PropertyInfo(Variant::INT, "axis_stretch_horizontal", PROPERTY_HINT_ENUM, "Stretch,Tile,Tile Fit"), "set_h_axis_stretch_mode", "get_h_axis_stretch_mode");
ADD_PROPERTY(PropertyInfo(Variant::INT, "axis_stretch_vertical", PROPERTY_HINT_ENUM, "Stretch,Tile,Tile Fit"), "set_v_axis_stretch_mode", "get_v_axis_stretch_mode");
diff --git a/scene/gui/popup.cpp b/scene/gui/popup.cpp
index 6532fc5934..c4396f636a 100644
--- a/scene/gui/popup.cpp
+++ b/scene/gui/popup.cpp
@@ -108,9 +108,7 @@ void Popup::_close_pressed() {
_deinitialize_visible_parents();
- // Hide after returning to process events, but only if we don't
- // get popped up in the interim.
- call_deferred(SNAME("_popup_conditional_hide"));
+ call_deferred(SNAME("hide"));
}
void Popup::_post_popup() {
@@ -118,15 +116,8 @@ void Popup::_post_popup() {
popped_up = true;
}
-void Popup::_popup_conditional_hide() {
- if (!popped_up) {
- hide();
- }
-}
-
void Popup::_bind_methods() {
ADD_SIGNAL(MethodInfo("popup_hide"));
- ClassDB::bind_method(D_METHOD("_popup_conditional_hide"), &Popup::_popup_conditional_hide);
}
Rect2i Popup::_popup_adjust_rect() const {
diff --git a/scene/gui/popup.h b/scene/gui/popup.h
index 27f46d4a97..b53c8be50f 100644
--- a/scene/gui/popup.h
+++ b/scene/gui/popup.h
@@ -48,8 +48,6 @@ class Popup : public Window {
void _initialize_visible_parents();
void _deinitialize_visible_parents();
- void _parent_focused();
-
protected:
void _close_pressed();
virtual Rect2i _popup_adjust_rect() const override;
@@ -57,7 +55,7 @@ protected:
void _notification(int p_what);
static void _bind_methods();
- void _popup_conditional_hide();
+ virtual void _parent_focused();
virtual void _post_popup() override;
diff --git a/scene/gui/popup_menu.cpp b/scene/gui/popup_menu.cpp
index 8303d6db57..c9eecf54dd 100644
--- a/scene/gui/popup_menu.cpp
+++ b/scene/gui/popup_menu.cpp
@@ -243,6 +243,29 @@ void PopupMenu::_activate_submenu(int p_over, bool p_by_keyboard) {
}
}
+void PopupMenu::_parent_focused() {
+ if (is_embedded()) {
+ Point2 mouse_pos_adjusted;
+ Window *window_parent = Object::cast_to<Window>(get_parent()->get_viewport());
+ while (window_parent) {
+ if (!window_parent->is_embedded()) {
+ mouse_pos_adjusted += window_parent->get_position();
+ break;
+ }
+
+ window_parent = Object::cast_to<Window>(window_parent->get_parent()->get_viewport());
+ }
+
+ Rect2 safe_area = DisplayServer::get_singleton()->window_get_popup_safe_rect(get_window_id());
+ Point2 pos = DisplayServer::get_singleton()->mouse_get_position() - mouse_pos_adjusted;
+ if (safe_area == Rect2i() || !safe_area.has_point(pos)) {
+ Popup::_parent_focused();
+ } else {
+ grab_focus();
+ }
+ }
+}
+
void PopupMenu::_submenu_timeout() {
if (mouse_over == submenu_over) {
_activate_submenu(mouse_over);
@@ -1895,7 +1918,7 @@ void PopupMenu::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "hide_on_item_selection"), "set_hide_on_item_selection", "is_hide_on_item_selection");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "hide_on_checkable_item_selection"), "set_hide_on_checkable_item_selection", "is_hide_on_checkable_item_selection");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "hide_on_state_item_selection"), "set_hide_on_state_item_selection", "is_hide_on_state_item_selection");
- ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "submenu_popup_delay"), "set_submenu_popup_delay", "get_submenu_popup_delay");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "submenu_popup_delay", PROPERTY_HINT_NONE, "suffix:s"), "set_submenu_popup_delay", "get_submenu_popup_delay");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "allow_search"), "set_allow_search", "get_allow_search");
ADD_ARRAY_COUNT("Items", "item_count", "set_item_count", "get_item_count", "item_");
diff --git a/scene/gui/popup_menu.h b/scene/gui/popup_menu.h
index 12587b7e73..53bc5a8c22 100644
--- a/scene/gui/popup_menu.h
+++ b/scene/gui/popup_menu.h
@@ -148,6 +148,8 @@ public:
// this value should be updated to reflect the new size.
static const int ITEM_PROPERTY_SIZE = 10;
+ virtual void _parent_focused() override;
+
void add_item(const String &p_label, int p_id = -1, Key p_accel = Key::NONE);
void add_icon_item(const Ref<Texture2D> &p_icon, const String &p_label, int p_id = -1, Key p_accel = Key::NONE);
void add_check_item(const String &p_label, int p_id = -1, Key p_accel = Key::NONE);
diff --git a/scene/gui/reference_rect.cpp b/scene/gui/reference_rect.cpp
index ed79da5c22..5190a5a7d2 100644
--- a/scene/gui/reference_rect.cpp
+++ b/scene/gui/reference_rect.cpp
@@ -83,6 +83,6 @@ void ReferenceRect::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_editor_only", "enabled"), &ReferenceRect::set_editor_only);
ADD_PROPERTY(PropertyInfo(Variant::COLOR, "border_color"), "set_border_color", "get_border_color");
- ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "border_width", PROPERTY_HINT_RANGE, "0.0,5.0,0.1,or_greater"), "set_border_width", "get_border_width");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "border_width", PROPERTY_HINT_RANGE, "0.0,5.0,0.1,or_greater,suffix:px"), "set_border_width", "get_border_width");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "editor_only"), "set_editor_only", "get_editor_only");
}
diff --git a/scene/gui/rich_text_label.cpp b/scene/gui/rich_text_label.cpp
index cf7bf930a5..4a0edd85f5 100644
--- a/scene/gui/rich_text_label.cpp
+++ b/scene/gui/rich_text_label.cpp
@@ -1243,8 +1243,8 @@ int RichTextLabel::_draw_line(ItemFrame *p_frame, int p_line, const Vector2 &p_o
// Draw glyphs.
for (int j = 0; j < glyphs[i].repeat; j++) {
+ bool skip = (trim_chars && l.char_offset + glyphs[i].end > visible_characters) || (trim_glyphs_ltr && (r_processed_glyphs >= visible_glyphs)) || (trim_glyphs_rtl && (r_processed_glyphs < total_glyphs - visible_glyphs));
if (visible) {
- bool skip = (trim_chars && l.char_offset + glyphs[i].end > visible_characters) || (trim_glyphs_ltr && (r_processed_glyphs >= visible_glyphs)) || (trim_glyphs_rtl && (r_processed_glyphs < total_glyphs - visible_glyphs));
if (!skip) {
if (frid != RID()) {
TS->font_draw_glyph(frid, ci, glyphs[i].font_size, p_ofs + fx_offset + off, gl, selected ? selection_fg : font_color);
@@ -1254,6 +1254,27 @@ int RichTextLabel::_draw_line(ItemFrame *p_frame, int p_line, const Vector2 &p_o
}
r_processed_glyphs++;
}
+ if (skip) {
+ // End underline/overline/strikethrough is previous glyph is skipped.
+ if (ul_started) {
+ ul_started = false;
+ float y_off = TS->shaped_text_get_underline_position(rid);
+ float underline_width = TS->shaped_text_get_underline_thickness(rid) * get_theme_default_base_scale();
+ draw_line(ul_start + Vector2(0, y_off), p_ofs + Vector2(off.x, off.y + y_off), ul_color, underline_width);
+ }
+ if (dot_ul_started) {
+ dot_ul_started = false;
+ float y_off = TS->shaped_text_get_underline_position(rid);
+ float underline_width = TS->shaped_text_get_underline_thickness(rid) * get_theme_default_base_scale();
+ draw_dashed_line(dot_ul_start + Vector2(0, y_off), p_ofs + Vector2(off.x, off.y + y_off), dot_ul_color, underline_width, underline_width * 2);
+ }
+ if (st_started) {
+ st_started = false;
+ float y_off = -TS->shaped_text_get_ascent(rid) + TS->shaped_text_get_size(rid).y / 2;
+ float underline_width = TS->shaped_text_get_underline_thickness(rid) * get_theme_default_base_scale();
+ draw_line(st_start + Vector2(0, y_off), p_ofs + Vector2(off.x, off.y + y_off), st_color, underline_width);
+ }
+ }
off.x += glyphs[i].advance;
}
}
@@ -4974,7 +4995,7 @@ void RichTextLabel::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "bbcode_enabled"), "set_use_bbcode", "is_using_bbcode");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "threaded"), "set_threaded", "is_threaded");
- ADD_PROPERTY(PropertyInfo(Variant::INT, "progress_bar_delay"), "set_progress_bar_delay", "get_progress_bar_delay");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "progress_bar_delay", PROPERTY_HINT_NONE, "suffix:ms"), "set_progress_bar_delay", "get_progress_bar_delay");
ADD_PROPERTY(PropertyInfo(Variant::INT, "tab_size", PROPERTY_HINT_RANGE, "0,24,1"), "set_tab_size", "get_tab_size");
ADD_PROPERTY(PropertyInfo(Variant::STRING, "text", PROPERTY_HINT_MULTILINE_TEXT), "set_text", "get_text");
diff --git a/scene/gui/scroll_bar.cpp b/scene/gui/scroll_bar.cpp
index e1b0e8cca8..f387f91a8b 100644
--- a/scene/gui/scroll_bar.cpp
+++ b/scene/gui/scroll_bar.cpp
@@ -622,7 +622,7 @@ void ScrollBar::_bind_methods() {
ADD_SIGNAL(MethodInfo("scrolling"));
- ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "custom_step", PROPERTY_HINT_RANGE, "-1,4096"), "set_custom_step", "get_custom_step");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "custom_step", PROPERTY_HINT_RANGE, "-1,4096,suffix:px"), "set_custom_step", "get_custom_step");
}
ScrollBar::ScrollBar(Orientation p_orientation) {
diff --git a/scene/gui/scroll_container.cpp b/scene/gui/scroll_container.cpp
index 135bad4689..871cc520e9 100644
--- a/scene/gui/scroll_container.cpp
+++ b/scene/gui/scroll_container.cpp
@@ -578,8 +578,8 @@ void ScrollContainer::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "follow_focus"), "set_follow_focus", "is_following_focus");
ADD_GROUP("Scroll", "scroll_");
- ADD_PROPERTY(PropertyInfo(Variant::INT, "scroll_horizontal"), "set_h_scroll", "get_h_scroll");
- ADD_PROPERTY(PropertyInfo(Variant::INT, "scroll_vertical"), "set_v_scroll", "get_v_scroll");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "scroll_horizontal", PROPERTY_HINT_NONE, "suffix:px"), "set_h_scroll", "get_h_scroll");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "scroll_vertical", PROPERTY_HINT_NONE, "suffix:px"), "set_v_scroll", "get_v_scroll");
ADD_PROPERTY(PropertyInfo(Variant::INT, "horizontal_scroll_mode", PROPERTY_HINT_ENUM, "Disabled,Auto,Always Show,Never Show"), "set_horizontal_scroll_mode", "get_horizontal_scroll_mode");
ADD_PROPERTY(PropertyInfo(Variant::INT, "vertical_scroll_mode", PROPERTY_HINT_ENUM, "Disabled,Auto,Always Show,Never Show"), "set_vertical_scroll_mode", "get_vertical_scroll_mode");
ADD_PROPERTY(PropertyInfo(Variant::INT, "scroll_deadzone"), "set_deadzone", "get_deadzone");
diff --git a/scene/gui/split_container.cpp b/scene/gui/split_container.cpp
index 6845d46721..d7aa516ee6 100644
--- a/scene/gui/split_container.cpp
+++ b/scene/gui/split_container.cpp
@@ -377,7 +377,7 @@ void SplitContainer::_bind_methods() {
ADD_SIGNAL(MethodInfo("dragged", PropertyInfo(Variant::INT, "offset")));
- ADD_PROPERTY(PropertyInfo(Variant::INT, "split_offset"), "set_split_offset", "get_split_offset");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "split_offset", PROPERTY_HINT_NONE, "suffix:px"), "set_split_offset", "get_split_offset");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "collapsed"), "set_collapsed", "is_collapsed");
ADD_PROPERTY(PropertyInfo(Variant::INT, "dragger_visibility", PROPERTY_HINT_ENUM, "Visible,Hidden,Hidden and Collapsed"), "set_dragger_visibility", "get_dragger_visibility");
diff --git a/scene/gui/tab_bar.cpp b/scene/gui/tab_bar.cpp
index fec8d11bef..b4c90596f9 100644
--- a/scene/gui/tab_bar.cpp
+++ b/scene/gui/tab_bar.cpp
@@ -1606,7 +1606,7 @@ void TabBar::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::INT, "tab_alignment", PROPERTY_HINT_ENUM, "Left,Center,Right"), "set_tab_alignment", "get_tab_alignment");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "clip_tabs"), "set_clip_tabs", "get_clip_tabs");
ADD_PROPERTY(PropertyInfo(Variant::INT, "tab_close_display_policy", PROPERTY_HINT_ENUM, "Show Never,Show Active Only,Show Always"), "set_tab_close_display_policy", "get_tab_close_display_policy");
- ADD_PROPERTY(PropertyInfo(Variant::INT, "max_tab_width", PROPERTY_HINT_RANGE, "0,99999,1"), "set_max_tab_width", "get_max_tab_width");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "max_tab_width", PROPERTY_HINT_RANGE, "0,99999,1,suffix:px"), "set_max_tab_width", "get_max_tab_width");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "scrolling_enabled"), "set_scrolling_enabled", "get_scrolling_enabled");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "drag_to_rearrange_enabled"), "set_drag_to_rearrange_enabled", "get_drag_to_rearrange_enabled");
ADD_PROPERTY(PropertyInfo(Variant::INT, "tabs_rearrange_group"), "set_tabs_rearrange_group", "get_tabs_rearrange_group");
diff --git a/scene/gui/text_edit.cpp b/scene/gui/text_edit.cpp
index 8e948203f1..d9a91590f7 100644
--- a/scene/gui/text_edit.cpp
+++ b/scene/gui/text_edit.cpp
@@ -5420,19 +5420,19 @@ void TextEdit::_bind_methods() {
ADD_GROUP("Scroll", "scroll_");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "scroll_smooth"), "set_smooth_scroll_enable", "is_smooth_scroll_enabled");
- ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "scroll_v_scroll_speed"), "set_v_scroll_speed", "get_v_scroll_speed");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "scroll_v_scroll_speed", PROPERTY_HINT_NONE, "suffix:px/s"), "set_v_scroll_speed", "get_v_scroll_speed");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "scroll_past_end_of_file"), "set_scroll_past_end_of_file_enabled", "is_scroll_past_end_of_file_enabled");
- ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "scroll_vertical"), "set_v_scroll", "get_v_scroll");
- ADD_PROPERTY(PropertyInfo(Variant::INT, "scroll_horizontal"), "set_h_scroll", "get_h_scroll");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "scroll_vertical", PROPERTY_HINT_NONE, "suffix:px"), "set_v_scroll", "get_v_scroll");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "scroll_horizontal", PROPERTY_HINT_NONE, "suffix:px"), "set_h_scroll", "get_h_scroll");
ADD_GROUP("Minimap", "minimap_");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "minimap_draw"), "set_draw_minimap", "is_drawing_minimap");
- ADD_PROPERTY(PropertyInfo(Variant::INT, "minimap_width"), "set_minimap_width", "get_minimap_width");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "minimap_width", PROPERTY_HINT_NONE, "suffix:px"), "set_minimap_width", "get_minimap_width");
ADD_GROUP("Caret", "caret_");
ADD_PROPERTY(PropertyInfo(Variant::INT, "caret_type", PROPERTY_HINT_ENUM, "Line,Block"), "set_caret_type", "get_caret_type");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "caret_blink"), "set_caret_blink_enabled", "is_caret_blink_enabled");
- ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "caret_blink_speed", PROPERTY_HINT_RANGE, "0.1,10,0.01"), "set_caret_blink_speed", "get_caret_blink_speed");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "caret_blink_speed", PROPERTY_HINT_RANGE, "0.1,10,0.01,suffix:s"), "set_caret_blink_speed", "get_caret_blink_speed");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "caret_move_on_right_click"), "set_move_caret_on_right_click_enabled", "is_move_caret_on_right_click_enabled");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "caret_mid_grapheme"), "set_caret_mid_grapheme_enabled", "is_caret_mid_grapheme_enabled");
diff --git a/scene/gui/texture_progress_bar.cpp b/scene/gui/texture_progress_bar.cpp
index 081d065efe..94e0a6f226 100644
--- a/scene/gui/texture_progress_bar.cpp
+++ b/scene/gui/texture_progress_bar.cpp
@@ -633,16 +633,16 @@ void TextureProgressBar::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "nine_patch_stretch"), "set_nine_patch_stretch", "get_nine_patch_stretch");
ADD_GROUP("Stretch Margin", "stretch_margin_");
- ADD_PROPERTYI(PropertyInfo(Variant::INT, "stretch_margin_left", PROPERTY_HINT_RANGE, "0,16384,1"), "set_stretch_margin", "get_stretch_margin", SIDE_LEFT);
- ADD_PROPERTYI(PropertyInfo(Variant::INT, "stretch_margin_top", PROPERTY_HINT_RANGE, "0,16384,1"), "set_stretch_margin", "get_stretch_margin", SIDE_TOP);
- ADD_PROPERTYI(PropertyInfo(Variant::INT, "stretch_margin_right", PROPERTY_HINT_RANGE, "0,16384,1"), "set_stretch_margin", "get_stretch_margin", SIDE_RIGHT);
- ADD_PROPERTYI(PropertyInfo(Variant::INT, "stretch_margin_bottom", PROPERTY_HINT_RANGE, "0,16384,1"), "set_stretch_margin", "get_stretch_margin", SIDE_BOTTOM);
+ ADD_PROPERTYI(PropertyInfo(Variant::INT, "stretch_margin_left", PROPERTY_HINT_RANGE, "0,16384,1,suffix:px"), "set_stretch_margin", "get_stretch_margin", SIDE_LEFT);
+ ADD_PROPERTYI(PropertyInfo(Variant::INT, "stretch_margin_top", PROPERTY_HINT_RANGE, "0,16384,1,suffix:px"), "set_stretch_margin", "get_stretch_margin", SIDE_TOP);
+ ADD_PROPERTYI(PropertyInfo(Variant::INT, "stretch_margin_right", PROPERTY_HINT_RANGE, "0,16384,1,suffix:px"), "set_stretch_margin", "get_stretch_margin", SIDE_RIGHT);
+ ADD_PROPERTYI(PropertyInfo(Variant::INT, "stretch_margin_bottom", PROPERTY_HINT_RANGE, "0,16384,1,suffix:px"), "set_stretch_margin", "get_stretch_margin", SIDE_BOTTOM);
ADD_GROUP("Textures", "texture_");
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "texture_under", PROPERTY_HINT_RESOURCE_TYPE, "Texture2D"), "set_under_texture", "get_under_texture");
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "texture_over", PROPERTY_HINT_RESOURCE_TYPE, "Texture2D"), "set_over_texture", "get_over_texture");
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "texture_progress", PROPERTY_HINT_RESOURCE_TYPE, "Texture2D"), "set_progress_texture", "get_progress_texture");
- ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "texture_progress_offset"), "set_texture_progress_offset", "get_texture_progress_offset");
+ ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "texture_progress_offset", PROPERTY_HINT_NONE, "suffix:px"), "set_texture_progress_offset", "get_texture_progress_offset");
ADD_GROUP("Tint", "tint_");
ADD_PROPERTY(PropertyInfo(Variant::COLOR, "tint_under"), "set_tint_under", "get_tint_under");
@@ -652,7 +652,7 @@ void TextureProgressBar::_bind_methods() {
ADD_GROUP("Radial Fill", "radial_");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "radial_initial_angle", PROPERTY_HINT_RANGE, "0.0,360.0,0.1,slider,degrees"), "set_radial_initial_angle", "get_radial_initial_angle");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "radial_fill_degrees", PROPERTY_HINT_RANGE, "0.0,360.0,0.1,slider,degrees"), "set_fill_degrees", "get_fill_degrees");
- ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "radial_center_offset"), "set_radial_center_offset", "get_radial_center_offset");
+ ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "radial_center_offset", PROPERTY_HINT_NONE, "suffix:px"), "set_radial_center_offset", "get_radial_center_offset");
BIND_ENUM_CONSTANT(FILL_LEFT_TO_RIGHT);
BIND_ENUM_CONSTANT(FILL_RIGHT_TO_LEFT);
diff --git a/scene/gui/video_stream_player.cpp b/scene/gui/video_stream_player.cpp
index 20bc9a1028..122e36904b 100644
--- a/scene/gui/video_stream_player.cpp
+++ b/scene/gui/video_stream_player.cpp
@@ -448,7 +448,7 @@ void VideoStreamPlayer::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "autoplay"), "set_autoplay", "has_autoplay");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "paused"), "set_paused", "is_paused");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "expand"), "set_expand", "has_expand");
- ADD_PROPERTY(PropertyInfo(Variant::INT, "buffering_msec", PROPERTY_HINT_RANGE, "10,1000"), "set_buffering_msec", "get_buffering_msec");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "buffering_msec", PROPERTY_HINT_RANGE, "10,1000,suffix:ms"), "set_buffering_msec", "get_buffering_msec");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "stream_position", PROPERTY_HINT_RANGE, "0,1280000,0.1", PROPERTY_USAGE_NONE), "set_stream_position", "get_stream_position");
ADD_PROPERTY(PropertyInfo(Variant::STRING_NAME, "bus", PROPERTY_HINT_ENUM, ""), "set_bus", "get_bus");
diff --git a/scene/main/canvas_layer.cpp b/scene/main/canvas_layer.cpp
index da96246de2..3a071ef542 100644
--- a/scene/main/canvas_layer.cpp
+++ b/scene/main/canvas_layer.cpp
@@ -328,10 +328,10 @@ void CanvasLayer::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::INT, "layer", PROPERTY_HINT_RANGE, "-128,128,1"), "set_layer", "get_layer");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "visible"), "set_visible", "is_visible");
ADD_GROUP("Transform", "");
- ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "offset"), "set_offset", "get_offset");
+ 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::TRANSFORM2D, "transform"), "set_transform", "get_transform");
+ 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");
ADD_GROUP("Follow Viewport", "follow_viewport");
diff --git a/scene/main/http_request.cpp b/scene/main/http_request.cpp
index 34b0e19d31..9a23bc65bf 100644
--- a/scene/main/http_request.cpp
+++ b/scene/main/http_request.cpp
@@ -607,12 +607,12 @@ void HTTPRequest::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_https_proxy", "host", "port"), &HTTPRequest::set_https_proxy);
ADD_PROPERTY(PropertyInfo(Variant::STRING, "download_file", PROPERTY_HINT_FILE), "set_download_file", "get_download_file");
- ADD_PROPERTY(PropertyInfo(Variant::INT, "download_chunk_size", PROPERTY_HINT_RANGE, "256,16777216"), "set_download_chunk_size", "get_download_chunk_size");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "download_chunk_size", PROPERTY_HINT_RANGE, "256,16777216,suffix:B"), "set_download_chunk_size", "get_download_chunk_size");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "use_threads"), "set_use_threads", "is_using_threads");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "accept_gzip"), "set_accept_gzip", "is_accepting_gzip");
- ADD_PROPERTY(PropertyInfo(Variant::INT, "body_size_limit", PROPERTY_HINT_RANGE, "-1,2000000000"), "set_body_size_limit", "get_body_size_limit");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "body_size_limit", PROPERTY_HINT_RANGE, "-1,2000000000,suffix:B"), "set_body_size_limit", "get_body_size_limit");
ADD_PROPERTY(PropertyInfo(Variant::INT, "max_redirects", PROPERTY_HINT_RANGE, "-1,64"), "set_max_redirects", "get_max_redirects");
- ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "timeout", PROPERTY_HINT_RANGE, "0,3600,0.1,or_greater"), "set_timeout", "get_timeout");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "timeout", PROPERTY_HINT_RANGE, "0,3600,0.1,or_greater,suffix:s"), "set_timeout", "get_timeout");
ADD_SIGNAL(MethodInfo("request_completed", PropertyInfo(Variant::INT, "result"), PropertyInfo(Variant::INT, "response_code"), PropertyInfo(Variant::PACKED_STRING_ARRAY, "headers"), PropertyInfo(Variant::PACKED_BYTE_ARRAY, "body")));
diff --git a/scene/main/scene_tree.cpp b/scene/main/scene_tree.cpp
index 14daf2c108..f8abda35d2 100644
--- a/scene/main/scene_tree.cpp
+++ b/scene/main/scene_tree.cpp
@@ -1373,15 +1373,15 @@ SceneTree::SceneTree() {
root->set_as_audio_listener_2d(true);
current_scene = nullptr;
- const int msaa_mode = GLOBAL_DEF("rendering/anti_aliasing/quality/msaa", 0);
+ const int msaa_mode = GLOBAL_DEF_BASIC("rendering/anti_aliasing/quality/msaa", 0);
ProjectSettings::get_singleton()->set_custom_property_info("rendering/anti_aliasing/quality/msaa", PropertyInfo(Variant::INT, "rendering/anti_aliasing/quality/msaa", PROPERTY_HINT_ENUM, String::utf8("Disabled (Fastest),2× (Average),4× (Slow),8× (Slowest)")));
root->set_msaa(Viewport::MSAA(msaa_mode));
- const int ssaa_mode = GLOBAL_DEF("rendering/anti_aliasing/quality/screen_space_aa", 0);
+ const int ssaa_mode = GLOBAL_DEF_BASIC("rendering/anti_aliasing/quality/screen_space_aa", 0);
ProjectSettings::get_singleton()->set_custom_property_info("rendering/anti_aliasing/quality/screen_space_aa", PropertyInfo(Variant::INT, "rendering/anti_aliasing/quality/screen_space_aa", PROPERTY_HINT_ENUM, "Disabled (Fastest),FXAA (Fast)"));
root->set_screen_space_aa(Viewport::ScreenSpaceAA(ssaa_mode));
- const bool use_taa = GLOBAL_DEF("rendering/anti_aliasing/quality/use_taa", false);
+ const bool use_taa = GLOBAL_DEF_BASIC("rendering/anti_aliasing/quality/use_taa", false);
root->set_use_taa(use_taa);
const bool use_debanding = GLOBAL_DEF("rendering/anti_aliasing/quality/use_debanding", false);
diff --git a/scene/main/viewport.cpp b/scene/main/viewport.cpp
index 0e00e51181..1ad011f867 100644
--- a/scene/main/viewport.cpp
+++ b/scene/main/viewport.cpp
@@ -4049,8 +4049,8 @@ void SubViewport::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_clear_mode", "mode"), &SubViewport::set_clear_mode);
ClassDB::bind_method(D_METHOD("get_clear_mode"), &SubViewport::get_clear_mode);
- ADD_PROPERTY(PropertyInfo(Variant::VECTOR2I, "size"), "set_size", "get_size");
- ADD_PROPERTY(PropertyInfo(Variant::VECTOR2I, "size_2d_override"), "set_size_2d_override", "get_size_2d_override");
+ ADD_PROPERTY(PropertyInfo(Variant::VECTOR2I, "size", PROPERTY_HINT_NONE, "suffix:px"), "set_size", "get_size");
+ ADD_PROPERTY(PropertyInfo(Variant::VECTOR2I, "size_2d_override", PROPERTY_HINT_NONE, "suffix:px"), "set_size_2d_override", "get_size_2d_override");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "size_2d_override_stretch"), "set_size_2d_override_stretch", "is_size_2d_override_stretch_enabled");
ADD_GROUP("Render Target", "render_target_");
ADD_PROPERTY(PropertyInfo(Variant::INT, "render_target_clear_mode", PROPERTY_HINT_ENUM, "Always,Never,Next Frame"), "set_clear_mode", "get_clear_mode");
diff --git a/scene/main/window.cpp b/scene/main/window.cpp
index 9b347ed7c8..1d697a2176 100644
--- a/scene/main/window.cpp
+++ b/scene/main/window.cpp
@@ -165,14 +165,26 @@ void Window::set_flag(Flags p_flag, bool p_enabled) {
embedder->_sub_window_update(this);
} else if (window_id != DisplayServer::INVALID_WINDOW_ID) {
+#ifdef TOOLS_ENABLED
+ if ((p_flag != FLAG_POPUP) || !(Engine::get_singleton()->is_editor_hint() && get_tree()->get_edited_scene_root() && get_tree()->get_edited_scene_root()->is_ancestor_of(this))) {
+ DisplayServer::get_singleton()->window_set_flag(DisplayServer::WindowFlags(p_flag), p_enabled, window_id);
+ }
+#else
DisplayServer::get_singleton()->window_set_flag(DisplayServer::WindowFlags(p_flag), p_enabled, window_id);
+#endif
}
}
bool Window::get_flag(Flags p_flag) const {
ERR_FAIL_INDEX_V(p_flag, FLAG_MAX, false);
if (window_id != DisplayServer::INVALID_WINDOW_ID) {
+#ifdef TOOLS_ENABLED
+ if ((p_flag != FLAG_POPUP) || !(Engine::get_singleton()->is_editor_hint() && get_tree()->get_edited_scene_root() && get_tree()->get_edited_scene_root()->is_ancestor_of(this))) {
+ flags[p_flag] = DisplayServer::get_singleton()->window_get_flag(DisplayServer::WindowFlags(p_flag), window_id);
+ }
+#else
flags[p_flag] = DisplayServer::get_singleton()->window_get_flag(DisplayServer::WindowFlags(p_flag), window_id);
+#endif
}
return flags[p_flag];
}
@@ -255,7 +267,15 @@ void Window::_make_window() {
#endif
DisplayServer::get_singleton()->window_set_title(tr_title, window_id);
DisplayServer::get_singleton()->window_attach_instance_id(get_instance_id(), window_id);
+#ifdef TOOLS_ENABLED
+ if (!(Engine::get_singleton()->is_editor_hint() && get_tree()->get_edited_scene_root() && get_tree()->get_edited_scene_root()->is_ancestor_of(this))) {
+ DisplayServer::get_singleton()->window_set_exclusive(window_id, exclusive);
+ } else {
+ DisplayServer::get_singleton()->window_set_exclusive(window_id, false);
+ }
+#else
DisplayServer::get_singleton()->window_set_exclusive(window_id, exclusive);
+#endif
_update_window_size();
@@ -441,6 +461,8 @@ void Window::set_visible(bool p_visible) {
ERR_FAIL_COND_MSG(transient_parent->exclusive_child && transient_parent->exclusive_child != this, "Transient parent has another exclusive child.");
transient_parent->exclusive_child = this;
}
+#else
+ transient_parent->exclusive_child = this;
#endif
} else {
if (transient_parent->exclusive_child == this) {
@@ -488,7 +510,13 @@ void Window::_make_transient() {
window->transient_children.insert(this);
if (is_inside_tree() && is_visible() && exclusive) {
if (transient_parent->exclusive_child == nullptr) {
+#ifdef TOOLS_ENABLED
+ if (!(Engine::get_singleton()->is_editor_hint() && get_tree()->get_edited_scene_root() && get_tree()->get_edited_scene_root()->is_ancestor_of(this))) {
+ transient_parent->exclusive_child = this;
+ }
+#else
transient_parent->exclusive_child = this;
+#endif
} else if (transient_parent->exclusive_child != this) {
ERR_PRINT("Making child transient exclusive, but parent has another exclusive child");
}
@@ -531,13 +559,27 @@ void Window::set_exclusive(bool p_exclusive) {
exclusive = p_exclusive;
if (!embedder && window_id != DisplayServer::INVALID_WINDOW_ID) {
+#ifdef TOOLS_ENABLED
+ if (!(Engine::get_singleton()->is_editor_hint() && get_tree()->get_edited_scene_root() && get_tree()->get_edited_scene_root()->is_ancestor_of(this))) {
+ DisplayServer::get_singleton()->window_set_exclusive(window_id, exclusive);
+ } else {
+ DisplayServer::get_singleton()->window_set_exclusive(window_id, false);
+ }
+#else
DisplayServer::get_singleton()->window_set_exclusive(window_id, exclusive);
+#endif
}
if (transient_parent) {
if (p_exclusive && is_inside_tree() && is_visible()) {
ERR_FAIL_COND_MSG(transient_parent->exclusive_child && transient_parent->exclusive_child != this, "Transient parent has another exclusive child.");
+#ifdef TOOLS_ENABLED
+ if (!(Engine::get_singleton()->is_editor_hint() && get_tree()->get_edited_scene_root() && get_tree()->get_edited_scene_root()->is_ancestor_of(this))) {
+ transient_parent->exclusive_child = this;
+ }
+#else
transient_parent->exclusive_child = this;
+#endif
} else {
if (transient_parent->exclusive_child == this) {
transient_parent->exclusive_child = nullptr;
@@ -1591,8 +1633,8 @@ void Window::_bind_methods() {
ClassDB::bind_method(D_METHOD("popup_centered_clamped", "minsize", "fallback_ratio"), &Window::popup_centered_clamped, DEFVAL(Size2i()), DEFVAL(0.75));
ADD_PROPERTY(PropertyInfo(Variant::STRING, "title"), "set_title", "get_title");
- ADD_PROPERTY(PropertyInfo(Variant::VECTOR2I, "position"), "set_position", "get_position");
- ADD_PROPERTY(PropertyInfo(Variant::VECTOR2I, "size"), "set_size", "get_size");
+ ADD_PROPERTY(PropertyInfo(Variant::VECTOR2I, "position", PROPERTY_HINT_NONE, "suffix:px"), "set_position", "get_position");
+ ADD_PROPERTY(PropertyInfo(Variant::VECTOR2I, "size", PROPERTY_HINT_NONE, "suffix:px"), "set_size", "get_size");
ADD_PROPERTY(PropertyInfo(Variant::INT, "mode", PROPERTY_HINT_ENUM, "Windowed,Minimized,Maximized,Fullscreen"), "set_mode", "get_mode");
ADD_PROPERTY(PropertyInfo(Variant::INT, "current_screen"), "set_current_screen", "get_current_screen");
@@ -1609,8 +1651,8 @@ void Window::_bind_methods() {
ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "popup_window"), "set_flag", "get_flag", FLAG_POPUP);
ADD_GROUP("Limits", "");
- ADD_PROPERTY(PropertyInfo(Variant::VECTOR2I, "min_size"), "set_min_size", "get_min_size");
- ADD_PROPERTY(PropertyInfo(Variant::VECTOR2I, "max_size"), "set_max_size", "get_max_size");
+ ADD_PROPERTY(PropertyInfo(Variant::VECTOR2I, "min_size", PROPERTY_HINT_NONE, "suffix:px"), "set_min_size", "get_min_size");
+ ADD_PROPERTY(PropertyInfo(Variant::VECTOR2I, "max_size", PROPERTY_HINT_NONE, "suffix:px"), "set_max_size", "get_max_size");
ADD_GROUP("Content Scale", "content_scale_");
ADD_PROPERTY(PropertyInfo(Variant::VECTOR2I, "content_scale_size"), "set_content_scale_size", "get_content_scale_size");
diff --git a/scene/multiplayer/multiplayer_synchronizer.cpp b/scene/multiplayer/multiplayer_synchronizer.cpp
index 78cec9ee10..68f6e54fa8 100644
--- a/scene/multiplayer/multiplayer_synchronizer.cpp
+++ b/scene/multiplayer/multiplayer_synchronizer.cpp
@@ -88,14 +88,15 @@ Error MultiplayerSynchronizer::set_state(const List<NodePath> &p_properties, Obj
void MultiplayerSynchronizer::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_root_path", "path"), &MultiplayerSynchronizer::set_root_path);
ClassDB::bind_method(D_METHOD("get_root_path"), &MultiplayerSynchronizer::get_root_path);
- ADD_PROPERTY(PropertyInfo(Variant::NODE_PATH, "root_path"), "set_root_path", "get_root_path");
ClassDB::bind_method(D_METHOD("set_replication_interval", "milliseconds"), &MultiplayerSynchronizer::set_replication_interval);
ClassDB::bind_method(D_METHOD("get_replication_interval"), &MultiplayerSynchronizer::get_replication_interval);
- ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "replication_interval", PROPERTY_HINT_RANGE, "0,5,0.001"), "set_replication_interval", "get_replication_interval");
ClassDB::bind_method(D_METHOD("set_replication_config", "config"), &MultiplayerSynchronizer::set_replication_config);
ClassDB::bind_method(D_METHOD("get_replication_config"), &MultiplayerSynchronizer::get_replication_config);
+
+ ADD_PROPERTY(PropertyInfo(Variant::NODE_PATH, "root_path"), "set_root_path", "get_root_path");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "replication_interval", PROPERTY_HINT_RANGE, "0,5,0.001,suffix:s"), "set_replication_interval", "get_replication_interval");
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "replication_config", PROPERTY_HINT_RESOURCE_TYPE, "SceneReplicationConfig"), "set_replication_config", "get_replication_config");
}
diff --git a/scene/resources/animation.cpp b/scene/resources/animation.cpp
index dbbbb72a49..8ae4872d14 100644
--- a/scene/resources/animation.cpp
+++ b/scene/resources/animation.cpp
@@ -3829,7 +3829,7 @@ void Animation::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "length", PROPERTY_HINT_RANGE, "0.001,99999,0.001,suffix:s"), "set_length", "get_length");
ADD_PROPERTY(PropertyInfo(Variant::INT, "loop_mode", PROPERTY_HINT_ENUM, "None,Linear,Ping-Pong"), "set_loop_mode", "get_loop_mode");
- ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "step", PROPERTY_HINT_RANGE, "0,4096,0.001"), "set_step", "get_step");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "step", PROPERTY_HINT_RANGE, "0,4096,0.001,suffix:s"), "set_step", "get_step");
ADD_SIGNAL(MethodInfo("tracks_changed"));
diff --git a/scene/resources/animation_library.cpp b/scene/resources/animation_library.cpp
index 361bfd0cb3..5f725b2fbe 100644
--- a/scene/resources/animation_library.cpp
+++ b/scene/resources/animation_library.cpp
@@ -143,9 +143,9 @@ void AnimationLibrary::_bind_methods() {
ClassDB::bind_method(D_METHOD("_get_data"), &AnimationLibrary::_get_data);
ADD_PROPERTY(PropertyInfo(Variant::DICTIONARY, "_data", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR), "_set_data", "_get_data");
- ADD_SIGNAL(MethodInfo("animation_added", PropertyInfo(Variant::OBJECT, "name", PROPERTY_HINT_RESOURCE_TYPE, "Animation")));
- ADD_SIGNAL(MethodInfo("animation_removed", PropertyInfo(Variant::OBJECT, "name", PROPERTY_HINT_RESOURCE_TYPE, "Animation")));
- ADD_SIGNAL(MethodInfo("animation_renamed", PropertyInfo(Variant::OBJECT, "name", PROPERTY_HINT_RESOURCE_TYPE, "Animation"), PropertyInfo(Variant::OBJECT, "to_name", PROPERTY_HINT_RESOURCE_TYPE, "Animation")));
+ ADD_SIGNAL(MethodInfo("animation_added", PropertyInfo(Variant::STRING_NAME, "name")));
+ ADD_SIGNAL(MethodInfo("animation_removed", PropertyInfo(Variant::STRING_NAME, "name")));
+ ADD_SIGNAL(MethodInfo("animation_renamed", PropertyInfo(Variant::STRING_NAME, "name"), PropertyInfo(Variant::STRING_NAME, "to_name")));
}
AnimationLibrary::AnimationLibrary() {
}
diff --git a/scene/resources/environment.cpp b/scene/resources/environment.cpp
index f6ffc8db53..854bd34d6a 100644
--- a/scene/resources/environment.cpp
+++ b/scene/resources/environment.cpp
@@ -1298,7 +1298,7 @@ void Environment::_bind_methods() {
ADD_GROUP("SSIL", "ssil_");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "ssil_enabled"), "set_ssil_enabled", "is_ssil_enabled");
- ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "ssil_radius", PROPERTY_HINT_RANGE, "0.01,16,0.01,or_greater"), "set_ssil_radius", "get_ssil_radius");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "ssil_radius", PROPERTY_HINT_RANGE, "0.01,16,0.01,or_greater,suffix:m"), "set_ssil_radius", "get_ssil_radius");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "ssil_intensity", PROPERTY_HINT_RANGE, "0,16,0.01,or_greater"), "set_ssil_intensity", "get_ssil_intensity");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "ssil_sharpness", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_ssil_sharpness", "get_ssil_sharpness");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "ssil_normal_rejection", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_ssil_normal_rejection", "get_ssil_normal_rejection");
@@ -1425,7 +1425,7 @@ void Environment::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "fog_density", PROPERTY_HINT_RANGE, "0,16,0.0001"), "set_fog_density", "get_fog_density");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "fog_aerial_perspective", PROPERTY_HINT_RANGE, "0,1,0.001"), "set_fog_aerial_perspective", "get_fog_aerial_perspective");
- ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "fog_height", PROPERTY_HINT_RANGE, "-1024,1024,0.01,or_lesser,or_greater"), "set_fog_height", "get_fog_height");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "fog_height", PROPERTY_HINT_RANGE, "-1024,1024,0.01,or_lesser,or_greater,suffix:m"), "set_fog_height", "get_fog_height");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "fog_height_density", PROPERTY_HINT_RANGE, "-16,16,0.0001,or_lesser,or_greater"), "set_fog_height_density", "get_fog_height_density");
ClassDB::bind_method(D_METHOD("set_volumetric_fog_enabled", "enabled"), &Environment::set_volumetric_fog_enabled);
diff --git a/scene/resources/font.cpp b/scene/resources/font.cpp
index d586abac14..8a353f4b49 100644
--- a/scene/resources/font.cpp
+++ b/scene/resources/font.cpp
@@ -54,6 +54,7 @@ _FORCE_INLINE_ void FontData::_ensure_rid(int p_cache_index) const {
if (unlikely(!cache[p_cache_index].is_valid())) {
cache.write[p_cache_index] = TS->create_font();
TS->font_set_data_ptr(cache[p_cache_index], data_ptr, data_size);
+ TS->font_set_face_index(cache[p_cache_index], face_index);
TS->font_set_antialiased(cache[p_cache_index], antialiased);
TS->font_set_generate_mipmaps(cache[p_cache_index], mipmaps);
TS->font_set_multichannel_signed_distance_field(cache[p_cache_index], msdf);
@@ -76,6 +77,11 @@ void FontData::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_data", "data"), &FontData::set_data);
ClassDB::bind_method(D_METHOD("get_data"), &FontData::get_data);
+ ClassDB::bind_method(D_METHOD("set_face_index", "face_index"), &FontData::set_face_index);
+ ClassDB::bind_method(D_METHOD("get_face_index"), &FontData::get_face_index);
+
+ ClassDB::bind_method(D_METHOD("get_face_count"), &FontData::get_face_count);
+
ClassDB::bind_method(D_METHOD("set_antialiased", "antialiased"), &FontData::set_antialiased);
ClassDB::bind_method(D_METHOD("is_antialiased"), &FontData::is_antialiased);
@@ -217,6 +223,7 @@ void FontData::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_supported_variation_list"), &FontData::get_supported_variation_list);
ADD_PROPERTY(PropertyInfo(Variant::PACKED_BYTE_ARRAY, "data", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_STORAGE), "set_data", "get_data");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "face_index", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_STORAGE), "set_face_index", "get_face_index");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "generate_mipmaps", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_STORAGE), "set_generate_mipmaps", "get_generate_mipmaps");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "antialiased", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_STORAGE), "set_antialiased", "is_antialiased");
ADD_PROPERTY(PropertyInfo(Variant::STRING, "font_name", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_STORAGE), "set_font_name", "get_font_name");
@@ -445,6 +452,7 @@ void FontData::reset_state() {
data.clear();
data_ptr = nullptr;
data_size = 0;
+ face_index = 0;
cache.clear();
antialiased = true;
@@ -1244,6 +1252,31 @@ void FontData::set_data(const PackedByteArray &p_data) {
}
}
+void FontData::set_face_index(int64_t p_index) {
+ ERR_FAIL_COND(p_index < 0);
+ ERR_FAIL_COND(p_index >= 0x7FFF);
+
+ if (face_index != p_index) {
+ face_index = p_index;
+ if (data_ptr != nullptr) {
+ for (int i = 0; i < cache.size(); i++) {
+ if (cache[i].is_valid()) {
+ TS->font_set_face_index(cache[i], face_index);
+ }
+ }
+ }
+ }
+}
+
+int64_t FontData::get_face_index() const {
+ return face_index;
+}
+
+int64_t FontData::get_face_count() const {
+ _ensure_rid(0);
+ return TS->font_get_face_count(cache[0]);
+}
+
PackedByteArray FontData::get_data() const {
if (unlikely((size_t)data.size() != data_size)) {
PackedByteArray *data_w = const_cast<PackedByteArray *>(&data);
@@ -1923,8 +1956,8 @@ void Font::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_spacing", "spacing"), &Font::get_spacing);
ADD_GROUP("Extra Spacing", "spacing");
- ADD_PROPERTYI(PropertyInfo(Variant::INT, "spacing_top"), "set_spacing", "get_spacing", TextServer::SPACING_TOP);
- ADD_PROPERTYI(PropertyInfo(Variant::INT, "spacing_bottom"), "set_spacing", "get_spacing", TextServer::SPACING_BOTTOM);
+ ADD_PROPERTYI(PropertyInfo(Variant::INT, "spacing_top", PROPERTY_HINT_NONE, "suffix:px"), "set_spacing", "get_spacing", TextServer::SPACING_TOP);
+ ADD_PROPERTYI(PropertyInfo(Variant::INT, "spacing_bottom", PROPERTY_HINT_NONE, "suffix:px"), "set_spacing", "get_spacing", TextServer::SPACING_BOTTOM);
ClassDB::bind_method(D_METHOD("get_height", "size"), &Font::get_height, DEFVAL(DEFAULT_FONT_SIZE));
ClassDB::bind_method(D_METHOD("get_ascent", "size"), &Font::get_ascent, DEFVAL(DEFAULT_FONT_SIZE));
diff --git a/scene/resources/font.h b/scene/resources/font.h
index 96bfe3678b..950959e054 100644
--- a/scene/resources/font.h
+++ b/scene/resources/font.h
@@ -46,6 +46,7 @@ class FontData : public Resource {
// Font source data.
const uint8_t *data_ptr = nullptr;
size_t data_size = 0;
+ int face_index = 0;
PackedByteArray data;
bool antialiased = true;
@@ -91,6 +92,11 @@ public:
virtual void set_data(const PackedByteArray &p_data);
virtual PackedByteArray get_data() const;
+ virtual void set_face_index(int64_t p_index);
+ virtual int64_t get_face_index() const;
+
+ virtual int64_t get_face_count() const;
+
// Common properties.
virtual void set_font_name(const String &p_name);
virtual String get_font_name() const;
diff --git a/scene/resources/material.cpp b/scene/resources/material.cpp
index 997a45cce5..fc207d358e 100644
--- a/scene/resources/material.cpp
+++ b/scene/resources/material.cpp
@@ -472,24 +472,33 @@ void BaseMaterial3D::_update_shader() {
}
String texfilter_str;
+ // Force linear filtering for the heightmap texture, as the heightmap effect
+ // looks broken with nearest-neighbor filtering (with and without Deep Parallax).
+ String texfilter_height_str;
switch (texture_filter) {
case TEXTURE_FILTER_NEAREST:
texfilter_str = "filter_nearest";
+ texfilter_height_str = "filter_linear";
break;
case TEXTURE_FILTER_LINEAR:
texfilter_str = "filter_linear";
+ texfilter_height_str = "filter_linear";
break;
case TEXTURE_FILTER_NEAREST_WITH_MIPMAPS:
texfilter_str = "filter_nearest_mipmap";
+ texfilter_height_str = "filter_linear_mipmap";
break;
case TEXTURE_FILTER_LINEAR_WITH_MIPMAPS:
texfilter_str = "filter_linear_mipmap";
+ texfilter_height_str = "filter_linear_mipmap";
break;
case TEXTURE_FILTER_NEAREST_WITH_MIPMAPS_ANISOTROPIC:
texfilter_str = "filter_nearest_mipmap_anisotropic";
+ texfilter_height_str = "filter_linear_mipmap_anisotropic";
break;
case TEXTURE_FILTER_LINEAR_WITH_MIPMAPS_ANISOTROPIC:
texfilter_str = "filter_linear_mipmap_anisotropic";
+ texfilter_height_str = "filter_linear_mipmap_anisotropic";
break;
case TEXTURE_FILTER_MAX:
break; // Internal value, skip.
@@ -497,8 +506,10 @@ void BaseMaterial3D::_update_shader() {
if (flags[FLAG_USE_TEXTURE_REPEAT]) {
texfilter_str += ",repeat_enable";
+ texfilter_height_str += ",repeat_enable";
} else {
texfilter_str += ",repeat_disable";
+ texfilter_height_str += ",repeat_disable";
}
//must create a shader!
@@ -763,7 +774,7 @@ void BaseMaterial3D::_update_shader() {
}
if (features[FEATURE_HEIGHT_MAPPING]) {
- code += "uniform sampler2D texture_heightmap : hint_default_black," + texfilter_str + ";\n";
+ code += "uniform sampler2D texture_heightmap : hint_default_black," + texfilter_height_str + ";\n";
code += "uniform float heightmap_scale;\n";
code += "uniform int heightmap_min_layers;\n";
code += "uniform int heightmap_max_layers;\n";
@@ -2655,14 +2666,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");
@@ -2687,22 +2698,22 @@ void BaseMaterial3D::_bind_methods() {
ADD_GROUP("Grow", "grow_");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "grow"), "set_grow_enabled", "is_grow_enabled");
- ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "grow_amount", PROPERTY_HINT_RANGE, "-16,16,0.001"), "set_grow", "get_grow");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "grow_amount", PROPERTY_HINT_RANGE, "-16,16,0.001,suffix:m"), "set_grow", "get_grow");
ADD_GROUP("Transform", "");
ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "fixed_size"), "set_flag", "get_flag", FLAG_FIXED_SIZE);
ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "use_point_size"), "set_flag", "get_flag", FLAG_USE_POINT_SIZE);
- ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "point_size", PROPERTY_HINT_RANGE, "0.1,128,0.1"), "set_point_size", "get_point_size");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "point_size", PROPERTY_HINT_RANGE, "0.1,128,0.1,suffix:px"), "set_point_size", "get_point_size");
ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "use_particle_trails"), "set_flag", "get_flag", FLAG_PARTICLE_TRAILS_MODE);
ADD_GROUP("Proximity Fade", "proximity_fade_");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "proximity_fade_enable"), "set_proximity_fade", "is_proximity_fade_enabled");
- ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "proximity_fade_distance", PROPERTY_HINT_RANGE, "0,4096,0.01"), "set_proximity_fade_distance", "get_proximity_fade_distance");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "proximity_fade_distance", PROPERTY_HINT_RANGE, "0,4096,0.01,suffix:m"), "set_proximity_fade_distance", "get_proximity_fade_distance");
ADD_GROUP("MSDF", "msdf_");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "msdf_pixel_range", PROPERTY_HINT_RANGE, "1,100,1"), "set_msdf_pixel_range", "get_msdf_pixel_range");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "msdf_outline_size", PROPERTY_HINT_RANGE, "1,250,1"), "set_msdf_outline_size", "get_msdf_outline_size");
ADD_GROUP("Distance Fade", "distance_fade_");
ADD_PROPERTY(PropertyInfo(Variant::INT, "distance_fade_mode", PROPERTY_HINT_ENUM, "Disabled,PixelAlpha,PixelDither,ObjectDither"), "set_distance_fade", "get_distance_fade");
- ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "distance_fade_min_distance", PROPERTY_HINT_RANGE, "0,4096,0.01"), "set_distance_fade_min_distance", "get_distance_fade_min_distance");
- ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "distance_fade_max_distance", PROPERTY_HINT_RANGE, "0,4096,0.01"), "set_distance_fade_max_distance", "get_distance_fade_max_distance");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "distance_fade_min_distance", PROPERTY_HINT_RANGE, "0,4096,0.01,suffix:m"), "set_distance_fade_min_distance", "get_distance_fade_min_distance");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "distance_fade_max_distance", PROPERTY_HINT_RANGE, "0,4096,0.01,suffix:m"), "set_distance_fade_max_distance", "get_distance_fade_max_distance");
BIND_ENUM_CONSTANT(TEXTURE_ALBEDO);
BIND_ENUM_CONSTANT(TEXTURE_METALLIC);
diff --git a/scene/resources/mesh.cpp b/scene/resources/mesh.cpp
index 5c34c7cafa..b8c83ac89e 100644
--- a/scene/resources/mesh.cpp
+++ b/scene/resources/mesh.cpp
@@ -2096,7 +2096,7 @@ void ArrayMesh::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::PACKED_STRING_ARRAY, "_blend_shape_names", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR | PROPERTY_USAGE_INTERNAL), "_set_blend_shape_names", "_get_blend_shape_names");
ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "_surfaces", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR | PROPERTY_USAGE_INTERNAL), "_set_surfaces", "_get_surfaces");
ADD_PROPERTY(PropertyInfo(Variant::INT, "blend_shape_mode", PROPERTY_HINT_ENUM, "Normalized,Relative"), "set_blend_shape_mode", "get_blend_shape_mode");
- ADD_PROPERTY(PropertyInfo(Variant::AABB, "custom_aabb", PROPERTY_HINT_NONE, ""), "set_custom_aabb", "get_custom_aabb");
+ ADD_PROPERTY(PropertyInfo(Variant::AABB, "custom_aabb", PROPERTY_HINT_NONE, "suffix:m"), "set_custom_aabb", "get_custom_aabb");
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "shadow_mesh", PROPERTY_HINT_RESOURCE_TYPE, "ArrayMesh"), "set_shadow_mesh", "get_shadow_mesh");
}
@@ -2125,7 +2125,7 @@ ArrayMesh::~ArrayMesh() {
void PlaceholderMesh::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_aabb", "aabb"), &PlaceholderMesh::set_aabb);
- ADD_PROPERTY(PropertyInfo(Variant::AABB, "aabb", PROPERTY_HINT_NONE, ""), "set_aabb", "get_aabb");
+ ADD_PROPERTY(PropertyInfo(Variant::AABB, "aabb", PROPERTY_HINT_NONE, "suffix:m"), "set_aabb", "get_aabb");
}
PlaceholderMesh::PlaceholderMesh() {
diff --git a/scene/resources/mesh_library.cpp b/scene/resources/mesh_library.cpp
index a90999bf07..c8bfb73b2d 100644
--- a/scene/resources/mesh_library.cpp
+++ b/scene/resources/mesh_library.cpp
@@ -103,10 +103,10 @@ void MeshLibrary::_get_property_list(List<PropertyInfo> *p_list) const {
String name = vformat("%s/%d/", PNAME("item"), E.key);
p_list->push_back(PropertyInfo(Variant::STRING, name + PNAME("name")));
p_list->push_back(PropertyInfo(Variant::OBJECT, name + PNAME("mesh"), PROPERTY_HINT_RESOURCE_TYPE, "Mesh"));
- p_list->push_back(PropertyInfo(Variant::TRANSFORM3D, name + PNAME("mesh_transform")));
+ p_list->push_back(PropertyInfo(Variant::TRANSFORM3D, name + PNAME("mesh_transform"), PROPERTY_HINT_NONE, "suffix:m"));
p_list->push_back(PropertyInfo(Variant::ARRAY, name + PNAME("shapes")));
p_list->push_back(PropertyInfo(Variant::OBJECT, name + PNAME("navmesh"), PROPERTY_HINT_RESOURCE_TYPE, "NavigationMesh"));
- p_list->push_back(PropertyInfo(Variant::TRANSFORM3D, name + PNAME("navmesh_transform")));
+ p_list->push_back(PropertyInfo(Variant::TRANSFORM3D, name + PNAME("navmesh_transform"), PROPERTY_HINT_NONE, "suffix:m"));
p_list->push_back(PropertyInfo(Variant::OBJECT, name + PNAME("preview"), PROPERTY_HINT_RESOURCE_TYPE, "Texture2D", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_EDITOR_HELPER));
}
}
diff --git a/scene/resources/navigation_mesh.cpp b/scene/resources/navigation_mesh.cpp
index 7f5ce1eb6b..784ecc3a4d 100644
--- a/scene/resources/navigation_mesh.cpp
+++ b/scene/resources/navigation_mesh.cpp
@@ -491,27 +491,27 @@ void NavigationMesh::_bind_methods() {
ADD_GROUP("Geometry", "geometry_");
ADD_PROPERTY(PropertyInfo(Variant::INT, "geometry_parsed_geometry_type", PROPERTY_HINT_ENUM, "Mesh Instances,Static Colliders,Both"), "set_parsed_geometry_type", "get_parsed_geometry_type");
ADD_PROPERTY(PropertyInfo(Variant::INT, "geometry_collision_mask", PROPERTY_HINT_LAYERS_3D_PHYSICS), "set_collision_mask", "get_collision_mask");
- ADD_PROPERTY(PropertyInfo(Variant::INT, "geometry_source_geometry_mode", PROPERTY_HINT_ENUM, "Navmesh Children, Group With Children, Group Explicit"), "set_source_geometry_mode", "get_source_geometry_mode");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "geometry_source_geometry_mode", PROPERTY_HINT_ENUM, "NavMesh Children, Group With Children, Group Explicit"), "set_source_geometry_mode", "get_source_geometry_mode");
ADD_PROPERTY(PropertyInfo(Variant::STRING, "geometry_source_group_name"), "set_source_group_name", "get_source_group_name");
ADD_GROUP("Cells", "cell_");
- ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "cell_size", PROPERTY_HINT_RANGE, "0.01,500.0,0.01,or_greater"), "set_cell_size", "get_cell_size");
- ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "cell_height", PROPERTY_HINT_RANGE, "0.01,500.0,0.01,or_greater"), "set_cell_height", "get_cell_height");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "cell_size", PROPERTY_HINT_RANGE, "0.01,500.0,0.01,or_greater,suffix:m"), "set_cell_size", "get_cell_size");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "cell_height", PROPERTY_HINT_RANGE, "0.01,500.0,0.01,or_greater,suffix:m"), "set_cell_height", "get_cell_height");
ADD_GROUP("Agents", "agent_");
- ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "agent_height", PROPERTY_HINT_RANGE, "0.0,500.0,0.01,or_greater"), "set_agent_height", "get_agent_height");
- ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "agent_radius", PROPERTY_HINT_RANGE, "0.0,500.0,0.01,or_greater"), "set_agent_radius", "get_agent_radius");
- ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "agent_max_climb", PROPERTY_HINT_RANGE, "0.0,500.0,0.01,or_greater"), "set_agent_max_climb", "get_agent_max_climb");
- ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "agent_max_slope", PROPERTY_HINT_RANGE, "0.02,90.0,0.01"), "set_agent_max_slope", "get_agent_max_slope");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "agent_height", PROPERTY_HINT_RANGE, "0.0,500.0,0.01,or_greater,suffix:m"), "set_agent_height", "get_agent_height");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "agent_radius", PROPERTY_HINT_RANGE, "0.0,500.0,0.01,or_greater,suffix:m"), "set_agent_radius", "get_agent_radius");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "agent_max_climb", PROPERTY_HINT_RANGE, "0.0,500.0,0.01,or_greater,suffix:m"), "set_agent_max_climb", "get_agent_max_climb");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "agent_max_slope", PROPERTY_HINT_RANGE, "0.02,90.0,0.01,degrees"), "set_agent_max_slope", "get_agent_max_slope");
ADD_GROUP("Regions", "region_");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "region_min_size", PROPERTY_HINT_RANGE, "0.0,150.0,0.01,or_greater"), "set_region_min_size", "get_region_min_size");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "region_merge_size", PROPERTY_HINT_RANGE, "0.0,150.0,0.01,or_greater"), "set_region_merge_size", "get_region_merge_size");
ADD_GROUP("Edges", "edge_");
- ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "edge_max_length", PROPERTY_HINT_RANGE, "0.0,50.0,0.01,or_greater"), "set_edge_max_length", "get_edge_max_length");
- ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "edge_max_error", PROPERTY_HINT_RANGE, "0.1,3.0,0.01,or_greater"), "set_edge_max_error", "get_edge_max_error");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "edge_max_length", PROPERTY_HINT_RANGE, "0.0,50.0,0.01,or_greater,suffix:m"), "set_edge_max_length", "get_edge_max_length");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "edge_max_error", PROPERTY_HINT_RANGE, "0.1,3.0,0.01,or_greater,suffix:m"), "set_edge_max_error", "get_edge_max_error");
ADD_GROUP("Polygons", "polygon_");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "polygon_verts_per_poly", PROPERTY_HINT_RANGE, "3.0,12.0,1.0,or_greater"), "set_verts_per_poly", "get_verts_per_poly");
ADD_GROUP("Details", "detail_");
- ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "detail_sample_distance", PROPERTY_HINT_RANGE, "0.1,16.0,0.01,or_greater"), "set_detail_sample_distance", "get_detail_sample_distance");
- ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "detail_sample_max_error", PROPERTY_HINT_RANGE, "0.0,16.0,0.01,or_greater"), "set_detail_sample_max_error", "get_detail_sample_max_error");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "detail_sample_distance", PROPERTY_HINT_RANGE, "0.1,16.0,0.01,or_greater,suffix:m"), "set_detail_sample_distance", "get_detail_sample_distance");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "detail_sample_max_error", PROPERTY_HINT_RANGE, "0.0,16.0,0.01,or_greater,suffix:m"), "set_detail_sample_max_error", "get_detail_sample_max_error");
ADD_GROUP("Filters", "filter_");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "filter_low_hanging_obstacles"), "set_filter_low_hanging_obstacles", "get_filter_low_hanging_obstacles");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "filter_ledge_spans"), "set_filter_ledge_spans", "get_filter_ledge_spans");
diff --git a/scene/resources/primitive_meshes.cpp b/scene/resources/primitive_meshes.cpp
index f5ab0085f1..f8fb51ae42 100644
--- a/scene/resources/primitive_meshes.cpp
+++ b/scene/resources/primitive_meshes.cpp
@@ -219,7 +219,7 @@ void PrimitiveMesh::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_flip_faces"), &PrimitiveMesh::get_flip_faces);
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "material", PROPERTY_HINT_RESOURCE_TYPE, "BaseMaterial3D,ShaderMaterial"), "set_material", "get_material");
- ADD_PROPERTY(PropertyInfo(Variant::AABB, "custom_aabb", PROPERTY_HINT_NONE, ""), "set_custom_aabb", "get_custom_aabb");
+ ADD_PROPERTY(PropertyInfo(Variant::AABB, "custom_aabb", PROPERTY_HINT_NONE, "suffix:m"), "set_custom_aabb", "get_custom_aabb");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "flip_faces"), "set_flip_faces", "get_flip_faces");
GDVIRTUAL_BIND(_create_mesh_array);
@@ -1056,7 +1056,7 @@ void PlaneMesh::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "size", PROPERTY_HINT_NONE, "suffix:m"), "set_size", "get_size");
ADD_PROPERTY(PropertyInfo(Variant::INT, "subdivide_width", PROPERTY_HINT_RANGE, "0,100,1,or_greater"), "set_subdivide_width", "get_subdivide_width");
ADD_PROPERTY(PropertyInfo(Variant::INT, "subdivide_depth", PROPERTY_HINT_RANGE, "0,100,1,or_greater"), "set_subdivide_depth", "get_subdivide_depth");
- ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "center_offset"), "set_center_offset", "get_center_offset");
+ ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "center_offset", PROPERTY_HINT_NONE, "suffix:m"), "set_center_offset", "get_center_offset");
}
void PlaneMesh::set_size(const Size2 &p_size) {
@@ -2701,17 +2701,17 @@ void TextMesh::_bind_methods() {
ADD_GROUP("Text", "");
ADD_PROPERTY(PropertyInfo(Variant::STRING, "text"), "set_text", "get_text");
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "font", PROPERTY_HINT_RESOURCE_TYPE, "Font"), "set_font", "get_font");
- ADD_PROPERTY(PropertyInfo(Variant::INT, "font_size", PROPERTY_HINT_RANGE, "1,127,1"), "set_font_size", "get_font_size");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "font_size", PROPERTY_HINT_RANGE, "1,127,1,suffix:px"), "set_font_size", "get_font_size");
ADD_PROPERTY(PropertyInfo(Variant::INT, "horizontal_alignment", PROPERTY_HINT_ENUM, "Left,Center,Right,Fill"), "set_horizontal_alignment", "get_horizontal_alignment");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "uppercase"), "set_uppercase", "is_uppercase");
ADD_PROPERTY(PropertyInfo(Variant::INT, "structured_text_bidi_override", PROPERTY_HINT_ENUM, "Default,URI,File,Email,List,None,Custom"), "set_structured_text_bidi_override", "get_structured_text_bidi_override");
ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "structured_text_bidi_override_options"), "set_structured_text_bidi_override_options", "get_structured_text_bidi_override_options");
ADD_GROUP("Mesh", "");
- ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "pixel_size", PROPERTY_HINT_RANGE, "0.0001,128,0.0001"), "set_pixel_size", "get_pixel_size");
- ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "curve_step", PROPERTY_HINT_RANGE, "0.1,10,0.1"), "set_curve_step", "get_curve_step");
- ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "depth", PROPERTY_HINT_RANGE, "0.0,100.0,0.001,or_greater"), "set_depth", "get_depth");
- ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "width"), "set_width", "get_width");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "pixel_size", PROPERTY_HINT_RANGE, "0.0001,128,0.0001,suffix:m"), "set_pixel_size", "get_pixel_size");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "curve_step", PROPERTY_HINT_RANGE, "0.1,10,0.1,suffix:px"), "set_curve_step", "get_curve_step");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "depth", PROPERTY_HINT_RANGE, "0.0,100.0,0.001,or_greater,suffix:m"), "set_depth", "get_depth");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "width", PROPERTY_HINT_NONE, "suffix:m"), "set_width", "get_width");
ADD_GROUP("Locale", "");
ADD_PROPERTY(PropertyInfo(Variant::INT, "text_direction", PROPERTY_HINT_ENUM, "Auto,Left-to-Right,Right-to-Left"), "set_text_direction", "get_text_direction");
diff --git a/scene/resources/separation_ray_shape_2d.cpp b/scene/resources/separation_ray_shape_2d.cpp
index df7b0d969a..0d6aee47d8 100644
--- a/scene/resources/separation_ray_shape_2d.cpp
+++ b/scene/resources/separation_ray_shape_2d.cpp
@@ -89,7 +89,7 @@ void SeparationRayShape2D::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_slide_on_slope", "active"), &SeparationRayShape2D::set_slide_on_slope);
ClassDB::bind_method(D_METHOD("get_slide_on_slope"), &SeparationRayShape2D::get_slide_on_slope);
- ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "length", PROPERTY_HINT_RANGE, "0.01,1024,0.01,or_greater"), "set_length", "get_length");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "length", PROPERTY_HINT_RANGE, "0.01,1024,0.01,or_greater,suffix:px"), "set_length", "get_length");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "slide_on_slope"), "set_slide_on_slope", "get_slide_on_slope");
}
diff --git a/scene/resources/separation_ray_shape_3d.cpp b/scene/resources/separation_ray_shape_3d.cpp
index 736cb60c1c..7306d5b985 100644
--- a/scene/resources/separation_ray_shape_3d.cpp
+++ b/scene/resources/separation_ray_shape_3d.cpp
@@ -80,7 +80,7 @@ void SeparationRayShape3D::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_slide_on_slope", "active"), &SeparationRayShape3D::set_slide_on_slope);
ClassDB::bind_method(D_METHOD("get_slide_on_slope"), &SeparationRayShape3D::get_slide_on_slope);
- ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "length", PROPERTY_HINT_RANGE, "0.001,100,0.001,or_greater"), "set_length", "get_length");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "length", PROPERTY_HINT_RANGE, "0.001,100,0.001,or_greater,suffix:m"), "set_length", "get_length");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "slide_on_slope"), "set_slide_on_slope", "get_slide_on_slope");
}
diff --git a/scene/resources/skeleton_modification_2d_twoboneik.cpp b/scene/resources/skeleton_modification_2d_twoboneik.cpp
index b08fd82381..d3c62e441f 100644
--- a/scene/resources/skeleton_modification_2d_twoboneik.cpp
+++ b/scene/resources/skeleton_modification_2d_twoboneik.cpp
@@ -464,8 +464,8 @@ void SkeletonModification2DTwoBoneIK::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_joint_two_bone_idx"), &SkeletonModification2DTwoBoneIK::get_joint_two_bone_idx);
ADD_PROPERTY(PropertyInfo(Variant::NODE_PATH, "target_nodepath", PROPERTY_HINT_NODE_PATH_VALID_TYPES, "Node2D"), "set_target_node", "get_target_node");
- ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "target_minimum_distance", PROPERTY_HINT_RANGE, "0, 100000000, 0.01"), "set_target_minimum_distance", "get_target_minimum_distance");
- ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "target_maximum_distance", PROPERTY_HINT_NONE, "0, 100000000, 0.01"), "set_target_maximum_distance", "get_target_maximum_distance");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "target_minimum_distance", PROPERTY_HINT_RANGE, "0,100000000,0.01,suffix:m"), "set_target_minimum_distance", "get_target_minimum_distance");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "target_maximum_distance", PROPERTY_HINT_NONE, "0,100000000,0.01,suffix:m"), "set_target_maximum_distance", "get_target_maximum_distance");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "flip_bend_direction", PROPERTY_HINT_NONE, ""), "set_flip_bend_direction", "get_flip_bend_direction");
ADD_GROUP("", "");
}
diff --git a/scene/resources/style_box.cpp b/scene/resources/style_box.cpp
index b54bbc1478..a53c299d00 100644
--- a/scene/resources/style_box.cpp
+++ b/scene/resources/style_box.cpp
@@ -123,10 +123,10 @@ void StyleBox::_bind_methods() {
ClassDB::bind_method(D_METHOD("draw", "canvas_item", "rect"), &StyleBox::draw);
ADD_GROUP("Content Margins", "content_margin_");
- ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "content_margin_left", PROPERTY_HINT_RANGE, "-1,2048,1"), "set_default_margin", "get_default_margin", SIDE_LEFT);
- ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "content_margin_top", PROPERTY_HINT_RANGE, "-1,2048,1"), "set_default_margin", "get_default_margin", SIDE_TOP);
- ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "content_margin_right", PROPERTY_HINT_RANGE, "-1,2048,1"), "set_default_margin", "get_default_margin", SIDE_RIGHT);
- ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "content_margin_bottom", PROPERTY_HINT_RANGE, "-1,2048,1"), "set_default_margin", "get_default_margin", SIDE_BOTTOM);
+ ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "content_margin_left", PROPERTY_HINT_RANGE, "-1,2048,1,suffix:px"), "set_default_margin", "get_default_margin", SIDE_LEFT);
+ ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "content_margin_top", PROPERTY_HINT_RANGE, "-1,2048,1,suffix:px"), "set_default_margin", "get_default_margin", SIDE_TOP);
+ ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "content_margin_right", PROPERTY_HINT_RANGE, "-1,2048,1,suffix:px"), "set_default_margin", "get_default_margin", SIDE_RIGHT);
+ ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "content_margin_bottom", PROPERTY_HINT_RANGE, "-1,2048,1,suffix:px"), "set_default_margin", "get_default_margin", SIDE_BOTTOM);
GDVIRTUAL_BIND(_get_style_margin, "side")
GDVIRTUAL_BIND(_test_mask, "point", "rect")
@@ -317,23 +317,23 @@ void StyleBoxTexture::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "texture", PROPERTY_HINT_RESOURCE_TYPE, "Texture2D"), "set_texture", "get_texture");
ADD_GROUP("Margins", "margin_");
- ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "margin_left", PROPERTY_HINT_RANGE, "0,2048,1"), "set_margin_size", "get_margin_size", SIDE_LEFT);
- ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "margin_top", PROPERTY_HINT_RANGE, "0,2048,1"), "set_margin_size", "get_margin_size", SIDE_TOP);
- ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "margin_right", PROPERTY_HINT_RANGE, "0,2048,1"), "set_margin_size", "get_margin_size", SIDE_RIGHT);
- ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "margin_bottom", PROPERTY_HINT_RANGE, "0,2048,1"), "set_margin_size", "get_margin_size", SIDE_BOTTOM);
+ ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "margin_left", PROPERTY_HINT_RANGE, "0,2048,1,suffix:px"), "set_margin_size", "get_margin_size", SIDE_LEFT);
+ ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "margin_top", PROPERTY_HINT_RANGE, "0,2048,1,suffix:px"), "set_margin_size", "get_margin_size", SIDE_TOP);
+ ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "margin_right", PROPERTY_HINT_RANGE, "0,2048,1,suffix:px"), "set_margin_size", "get_margin_size", SIDE_RIGHT);
+ ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "margin_bottom", PROPERTY_HINT_RANGE, "0,2048,1,suffix:px"), "set_margin_size", "get_margin_size", SIDE_BOTTOM);
ADD_GROUP("Expand Margins", "expand_margin_");
- ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "expand_margin_left", PROPERTY_HINT_RANGE, "0,2048,1"), "set_expand_margin_size", "get_expand_margin_size", SIDE_LEFT);
- ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "expand_margin_top", PROPERTY_HINT_RANGE, "0,2048,1"), "set_expand_margin_size", "get_expand_margin_size", SIDE_TOP);
- ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "expand_margin_right", PROPERTY_HINT_RANGE, "0,2048,1"), "set_expand_margin_size", "get_expand_margin_size", SIDE_RIGHT);
- ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "expand_margin_bottom", PROPERTY_HINT_RANGE, "0,2048,1"), "set_expand_margin_size", "get_expand_margin_size", SIDE_BOTTOM);
+ ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "expand_margin_left", PROPERTY_HINT_RANGE, "0,2048,1,suffix:px"), "set_expand_margin_size", "get_expand_margin_size", SIDE_LEFT);
+ ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "expand_margin_top", PROPERTY_HINT_RANGE, "0,2048,1,suffix:px"), "set_expand_margin_size", "get_expand_margin_size", SIDE_TOP);
+ ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "expand_margin_right", PROPERTY_HINT_RANGE, "0,2048,1,suffix:px"), "set_expand_margin_size", "get_expand_margin_size", SIDE_RIGHT);
+ ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "expand_margin_bottom", PROPERTY_HINT_RANGE, "0,2048,1,suffix:px"), "set_expand_margin_size", "get_expand_margin_size", SIDE_BOTTOM);
ADD_GROUP("Axis Stretch", "axis_stretch_");
ADD_PROPERTY(PropertyInfo(Variant::INT, "axis_stretch_horizontal", PROPERTY_HINT_ENUM, "Stretch,Tile,Tile Fit"), "set_h_axis_stretch_mode", "get_h_axis_stretch_mode");
ADD_PROPERTY(PropertyInfo(Variant::INT, "axis_stretch_vertical", PROPERTY_HINT_ENUM, "Stretch,Tile,Tile Fit"), "set_v_axis_stretch_mode", "get_v_axis_stretch_mode");
ADD_GROUP("Sub-Region", "region_");
- ADD_PROPERTY(PropertyInfo(Variant::RECT2, "region_rect"), "set_region_rect", "get_region_rect");
+ ADD_PROPERTY(PropertyInfo(Variant::RECT2, "region_rect", PROPERTY_HINT_NONE, "suffix:px"), "set_region_rect", "get_region_rect");
ADD_GROUP("Modulate", "modulate_");
ADD_PROPERTY(PropertyInfo(Variant::COLOR, "modulate_color"), "set_modulate", "get_modulate");
@@ -905,10 +905,10 @@ void StyleBoxFlat::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "skew"), "set_skew", "get_skew");
ADD_GROUP("Border Width", "border_width_");
- ADD_PROPERTYI(PropertyInfo(Variant::INT, "border_width_left", PROPERTY_HINT_RANGE, "0,1024,1"), "set_border_width", "get_border_width", SIDE_LEFT);
- ADD_PROPERTYI(PropertyInfo(Variant::INT, "border_width_top", PROPERTY_HINT_RANGE, "0,1024,1"), "set_border_width", "get_border_width", SIDE_TOP);
- ADD_PROPERTYI(PropertyInfo(Variant::INT, "border_width_right", PROPERTY_HINT_RANGE, "0,1024,1"), "set_border_width", "get_border_width", SIDE_RIGHT);
- ADD_PROPERTYI(PropertyInfo(Variant::INT, "border_width_bottom", PROPERTY_HINT_RANGE, "0,1024,1"), "set_border_width", "get_border_width", SIDE_BOTTOM);
+ ADD_PROPERTYI(PropertyInfo(Variant::INT, "border_width_left", PROPERTY_HINT_RANGE, "0,1024,1,suffix:px"), "set_border_width", "get_border_width", SIDE_LEFT);
+ ADD_PROPERTYI(PropertyInfo(Variant::INT, "border_width_top", PROPERTY_HINT_RANGE, "0,1024,1,suffix:px"), "set_border_width", "get_border_width", SIDE_TOP);
+ ADD_PROPERTYI(PropertyInfo(Variant::INT, "border_width_right", PROPERTY_HINT_RANGE, "0,1024,1,suffix:px"), "set_border_width", "get_border_width", SIDE_RIGHT);
+ ADD_PROPERTYI(PropertyInfo(Variant::INT, "border_width_bottom", PROPERTY_HINT_RANGE, "0,1024,1,suffix:px"), "set_border_width", "get_border_width", SIDE_BOTTOM);
ADD_GROUP("Border", "border_");
ADD_PROPERTY(PropertyInfo(Variant::COLOR, "border_color"), "set_border_color", "get_border_color");
@@ -916,27 +916,27 @@ void StyleBoxFlat::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "border_blend"), "set_border_blend", "get_border_blend");
ADD_GROUP("Corner Radius", "corner_radius_");
- ADD_PROPERTYI(PropertyInfo(Variant::INT, "corner_radius_top_left", PROPERTY_HINT_RANGE, "0,1024,1"), "set_corner_radius", "get_corner_radius", CORNER_TOP_LEFT);
- ADD_PROPERTYI(PropertyInfo(Variant::INT, "corner_radius_top_right", PROPERTY_HINT_RANGE, "0,1024,1"), "set_corner_radius", "get_corner_radius", CORNER_TOP_RIGHT);
- ADD_PROPERTYI(PropertyInfo(Variant::INT, "corner_radius_bottom_right", PROPERTY_HINT_RANGE, "0,1024,1"), "set_corner_radius", "get_corner_radius", CORNER_BOTTOM_RIGHT);
- ADD_PROPERTYI(PropertyInfo(Variant::INT, "corner_radius_bottom_left", PROPERTY_HINT_RANGE, "0,1024,1"), "set_corner_radius", "get_corner_radius", CORNER_BOTTOM_LEFT);
+ ADD_PROPERTYI(PropertyInfo(Variant::INT, "corner_radius_top_left", PROPERTY_HINT_RANGE, "0,1024,1,suffix:px"), "set_corner_radius", "get_corner_radius", CORNER_TOP_LEFT);
+ ADD_PROPERTYI(PropertyInfo(Variant::INT, "corner_radius_top_right", PROPERTY_HINT_RANGE, "0,1024,1,suffix:px"), "set_corner_radius", "get_corner_radius", CORNER_TOP_RIGHT);
+ ADD_PROPERTYI(PropertyInfo(Variant::INT, "corner_radius_bottom_right", PROPERTY_HINT_RANGE, "0,1024,1,suffix:px"), "set_corner_radius", "get_corner_radius", CORNER_BOTTOM_RIGHT);
+ ADD_PROPERTYI(PropertyInfo(Variant::INT, "corner_radius_bottom_left", PROPERTY_HINT_RANGE, "0,1024,1,suffix:px"), "set_corner_radius", "get_corner_radius", CORNER_BOTTOM_LEFT);
ADD_PROPERTY(PropertyInfo(Variant::INT, "corner_detail", PROPERTY_HINT_RANGE, "1,20,1"), "set_corner_detail", "get_corner_detail");
ADD_GROUP("Expand Margins", "expand_margin_");
- ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "expand_margin_left", PROPERTY_HINT_RANGE, "0,2048,1"), "set_expand_margin", "get_expand_margin", SIDE_LEFT);
- ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "expand_margin_top", PROPERTY_HINT_RANGE, "0,2048,1"), "set_expand_margin", "get_expand_margin", SIDE_TOP);
- ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "expand_margin_right", PROPERTY_HINT_RANGE, "0,2048,1"), "set_expand_margin", "get_expand_margin", SIDE_RIGHT);
- ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "expand_margin_bottom", PROPERTY_HINT_RANGE, "0,2048,1"), "set_expand_margin", "get_expand_margin", SIDE_BOTTOM);
+ ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "expand_margin_left", PROPERTY_HINT_RANGE, "0,2048,1,suffix:px"), "set_expand_margin", "get_expand_margin", SIDE_LEFT);
+ ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "expand_margin_top", PROPERTY_HINT_RANGE, "0,2048,1,suffix:px"), "set_expand_margin", "get_expand_margin", SIDE_TOP);
+ ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "expand_margin_right", PROPERTY_HINT_RANGE, "0,2048,1,suffix:px"), "set_expand_margin", "get_expand_margin", SIDE_RIGHT);
+ ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "expand_margin_bottom", PROPERTY_HINT_RANGE, "0,2048,1,suffix:px"), "set_expand_margin", "get_expand_margin", SIDE_BOTTOM);
ADD_GROUP("Shadow", "shadow_");
ADD_PROPERTY(PropertyInfo(Variant::COLOR, "shadow_color"), "set_shadow_color", "get_shadow_color");
- ADD_PROPERTY(PropertyInfo(Variant::INT, "shadow_size", PROPERTY_HINT_RANGE, "0,100,1,or_greater"), "set_shadow_size", "get_shadow_size");
- ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "shadow_offset"), "set_shadow_offset", "get_shadow_offset");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "shadow_size", PROPERTY_HINT_RANGE, "0,100,1,or_greater,suffix:px"), "set_shadow_size", "get_shadow_size");
+ ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "shadow_offset", PROPERTY_HINT_NONE, "suffix:px"), "set_shadow_offset", "get_shadow_offset");
ADD_GROUP("Anti Aliasing", "anti_aliasing_");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "anti_aliasing"), "set_anti_aliased", "is_anti_aliased");
- ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "anti_aliasing_size", PROPERTY_HINT_RANGE, "0.01,10,0.001"), "set_aa_size", "get_aa_size");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "anti_aliasing_size", PROPERTY_HINT_RANGE, "0.01,10,0.001,suffix:px"), "set_aa_size", "get_aa_size");
}
StyleBoxFlat::StyleBoxFlat() {}
@@ -1001,9 +1001,9 @@ void StyleBoxLine::_bind_methods() {
ClassDB::bind_method(D_METHOD("is_vertical"), &StyleBoxLine::is_vertical);
ADD_PROPERTY(PropertyInfo(Variant::COLOR, "color"), "set_color", "get_color");
- ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "grow_begin", PROPERTY_HINT_RANGE, "-300,300,1"), "set_grow_begin", "get_grow_begin");
- ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "grow_end", PROPERTY_HINT_RANGE, "-300,300,1"), "set_grow_end", "get_grow_end");
- ADD_PROPERTY(PropertyInfo(Variant::INT, "thickness", PROPERTY_HINT_RANGE, "0,10"), "set_thickness", "get_thickness");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "grow_begin", PROPERTY_HINT_RANGE, "-300,300,1,suffix:px"), "set_grow_begin", "get_grow_begin");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "grow_end", PROPERTY_HINT_RANGE, "-300,300,1,suffix:px"), "set_grow_end", "get_grow_end");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "thickness", PROPERTY_HINT_RANGE, "0,10,suffix:px"), "set_thickness", "get_thickness");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "vertical"), "set_vertical", "is_vertical");
}
diff --git a/scene/resources/texture.cpp b/scene/resources/texture.cpp
index 8994bb5983..f31a71eada 100644
--- a/scene/resources/texture.cpp
+++ b/scene/resources/texture.cpp
@@ -613,7 +613,7 @@ void PortableCompressedTexture2D::_bind_methods() {
ClassDB::bind_static_method("PortableCompressedTexture2D", D_METHOD("is_keeping_all_compressed_buffers"), &PortableCompressedTexture2D::is_keeping_all_compressed_buffers);
ADD_PROPERTY(PropertyInfo(Variant::PACKED_BYTE_ARRAY, "_data", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR), "_set_data", "_get_data");
- ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "size_override"), "set_size_override", "get_size_override");
+ ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "size_override", PROPERTY_HINT_NONE, "suffix:px"), "set_size_override", "get_size_override");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "keep_compressed_buffer"), "set_keep_compressed_buffer", "is_keeping_compressed_buffer");
BIND_ENUM_CONSTANT(COMPRESSION_MODE_LOSSLESS);
@@ -1533,8 +1533,8 @@ void AtlasTexture::_bind_methods() {
ClassDB::bind_method(D_METHOD("has_filter_clip"), &AtlasTexture::has_filter_clip);
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "atlas", PROPERTY_HINT_RESOURCE_TYPE, "Texture2D"), "set_atlas", "get_atlas");
- ADD_PROPERTY(PropertyInfo(Variant::RECT2, "region"), "set_region", "get_region");
- ADD_PROPERTY(PropertyInfo(Variant::RECT2, "margin"), "set_margin", "get_margin");
+ ADD_PROPERTY(PropertyInfo(Variant::RECT2, "region", PROPERTY_HINT_NONE, "suffix:px"), "set_region", "get_region");
+ ADD_PROPERTY(PropertyInfo(Variant::RECT2, "margin", PROPERTY_HINT_NONE, "suffix:px"), "set_margin", "get_margin");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "filter_clip"), "set_filter_clip", "has_filter_clip");
}
@@ -1775,7 +1775,7 @@ void MeshTexture::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "mesh", PROPERTY_HINT_RESOURCE_TYPE, "Mesh"), "set_mesh", "get_mesh");
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "base_texture", PROPERTY_HINT_RESOURCE_TYPE, "Texture2D"), "set_base_texture", "get_base_texture");
- ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "image_size", PROPERTY_HINT_RANGE, "0,16384,1"), "set_image_size", "get_image_size");
+ ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "image_size", PROPERTY_HINT_RANGE, "0,16384,1,suffix:px"), "set_image_size", "get_image_size");
}
MeshTexture::MeshTexture() {
@@ -1794,7 +1794,7 @@ void CurveTexture::_bind_methods() {
ClassDB::bind_method(D_METHOD("_update"), &CurveTexture::_update);
- ADD_PROPERTY(PropertyInfo(Variant::INT, "width", PROPERTY_HINT_RANGE, "1,4096"), "set_width", "get_width");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "width", PROPERTY_HINT_RANGE, "1,4096,suffix:px"), "set_width", "get_width");
ADD_PROPERTY(PropertyInfo(Variant::INT, "texture_mode", PROPERTY_HINT_ENUM, "RGB,Red"), "set_texture_mode", "get_texture_mode");
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "curve", PROPERTY_HINT_RESOURCE_TYPE, "Curve"), "set_curve", "get_curve");
@@ -1942,7 +1942,7 @@ void CurveXYZTexture::_bind_methods() {
ClassDB::bind_method(D_METHOD("_update"), &CurveXYZTexture::_update);
- ADD_PROPERTY(PropertyInfo(Variant::INT, "width", PROPERTY_HINT_RANGE, "1,4096"), "set_width", "get_width");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "width", PROPERTY_HINT_RANGE, "1,4096,suffix:px"), "set_width", "get_width");
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "curve_x", PROPERTY_HINT_RESOURCE_TYPE, "Curve"), "set_curve_x", "get_curve_x");
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "curve_y", PROPERTY_HINT_RESOURCE_TYPE, "Curve"), "set_curve_y", "get_curve_y");
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "curve_z", PROPERTY_HINT_RESOURCE_TYPE, "Curve"), "set_curve_z", "get_curve_z");
@@ -2149,7 +2149,7 @@ void GradientTexture1D::_bind_methods() {
ClassDB::bind_method(D_METHOD("_update"), &GradientTexture1D::_update);
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "gradient", PROPERTY_HINT_RESOURCE_TYPE, "Gradient"), "set_gradient", "get_gradient");
- ADD_PROPERTY(PropertyInfo(Variant::INT, "width", PROPERTY_HINT_RANGE, "1,16384"), "set_width", "get_width");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "width", PROPERTY_HINT_RANGE, "1,16384,suffix:px"), "set_width", "get_width");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "use_hdr"), "set_use_hdr", "is_using_hdr");
}
@@ -2505,8 +2505,8 @@ void GradientTexture2D::_bind_methods() {
ClassDB::bind_method(D_METHOD("_update"), &GradientTexture2D::_update);
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "gradient", PROPERTY_HINT_RESOURCE_TYPE, "Gradient", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_EDITOR_INSTANTIATE_OBJECT), "set_gradient", "get_gradient");
- ADD_PROPERTY(PropertyInfo(Variant::INT, "width", PROPERTY_HINT_RANGE, "1,2048,or_greater"), "set_width", "get_width");
- ADD_PROPERTY(PropertyInfo(Variant::INT, "height", PROPERTY_HINT_RANGE, "1,2048,or_greater"), "set_height", "get_height");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "width", PROPERTY_HINT_RANGE, "1,2048,or_greater,suffix:px"), "set_width", "get_width");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "height", PROPERTY_HINT_RANGE, "1,2048,or_greater,suffix:px"), "set_height", "get_height");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "use_hdr"), "set_use_hdr", "is_using_hdr");
ADD_GROUP("Fill", "fill_");
@@ -2826,7 +2826,7 @@ void AnimatedTexture::_bind_methods() {
for (int i = 0; i < MAX_FRAMES; i++) {
ADD_PROPERTYI(PropertyInfo(Variant::OBJECT, "frame_" + itos(i) + "/texture", PROPERTY_HINT_RESOURCE_TYPE, "Texture2D", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_INTERNAL), "set_frame_texture", "get_frame_texture", i);
- ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "frame_" + itos(i) + "/delay_sec", PROPERTY_HINT_RANGE, "0.0,16.0,0.01", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_INTERNAL), "set_frame_delay", "get_frame_delay", i);
+ ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "frame_" + itos(i) + "/delay_sec", PROPERTY_HINT_RANGE, "0.0,16.0,0.01,suffix:s", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_INTERNAL), "set_frame_delay", "get_frame_delay", i);
}
BIND_CONSTANT(MAX_FRAMES);
@@ -3415,7 +3415,7 @@ RID PlaceholderTexture2D::get_rid() const {
void PlaceholderTexture2D::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_size", "size"), &PlaceholderTexture2D::set_size);
- ADD_PROPERTY(PropertyInfo(Variant::VECTOR2I, "size"), "set_size", "get_size");
+ ADD_PROPERTY(PropertyInfo(Variant::VECTOR2I, "size", PROPERTY_HINT_NONE, "suffix:px"), "set_size", "get_size");
}
PlaceholderTexture2D::PlaceholderTexture2D() {
@@ -3463,7 +3463,7 @@ Vector<Ref<Image>> PlaceholderTexture3D::get_data() const {
void PlaceholderTexture3D::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_size", "size"), &PlaceholderTexture3D::set_size);
ClassDB::bind_method(D_METHOD("get_size"), &PlaceholderTexture3D::get_size);
- ADD_PROPERTY(PropertyInfo(Variant::VECTOR3I, "size"), "set_size", "get_size");
+ ADD_PROPERTY(PropertyInfo(Variant::VECTOR3I, "size", PROPERTY_HINT_NONE, "suffix:px"), "set_size", "get_size");
}
PlaceholderTexture3D::PlaceholderTexture3D() {
@@ -3519,7 +3519,7 @@ void PlaceholderTextureLayered::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_size", "size"), &PlaceholderTextureLayered::set_size);
ClassDB::bind_method(D_METHOD("get_size"), &PlaceholderTextureLayered::get_size);
ClassDB::bind_method(D_METHOD("set_layers", "layers"), &PlaceholderTextureLayered::set_layers);
- ADD_PROPERTY(PropertyInfo(Variant::VECTOR2I, "size"), "set_size", "get_size");
+ ADD_PROPERTY(PropertyInfo(Variant::VECTOR2I, "size", PROPERTY_HINT_NONE, "suffix:px"), "set_size", "get_size");
ADD_PROPERTY(PropertyInfo(Variant::INT, "layers", PROPERTY_HINT_RANGE, "1,4096"), "set_layers", "get_layers");
}
diff --git a/scene/resources/theme.cpp b/scene/resources/theme.cpp
index 6af5d127a8..39b77568cf 100644
--- a/scene/resources/theme.cpp
+++ b/scene/resources/theme.cpp
@@ -152,7 +152,7 @@ void Theme::_get_property_list(List<PropertyInfo> *p_list) const {
// Font sizes.
for (const KeyValue<StringName, ThemeFontSizeMap> &E : font_size_map) {
for (const KeyValue<StringName, int> &F : E.value) {
- list.push_back(PropertyInfo(Variant::INT, String() + E.key + "/font_sizes/" + F.key, PROPERTY_HINT_RANGE, "0,256,1,or_greater"));
+ list.push_back(PropertyInfo(Variant::INT, String() + E.key + "/font_sizes/" + F.key, PROPERTY_HINT_RANGE, "0,256,1,or_greater,suffix:px"));
}
}
@@ -1818,7 +1818,7 @@ void Theme::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "default_base_scale", PROPERTY_HINT_RANGE, "0.0,2.0,0.01,or_greater"), "set_default_base_scale", "get_default_base_scale");
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "default_font", PROPERTY_HINT_RESOURCE_TYPE, "Font"), "set_default_font", "get_default_font");
- ADD_PROPERTY(PropertyInfo(Variant::INT, "default_font_size", PROPERTY_HINT_RANGE, "0,256,1,or_greater"), "set_default_font_size", "get_default_font_size");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "default_font_size", PROPERTY_HINT_RANGE, "0,256,1,or_greater,suffix:px"), "set_default_font_size", "get_default_font_size");
BIND_ENUM_CONSTANT(DATA_TYPE_COLOR);
BIND_ENUM_CONSTANT(DATA_TYPE_CONSTANT);
diff --git a/scene/resources/tile_set.cpp b/scene/resources/tile_set.cpp
index 9d2d4cdb20..8976aa17d2 100644
--- a/scene/resources/tile_set.cpp
+++ b/scene/resources/tile_set.cpp
@@ -236,6 +236,9 @@ bool TileSet::TerrainsPattern::operator<(const TerrainsPattern &p_terrains_patte
return is_valid_bit[i] < p_terrains_pattern.is_valid_bit[i];
}
}
+ if (terrain != p_terrains_pattern.terrain) {
+ return terrain < p_terrains_pattern.terrain;
+ }
for (int i = 0; i < TileSet::CELL_NEIGHBOR_MAX; i++) {
if (is_valid_bit[i] && bits[i] != p_terrains_pattern.bits[i]) {
return bits[i] < p_terrains_pattern.bits[i];
@@ -253,10 +256,23 @@ bool TileSet::TerrainsPattern::operator==(const TerrainsPattern &p_terrains_patt
return false;
}
}
+ if (terrain != p_terrains_pattern.terrain) {
+ return false;
+ }
return true;
}
-void TileSet::TerrainsPattern::set_terrain(TileSet::CellNeighbor p_peering_bit, int p_terrain) {
+void TileSet::TerrainsPattern::set_terrain(int p_terrain) {
+ ERR_FAIL_COND(p_terrain < -1);
+
+ terrain = p_terrain;
+}
+
+int TileSet::TerrainsPattern::get_terrain() const {
+ return terrain;
+}
+
+void TileSet::TerrainsPattern::set_terrain_peering_bit(TileSet::CellNeighbor p_peering_bit, int p_terrain) {
ERR_FAIL_COND(p_peering_bit == TileSet::CELL_NEIGHBOR_MAX);
ERR_FAIL_COND(!is_valid_bit[p_peering_bit]);
ERR_FAIL_COND(p_terrain < -1);
@@ -271,25 +287,27 @@ void TileSet::TerrainsPattern::set_terrain(TileSet::CellNeighbor p_peering_bit,
bits[p_peering_bit] = p_terrain;
}
-int TileSet::TerrainsPattern::get_terrain(TileSet::CellNeighbor p_peering_bit) const {
+int TileSet::TerrainsPattern::get_terrain_peering_bit(TileSet::CellNeighbor p_peering_bit) const {
ERR_FAIL_COND_V(p_peering_bit == TileSet::CELL_NEIGHBOR_MAX, -1);
ERR_FAIL_COND_V(!is_valid_bit[p_peering_bit], -1);
return bits[p_peering_bit];
}
-void TileSet::TerrainsPattern::set_terrains_from_array(Array p_terrains) {
- int in_array_index = 0;
+void TileSet::TerrainsPattern::from_array(Array p_terrains) {
+ set_terrain(p_terrains[0]);
+ int in_array_index = 1;
for (int i = 0; i < TileSet::CELL_NEIGHBOR_MAX; i++) {
if (is_valid_bit[i]) {
ERR_FAIL_INDEX(in_array_index, p_terrains.size());
- set_terrain(TileSet::CellNeighbor(i), p_terrains[in_array_index]);
+ set_terrain_peering_bit(TileSet::CellNeighbor(i), p_terrains[in_array_index]);
in_array_index++;
}
}
}
-Array TileSet::TerrainsPattern::get_terrains_as_array() const {
+Array TileSet::TerrainsPattern::as_array() const {
Array output;
+ output.push_back(get_terrain());
for (int i = 0; i < TileSet::CELL_NEIGHBOR_MAX; i++) {
if (is_valid_bit[i]) {
output.push_back(bits[i]);
@@ -297,10 +315,11 @@ Array TileSet::TerrainsPattern::get_terrains_as_array() const {
}
return output;
}
+
TileSet::TerrainsPattern::TerrainsPattern(const TileSet *p_tile_set, int p_terrain_set) {
ERR_FAIL_COND(p_terrain_set < 0);
for (int i = 0; i < TileSet::CELL_NEIGHBOR_MAX; i++) {
- is_valid_bit[i] = (p_tile_set->is_valid_peering_bit_terrain(p_terrain_set, TileSet::CellNeighbor(i)));
+ is_valid_bit[i] = (p_tile_set->is_valid_terrain_peering_bit(p_terrain_set, TileSet::CellNeighbor(i)));
bits[i] = -1;
}
valid = true;
@@ -410,11 +429,16 @@ void TileSet::_update_terrains_cache() {
TileSet::TerrainsPattern terrains_pattern = tile_data->get_terrains_pattern();
+ // Main terrain.
+ if (terrains_pattern.get_terrain() >= 0) {
+ per_terrain_pattern_tiles[terrain_set][terrains_pattern].insert(cell);
+ }
+
// Terrain bits.
for (int i = 0; i < TileSet::CELL_NEIGHBOR_MAX; i++) {
CellNeighbor bit = CellNeighbor(i);
- if (is_valid_peering_bit_terrain(terrain_set, bit)) {
- int terrain = terrains_pattern.get_terrain(bit);
+ if (is_valid_terrain_peering_bit(terrain_set, bit)) {
+ int terrain = terrains_pattern.get_terrain_peering_bit(bit);
if (terrain >= 0) {
per_terrain_pattern_tiles[terrain_set][terrains_pattern].insert(cell);
}
@@ -822,7 +846,7 @@ Color TileSet::get_terrain_color(int p_terrain_set, int p_terrain_index) const {
return terrain_sets[p_terrain_set].terrains[p_terrain_index].color;
}
-bool TileSet::is_valid_peering_bit_for_mode(TileSet::TerrainMode p_terrain_mode, TileSet::CellNeighbor p_peering_bit) const {
+bool TileSet::is_valid_terrain_peering_bit_for_mode(TileSet::TerrainMode p_terrain_mode, TileSet::CellNeighbor p_peering_bit) const {
if (tile_shape == TileSet::TILE_SHAPE_SQUARE) {
if (p_terrain_mode == TileSet::TERRAIN_MODE_MATCH_CORNERS_AND_SIDES || p_terrain_mode == TileSet::TERRAIN_MODE_MATCH_SIDES) {
if (p_peering_bit == TileSet::CELL_NEIGHBOR_RIGHT_SIDE ||
@@ -905,13 +929,13 @@ bool TileSet::is_valid_peering_bit_for_mode(TileSet::TerrainMode p_terrain_mode,
return false;
}
-bool TileSet::is_valid_peering_bit_terrain(int p_terrain_set, TileSet::CellNeighbor p_peering_bit) const {
+bool TileSet::is_valid_terrain_peering_bit(int p_terrain_set, TileSet::CellNeighbor p_peering_bit) const {
if (p_terrain_set < 0 || p_terrain_set >= get_terrain_sets_count()) {
return false;
}
TileSet::TerrainMode terrain_mode = get_terrain_set_mode(p_terrain_set);
- return is_valid_peering_bit_for_mode(terrain_mode, p_peering_bit);
+ return is_valid_terrain_peering_bit_for_mode(terrain_mode, p_peering_bit);
}
// Navigation
@@ -1494,26 +1518,48 @@ void TileSet::draw_tile_shape(CanvasItem *p_canvas_item, Transform2D p_transform
}
}
-Vector<Point2> TileSet::get_terrain_bit_polygon(int p_terrain_set, TileSet::CellNeighbor p_bit) {
+Vector<Point2> TileSet::get_terrain_polygon(int p_terrain_set) {
+ if (tile_shape == TileSet::TILE_SHAPE_SQUARE) {
+ return _get_square_terrain_polygon(tile_size);
+ } else if (tile_shape == TileSet::TILE_SHAPE_ISOMETRIC) {
+ return _get_isometric_terrain_polygon(tile_size);
+ } else {
+ float overlap = 0.0;
+ switch (tile_shape) {
+ case TileSet::TILE_SHAPE_HEXAGON:
+ overlap = 0.25;
+ break;
+ case TileSet::TILE_SHAPE_HALF_OFFSET_SQUARE:
+ overlap = 0.0;
+ break;
+ default:
+ break;
+ }
+ return _get_half_offset_terrain_polygon(tile_size, overlap, tile_offset_axis);
+ }
+ return Vector<Point2>();
+}
+
+Vector<Point2> TileSet::get_terrain_peering_bit_polygon(int p_terrain_set, TileSet::CellNeighbor p_bit) {
ERR_FAIL_COND_V(p_terrain_set < 0 || p_terrain_set >= get_terrain_sets_count(), Vector<Point2>());
TileSet::TerrainMode terrain_mode = get_terrain_set_mode(p_terrain_set);
if (tile_shape == TileSet::TILE_SHAPE_SQUARE) {
if (terrain_mode == TileSet::TERRAIN_MODE_MATCH_CORNERS_AND_SIDES) {
- return _get_square_corner_or_side_terrain_bit_polygon(tile_size, p_bit);
+ return _get_square_corner_or_side_terrain_peering_bit_polygon(tile_size, p_bit);
} else if (terrain_mode == TileSet::TERRAIN_MODE_MATCH_CORNERS) {
- return _get_square_corner_terrain_bit_polygon(tile_size, p_bit);
+ return _get_square_corner_terrain_peering_bit_polygon(tile_size, p_bit);
} else { // TileData::TERRAIN_MODE_MATCH_SIDES
- return _get_square_side_terrain_bit_polygon(tile_size, p_bit);
+ return _get_square_side_terrain_peering_bit_polygon(tile_size, p_bit);
}
} else if (tile_shape == TileSet::TILE_SHAPE_ISOMETRIC) {
if (terrain_mode == TileSet::TERRAIN_MODE_MATCH_CORNERS_AND_SIDES) {
- return _get_isometric_corner_or_side_terrain_bit_polygon(tile_size, p_bit);
+ return _get_isometric_corner_or_side_terrain_peering_bit_polygon(tile_size, p_bit);
} else if (terrain_mode == TileSet::TERRAIN_MODE_MATCH_CORNERS) {
- return _get_isometric_corner_terrain_bit_polygon(tile_size, p_bit);
+ return _get_isometric_corner_terrain_peering_bit_polygon(tile_size, p_bit);
} else { // TileData::TERRAIN_MODE_MATCH_SIDES
- return _get_isometric_side_terrain_bit_polygon(tile_size, p_bit);
+ return _get_isometric_side_terrain_peering_bit_polygon(tile_size, p_bit);
}
} else {
float overlap = 0.0;
@@ -1528,11 +1574,11 @@ Vector<Point2> TileSet::get_terrain_bit_polygon(int p_terrain_set, TileSet::Cell
break;
}
if (terrain_mode == TileSet::TERRAIN_MODE_MATCH_CORNERS_AND_SIDES) {
- return _get_half_offset_corner_or_side_terrain_bit_polygon(tile_size, p_bit, overlap, tile_offset_axis);
+ return _get_half_offset_corner_or_side_terrain_peering_bit_polygon(tile_size, overlap, tile_offset_axis, p_bit);
} else if (terrain_mode == TileSet::TERRAIN_MODE_MATCH_CORNERS) {
- return _get_half_offset_corner_terrain_bit_polygon(tile_size, p_bit, overlap, tile_offset_axis);
+ return _get_half_offset_corner_terrain_peering_bit_polygon(tile_size, overlap, tile_offset_axis, p_bit);
} else { // TileData::TERRAIN_MODE_MATCH_SIDES
- return _get_half_offset_side_terrain_bit_polygon(tile_size, p_bit, overlap, tile_offset_axis);
+ return _get_half_offset_side_terrain_peering_bit_polygon(tile_size, overlap, tile_offset_axis, p_bit);
}
}
}
@@ -1544,30 +1590,68 @@ void TileSet::draw_terrains(CanvasItem *p_canvas_item, Transform2D p_transform,
if (terrain_bits_meshes_dirty) {
// Recompute the meshes.
- terrain_bits_meshes.clear();
+ terrain_peering_bits_meshes.clear();
for (int terrain_mode_index = 0; terrain_mode_index < 3; terrain_mode_index++) {
TerrainMode terrain_mode = TerrainMode(terrain_mode_index);
+
+ // Center terrain
+ Vector<Vector2> polygon;
+ if (tile_shape == TileSet::TILE_SHAPE_SQUARE) {
+ polygon = _get_square_terrain_polygon(tile_size);
+ } else if (tile_shape == TileSet::TILE_SHAPE_ISOMETRIC) {
+ polygon = _get_isometric_terrain_polygon(tile_size);
+ } else {
+ float overlap = 0.0;
+ switch (tile_shape) {
+ case TileSet::TILE_SHAPE_HEXAGON:
+ overlap = 0.25;
+ break;
+ case TileSet::TILE_SHAPE_HALF_OFFSET_SQUARE:
+ overlap = 0.0;
+ break;
+ default:
+ break;
+ }
+ polygon = _get_half_offset_terrain_polygon(tile_size, overlap, tile_offset_axis);
+ }
+ {
+ Ref<ArrayMesh> mesh;
+ mesh.instantiate();
+ Vector<Vector2> uvs;
+ uvs.resize(polygon.size());
+ Vector<Color> colors;
+ colors.resize(polygon.size());
+ colors.fill(Color(1.0, 1.0, 1.0, 1.0));
+ Array a;
+ a.resize(Mesh::ARRAY_MAX);
+ a[Mesh::ARRAY_VERTEX] = polygon;
+ a[Mesh::ARRAY_TEX_UV] = uvs;
+ a[Mesh::ARRAY_COLOR] = colors;
+ a[Mesh::ARRAY_INDEX] = Geometry2D::triangulate_polygon(polygon);
+ mesh->add_surface_from_arrays(Mesh::PRIMITIVE_TRIANGLES, a, Array(), Dictionary(), Mesh::ARRAY_FLAG_USE_2D_VERTICES);
+ terrain_meshes[terrain_mode] = mesh;
+ }
+ // Peering bits
for (int i = 0; i < TileSet::CELL_NEIGHBOR_MAX; i++) {
CellNeighbor bit = CellNeighbor(i);
- if (is_valid_peering_bit_for_mode(terrain_mode, bit)) {
- Vector<Vector2> polygon;
+ if (is_valid_terrain_peering_bit_for_mode(terrain_mode, bit)) {
if (tile_shape == TileSet::TILE_SHAPE_SQUARE) {
if (terrain_mode == TileSet::TERRAIN_MODE_MATCH_CORNERS_AND_SIDES) {
- polygon = _get_square_corner_or_side_terrain_bit_polygon(tile_size, bit);
+ polygon = _get_square_corner_or_side_terrain_peering_bit_polygon(tile_size, bit);
} else if (terrain_mode == TileSet::TERRAIN_MODE_MATCH_CORNERS) {
- polygon = _get_square_corner_terrain_bit_polygon(tile_size, bit);
+ polygon = _get_square_corner_terrain_peering_bit_polygon(tile_size, bit);
} else { // TileData::TERRAIN_MODE_MATCH_SIDES
- polygon = _get_square_side_terrain_bit_polygon(tile_size, bit);
+ polygon = _get_square_side_terrain_peering_bit_polygon(tile_size, bit);
}
} else if (tile_shape == TileSet::TILE_SHAPE_ISOMETRIC) {
if (terrain_mode == TileSet::TERRAIN_MODE_MATCH_CORNERS_AND_SIDES) {
- polygon = _get_isometric_corner_or_side_terrain_bit_polygon(tile_size, bit);
+ polygon = _get_isometric_corner_or_side_terrain_peering_bit_polygon(tile_size, bit);
} else if (terrain_mode == TileSet::TERRAIN_MODE_MATCH_CORNERS) {
- polygon = _get_isometric_corner_terrain_bit_polygon(tile_size, bit);
+ polygon = _get_isometric_corner_terrain_peering_bit_polygon(tile_size, bit);
} else { // TileData::TERRAIN_MODE_MATCH_SIDES
- polygon = _get_isometric_side_terrain_bit_polygon(tile_size, bit);
+ polygon = _get_isometric_side_terrain_peering_bit_polygon(tile_size, bit);
}
} else {
float overlap = 0.0;
@@ -1582,29 +1666,30 @@ void TileSet::draw_terrains(CanvasItem *p_canvas_item, Transform2D p_transform,
break;
}
if (terrain_mode == TileSet::TERRAIN_MODE_MATCH_CORNERS_AND_SIDES) {
- polygon = _get_half_offset_corner_or_side_terrain_bit_polygon(tile_size, bit, overlap, tile_offset_axis);
+ polygon = _get_half_offset_corner_or_side_terrain_peering_bit_polygon(tile_size, overlap, tile_offset_axis, bit);
} else if (terrain_mode == TileSet::TERRAIN_MODE_MATCH_CORNERS) {
- polygon = _get_half_offset_corner_terrain_bit_polygon(tile_size, bit, overlap, tile_offset_axis);
+ polygon = _get_half_offset_corner_terrain_peering_bit_polygon(tile_size, overlap, tile_offset_axis, bit);
} else { // TileData::TERRAIN_MODE_MATCH_SIDES
- polygon = _get_half_offset_side_terrain_bit_polygon(tile_size, bit, overlap, tile_offset_axis);
+ polygon = _get_half_offset_side_terrain_peering_bit_polygon(tile_size, overlap, tile_offset_axis, bit);
}
}
-
- Ref<ArrayMesh> mesh;
- mesh.instantiate();
- Vector<Vector2> uvs;
- uvs.resize(polygon.size());
- Vector<Color> colors;
- colors.resize(polygon.size());
- colors.fill(Color(1.0, 1.0, 1.0, 1.0));
- Array a;
- a.resize(Mesh::ARRAY_MAX);
- a[Mesh::ARRAY_VERTEX] = polygon;
- a[Mesh::ARRAY_TEX_UV] = uvs;
- a[Mesh::ARRAY_COLOR] = colors;
- a[Mesh::ARRAY_INDEX] = Geometry2D::triangulate_polygon(polygon);
- mesh->add_surface_from_arrays(Mesh::PRIMITIVE_TRIANGLES, a, Array(), Dictionary(), Mesh::ARRAY_FLAG_USE_2D_VERTICES);
- terrain_bits_meshes[terrain_mode][bit] = mesh;
+ {
+ Ref<ArrayMesh> mesh;
+ mesh.instantiate();
+ Vector<Vector2> uvs;
+ uvs.resize(polygon.size());
+ Vector<Color> colors;
+ colors.resize(polygon.size());
+ colors.fill(Color(1.0, 1.0, 1.0, 1.0));
+ Array a;
+ a.resize(Mesh::ARRAY_MAX);
+ a[Mesh::ARRAY_VERTEX] = polygon;
+ a[Mesh::ARRAY_TEX_UV] = uvs;
+ a[Mesh::ARRAY_COLOR] = colors;
+ a[Mesh::ARRAY_INDEX] = Geometry2D::triangulate_polygon(polygon);
+ mesh->add_surface_from_arrays(Mesh::PRIMITIVE_TRIANGLES, a, Array(), Dictionary(), Mesh::ARRAY_FLAG_USE_2D_VERTICES);
+ terrain_peering_bits_meshes[terrain_mode][bit] = mesh;
+ }
}
}
}
@@ -1618,14 +1703,21 @@ void TileSet::draw_terrains(CanvasItem *p_canvas_item, Transform2D p_transform,
TileSet::TerrainMode terrain_mode = get_terrain_set_mode(terrain_set);
RenderingServer::get_singleton()->canvas_item_add_set_transform(p_canvas_item->get_canvas_item(), p_transform);
+ int terrain_id = p_tile_data->get_terrain();
+ if (terrain_id >= 0) {
+ Color color = get_terrain_color(terrain_set, terrain_id);
+ color.a = TERRAIN_ALPHA;
+ p_canvas_item->draw_mesh(terrain_meshes[terrain_mode], Ref<Texture2D>(), Transform2D(), color);
+ }
+
for (int i = 0; i < TileSet::CELL_NEIGHBOR_MAX; i++) {
CellNeighbor bit = CellNeighbor(i);
- if (is_valid_peering_bit_terrain(terrain_set, bit)) {
- int terrain_id = p_tile_data->get_peering_bit_terrain(bit);
+ if (is_valid_terrain_peering_bit(terrain_set, bit)) {
+ terrain_id = p_tile_data->get_terrain_peering_bit(bit);
if (terrain_id >= 0) {
Color color = get_terrain_color(terrain_set, terrain_id);
color.a = TERRAIN_ALPHA;
- p_canvas_item->draw_mesh(terrain_bits_meshes[terrain_mode][bit], Ref<Texture2D>(), Transform2D(), color);
+ p_canvas_item->draw_mesh(terrain_peering_bits_meshes[terrain_mode][bit], Ref<Texture2D>(), Transform2D(), color);
}
}
}
@@ -1670,13 +1762,16 @@ Vector<Vector<Ref<Texture2D>>> TileSet::generate_terrains_icons(Size2i p_size) {
for (int terrain = 0; terrain < get_terrains_count(terrain_set); terrain++) {
bit_counts[terrain] = 0;
}
+ if (tile_data->get_terrain() >= 0) {
+ bit_counts[tile_data->get_terrain()] += 10;
+ }
for (int terrain_bit = 0; terrain_bit < TileSet::CELL_NEIGHBOR_MAX; terrain_bit++) {
TileSet::CellNeighbor cell_neighbor = TileSet::CellNeighbor(terrain_bit);
- if (is_valid_peering_bit_terrain(terrain_set, cell_neighbor)) {
- int terrain = tile_data->get_peering_bit_terrain(cell_neighbor);
+ if (is_valid_terrain_peering_bit(terrain_set, cell_neighbor)) {
+ int terrain = tile_data->get_terrain_peering_bit(cell_neighbor);
if (terrain >= 0) {
if (terrain >= (int)bit_counts.size()) {
- WARN_PRINT(vformat("Invalid peering bit terrain: %d", terrain));
+ WARN_PRINT(vformat("Invalid terrain peering bit: %d", terrain));
} else {
bit_counts[terrain] += 1;
}
@@ -1730,7 +1825,17 @@ void TileSet::_source_changed() {
emit_changed();
}
-Vector<Point2> TileSet::_get_square_corner_or_side_terrain_bit_polygon(Vector2i p_size, TileSet::CellNeighbor p_bit) {
+Vector<Point2> TileSet::_get_square_terrain_polygon(Vector2i p_size) {
+ Rect2 rect(-Vector2(p_size) / 6.0, Vector2(p_size) / 3.0);
+ return {
+ rect.position,
+ Vector2(rect.get_end().x, rect.position.y),
+ rect.get_end(),
+ Vector2(rect.position.x, rect.get_end().y)
+ };
+}
+
+Vector<Point2> TileSet::_get_square_corner_or_side_terrain_peering_bit_polygon(Vector2i p_size, TileSet::CellNeighbor p_bit) {
Rect2 bit_rect;
bit_rect.size = Vector2(p_size) / 3;
switch (p_bit) {
@@ -1773,7 +1878,7 @@ Vector<Point2> TileSet::_get_square_corner_or_side_terrain_bit_polygon(Vector2i
return polygon;
}
-Vector<Point2> TileSet::_get_square_corner_terrain_bit_polygon(Vector2i p_size, TileSet::CellNeighbor p_bit) {
+Vector<Point2> TileSet::_get_square_corner_terrain_peering_bit_polygon(Vector2i p_size, TileSet::CellNeighbor p_bit) {
Vector2 unit = Vector2(p_size) / 6.0;
Vector<Vector2> polygon;
switch (p_bit) {
@@ -1815,7 +1920,7 @@ Vector<Point2> TileSet::_get_square_corner_terrain_bit_polygon(Vector2i p_size,
return polygon;
}
-Vector<Point2> TileSet::_get_square_side_terrain_bit_polygon(Vector2i p_size, TileSet::CellNeighbor p_bit) {
+Vector<Point2> TileSet::_get_square_side_terrain_peering_bit_polygon(Vector2i p_size, TileSet::CellNeighbor p_bit) {
Vector2 unit = Vector2(p_size) / 6.0;
Vector<Vector2> polygon;
switch (p_bit) {
@@ -1849,7 +1954,17 @@ Vector<Point2> TileSet::_get_square_side_terrain_bit_polygon(Vector2i p_size, Ti
return polygon;
}
-Vector<Point2> TileSet::_get_isometric_corner_or_side_terrain_bit_polygon(Vector2i p_size, TileSet::CellNeighbor p_bit) {
+Vector<Point2> TileSet::_get_isometric_terrain_polygon(Vector2i p_size) {
+ Vector2 unit = Vector2(p_size) / 6.0;
+ return {
+ Vector2(1, 0) * unit,
+ Vector2(0, 1) * unit,
+ Vector2(-1, 0) * unit,
+ Vector2(0, -1) * unit,
+ };
+}
+
+Vector<Point2> TileSet::_get_isometric_corner_or_side_terrain_peering_bit_polygon(Vector2i p_size, TileSet::CellNeighbor p_bit) {
Vector2 unit = Vector2(p_size) / 6.0;
Vector<Vector2> polygon;
switch (p_bit) {
@@ -1907,7 +2022,7 @@ Vector<Point2> TileSet::_get_isometric_corner_or_side_terrain_bit_polygon(Vector
return polygon;
}
-Vector<Point2> TileSet::_get_isometric_corner_terrain_bit_polygon(Vector2i p_size, TileSet::CellNeighbor p_bit) {
+Vector<Point2> TileSet::_get_isometric_corner_terrain_peering_bit_polygon(Vector2i p_size, TileSet::CellNeighbor p_bit) {
Vector2 unit = Vector2(p_size) / 6.0;
Vector<Vector2> polygon;
switch (p_bit) {
@@ -1949,7 +2064,7 @@ Vector<Point2> TileSet::_get_isometric_corner_terrain_bit_polygon(Vector2i p_siz
return polygon;
}
-Vector<Point2> TileSet::_get_isometric_side_terrain_bit_polygon(Vector2i p_size, TileSet::CellNeighbor p_bit) {
+Vector<Point2> TileSet::_get_isometric_side_terrain_peering_bit_polygon(Vector2i p_size, TileSet::CellNeighbor p_bit) {
Vector2 unit = Vector2(p_size) / 6.0;
Vector<Vector2> polygon;
switch (p_bit) {
@@ -1983,7 +2098,30 @@ Vector<Point2> TileSet::_get_isometric_side_terrain_bit_polygon(Vector2i p_size,
return polygon;
}
-Vector<Point2> TileSet::_get_half_offset_corner_or_side_terrain_bit_polygon(Vector2i p_size, TileSet::CellNeighbor p_bit, float p_overlap, TileSet::TileOffsetAxis p_offset_axis) {
+Vector<Point2> TileSet::_get_half_offset_terrain_polygon(Vector2i p_size, float p_overlap, TileSet::TileOffsetAxis p_offset_axis) {
+ Vector2 unit = Vector2(p_size) / 6.0;
+ if (p_offset_axis == TileSet::TILE_OFFSET_AXIS_HORIZONTAL) {
+ return {
+ Vector2(1, 1.0 - p_overlap * 2.0) * unit,
+ Vector2(0, 1) * unit,
+ Vector2(-1, 1.0 - p_overlap * 2.0) * unit,
+ Vector2(-1, -1.0 + p_overlap * 2.0) * unit,
+ Vector2(0, -1) * unit,
+ Vector2(1, -1.0 + p_overlap * 2.0) * unit,
+ };
+ } else {
+ return {
+ Vector2(1, 0) * unit,
+ Vector2(1.0 - p_overlap * 2.0, -1) * unit,
+ Vector2(-1.0 + p_overlap * 2.0, -1) * unit,
+ Vector2(-1, 0) * unit,
+ Vector2(-1.0 + p_overlap * 2.0, 1) * unit,
+ Vector2(1.0 - p_overlap * 2.0, 1) * unit,
+ };
+ }
+}
+
+Vector<Point2> TileSet::_get_half_offset_corner_or_side_terrain_peering_bit_polygon(Vector2i p_size, float p_overlap, TileSet::TileOffsetAxis p_offset_axis, TileSet::CellNeighbor p_bit) {
Vector<Vector2> point_list = {
Vector2(3, (3.0 * (1.0 - p_overlap * 2.0)) / 2.0),
Vector2(3, 3.0 * (1.0 - p_overlap * 2.0)),
@@ -2006,12 +2144,11 @@ Vector<Point2> TileSet::_get_half_offset_corner_or_side_terrain_bit_polygon(Vect
};
Vector2 unit = Vector2(p_size) / 6.0;
- for (int i = 0; i < point_list.size(); i++) {
- point_list.write[i] = point_list[i] * unit;
- }
-
Vector<Vector2> polygon;
if (p_offset_axis == TileSet::TILE_OFFSET_AXIS_HORIZONTAL) {
+ for (int i = 0; i < point_list.size(); i++) {
+ point_list.write[i] = point_list[i] * unit;
+ }
switch (p_bit) {
case TileSet::CELL_NEIGHBOR_RIGHT_SIDE:
polygon.push_back(point_list[17]);
@@ -2071,10 +2208,8 @@ Vector<Point2> TileSet::_get_half_offset_corner_or_side_terrain_bit_polygon(Vect
break;
}
} else {
- if (p_offset_axis == TileSet::TILE_OFFSET_AXIS_VERTICAL) {
- for (int i = 0; i < point_list.size(); i++) {
- point_list.write[i] = Vector2(point_list[i].y, point_list[i].x);
- }
+ for (int i = 0; i < point_list.size(); i++) {
+ point_list.write[i] = Vector2(point_list[i].y, point_list[i].x) * unit;
}
switch (p_bit) {
case TileSet::CELL_NEIGHBOR_RIGHT_CORNER:
@@ -2144,7 +2279,7 @@ Vector<Point2> TileSet::_get_half_offset_corner_or_side_terrain_bit_polygon(Vect
return polygon;
}
-Vector<Point2> TileSet::_get_half_offset_corner_terrain_bit_polygon(Vector2i p_size, TileSet::CellNeighbor p_bit, float p_overlap, TileSet::TileOffsetAxis p_offset_axis) {
+Vector<Point2> TileSet::_get_half_offset_corner_terrain_peering_bit_polygon(Vector2i p_size, float p_overlap, TileSet::TileOffsetAxis p_offset_axis, TileSet::CellNeighbor p_bit) {
Vector<Vector2> point_list = {
Vector2(3, 0),
Vector2(3, 3.0 * (1.0 - p_overlap * 2.0)),
@@ -2161,12 +2296,11 @@ Vector<Point2> TileSet::_get_half_offset_corner_terrain_bit_polygon(Vector2i p_s
};
Vector2 unit = Vector2(p_size) / 6.0;
- for (int i = 0; i < point_list.size(); i++) {
- point_list.write[i] = point_list[i] * unit;
- }
-
Vector<Vector2> polygon;
if (p_offset_axis == TileSet::TILE_OFFSET_AXIS_HORIZONTAL) {
+ for (int i = 0; i < point_list.size(); i++) {
+ point_list.write[i] = point_list[i] * unit;
+ }
switch (p_bit) {
case TileSet::CELL_NEIGHBOR_BOTTOM_RIGHT_CORNER:
polygon.push_back(point_list[0]);
@@ -2202,10 +2336,8 @@ Vector<Point2> TileSet::_get_half_offset_corner_terrain_bit_polygon(Vector2i p_s
break;
}
} else {
- if (p_offset_axis == TileSet::TILE_OFFSET_AXIS_VERTICAL) {
- for (int i = 0; i < point_list.size(); i++) {
- point_list.write[i] = Vector2(point_list[i].y, point_list[i].x);
- }
+ for (int i = 0; i < point_list.size(); i++) {
+ point_list.write[i] = Vector2(point_list[i].y, point_list[i].x) * unit;
}
switch (p_bit) {
case TileSet::CELL_NEIGHBOR_RIGHT_CORNER:
@@ -2251,7 +2383,7 @@ Vector<Point2> TileSet::_get_half_offset_corner_terrain_bit_polygon(Vector2i p_s
return polygon;
}
-Vector<Point2> TileSet::_get_half_offset_side_terrain_bit_polygon(Vector2i p_size, TileSet::CellNeighbor p_bit, float p_overlap, TileSet::TileOffsetAxis p_offset_axis) {
+Vector<Point2> TileSet::_get_half_offset_side_terrain_peering_bit_polygon(Vector2i p_size, float p_overlap, TileSet::TileOffsetAxis p_offset_axis, TileSet::CellNeighbor p_bit) {
Vector<Vector2> point_list = {
Vector2(3, 3.0 * (1.0 - p_overlap * 2.0)),
Vector2(0, 3),
@@ -2262,12 +2394,11 @@ Vector<Point2> TileSet::_get_half_offset_side_terrain_bit_polygon(Vector2i p_siz
};
Vector2 unit = Vector2(p_size) / 6.0;
- for (int i = 0; i < point_list.size(); i++) {
- point_list.write[i] = point_list[i] * unit;
- }
-
Vector<Vector2> polygon;
if (p_offset_axis == TileSet::TILE_OFFSET_AXIS_HORIZONTAL) {
+ for (int i = 0; i < point_list.size(); i++) {
+ point_list.write[i] = point_list[i] * unit;
+ }
switch (p_bit) {
case TileSet::CELL_NEIGHBOR_RIGHT_SIDE:
polygon.push_back(point_list[5]);
@@ -2297,10 +2428,8 @@ Vector<Point2> TileSet::_get_half_offset_side_terrain_bit_polygon(Vector2i p_siz
break;
}
} else {
- if (p_offset_axis == TileSet::TILE_OFFSET_AXIS_VERTICAL) {
- for (int i = 0; i < point_list.size(); i++) {
- point_list.write[i] = Vector2(point_list[i].y, point_list[i].x);
- }
+ for (int i = 0; i < point_list.size(); i++) {
+ point_list.write[i] = Vector2(point_list[i].y, point_list[i].x) * unit;
}
switch (p_bit) {
case TileSet::CELL_NEIGHBOR_BOTTOM_RIGHT_SIDE:
@@ -5114,36 +5243,51 @@ int TileData::get_terrain_set() const {
return terrain_set;
}
-void TileData::set_peering_bit_terrain(TileSet::CellNeighbor p_peering_bit, int p_terrain_index) {
+void TileData::set_terrain(int p_terrain) {
+ ERR_FAIL_COND(terrain_set < 0);
+ ERR_FAIL_COND(p_terrain < -1);
+ if (tile_set) {
+ ERR_FAIL_COND(p_terrain >= tile_set->get_terrains_count(terrain_set));
+ }
+ terrain = p_terrain;
+ emit_signal(SNAME("changed"));
+}
+
+int TileData::get_terrain() const {
+ return terrain;
+}
+
+void TileData::set_terrain_peering_bit(TileSet::CellNeighbor p_peering_bit, int p_terrain_index) {
ERR_FAIL_INDEX(p_peering_bit, TileSet::CellNeighbor::CELL_NEIGHBOR_MAX);
ERR_FAIL_COND(terrain_set < 0);
ERR_FAIL_COND(p_terrain_index < -1);
if (tile_set) {
ERR_FAIL_COND(p_terrain_index >= tile_set->get_terrains_count(terrain_set));
- ERR_FAIL_COND(!is_valid_peering_bit_terrain(p_peering_bit));
+ ERR_FAIL_COND(!is_valid_terrain_peering_bit(p_peering_bit));
}
terrain_peering_bits[p_peering_bit] = p_terrain_index;
emit_signal(SNAME("changed"));
}
-int TileData::get_peering_bit_terrain(TileSet::CellNeighbor p_peering_bit) const {
- ERR_FAIL_COND_V(!is_valid_peering_bit_terrain(p_peering_bit), -1);
+int TileData::get_terrain_peering_bit(TileSet::CellNeighbor p_peering_bit) const {
+ ERR_FAIL_COND_V(!is_valid_terrain_peering_bit(p_peering_bit), -1);
return terrain_peering_bits[p_peering_bit];
}
-bool TileData::is_valid_peering_bit_terrain(TileSet::CellNeighbor p_peering_bit) const {
+bool TileData::is_valid_terrain_peering_bit(TileSet::CellNeighbor p_peering_bit) const {
ERR_FAIL_COND_V(!tile_set, false);
- return tile_set->is_valid_peering_bit_terrain(terrain_set, p_peering_bit);
+ return tile_set->is_valid_terrain_peering_bit(terrain_set, p_peering_bit);
}
TileSet::TerrainsPattern TileData::get_terrains_pattern() const {
ERR_FAIL_COND_V(!tile_set, TileSet::TerrainsPattern());
TileSet::TerrainsPattern output(tile_set, terrain_set);
+ output.set_terrain(terrain);
for (int i = 0; i < TileSet::CELL_NEIGHBOR_MAX; i++) {
- if (tile_set->is_valid_peering_bit_terrain(terrain_set, TileSet::CellNeighbor(i))) {
- output.set_terrain(TileSet::CellNeighbor(i), get_peering_bit_terrain(TileSet::CellNeighbor(i)));
+ if (tile_set->is_valid_terrain_peering_bit(terrain_set, TileSet::CellNeighbor(i))) {
+ output.set_terrain_peering_bit(TileSet::CellNeighbor(i), get_terrain_peering_bit(TileSet::CellNeighbor(i)));
}
}
return output;
@@ -5293,7 +5437,7 @@ bool TileData::_set(const StringName &p_name, const Variant &p_value) {
for (int i = 0; i < TileSet::CELL_NEIGHBOR_MAX; i++) {
TileSet::CellNeighbor bit = TileSet::CellNeighbor(i);
if (components[1] == TileSet::CELL_NEIGHBOR_ENUM_TO_TEXT[i]) {
- set_peering_bit_terrain(bit, p_value);
+ set_terrain_peering_bit(bit, p_value);
return true;
}
}
@@ -5455,9 +5599,9 @@ void TileData::_get_property_list(List<PropertyInfo> *p_list) const {
p_list->push_back(PropertyInfo(Variant::NIL, "Terrains", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_GROUP));
for (int i = 0; i < TileSet::CELL_NEIGHBOR_MAX; i++) {
TileSet::CellNeighbor bit = TileSet::CellNeighbor(i);
- if (is_valid_peering_bit_terrain(bit)) {
+ if (is_valid_terrain_peering_bit(bit)) {
property_info = PropertyInfo(Variant::INT, "terrains_peering_bit/" + String(TileSet::CELL_NEIGHBOR_ENUM_TO_TEXT[i]));
- if (get_peering_bit_terrain(bit) == -1) {
+ if (get_terrain_peering_bit(bit) == -1) {
property_info.usage ^= PROPERTY_USAGE_STORAGE;
}
p_list->push_back(property_info);
@@ -5531,8 +5675,10 @@ void TileData::_bind_methods() {
// Terrain
ClassDB::bind_method(D_METHOD("set_terrain_set", "terrain_set"), &TileData::set_terrain_set);
ClassDB::bind_method(D_METHOD("get_terrain_set"), &TileData::get_terrain_set);
- ClassDB::bind_method(D_METHOD("set_peering_bit_terrain", "peering_bit", "terrain"), &TileData::set_peering_bit_terrain);
- ClassDB::bind_method(D_METHOD("get_peering_bit_terrain", "peering_bit"), &TileData::get_peering_bit_terrain);
+ ClassDB::bind_method(D_METHOD("set_terrain", "terrain"), &TileData::set_terrain);
+ ClassDB::bind_method(D_METHOD("get_terrain"), &TileData::get_terrain);
+ ClassDB::bind_method(D_METHOD("set_terrain_peering_bit", "peering_bit", "terrain"), &TileData::set_terrain_peering_bit);
+ ClassDB::bind_method(D_METHOD("get_terrain_peering_bit", "peering_bit"), &TileData::get_terrain_peering_bit);
// Navigation
ClassDB::bind_method(D_METHOD("set_navigation_polygon", "layer_id", "navigation_polygon"), &TileData::set_navigation_polygon);
@@ -5560,6 +5706,7 @@ void TileData::_bind_methods() {
ADD_GROUP("Terrains", "");
ADD_PROPERTY(PropertyInfo(Variant::INT, "terrain_set"), "set_terrain_set", "get_terrain_set");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "terrain"), "set_terrain", "get_terrain");
ADD_GROUP("Miscellaneous", "");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "probability"), "set_probability", "get_probability");
diff --git a/scene/resources/tile_set.h b/scene/resources/tile_set.h
index 615ab35615..181782e5af 100644
--- a/scene/resources/tile_set.h
+++ b/scene/resources/tile_set.h
@@ -265,6 +265,7 @@ public:
class TerrainsPattern {
bool valid = false;
+ int terrain = -1;
int bits[TileSet::CELL_NEIGHBOR_MAX];
bool is_valid_bit[TileSet::CELL_NEIGHBOR_MAX];
@@ -277,11 +278,14 @@ public:
bool operator<(const TerrainsPattern &p_terrains_pattern) const;
bool operator==(const TerrainsPattern &p_terrains_pattern) const;
- void set_terrain(TileSet::CellNeighbor p_peering_bit, int p_terrain);
- int get_terrain(TileSet::CellNeighbor p_peering_bit) const;
+ void set_terrain(int p_terrain);
+ int get_terrain() const;
- void set_terrains_from_array(Array p_terrains);
- Array get_terrains_as_array() const;
+ void set_terrain_peering_bit(TileSet::CellNeighbor p_peering_bit, int p_terrain);
+ int get_terrain_peering_bit(TileSet::CellNeighbor p_peering_bit) const;
+
+ void from_array(Array p_terrains);
+ Array as_array() const;
TerrainsPattern(const TileSet *p_tile_set, int p_terrain_set);
TerrainsPattern() {}
@@ -333,7 +337,8 @@ private:
};
Vector<TerrainSet> terrain_sets;
- HashMap<TerrainMode, HashMap<CellNeighbor, Ref<ArrayMesh>>> terrain_bits_meshes;
+ HashMap<TerrainMode, Ref<ArrayMesh>> terrain_meshes;
+ HashMap<TerrainMode, HashMap<CellNeighbor, Ref<ArrayMesh>>> terrain_peering_bits_meshes;
bool terrain_bits_meshes_dirty = true;
LocalVector<RBMap<TileSet::TerrainsPattern, RBSet<TileMapCell>>> per_terrain_pattern_tiles; // Cached data.
@@ -371,17 +376,20 @@ private:
RBMap<Array, Array> alternative_level_proxies;
// Helpers
- Vector<Point2> _get_square_corner_or_side_terrain_bit_polygon(Vector2i p_size, TileSet::CellNeighbor p_bit);
- Vector<Point2> _get_square_corner_terrain_bit_polygon(Vector2i p_size, TileSet::CellNeighbor p_bit);
- Vector<Point2> _get_square_side_terrain_bit_polygon(Vector2i p_size, TileSet::CellNeighbor p_bit);
+ Vector<Point2> _get_square_terrain_polygon(Vector2i p_size);
+ Vector<Point2> _get_square_corner_or_side_terrain_peering_bit_polygon(Vector2i p_size, TileSet::CellNeighbor p_bit);
+ Vector<Point2> _get_square_corner_terrain_peering_bit_polygon(Vector2i p_size, TileSet::CellNeighbor p_bit);
+ Vector<Point2> _get_square_side_terrain_peering_bit_polygon(Vector2i p_size, TileSet::CellNeighbor p_bit);
- Vector<Point2> _get_isometric_corner_or_side_terrain_bit_polygon(Vector2i p_size, TileSet::CellNeighbor p_bit);
- Vector<Point2> _get_isometric_corner_terrain_bit_polygon(Vector2i p_size, TileSet::CellNeighbor p_bit);
- Vector<Point2> _get_isometric_side_terrain_bit_polygon(Vector2i p_size, TileSet::CellNeighbor p_bit);
+ Vector<Point2> _get_isometric_terrain_polygon(Vector2i p_size);
+ Vector<Point2> _get_isometric_corner_or_side_terrain_peering_bit_polygon(Vector2i p_size, TileSet::CellNeighbor p_bit);
+ Vector<Point2> _get_isometric_corner_terrain_peering_bit_polygon(Vector2i p_size, TileSet::CellNeighbor p_bit);
+ Vector<Point2> _get_isometric_side_terrain_peering_bit_polygon(Vector2i p_size, TileSet::CellNeighbor p_bit);
- Vector<Point2> _get_half_offset_corner_or_side_terrain_bit_polygon(Vector2i p_size, TileSet::CellNeighbor p_bit, float p_overlap, TileSet::TileOffsetAxis p_offset_axis);
- Vector<Point2> _get_half_offset_corner_terrain_bit_polygon(Vector2i p_size, TileSet::CellNeighbor p_bit, float p_overlap, TileSet::TileOffsetAxis p_offset_axis);
- Vector<Point2> _get_half_offset_side_terrain_bit_polygon(Vector2i p_size, TileSet::CellNeighbor p_bit, float p_overlap, TileSet::TileOffsetAxis p_offset_axis);
+ Vector<Point2> _get_half_offset_terrain_polygon(Vector2i p_size, float p_overlap, TileSet::TileOffsetAxis p_offset_axis);
+ Vector<Point2> _get_half_offset_corner_or_side_terrain_peering_bit_polygon(Vector2i p_size, float p_overlap, TileSet::TileOffsetAxis p_offset_axis, TileSet::CellNeighbor p_bit);
+ Vector<Point2> _get_half_offset_corner_terrain_peering_bit_polygon(Vector2i p_size, float p_overlap, TileSet::TileOffsetAxis p_offset_axis, TileSet::CellNeighbor p_bit);
+ Vector<Point2> _get_half_offset_side_terrain_peering_bit_polygon(Vector2i p_size, float p_overlap, TileSet::TileOffsetAxis p_offset_axis, TileSet::CellNeighbor p_bit);
protected:
static void _bind_methods();
@@ -454,8 +462,8 @@ public:
String get_terrain_name(int p_terrain_set, int p_terrain_index) const;
void set_terrain_color(int p_terrain_set, int p_terrain_index, Color p_color);
Color get_terrain_color(int p_terrain_set, int p_terrain_index) const;
- bool is_valid_peering_bit_for_mode(TileSet::TerrainMode p_terrain_mode, TileSet::CellNeighbor p_peering_bit) const;
- bool is_valid_peering_bit_terrain(int p_terrain_set, TileSet::CellNeighbor p_peering_bit) const;
+ bool is_valid_terrain_peering_bit_for_mode(TileSet::TerrainMode p_terrain_mode, TileSet::CellNeighbor p_peering_bit) const;
+ bool is_valid_terrain_peering_bit(int p_terrain_set, TileSet::CellNeighbor p_peering_bit) const;
// Navigation
int get_navigation_layers_count() const;
@@ -516,7 +524,8 @@ public:
Vector<Vector2> get_tile_shape_polygon();
void draw_tile_shape(CanvasItem *p_canvas_item, Transform2D p_transform, Color p_color, bool p_filled = false, Ref<Texture2D> p_texture = Ref<Texture2D>());
- Vector<Point2> get_terrain_bit_polygon(int p_terrain_set, TileSet::CellNeighbor p_bit);
+ Vector<Point2> get_terrain_polygon(int p_terrain_set);
+ Vector<Point2> get_terrain_peering_bit_polygon(int p_terrain_set, TileSet::CellNeighbor p_bit);
void draw_terrains(CanvasItem *p_canvas_item, Transform2D p_transform, const TileData *p_tile_data);
Vector<Vector<Ref<Texture2D>>> generate_terrains_icons(Size2i p_size);
@@ -798,6 +807,7 @@ private:
// Terrain
int terrain_set = -1;
+ int terrain = -1;
int terrain_peering_bits[16] = { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 };
// Navigation
@@ -887,9 +897,11 @@ public:
// Terrain
void set_terrain_set(int p_terrain_id);
int get_terrain_set() const;
- void set_peering_bit_terrain(TileSet::CellNeighbor p_peering_bit, int p_terrain_id);
- int get_peering_bit_terrain(TileSet::CellNeighbor p_peering_bit) const;
- bool is_valid_peering_bit_terrain(TileSet::CellNeighbor p_peering_bit) const;
+ void set_terrain(int p_terrain_id);
+ int get_terrain() const;
+ void set_terrain_peering_bit(TileSet::CellNeighbor p_peering_bit, int p_terrain_id);
+ int get_terrain_peering_bit(TileSet::CellNeighbor p_peering_bit) const;
+ bool is_valid_terrain_peering_bit(TileSet::CellNeighbor p_peering_bit) const;
TileSet::TerrainsPattern get_terrains_pattern() const; // Not exposed.
diff --git a/scene/resources/visual_shader.cpp b/scene/resources/visual_shader.cpp
index a1a23124a3..0ab9ef7e16 100644
--- a/scene/resources/visual_shader.cpp
+++ b/scene/resources/visual_shader.cpp
@@ -3528,7 +3528,8 @@ const VisualShaderNodeOutput::Port VisualShaderNodeOutput::ports[] = {
{ Shader::MODE_SPATIAL, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_VECTOR_3D, "Binormal", "BINORMAL" },
{ Shader::MODE_SPATIAL, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_VECTOR_2D, "UV", "UV" },
{ Shader::MODE_SPATIAL, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_VECTOR_2D, "UV2", "UV2" },
- { Shader::MODE_SPATIAL, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_VECTOR_4D, "Color", "COLOR" },
+ { Shader::MODE_SPATIAL, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_VECTOR_3D, "Color", "COLOR.rgb" },
+ { Shader::MODE_SPATIAL, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_SCALAR, "Alpha", "COLOR.a" },
{ Shader::MODE_SPATIAL, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_SCALAR, "Roughness", "ROUGHNESS" },
{ Shader::MODE_SPATIAL, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_SCALAR, "Point Size", "POINT_SIZE" },
{ Shader::MODE_SPATIAL, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_TRANSFORM, "Model View Matrix", "MODELVIEW_MATRIX" },
@@ -3576,12 +3577,14 @@ const VisualShaderNodeOutput::Port VisualShaderNodeOutput::ports[] = {
////////////////////////////////////////////////////////////////////////
{ Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_VECTOR_2D, "Vertex", "VERTEX" },
{ Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_VECTOR_2D, "UV", "UV" },
- { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_VECTOR_4D, "Color", "COLOR" },
+ { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_VECTOR_3D, "Color", "COLOR.rgb" },
+ { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_SCALAR, "Alpha", "COLOR.a" },
{ Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_SCALAR, "Point Size", "POINT_SIZE" },
////////////////////////////////////////////////////////////////////////
// Canvas Item, Fragment.
////////////////////////////////////////////////////////////////////////
- { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_VECTOR_4D, "Color", "COLOR" },
+ { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_VECTOR_3D, "Color", "COLOR.rgb" },
+ { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_SCALAR, "Alpha", "COLOR.a" },
{ Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_VECTOR_3D, "Normal", "NORMAL" },
{ Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_VECTOR_3D, "Normal Map", "NORMAL_MAP" },
{ Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_SCALAR, "Normal Map Depth", "NORMAL_MAP_DEPTH" },
@@ -3590,14 +3593,16 @@ const VisualShaderNodeOutput::Port VisualShaderNodeOutput::ports[] = {
////////////////////////////////////////////////////////////////////////
// Canvas Item, Light.
////////////////////////////////////////////////////////////////////////
- { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_LIGHT, VisualShaderNode::PORT_TYPE_VECTOR_4D, "Light", "LIGHT" },
+ { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_LIGHT, VisualShaderNode::PORT_TYPE_VECTOR_3D, "Light", "LIGHT.rgb" },
+ { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_LIGHT, VisualShaderNode::PORT_TYPE_SCALAR, "Light Alpha", "LIGHT.a" },
////////////////////////////////////////////////////////////////////////
// Sky, Sky.
////////////////////////////////////////////////////////////////////////
{ Shader::MODE_SKY, VisualShader::TYPE_SKY, VisualShaderNode::PORT_TYPE_VECTOR_3D, "Color", "COLOR" },
{ Shader::MODE_SKY, VisualShader::TYPE_SKY, VisualShaderNode::PORT_TYPE_SCALAR, "Alpha", "ALPHA" },
- { Shader::MODE_SKY, VisualShader::TYPE_SKY, VisualShaderNode::PORT_TYPE_VECTOR_4D, "Fog", "FOG" },
+ { Shader::MODE_SKY, VisualShader::TYPE_SKY, VisualShaderNode::PORT_TYPE_VECTOR_3D, "Fog", "FOG.rgb" },
+ { Shader::MODE_SKY, VisualShader::TYPE_SKY, VisualShaderNode::PORT_TYPE_SCALAR, "Fog Alpha", "FOG.a" },
////////////////////////////////////////////////////////////////////////
// Fog, Fog.
diff --git a/scene/resources/world_2d.cpp b/scene/resources/world_2d.cpp
index 9d8e0f7547..4dfbe5f079 100644
--- a/scene/resources/world_2d.cpp
+++ b/scene/resources/world_2d.cpp
@@ -73,8 +73,8 @@ World2D::World2D() {
// Create and configure space2D to be more friendly with pixels than meters
space = PhysicsServer2D::get_singleton()->space_create();
PhysicsServer2D::get_singleton()->space_set_active(space, true);
- PhysicsServer2D::get_singleton()->area_set_param(space, PhysicsServer2D::AREA_PARAM_GRAVITY, GLOBAL_DEF("physics/2d/default_gravity", 980.0));
- PhysicsServer2D::get_singleton()->area_set_param(space, PhysicsServer2D::AREA_PARAM_GRAVITY_VECTOR, GLOBAL_DEF("physics/2d/default_gravity_vector", Vector2(0, 1)));
+ PhysicsServer2D::get_singleton()->area_set_param(space, PhysicsServer2D::AREA_PARAM_GRAVITY, GLOBAL_DEF_BASIC("physics/2d/default_gravity", 980.0));
+ PhysicsServer2D::get_singleton()->area_set_param(space, PhysicsServer2D::AREA_PARAM_GRAVITY_VECTOR, GLOBAL_DEF_BASIC("physics/2d/default_gravity_vector", Vector2(0, 1)));
PhysicsServer2D::get_singleton()->area_set_param(space, PhysicsServer2D::AREA_PARAM_LINEAR_DAMP, GLOBAL_DEF("physics/2d/default_linear_damp", 0.1));
ProjectSettings::get_singleton()->set_custom_property_info("physics/2d/default_linear_damp", PropertyInfo(Variant::FLOAT, "physics/2d/default_linear_damp", PROPERTY_HINT_RANGE, "-1,100,0.001,or_greater"));
PhysicsServer2D::get_singleton()->area_set_param(space, PhysicsServer2D::AREA_PARAM_ANGULAR_DAMP, GLOBAL_DEF("physics/2d/default_angular_damp", 1.0));
diff --git a/scene/resources/world_3d.cpp b/scene/resources/world_3d.cpp
index eb0af63975..a84ee773b4 100644
--- a/scene/resources/world_3d.cpp
+++ b/scene/resources/world_3d.cpp
@@ -141,8 +141,8 @@ World3D::World3D() {
scenario = RenderingServer::get_singleton()->scenario_create();
PhysicsServer3D::get_singleton()->space_set_active(space, true);
- PhysicsServer3D::get_singleton()->area_set_param(space, PhysicsServer3D::AREA_PARAM_GRAVITY, GLOBAL_DEF("physics/3d/default_gravity", 9.8));
- PhysicsServer3D::get_singleton()->area_set_param(space, PhysicsServer3D::AREA_PARAM_GRAVITY_VECTOR, GLOBAL_DEF("physics/3d/default_gravity_vector", Vector3(0, -1, 0)));
+ PhysicsServer3D::get_singleton()->area_set_param(space, PhysicsServer3D::AREA_PARAM_GRAVITY, GLOBAL_DEF_BASIC("physics/3d/default_gravity", 9.8));
+ PhysicsServer3D::get_singleton()->area_set_param(space, PhysicsServer3D::AREA_PARAM_GRAVITY_VECTOR, GLOBAL_DEF_BASIC("physics/3d/default_gravity_vector", Vector3(0, -1, 0)));
PhysicsServer3D::get_singleton()->area_set_param(space, PhysicsServer3D::AREA_PARAM_LINEAR_DAMP, GLOBAL_DEF("physics/3d/default_linear_damp", 0.1));
ProjectSettings::get_singleton()->set_custom_property_info("physics/3d/default_linear_damp", PropertyInfo(Variant::FLOAT, "physics/3d/default_linear_damp", PROPERTY_HINT_RANGE, "0,100,0.001,or_greater"));
PhysicsServer3D::get_singleton()->area_set_param(space, PhysicsServer3D::AREA_PARAM_ANGULAR_DAMP, GLOBAL_DEF("physics/3d/default_angular_damp", 0.1));
diff --git a/servers/audio/audio_stream.cpp b/servers/audio/audio_stream.cpp
index 8399a92be9..3983bc5cb1 100644
--- a/servers/audio/audio_stream.cpp
+++ b/servers/audio/audio_stream.cpp
@@ -699,7 +699,7 @@ void AudioStreamRandomizer::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::INT, "streams_count", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR), "set_streams_count", "get_streams_count");
ADD_PROPERTY(PropertyInfo(Variant::INT, "playback_mode", PROPERTY_HINT_ENUM, "Random (Avoid Repeats),Random,Sequential"), "set_playback_mode", "get_playback_mode");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "random_pitch", PROPERTY_HINT_RANGE, "1,16,0.01"), "set_random_pitch", "get_random_pitch");
- ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "random_volume_offset_db", PROPERTY_HINT_RANGE, "0,40,0"), "set_random_volume_offset_db", "get_random_volume_offset_db");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "random_volume_offset_db", PROPERTY_HINT_RANGE, "0,40,0,suffix:dB"), "set_random_volume_offset_db", "get_random_volume_offset_db");
BIND_ENUM_CONSTANT(PLAYBACK_RANDOM_NO_REPEATS);
BIND_ENUM_CONSTANT(PLAYBACK_RANDOM);
diff --git a/servers/audio/effects/audio_effect_capture.cpp b/servers/audio/effects/audio_effect_capture.cpp
index f605cfc9d4..1f5f5e259a 100644
--- a/servers/audio/effects/audio_effect_capture.cpp
+++ b/servers/audio/effects/audio_effect_capture.cpp
@@ -70,7 +70,7 @@ void AudioEffectCapture::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_buffer_length_frames"), &AudioEffectCapture::get_buffer_length_frames);
ClassDB::bind_method(D_METHOD("get_pushed_frames"), &AudioEffectCapture::get_pushed_frames);
- ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "buffer_length", PROPERTY_HINT_RANGE, "0.01,10,0.01"), "set_buffer_length", "get_buffer_length");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "buffer_length", PROPERTY_HINT_RANGE, "0.01,10,0.01,suffix:s"), "set_buffer_length", "get_buffer_length");
}
Ref<AudioEffectInstance> AudioEffectCapture::instantiate() {
diff --git a/servers/audio/effects/audio_effect_chorus.cpp b/servers/audio/effects/audio_effect_chorus.cpp
index 8b1fe9cfd2..e5434eac02 100644
--- a/servers/audio/effects/audio_effect_chorus.cpp
+++ b/servers/audio/effects/audio_effect_chorus.cpp
@@ -313,32 +313,32 @@ void AudioEffectChorus::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "dry", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_dry", "get_dry");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "wet", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_wet", "get_wet");
- ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "voice/1/delay_ms", PROPERTY_HINT_RANGE, "0,50,0.01"), "set_voice_delay_ms", "get_voice_delay_ms", 0);
- ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "voice/1/rate_hz", PROPERTY_HINT_RANGE, "0.1,20,0.1"), "set_voice_rate_hz", "get_voice_rate_hz", 0);
- ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "voice/1/depth_ms", PROPERTY_HINT_RANGE, "0,20,0.01"), "set_voice_depth_ms", "get_voice_depth_ms", 0);
- ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "voice/1/level_db", PROPERTY_HINT_RANGE, "-60,24,0.1"), "set_voice_level_db", "get_voice_level_db", 0);
- ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "voice/1/cutoff_hz", PROPERTY_HINT_RANGE, "1,20500,1"), "set_voice_cutoff_hz", "get_voice_cutoff_hz", 0);
+ ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "voice/1/delay_ms", PROPERTY_HINT_RANGE, "0,50,0.01,suffix:ms"), "set_voice_delay_ms", "get_voice_delay_ms", 0);
+ ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "voice/1/rate_hz", PROPERTY_HINT_RANGE, "0.1,20,0.1,suffix:Hz"), "set_voice_rate_hz", "get_voice_rate_hz", 0);
+ ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "voice/1/depth_ms", PROPERTY_HINT_RANGE, "0,20,0.01,suffix:ms"), "set_voice_depth_ms", "get_voice_depth_ms", 0);
+ ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "voice/1/level_db", PROPERTY_HINT_RANGE, "-60,24,0.1,suffix:dB"), "set_voice_level_db", "get_voice_level_db", 0);
+ ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "voice/1/cutoff_hz", PROPERTY_HINT_RANGE, "1,20500,1,suffix:Hz"), "set_voice_cutoff_hz", "get_voice_cutoff_hz", 0);
ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "voice/1/pan", PROPERTY_HINT_RANGE, "-1,1,0.01"), "set_voice_pan", "get_voice_pan", 0);
- ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "voice/2/delay_ms", PROPERTY_HINT_RANGE, "0,50,0.01"), "set_voice_delay_ms", "get_voice_delay_ms", 1);
- ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "voice/2/rate_hz", PROPERTY_HINT_RANGE, "0.1,20,0.1"), "set_voice_rate_hz", "get_voice_rate_hz", 1);
- ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "voice/2/depth_ms", PROPERTY_HINT_RANGE, "0,20,0.01"), "set_voice_depth_ms", "get_voice_depth_ms", 1);
- ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "voice/2/level_db", PROPERTY_HINT_RANGE, "-60,24,0.1"), "set_voice_level_db", "get_voice_level_db", 1);
- ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "voice/2/cutoff_hz", PROPERTY_HINT_RANGE, "1,20500,1"), "set_voice_cutoff_hz", "get_voice_cutoff_hz", 1);
+ ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "voice/2/delay_ms", PROPERTY_HINT_RANGE, "0,50,0.01,suffix:ms"), "set_voice_delay_ms", "get_voice_delay_ms", 1);
+ ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "voice/2/rate_hz", PROPERTY_HINT_RANGE, "0.1,20,0.1,suffix:Hz"), "set_voice_rate_hz", "get_voice_rate_hz", 1);
+ ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "voice/2/depth_ms", PROPERTY_HINT_RANGE, "0,20,0.01,suffix:ms"), "set_voice_depth_ms", "get_voice_depth_ms", 1);
+ ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "voice/2/level_db", PROPERTY_HINT_RANGE, "-60,24,0.1,suffix:dB"), "set_voice_level_db", "get_voice_level_db", 1);
+ ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "voice/2/cutoff_hz", PROPERTY_HINT_RANGE, "1,20500,1,suffix:Hz"), "set_voice_cutoff_hz", "get_voice_cutoff_hz", 1);
ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "voice/2/pan", PROPERTY_HINT_RANGE, "-1,1,0.01"), "set_voice_pan", "get_voice_pan", 1);
- ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "voice/3/delay_ms", PROPERTY_HINT_RANGE, "0,50,0.01"), "set_voice_delay_ms", "get_voice_delay_ms", 2);
- ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "voice/3/rate_hz", PROPERTY_HINT_RANGE, "0.1,20,0.1"), "set_voice_rate_hz", "get_voice_rate_hz", 2);
- ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "voice/3/depth_ms", PROPERTY_HINT_RANGE, "0,20,0.01"), "set_voice_depth_ms", "get_voice_depth_ms", 2);
- ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "voice/3/level_db", PROPERTY_HINT_RANGE, "-60,24,0.1"), "set_voice_level_db", "get_voice_level_db", 2);
- ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "voice/3/cutoff_hz", PROPERTY_HINT_RANGE, "1,20500,1"), "set_voice_cutoff_hz", "get_voice_cutoff_hz", 2);
+ ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "voice/3/delay_ms", PROPERTY_HINT_RANGE, "0,50,0.01,suffix:ms"), "set_voice_delay_ms", "get_voice_delay_ms", 2);
+ ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "voice/3/rate_hz", PROPERTY_HINT_RANGE, "0.1,20,0.1,suffix:Hz"), "set_voice_rate_hz", "get_voice_rate_hz", 2);
+ ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "voice/3/depth_ms", PROPERTY_HINT_RANGE, "0,20,0.01,suffix:ms"), "set_voice_depth_ms", "get_voice_depth_ms", 2);
+ ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "voice/3/level_db", PROPERTY_HINT_RANGE, "-60,24,0.1,suffix:dB"), "set_voice_level_db", "get_voice_level_db", 2);
+ ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "voice/3/cutoff_hz", PROPERTY_HINT_RANGE, "1,20500,1,suffix:Hz"), "set_voice_cutoff_hz", "get_voice_cutoff_hz", 2);
ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "voice/3/pan", PROPERTY_HINT_RANGE, "-1,1,0.01"), "set_voice_pan", "get_voice_pan", 2);
- ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "voice/4/delay_ms", PROPERTY_HINT_RANGE, "0,50,0.01"), "set_voice_delay_ms", "get_voice_delay_ms", 3);
- ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "voice/4/rate_hz", PROPERTY_HINT_RANGE, "0.1,20,0.1"), "set_voice_rate_hz", "get_voice_rate_hz", 3);
- ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "voice/4/depth_ms", PROPERTY_HINT_RANGE, "0,20,0.01"), "set_voice_depth_ms", "get_voice_depth_ms", 3);
- ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "voice/4/level_db", PROPERTY_HINT_RANGE, "-60,24,0.1"), "set_voice_level_db", "get_voice_level_db", 3);
- ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "voice/4/cutoff_hz", PROPERTY_HINT_RANGE, "1,20500,1"), "set_voice_cutoff_hz", "get_voice_cutoff_hz", 3);
+ ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "voice/4/delay_ms", PROPERTY_HINT_RANGE, "0,50,0.01,suffix:ms"), "set_voice_delay_ms", "get_voice_delay_ms", 3);
+ ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "voice/4/rate_hz", PROPERTY_HINT_RANGE, "0.1,20,0.1,suffix:Hz"), "set_voice_rate_hz", "get_voice_rate_hz", 3);
+ ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "voice/4/depth_ms", PROPERTY_HINT_RANGE, "0,20,0.01,suffix:ms"), "set_voice_depth_ms", "get_voice_depth_ms", 3);
+ ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "voice/4/level_db", PROPERTY_HINT_RANGE, "-60,24,0.1,suffix:dB"), "set_voice_level_db", "get_voice_level_db", 3);
+ ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "voice/4/cutoff_hz", PROPERTY_HINT_RANGE, "1,20500,1,suffix:Hz"), "set_voice_cutoff_hz", "get_voice_cutoff_hz", 3);
ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "voice/4/pan", PROPERTY_HINT_RANGE, "-1,1,0.01"), "set_voice_pan", "get_voice_pan", 3);
}
diff --git a/servers/audio/effects/audio_effect_compressor.cpp b/servers/audio/effects/audio_effect_compressor.cpp
index f75d092dd3..ee71a6dba7 100644
--- a/servers/audio/effects/audio_effect_compressor.cpp
+++ b/servers/audio/effects/audio_effect_compressor.cpp
@@ -221,8 +221,8 @@ void AudioEffectCompressor::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "threshold", PROPERTY_HINT_RANGE, "-60,0,0.1"), "set_threshold", "get_threshold");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "ratio", PROPERTY_HINT_RANGE, "1,48,0.1"), "set_ratio", "get_ratio");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "gain", PROPERTY_HINT_RANGE, "-20,20,0.1"), "set_gain", "get_gain");
- ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "attack_us", PROPERTY_HINT_RANGE, "20,2000,1"), "set_attack_us", "get_attack_us");
- ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "release_ms", PROPERTY_HINT_RANGE, "20,2000,1"), "set_release_ms", "get_release_ms");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "attack_us", PROPERTY_HINT_RANGE, U"20,2000,1,suffix:\u00B5s"), "set_attack_us", "get_attack_us");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "release_ms", PROPERTY_HINT_RANGE, "20,2000,1,suffix:ms"), "set_release_ms", "get_release_ms");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "mix", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_mix", "get_mix");
ADD_PROPERTY(PropertyInfo(Variant::STRING_NAME, "sidechain", PROPERTY_HINT_ENUM), "set_sidechain", "get_sidechain");
}
diff --git a/servers/audio/effects/audio_effect_delay.cpp b/servers/audio/effects/audio_effect_delay.cpp
index 1909ab6eae..80e7a8223c 100644
--- a/servers/audio/effects/audio_effect_delay.cpp
+++ b/servers/audio/effects/audio_effect_delay.cpp
@@ -287,18 +287,18 @@ void AudioEffectDelay::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "dry", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_dry", "get_dry");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "tap1/active"), "set_tap1_active", "is_tap1_active");
- ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "tap1/delay_ms", PROPERTY_HINT_RANGE, "0,1500,1"), "set_tap1_delay_ms", "get_tap1_delay_ms");
- ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "tap1/level_db", PROPERTY_HINT_RANGE, "-60,0,0.01"), "set_tap1_level_db", "get_tap1_level_db");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "tap1/delay_ms", PROPERTY_HINT_RANGE, "0,1500,1,suffix:ms"), "set_tap1_delay_ms", "get_tap1_delay_ms");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "tap1/level_db", PROPERTY_HINT_RANGE, "-60,0,0.01,suffix:dB"), "set_tap1_level_db", "get_tap1_level_db");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "tap1/pan", PROPERTY_HINT_RANGE, "-1,1,0.01"), "set_tap1_pan", "get_tap1_pan");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "tap2/active"), "set_tap2_active", "is_tap2_active");
- ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "tap2/delay_ms", PROPERTY_HINT_RANGE, "0,1500,1"), "set_tap2_delay_ms", "get_tap2_delay_ms");
- ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "tap2/level_db", PROPERTY_HINT_RANGE, "-60,0,0.01"), "set_tap2_level_db", "get_tap2_level_db");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "tap2/delay_ms", PROPERTY_HINT_RANGE, "0,1500,1,suffix:ms"), "set_tap2_delay_ms", "get_tap2_delay_ms");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "tap2/level_db", PROPERTY_HINT_RANGE, "-60,0,0.01,suffix:dB"), "set_tap2_level_db", "get_tap2_level_db");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "tap2/pan", PROPERTY_HINT_RANGE, "-1,1,0.01"), "set_tap2_pan", "get_tap2_pan");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "feedback/active"), "set_feedback_active", "is_feedback_active");
- ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "feedback/delay_ms", PROPERTY_HINT_RANGE, "0,1500,1"), "set_feedback_delay_ms", "get_feedback_delay_ms");
- ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "feedback/level_db", PROPERTY_HINT_RANGE, "-60,0,0.01"), "set_feedback_level_db", "get_feedback_level_db");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "feedback/delay_ms", PROPERTY_HINT_RANGE, "0,1500,1,suffix:ms"), "set_feedback_delay_ms", "get_feedback_delay_ms");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "feedback/level_db", PROPERTY_HINT_RANGE, "-60,0,0.01,suffix:dB"), "set_feedback_level_db", "get_feedback_level_db");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "feedback/lowpass", PROPERTY_HINT_RANGE, "1,16000,1"), "set_feedback_lowpass", "get_feedback_lowpass");
}
diff --git a/servers/audio/effects/audio_effect_distortion.cpp b/servers/audio/effects/audio_effect_distortion.cpp
index afc4353bd7..6820d796a4 100644
--- a/servers/audio/effects/audio_effect_distortion.cpp
+++ b/servers/audio/effects/audio_effect_distortion.cpp
@@ -161,7 +161,7 @@ void AudioEffectDistortion::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::INT, "mode", PROPERTY_HINT_ENUM, "Clip,ATan,LoFi,Overdrive,Wave Shape"), "set_mode", "get_mode");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "pre_gain", PROPERTY_HINT_RANGE, "-60,60,0.01"), "set_pre_gain", "get_pre_gain");
- ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "keep_hf_hz", PROPERTY_HINT_RANGE, "1,20500,1"), "set_keep_hf_hz", "get_keep_hf_hz");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "keep_hf_hz", PROPERTY_HINT_RANGE, "1,20500,1,suffix:Hz"), "set_keep_hf_hz", "get_keep_hf_hz");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "drive", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_drive", "get_drive");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "post_gain", PROPERTY_HINT_RANGE, "-80,24,0.01"), "set_post_gain", "get_post_gain");
diff --git a/servers/audio/effects/audio_effect_filter.cpp b/servers/audio/effects/audio_effect_filter.cpp
index 06e66f22b1..a9409076cd 100644
--- a/servers/audio/effects/audio_effect_filter.cpp
+++ b/servers/audio/effects/audio_effect_filter.cpp
@@ -153,7 +153,7 @@ void AudioEffectFilter::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_db", "amount"), &AudioEffectFilter::set_db);
ClassDB::bind_method(D_METHOD("get_db"), &AudioEffectFilter::get_db);
- ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "cutoff_hz", PROPERTY_HINT_RANGE, "1,20500,1"), "set_cutoff", "get_cutoff");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "cutoff_hz", PROPERTY_HINT_RANGE, "1,20500,1,suffix:Hz"), "set_cutoff", "get_cutoff");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "resonance", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_resonance", "get_resonance");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "gain", PROPERTY_HINT_RANGE, "0,4,0.01"), "set_gain", "get_gain");
ADD_PROPERTY(PropertyInfo(Variant::INT, "db", PROPERTY_HINT_ENUM, "6 dB,12 dB,18 dB,24 dB"), "set_db", "get_db");
diff --git a/servers/audio/effects/audio_effect_limiter.cpp b/servers/audio/effects/audio_effect_limiter.cpp
index 5923cf8cf5..7bcd68d48b 100644
--- a/servers/audio/effects/audio_effect_limiter.cpp
+++ b/servers/audio/effects/audio_effect_limiter.cpp
@@ -120,9 +120,9 @@ void AudioEffectLimiter::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_soft_clip_ratio", "soft_clip"), &AudioEffectLimiter::set_soft_clip_ratio);
ClassDB::bind_method(D_METHOD("get_soft_clip_ratio"), &AudioEffectLimiter::get_soft_clip_ratio);
- ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "ceiling_db", PROPERTY_HINT_RANGE, "-20,-0.1,0.1"), "set_ceiling_db", "get_ceiling_db");
- ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "threshold_db", PROPERTY_HINT_RANGE, "-30,0,0.1"), "set_threshold_db", "get_threshold_db");
- ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "soft_clip_db", PROPERTY_HINT_RANGE, "0,6,0.1"), "set_soft_clip_db", "get_soft_clip_db");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "ceiling_db", PROPERTY_HINT_RANGE, "-20,-0.1,0.1,suffix:dB"), "set_ceiling_db", "get_ceiling_db");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "threshold_db", PROPERTY_HINT_RANGE, "-30,0,0.1,suffix:dB"), "set_threshold_db", "get_threshold_db");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "soft_clip_db", PROPERTY_HINT_RANGE, "0,6,0.1,suffix:dB"), "set_soft_clip_db", "get_soft_clip_db");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "soft_clip_ratio", PROPERTY_HINT_RANGE, "3,20,0.1"), "set_soft_clip_ratio", "get_soft_clip_ratio");
}
diff --git a/servers/audio/effects/audio_effect_phaser.cpp b/servers/audio/effects/audio_effect_phaser.cpp
index af5dce707e..2f86630ce9 100644
--- a/servers/audio/effects/audio_effect_phaser.cpp
+++ b/servers/audio/effects/audio_effect_phaser.cpp
@@ -144,9 +144,9 @@ void AudioEffectPhaser::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_depth", "depth"), &AudioEffectPhaser::set_depth);
ClassDB::bind_method(D_METHOD("get_depth"), &AudioEffectPhaser::get_depth);
- ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "range_min_hz", PROPERTY_HINT_RANGE, "10,10000"), "set_range_min_hz", "get_range_min_hz");
- ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "range_max_hz", PROPERTY_HINT_RANGE, "10,10000"), "set_range_max_hz", "get_range_max_hz");
- ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "rate_hz", PROPERTY_HINT_RANGE, "0.01,20"), "set_rate_hz", "get_rate_hz");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "range_min_hz", PROPERTY_HINT_RANGE, "10,10000,suffix:Hz"), "set_range_min_hz", "get_range_min_hz");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "range_max_hz", PROPERTY_HINT_RANGE, "10,10000,suffix:Hz"), "set_range_max_hz", "get_range_max_hz");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "rate_hz", PROPERTY_HINT_RANGE, "0.01,20,suffix:Hz"), "set_rate_hz", "get_rate_hz");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "feedback", PROPERTY_HINT_RANGE, "0.1,0.9,0.1"), "set_feedback", "get_feedback");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "depth", PROPERTY_HINT_RANGE, "0.1,4,0.1"), "set_depth", "get_depth");
}
diff --git a/servers/audio/effects/audio_effect_reverb.cpp b/servers/audio/effects/audio_effect_reverb.cpp
index 0d4eb14e6a..bfc68152a4 100644
--- a/servers/audio/effects/audio_effect_reverb.cpp
+++ b/servers/audio/effects/audio_effect_reverb.cpp
@@ -176,7 +176,7 @@ void AudioEffectReverb::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_hpf"), &AudioEffectReverb::get_hpf);
ADD_GROUP("Predelay", "predelay_");
- ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "predelay_msec", PROPERTY_HINT_RANGE, "20,500,1"), "set_predelay_msec", "get_predelay_msec");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "predelay_msec", PROPERTY_HINT_RANGE, "20,500,1,suffix:ms"), "set_predelay_msec", "get_predelay_msec");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "predelay_feedback", PROPERTY_HINT_RANGE, "0,0.98,0.01"), "set_predelay_feedback", "get_predelay_feedback");
ADD_GROUP("", "");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "room_size", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_room_size", "get_room_size");
diff --git a/servers/audio/effects/audio_effect_spectrum_analyzer.cpp b/servers/audio/effects/audio_effect_spectrum_analyzer.cpp
index 10627be74c..30ebf626ae 100644
--- a/servers/audio/effects/audio_effect_spectrum_analyzer.cpp
+++ b/servers/audio/effects/audio_effect_spectrum_analyzer.cpp
@@ -264,7 +264,7 @@ void AudioEffectSpectrumAnalyzer::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_fft_size", "size"), &AudioEffectSpectrumAnalyzer::set_fft_size);
ClassDB::bind_method(D_METHOD("get_fft_size"), &AudioEffectSpectrumAnalyzer::get_fft_size);
- ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "buffer_length", PROPERTY_HINT_RANGE, "0.1,4,0.1"), "set_buffer_length", "get_buffer_length");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "buffer_length", PROPERTY_HINT_RANGE, "0.1,4,0.1,suffix:s"), "set_buffer_length", "get_buffer_length");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "tap_back_pos", PROPERTY_HINT_RANGE, "0.1,4,0.1"), "set_tap_back_pos", "get_tap_back_pos");
ADD_PROPERTY(PropertyInfo(Variant::INT, "fft_size", PROPERTY_HINT_ENUM, "256,512,1024,2048,4096"), "set_fft_size", "get_fft_size");
diff --git a/servers/audio/effects/audio_effect_stereo_enhance.cpp b/servers/audio/effects/audio_effect_stereo_enhance.cpp
index 7bb62bcbed..e567add3e7 100644
--- a/servers/audio/effects/audio_effect_stereo_enhance.cpp
+++ b/servers/audio/effects/audio_effect_stereo_enhance.cpp
@@ -138,7 +138,7 @@ void AudioEffectStereoEnhance::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_surround"), &AudioEffectStereoEnhance::get_surround);
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "pan_pullout", PROPERTY_HINT_RANGE, "0,4,0.01"), "set_pan_pullout", "get_pan_pullout");
- ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "time_pullout_ms", PROPERTY_HINT_RANGE, "0,50,0.01"), "set_time_pullout", "get_time_pullout");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "time_pullout_ms", PROPERTY_HINT_RANGE, "0,50,0.01,suffix:ms"), "set_time_pullout", "get_time_pullout");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "surround", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_surround", "get_surround");
}
diff --git a/servers/audio/effects/audio_stream_generator.cpp b/servers/audio/effects/audio_stream_generator.cpp
index a3d615b925..46de1692e4 100644
--- a/servers/audio/effects/audio_stream_generator.cpp
+++ b/servers/audio/effects/audio_stream_generator.cpp
@@ -75,8 +75,8 @@ void AudioStreamGenerator::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_buffer_length", "seconds"), &AudioStreamGenerator::set_buffer_length);
ClassDB::bind_method(D_METHOD("get_buffer_length"), &AudioStreamGenerator::get_buffer_length);
- ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "mix_rate", PROPERTY_HINT_RANGE, "20,192000,1"), "set_mix_rate", "get_mix_rate");
- ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "buffer_length", PROPERTY_HINT_RANGE, "0.01,10,0.01"), "set_buffer_length", "get_buffer_length");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "mix_rate", PROPERTY_HINT_RANGE, "20,192000,1,suffix:Hz"), "set_mix_rate", "get_mix_rate");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "buffer_length", PROPERTY_HINT_RANGE, "0.01,10,0.01,suffix:s"), "set_buffer_length", "get_buffer_length");
}
AudioStreamGenerator::AudioStreamGenerator() {
diff --git a/servers/navigation_server_2d.cpp b/servers/navigation_server_2d.cpp
index ab323e76e8..0442089503 100644
--- a/servers/navigation_server_2d.cpp
+++ b/servers/navigation_server_2d.cpp
@@ -166,7 +166,7 @@ void NavigationServer2D::_bind_methods() {
ClassDB::bind_method(D_METHOD("map_get_cell_size", "map"), &NavigationServer2D::map_get_cell_size);
ClassDB::bind_method(D_METHOD("map_set_edge_connection_margin", "map", "margin"), &NavigationServer2D::map_set_edge_connection_margin);
ClassDB::bind_method(D_METHOD("map_get_edge_connection_margin", "map"), &NavigationServer2D::map_get_edge_connection_margin);
- ClassDB::bind_method(D_METHOD("map_get_path", "map", "origin", "destination", "optimize", "layers"), &NavigationServer2D::map_get_path, DEFVAL(1));
+ ClassDB::bind_method(D_METHOD("map_get_path", "map", "origin", "destination", "optimize", "navigation_layers"), &NavigationServer2D::map_get_path, DEFVAL(1));
ClassDB::bind_method(D_METHOD("map_get_closest_point", "map", "to_point"), &NavigationServer2D::map_get_closest_point);
ClassDB::bind_method(D_METHOD("map_get_closest_point_owner", "map", "to_point"), &NavigationServer2D::map_get_closest_point_owner);
@@ -180,8 +180,8 @@ void NavigationServer2D::_bind_methods() {
ClassDB::bind_method(D_METHOD("region_get_travel_cost", "region"), &NavigationServer2D::region_get_travel_cost);
ClassDB::bind_method(D_METHOD("region_set_map", "region", "map"), &NavigationServer2D::region_set_map);
ClassDB::bind_method(D_METHOD("region_get_map", "region"), &NavigationServer2D::region_get_map);
- ClassDB::bind_method(D_METHOD("region_set_layers", "region", "layers"), &NavigationServer2D::region_set_layers);
- ClassDB::bind_method(D_METHOD("region_get_layers", "region"), &NavigationServer2D::region_get_layers);
+ ClassDB::bind_method(D_METHOD("region_set_navigation_layers", "region", "navigation_layers"), &NavigationServer2D::region_set_navigation_layers);
+ ClassDB::bind_method(D_METHOD("region_get_navigation_layers", "region"), &NavigationServer2D::region_get_navigation_layers);
ClassDB::bind_method(D_METHOD("region_set_transform", "region", "transform"), &NavigationServer2D::region_set_transform);
ClassDB::bind_method(D_METHOD("region_set_navpoly", "region", "nav_poly"), &NavigationServer2D::region_set_navpoly);
ClassDB::bind_method(D_METHOD("region_get_connections_count", "region"), &NavigationServer2D::region_get_connections_count);
@@ -250,8 +250,8 @@ void FORWARD_2_C(region_set_travel_cost, RID, p_region, real_t, p_travel_cost, r
real_t FORWARD_1_C(region_get_travel_cost, RID, p_region, rid_to_rid);
void FORWARD_2_C(region_set_map, RID, p_region, RID, p_map, rid_to_rid, rid_to_rid);
-void FORWARD_2_C(region_set_layers, RID, p_region, uint32_t, p_layers, rid_to_rid, uint32_to_uint32);
-uint32_t FORWARD_1_C(region_get_layers, RID, p_region, rid_to_rid);
+void FORWARD_2_C(region_set_navigation_layers, RID, p_region, uint32_t, p_navigation_layers, rid_to_rid, uint32_to_uint32);
+uint32_t FORWARD_1_C(region_get_navigation_layers, RID, p_region, rid_to_rid);
void FORWARD_2_C(region_set_transform, RID, p_region, Transform2D, p_transform, rid_to_rid, trf2_to_trf3);
void NavigationServer2D::region_set_navpoly(RID p_region, Ref<NavigationPolygon> p_nav_mesh) const {
diff --git a/servers/navigation_server_2d.h b/servers/navigation_server_2d.h
index 8e285147b1..30f553d10b 100644
--- a/servers/navigation_server_2d.h
+++ b/servers/navigation_server_2d.h
@@ -75,7 +75,7 @@ public:
virtual real_t map_get_edge_connection_margin(RID p_map) const;
/// Returns the navigation path to reach the destination from the origin.
- virtual Vector<Vector2> map_get_path(RID p_map, Vector2 p_origin, Vector2 p_destination, bool p_optimize, uint32_t p_layers = 1) const;
+ virtual Vector<Vector2> map_get_path(RID p_map, Vector2 p_origin, Vector2 p_destination, bool p_optimize, uint32_t p_navigation_layers = 1) const;
virtual Vector2 map_get_closest_point(RID p_map, const Vector2 &p_point) const;
virtual RID map_get_closest_point_owner(RID p_map, const Vector2 &p_point) const;
@@ -99,8 +99,8 @@ public:
virtual RID region_get_map(RID p_region) const;
/// Set the region's layers
- virtual void region_set_layers(RID p_region, uint32_t p_layers) const;
- virtual uint32_t region_get_layers(RID p_region) const;
+ virtual void region_set_navigation_layers(RID p_region, uint32_t p_navigation_layers) const;
+ virtual uint32_t region_get_navigation_layers(RID p_region) const;
/// Set the global transformation of this region.
virtual void region_set_transform(RID p_region, Transform2D p_transform) const;
diff --git a/servers/navigation_server_3d.cpp b/servers/navigation_server_3d.cpp
index 6d99f6dfbb..60bbcec8d4 100644
--- a/servers/navigation_server_3d.cpp
+++ b/servers/navigation_server_3d.cpp
@@ -42,7 +42,7 @@ void NavigationServer3D::_bind_methods() {
ClassDB::bind_method(D_METHOD("map_get_cell_size", "map"), &NavigationServer3D::map_get_cell_size);
ClassDB::bind_method(D_METHOD("map_set_edge_connection_margin", "map", "margin"), &NavigationServer3D::map_set_edge_connection_margin);
ClassDB::bind_method(D_METHOD("map_get_edge_connection_margin", "map"), &NavigationServer3D::map_get_edge_connection_margin);
- ClassDB::bind_method(D_METHOD("map_get_path", "map", "origin", "destination", "optimize", "layers"), &NavigationServer3D::map_get_path, DEFVAL(1));
+ ClassDB::bind_method(D_METHOD("map_get_path", "map", "origin", "destination", "optimize", "navigation_layers"), &NavigationServer3D::map_get_path, DEFVAL(1));
ClassDB::bind_method(D_METHOD("map_get_closest_point_to_segment", "map", "start", "end", "use_collision"), &NavigationServer3D::map_get_closest_point_to_segment, DEFVAL(false));
ClassDB::bind_method(D_METHOD("map_get_closest_point", "map", "to_point"), &NavigationServer3D::map_get_closest_point);
ClassDB::bind_method(D_METHOD("map_get_closest_point_normal", "map", "to_point"), &NavigationServer3D::map_get_closest_point_normal);
@@ -58,8 +58,8 @@ void NavigationServer3D::_bind_methods() {
ClassDB::bind_method(D_METHOD("region_get_travel_cost", "region"), &NavigationServer3D::region_get_travel_cost);
ClassDB::bind_method(D_METHOD("region_set_map", "region", "map"), &NavigationServer3D::region_set_map);
ClassDB::bind_method(D_METHOD("region_get_map", "region"), &NavigationServer3D::region_get_map);
- ClassDB::bind_method(D_METHOD("region_set_layers", "region", "layers"), &NavigationServer3D::region_set_layers);
- ClassDB::bind_method(D_METHOD("region_get_layers", "region"), &NavigationServer3D::region_get_layers);
+ ClassDB::bind_method(D_METHOD("region_set_navigation_layers", "region", "navigation_layers"), &NavigationServer3D::region_set_navigation_layers);
+ ClassDB::bind_method(D_METHOD("region_get_navigation_layers", "region"), &NavigationServer3D::region_get_navigation_layers);
ClassDB::bind_method(D_METHOD("region_set_transform", "region", "transform"), &NavigationServer3D::region_set_transform);
ClassDB::bind_method(D_METHOD("region_set_navmesh", "region", "nav_mesh"), &NavigationServer3D::region_set_navmesh);
ClassDB::bind_method(D_METHOD("region_bake_navmesh", "mesh", "node"), &NavigationServer3D::region_bake_navmesh);
diff --git a/servers/navigation_server_3d.h b/servers/navigation_server_3d.h
index 9b7e48e8d1..9c04d68622 100644
--- a/servers/navigation_server_3d.h
+++ b/servers/navigation_server_3d.h
@@ -84,7 +84,7 @@ public:
virtual real_t map_get_edge_connection_margin(RID p_map) const = 0;
/// Returns the navigation path to reach the destination from the origin.
- virtual Vector<Vector3> map_get_path(RID p_map, Vector3 p_origin, Vector3 p_destination, bool p_optimize, uint32_t p_navigable_layers = 1) const = 0;
+ virtual Vector<Vector3> map_get_path(RID p_map, Vector3 p_origin, Vector3 p_destination, bool p_optimize, uint32_t p_navigation_layers = 1) const = 0;
virtual Vector3 map_get_closest_point_to_segment(RID p_map, const Vector3 &p_from, const Vector3 &p_to, const bool p_use_collision = false) const = 0;
virtual Vector3 map_get_closest_point(RID p_map, const Vector3 &p_point) const = 0;
@@ -110,8 +110,8 @@ public:
virtual RID region_get_map(RID p_region) const = 0;
/// Set the region's layers
- virtual void region_set_layers(RID p_region, uint32_t p_layers) const = 0;
- virtual uint32_t region_get_layers(RID p_region) const = 0;
+ virtual void region_set_navigation_layers(RID p_region, uint32_t p_navigation_layers) const = 0;
+ virtual uint32_t region_get_navigation_layers(RID p_region) const = 0;
/// Set the global transformation of this region.
virtual void region_set_transform(RID p_region, Transform3D p_transform) const = 0;
diff --git a/servers/rendering/renderer_rd/renderer_scene_render_rd.cpp b/servers/rendering/renderer_rd/renderer_scene_render_rd.cpp
index a1c6ff540d..ef959bc3c6 100644
--- a/servers/rendering/renderer_rd/renderer_scene_render_rd.cpp
+++ b/servers/rendering/renderer_rd/renderer_scene_render_rd.cpp
@@ -3457,7 +3457,9 @@ void RendererSceneRenderRD::_setup_lights(const PagedArray<RID> &p_lights, const
// technically this will keep expanding until reaching the sun, but all we care
// is expand until we reach the radius of the near plane (there can't be more occluders than that)
angular_diameter = Math::tan(Math::deg2rad(angular_diameter));
- if (light_storage->light_has_shadow(base)) {
+ if (light_storage->light_has_shadow(base) && light_storage->light_get_param(base, RS::LIGHT_PARAM_SHADOW_BLUR) > 0.0) {
+ // Only enable PCSS-like soft shadows if blurring is enabled.
+ // Otherwise, performance would decrease with no visual difference.
r_directional_light_soft_shadows = true;
}
} else {
@@ -3736,7 +3738,9 @@ void RendererSceneRenderRD::_setup_lights(const PagedArray<RID> &p_lights, const
RendererStorageRD::store_transform(proj, light_data.shadow_matrix);
- if (size > 0.0) {
+ if (size > 0.0 && light_data.soft_shadow_scale > 0.0) {
+ // Only enable PCSS-like soft shadows if blurring is enabled.
+ // Otherwise, performance would decrease with no visual difference.
light_data.soft_shadow_size = size;
} else {
light_data.soft_shadow_size = 0.0;
@@ -3753,7 +3757,9 @@ void RendererSceneRenderRD::_setup_lights(const PagedArray<RID> &p_lights, const
CameraMatrix shadow_mtx = bias * li->shadow_transform[0].camera * modelview;
RendererStorageRD::store_camera(shadow_mtx, light_data.shadow_matrix);
- if (size > 0.0) {
+ if (size > 0.0 && light_data.soft_shadow_scale > 0.0) {
+ // Only enable PCSS-like soft shadows if blurring is enabled.
+ // Otherwise, performance would decrease with no visual difference.
CameraMatrix cm = li->shadow_transform[0].camera;
float half_np = cm.get_z_near() * Math::tan(Math::deg2rad(spot_angle));
light_data.soft_shadow_size = (size * 0.5 / radius) / (half_np / cm.get_z_near()) * rect.size.width;
diff --git a/servers/rendering/shader_language.cpp b/servers/rendering/shader_language.cpp
index f9469fcae0..ad9b51ac0c 100644
--- a/servers/rendering/shader_language.cpp
+++ b/servers/rendering/shader_language.cpp
@@ -1858,21 +1858,21 @@ const ShaderLanguage::BuiltinFuncDef ShaderLanguage::builtin_func_defs[] = {
{ "ivec4", TYPE_IVEC4, { TYPE_IVEC3, TYPE_INT, TYPE_VOID }, { "" }, TAG_GLOBAL, false },
{ "ivec4", TYPE_IVEC4, { TYPE_IVEC2, TYPE_IVEC2, TYPE_VOID }, { "" }, TAG_GLOBAL, false },
- { "uint", TYPE_UINT, { TYPE_UINT, TYPE_VOID }, { "" }, TAG_GLOBAL, true },
- { "uvec2", TYPE_UVEC2, { TYPE_UINT, TYPE_VOID }, { "" }, TAG_GLOBAL, true },
- { "uvec2", TYPE_UVEC2, { TYPE_UINT, TYPE_UINT, TYPE_VOID }, { "" }, TAG_GLOBAL, true },
- { "uvec3", TYPE_UVEC3, { TYPE_UINT, TYPE_VOID }, { "" }, TAG_GLOBAL, true },
- { "uvec3", TYPE_UVEC3, { TYPE_UINT, TYPE_UINT, TYPE_UINT, TYPE_VOID }, { "" }, TAG_GLOBAL, true },
- { "uvec3", TYPE_UVEC3, { TYPE_UVEC2, TYPE_UINT, TYPE_VOID }, { "" }, TAG_GLOBAL, true },
- { "uvec3", TYPE_UVEC3, { TYPE_UINT, TYPE_UVEC2, TYPE_VOID }, { "" }, TAG_GLOBAL, true },
- { "uvec4", TYPE_UVEC4, { TYPE_UINT, TYPE_VOID }, { "" }, TAG_GLOBAL, true },
- { "uvec4", TYPE_UVEC4, { TYPE_UINT, TYPE_UINT, TYPE_UINT, TYPE_UINT, TYPE_VOID }, { "" }, TAG_GLOBAL, true },
- { "uvec4", TYPE_UVEC4, { TYPE_UINT, TYPE_UVEC2, TYPE_UINT, TYPE_VOID }, { "" }, TAG_GLOBAL, true },
- { "uvec4", TYPE_UVEC4, { TYPE_UVEC2, TYPE_UINT, TYPE_UINT, TYPE_VOID }, { "" }, TAG_GLOBAL, true },
- { "uvec4", TYPE_UVEC4, { TYPE_UINT, TYPE_UINT, TYPE_UVEC2, TYPE_VOID }, { "" }, TAG_GLOBAL, true },
- { "uvec4", TYPE_UVEC4, { TYPE_UINT, TYPE_UVEC3, TYPE_VOID }, { "" }, TAG_GLOBAL, true },
- { "uvec4", TYPE_UVEC4, { TYPE_UVEC3, TYPE_UINT, TYPE_VOID }, { "" }, TAG_GLOBAL, true },
- { "uvec4", TYPE_UVEC4, { TYPE_UVEC2, TYPE_UVEC2, TYPE_VOID }, { "" }, TAG_GLOBAL, true },
+ { "uint", TYPE_UINT, { TYPE_UINT, TYPE_VOID }, { "" }, TAG_GLOBAL, false },
+ { "uvec2", TYPE_UVEC2, { TYPE_UINT, TYPE_VOID }, { "" }, TAG_GLOBAL, false },
+ { "uvec2", TYPE_UVEC2, { TYPE_UINT, TYPE_UINT, TYPE_VOID }, { "" }, TAG_GLOBAL, false },
+ { "uvec3", TYPE_UVEC3, { TYPE_UINT, TYPE_VOID }, { "" }, TAG_GLOBAL, false },
+ { "uvec3", TYPE_UVEC3, { TYPE_UINT, TYPE_UINT, TYPE_UINT, TYPE_VOID }, { "" }, TAG_GLOBAL, false },
+ { "uvec3", TYPE_UVEC3, { TYPE_UVEC2, TYPE_UINT, TYPE_VOID }, { "" }, TAG_GLOBAL, false },
+ { "uvec3", TYPE_UVEC3, { TYPE_UINT, TYPE_UVEC2, TYPE_VOID }, { "" }, TAG_GLOBAL, false },
+ { "uvec4", TYPE_UVEC4, { TYPE_UINT, TYPE_VOID }, { "" }, TAG_GLOBAL, false },
+ { "uvec4", TYPE_UVEC4, { TYPE_UINT, TYPE_UINT, TYPE_UINT, TYPE_UINT, TYPE_VOID }, { "" }, TAG_GLOBAL, false },
+ { "uvec4", TYPE_UVEC4, { TYPE_UINT, TYPE_UVEC2, TYPE_UINT, TYPE_VOID }, { "" }, TAG_GLOBAL, false },
+ { "uvec4", TYPE_UVEC4, { TYPE_UVEC2, TYPE_UINT, TYPE_UINT, TYPE_VOID }, { "" }, TAG_GLOBAL, false },
+ { "uvec4", TYPE_UVEC4, { TYPE_UINT, TYPE_UINT, TYPE_UVEC2, TYPE_VOID }, { "" }, TAG_GLOBAL, false },
+ { "uvec4", TYPE_UVEC4, { TYPE_UINT, TYPE_UVEC3, TYPE_VOID }, { "" }, TAG_GLOBAL, false },
+ { "uvec4", TYPE_UVEC4, { TYPE_UVEC3, TYPE_UINT, TYPE_VOID }, { "" }, TAG_GLOBAL, false },
+ { "uvec4", TYPE_UVEC4, { TYPE_UVEC2, TYPE_UVEC2, TYPE_VOID }, { "" }, TAG_GLOBAL, false },
{ "mat2", TYPE_MAT2, { TYPE_VEC2, TYPE_VEC2, TYPE_VOID }, { "" }, TAG_GLOBAL, false },
{ "mat3", TYPE_MAT3, { TYPE_VEC3, TYPE_VEC3, TYPE_VEC3, TYPE_VOID }, { "" }, TAG_GLOBAL, false },
@@ -1886,22 +1886,22 @@ const ShaderLanguage::BuiltinFuncDef ShaderLanguage::builtin_func_defs[] = {
{ "int", TYPE_INT, { TYPE_BOOL, TYPE_VOID }, { "" }, TAG_GLOBAL, false },
{ "int", TYPE_INT, { TYPE_INT, TYPE_VOID }, { "" }, TAG_GLOBAL, false },
- { "int", TYPE_INT, { TYPE_UINT, TYPE_VOID }, { "" }, TAG_GLOBAL, true },
+ { "int", TYPE_INT, { TYPE_UINT, TYPE_VOID }, { "" }, TAG_GLOBAL, false },
{ "int", TYPE_INT, { TYPE_FLOAT, TYPE_VOID }, { "" }, TAG_GLOBAL, false },
{ "float", TYPE_FLOAT, { TYPE_BOOL, TYPE_VOID }, { "" }, TAG_GLOBAL, false },
{ "float", TYPE_FLOAT, { TYPE_INT, TYPE_VOID }, { "" }, TAG_GLOBAL, false },
- { "float", TYPE_FLOAT, { TYPE_UINT, TYPE_VOID }, { "" }, TAG_GLOBAL, true },
+ { "float", TYPE_FLOAT, { TYPE_UINT, TYPE_VOID }, { "" }, TAG_GLOBAL, false },
{ "float", TYPE_FLOAT, { TYPE_FLOAT, TYPE_VOID }, { "" }, TAG_GLOBAL, false },
- { "uint", TYPE_UINT, { TYPE_BOOL, TYPE_VOID }, { "" }, TAG_GLOBAL, true },
- { "uint", TYPE_UINT, { TYPE_INT, TYPE_VOID }, { "" }, TAG_GLOBAL, true },
- { "uint", TYPE_UINT, { TYPE_UINT, TYPE_VOID }, { "" }, TAG_GLOBAL, true },
- { "uint", TYPE_UINT, { TYPE_FLOAT, TYPE_VOID }, { "" }, TAG_GLOBAL, true },
+ { "uint", TYPE_UINT, { TYPE_BOOL, TYPE_VOID }, { "" }, TAG_GLOBAL, false },
+ { "uint", TYPE_UINT, { TYPE_INT, TYPE_VOID }, { "" }, TAG_GLOBAL, false },
+ { "uint", TYPE_UINT, { TYPE_UINT, TYPE_VOID }, { "" }, TAG_GLOBAL, false },
+ { "uint", TYPE_UINT, { TYPE_FLOAT, TYPE_VOID }, { "" }, TAG_GLOBAL, false },
{ "bool", TYPE_BOOL, { TYPE_BOOL, TYPE_VOID }, { "" }, TAG_GLOBAL, false },
{ "bool", TYPE_BOOL, { TYPE_INT, TYPE_VOID }, { "" }, TAG_GLOBAL, false },
- { "bool", TYPE_BOOL, { TYPE_UINT, TYPE_VOID }, { "" }, TAG_GLOBAL, true },
+ { "bool", TYPE_BOOL, { TYPE_UINT, TYPE_VOID }, { "" }, TAG_GLOBAL, false },
{ "bool", TYPE_BOOL, { TYPE_FLOAT, TYPE_VOID }, { "" }, TAG_GLOBAL, false },
// Conversion vectors.
@@ -1913,57 +1913,57 @@ const ShaderLanguage::BuiltinFuncDef ShaderLanguage::builtin_func_defs[] = {
{ "vec2", TYPE_VEC2, { TYPE_BVEC2, TYPE_VOID }, { "" }, TAG_GLOBAL, false },
{ "vec2", TYPE_VEC2, { TYPE_IVEC2, TYPE_VOID }, { "" }, TAG_GLOBAL, false },
- { "vec2", TYPE_VEC2, { TYPE_UVEC2, TYPE_VOID }, { "" }, TAG_GLOBAL, true },
+ { "vec2", TYPE_VEC2, { TYPE_UVEC2, TYPE_VOID }, { "" }, TAG_GLOBAL, false },
{ "vec2", TYPE_VEC2, { TYPE_VEC2, TYPE_VOID }, { "" }, TAG_GLOBAL, false },
- { "uvec2", TYPE_UVEC2, { TYPE_BVEC2, TYPE_VOID }, { "" }, TAG_GLOBAL, true },
- { "uvec2", TYPE_UVEC2, { TYPE_IVEC2, TYPE_VOID }, { "" }, TAG_GLOBAL, true },
- { "uvec2", TYPE_UVEC2, { TYPE_UVEC2, TYPE_VOID }, { "" }, TAG_GLOBAL, true },
- { "uvec2", TYPE_UVEC2, { TYPE_VEC2, TYPE_VOID }, { "" }, TAG_GLOBAL, true },
+ { "uvec2", TYPE_UVEC2, { TYPE_BVEC2, TYPE_VOID }, { "" }, TAG_GLOBAL, false },
+ { "uvec2", TYPE_UVEC2, { TYPE_IVEC2, TYPE_VOID }, { "" }, TAG_GLOBAL, false },
+ { "uvec2", TYPE_UVEC2, { TYPE_UVEC2, TYPE_VOID }, { "" }, TAG_GLOBAL, false },
+ { "uvec2", TYPE_UVEC2, { TYPE_VEC2, TYPE_VOID }, { "" }, TAG_GLOBAL, false },
{ "bvec2", TYPE_BVEC2, { TYPE_BVEC2, TYPE_VOID }, { "" }, TAG_GLOBAL, false },
{ "bvec2", TYPE_BVEC2, { TYPE_IVEC2, TYPE_VOID }, { "" }, TAG_GLOBAL, false },
- { "bvec2", TYPE_BVEC2, { TYPE_UVEC2, TYPE_VOID }, { "" }, TAG_GLOBAL, true },
+ { "bvec2", TYPE_BVEC2, { TYPE_UVEC2, TYPE_VOID }, { "" }, TAG_GLOBAL, false },
{ "bvec2", TYPE_BVEC2, { TYPE_VEC2, TYPE_VOID }, { "" }, TAG_GLOBAL, false },
{ "ivec3", TYPE_IVEC3, { TYPE_BVEC3, TYPE_VOID }, { "" }, TAG_GLOBAL, false },
{ "ivec3", TYPE_IVEC3, { TYPE_IVEC3, TYPE_VOID }, { "" }, TAG_GLOBAL, false },
- { "ivec3", TYPE_IVEC3, { TYPE_UVEC3, TYPE_VOID }, { "" }, TAG_GLOBAL, true },
+ { "ivec3", TYPE_IVEC3, { TYPE_UVEC3, TYPE_VOID }, { "" }, TAG_GLOBAL, false },
{ "ivec3", TYPE_IVEC3, { TYPE_VEC3, TYPE_VOID }, { "" }, TAG_GLOBAL, false },
{ "vec3", TYPE_VEC3, { TYPE_BVEC3, TYPE_VOID }, { "" }, TAG_GLOBAL, false },
{ "vec3", TYPE_VEC3, { TYPE_IVEC3, TYPE_VOID }, { "" }, TAG_GLOBAL, false },
- { "vec3", TYPE_VEC3, { TYPE_UVEC3, TYPE_VOID }, { "" }, TAG_GLOBAL, true },
+ { "vec3", TYPE_VEC3, { TYPE_UVEC3, TYPE_VOID }, { "" }, TAG_GLOBAL, false },
{ "vec3", TYPE_VEC3, { TYPE_VEC3, TYPE_VOID }, { "" }, TAG_GLOBAL, false },
- { "uvec3", TYPE_UVEC3, { TYPE_BVEC3, TYPE_VOID }, { "" }, TAG_GLOBAL, true },
- { "uvec3", TYPE_UVEC3, { TYPE_IVEC3, TYPE_VOID }, { "" }, TAG_GLOBAL, true },
- { "uvec3", TYPE_UVEC3, { TYPE_UVEC3, TYPE_VOID }, { "" }, TAG_GLOBAL, true },
- { "uvec3", TYPE_UVEC3, { TYPE_VEC3, TYPE_VOID }, { "" }, TAG_GLOBAL, true },
+ { "uvec3", TYPE_UVEC3, { TYPE_BVEC3, TYPE_VOID }, { "" }, TAG_GLOBAL, false },
+ { "uvec3", TYPE_UVEC3, { TYPE_IVEC3, TYPE_VOID }, { "" }, TAG_GLOBAL, false },
+ { "uvec3", TYPE_UVEC3, { TYPE_UVEC3, TYPE_VOID }, { "" }, TAG_GLOBAL, false },
+ { "uvec3", TYPE_UVEC3, { TYPE_VEC3, TYPE_VOID }, { "" }, TAG_GLOBAL, false },
{ "bvec3", TYPE_BVEC3, { TYPE_BVEC3, TYPE_VOID }, { "" }, TAG_GLOBAL, false },
{ "bvec3", TYPE_BVEC3, { TYPE_IVEC3, TYPE_VOID }, { "" }, TAG_GLOBAL, false },
- { "bvec3", TYPE_BVEC3, { TYPE_UVEC3, TYPE_VOID }, { "" }, TAG_GLOBAL, true },
+ { "bvec3", TYPE_BVEC3, { TYPE_UVEC3, TYPE_VOID }, { "" }, TAG_GLOBAL, false },
{ "bvec3", TYPE_BVEC3, { TYPE_VEC3, TYPE_VOID }, { "" }, TAG_GLOBAL, false },
{ "ivec4", TYPE_IVEC4, { TYPE_BVEC4, TYPE_VOID }, { "" }, TAG_GLOBAL, false },
{ "ivec4", TYPE_IVEC4, { TYPE_IVEC4, TYPE_VOID }, { "" }, TAG_GLOBAL, false },
- { "ivec4", TYPE_IVEC4, { TYPE_UVEC4, TYPE_VOID }, { "" }, TAG_GLOBAL, true },
+ { "ivec4", TYPE_IVEC4, { TYPE_UVEC4, TYPE_VOID }, { "" }, TAG_GLOBAL, false },
{ "ivec4", TYPE_IVEC4, { TYPE_VEC4, TYPE_VOID }, { "" }, TAG_GLOBAL, false },
{ "vec4", TYPE_VEC4, { TYPE_BVEC4, TYPE_VOID }, { "" }, TAG_GLOBAL, false },
{ "vec4", TYPE_VEC4, { TYPE_IVEC4, TYPE_VOID }, { "" }, TAG_GLOBAL, false },
- { "vec4", TYPE_VEC4, { TYPE_UVEC4, TYPE_VOID }, { "" }, TAG_GLOBAL, true },
+ { "vec4", TYPE_VEC4, { TYPE_UVEC4, TYPE_VOID }, { "" }, TAG_GLOBAL, false },
{ "vec4", TYPE_VEC4, { TYPE_VEC4, TYPE_VOID }, { "" }, TAG_GLOBAL, false },
- { "uvec4", TYPE_UVEC4, { TYPE_BVEC4, TYPE_VOID }, { "" }, TAG_GLOBAL, true },
- { "uvec4", TYPE_UVEC4, { TYPE_IVEC4, TYPE_VOID }, { "" }, TAG_GLOBAL, true },
- { "uvec4", TYPE_UVEC4, { TYPE_UVEC4, TYPE_VOID }, { "" }, TAG_GLOBAL, true },
- { "uvec4", TYPE_UVEC4, { TYPE_VEC4, TYPE_VOID }, { "" }, TAG_GLOBAL, true },
+ { "uvec4", TYPE_UVEC4, { TYPE_BVEC4, TYPE_VOID }, { "" }, TAG_GLOBAL, false },
+ { "uvec4", TYPE_UVEC4, { TYPE_IVEC4, TYPE_VOID }, { "" }, TAG_GLOBAL, false },
+ { "uvec4", TYPE_UVEC4, { TYPE_UVEC4, TYPE_VOID }, { "" }, TAG_GLOBAL, false },
+ { "uvec4", TYPE_UVEC4, { TYPE_VEC4, TYPE_VOID }, { "" }, TAG_GLOBAL, false },
{ "bvec4", TYPE_BVEC4, { TYPE_BVEC4, TYPE_VOID }, { "" }, TAG_GLOBAL, false },
{ "bvec4", TYPE_BVEC4, { TYPE_IVEC4, TYPE_VOID }, { "" }, TAG_GLOBAL, false },
- { "bvec4", TYPE_BVEC4, { TYPE_UVEC4, TYPE_VOID }, { "" }, TAG_GLOBAL, true },
+ { "bvec4", TYPE_BVEC4, { TYPE_UVEC4, TYPE_VOID }, { "" }, TAG_GLOBAL, false },
{ "bvec4", TYPE_BVEC4, { TYPE_VEC4, TYPE_VOID }, { "" }, TAG_GLOBAL, false },
// Conversion between matrixes.
@@ -2207,10 +2207,10 @@ const ShaderLanguage::BuiltinFuncDef ShaderLanguage::builtin_func_defs[] = {
// modf
- { "modf", TYPE_FLOAT, { TYPE_FLOAT, TYPE_FLOAT, TYPE_VOID }, { "x", "i" }, TAG_GLOBAL, true },
- { "modf", TYPE_VEC2, { TYPE_VEC2, TYPE_VEC2, TYPE_VOID }, { "x", "i" }, TAG_GLOBAL, true },
- { "modf", TYPE_VEC3, { TYPE_VEC3, TYPE_VEC3, TYPE_VOID }, { "x", "i" }, TAG_GLOBAL, true },
- { "modf", TYPE_VEC4, { TYPE_VEC4, TYPE_VEC4, TYPE_VOID }, { "x", "i" }, TAG_GLOBAL, true },
+ { "modf", TYPE_FLOAT, { TYPE_FLOAT, TYPE_FLOAT, TYPE_VOID }, { "x", "i" }, TAG_GLOBAL, false },
+ { "modf", TYPE_VEC2, { TYPE_VEC2, TYPE_VEC2, TYPE_VOID }, { "x", "i" }, TAG_GLOBAL, false },
+ { "modf", TYPE_VEC3, { TYPE_VEC3, TYPE_VEC3, TYPE_VOID }, { "x", "i" }, TAG_GLOBAL, false },
+ { "modf", TYPE_VEC4, { TYPE_VEC4, TYPE_VEC4, TYPE_VOID }, { "x", "i" }, TAG_GLOBAL, false },
// min
@@ -2230,13 +2230,13 @@ const ShaderLanguage::BuiltinFuncDef ShaderLanguage::builtin_func_defs[] = {
{ "min", TYPE_IVEC4, { TYPE_IVEC4, TYPE_IVEC4, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, false },
{ "min", TYPE_IVEC4, { TYPE_IVEC4, TYPE_INT, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, false },
- { "min", TYPE_UINT, { TYPE_UINT, TYPE_UINT, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, true },
- { "min", TYPE_UVEC2, { TYPE_UVEC2, TYPE_UVEC2, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, true },
- { "min", TYPE_UVEC2, { TYPE_UVEC2, TYPE_UINT, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, true },
- { "min", TYPE_UVEC3, { TYPE_UVEC3, TYPE_UVEC3, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, true },
- { "min", TYPE_UVEC3, { TYPE_UVEC3, TYPE_UINT, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, true },
- { "min", TYPE_UVEC4, { TYPE_UVEC4, TYPE_UVEC4, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, true },
- { "min", TYPE_UVEC4, { TYPE_UVEC4, TYPE_UINT, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, true },
+ { "min", TYPE_UINT, { TYPE_UINT, TYPE_UINT, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, false },
+ { "min", TYPE_UVEC2, { TYPE_UVEC2, TYPE_UVEC2, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, false },
+ { "min", TYPE_UVEC2, { TYPE_UVEC2, TYPE_UINT, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, false },
+ { "min", TYPE_UVEC3, { TYPE_UVEC3, TYPE_UVEC3, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, false },
+ { "min", TYPE_UVEC3, { TYPE_UVEC3, TYPE_UINT, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, false },
+ { "min", TYPE_UVEC4, { TYPE_UVEC4, TYPE_UVEC4, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, false },
+ { "min", TYPE_UVEC4, { TYPE_UVEC4, TYPE_UINT, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, false },
// max
@@ -2256,13 +2256,13 @@ const ShaderLanguage::BuiltinFuncDef ShaderLanguage::builtin_func_defs[] = {
{ "max", TYPE_IVEC4, { TYPE_IVEC4, TYPE_IVEC4, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, false },
{ "max", TYPE_IVEC4, { TYPE_IVEC4, TYPE_INT, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, false },
- { "max", TYPE_UINT, { TYPE_UINT, TYPE_UINT, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, true },
- { "max", TYPE_UVEC2, { TYPE_UVEC2, TYPE_UVEC2, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, true },
- { "max", TYPE_UVEC2, { TYPE_UVEC2, TYPE_UINT, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, true },
- { "max", TYPE_UVEC3, { TYPE_UVEC3, TYPE_UVEC3, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, true },
- { "max", TYPE_UVEC3, { TYPE_UVEC3, TYPE_UINT, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, true },
- { "max", TYPE_UVEC4, { TYPE_UVEC4, TYPE_UVEC4, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, true },
- { "max", TYPE_UVEC4, { TYPE_UVEC4, TYPE_UINT, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, true },
+ { "max", TYPE_UINT, { TYPE_UINT, TYPE_UINT, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, false },
+ { "max", TYPE_UVEC2, { TYPE_UVEC2, TYPE_UVEC2, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, false },
+ { "max", TYPE_UVEC2, { TYPE_UVEC2, TYPE_UINT, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, false },
+ { "max", TYPE_UVEC3, { TYPE_UVEC3, TYPE_UVEC3, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, false },
+ { "max", TYPE_UVEC3, { TYPE_UVEC3, TYPE_UINT, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, false },
+ { "max", TYPE_UVEC4, { TYPE_UVEC4, TYPE_UVEC4, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, false },
+ { "max", TYPE_UVEC4, { TYPE_UVEC4, TYPE_UINT, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, false },
// clamp
@@ -2282,13 +2282,13 @@ const ShaderLanguage::BuiltinFuncDef ShaderLanguage::builtin_func_defs[] = {
{ "clamp", TYPE_IVEC3, { TYPE_IVEC3, TYPE_INT, TYPE_INT, TYPE_VOID }, { "x", "minVal", "maxVal" }, TAG_GLOBAL, false },
{ "clamp", TYPE_IVEC4, { TYPE_IVEC4, TYPE_INT, TYPE_INT, TYPE_VOID }, { "x", "minVal", "maxVal" }, TAG_GLOBAL, false },
- { "clamp", TYPE_UINT, { TYPE_UINT, TYPE_UINT, TYPE_UINT, TYPE_VOID }, { "x", "minVal", "maxVal" }, TAG_GLOBAL, true },
- { "clamp", TYPE_UVEC2, { TYPE_UVEC2, TYPE_UVEC2, TYPE_UVEC2, TYPE_VOID }, { "x", "minVal", "maxVal" }, TAG_GLOBAL, true },
- { "clamp", TYPE_UVEC3, { TYPE_UVEC3, TYPE_UVEC3, TYPE_UVEC3, TYPE_VOID }, { "x", "minVal", "maxVal" }, TAG_GLOBAL, true },
- { "clamp", TYPE_UVEC4, { TYPE_UVEC4, TYPE_UVEC4, TYPE_UVEC4, TYPE_VOID }, { "x", "minVal", "maxVal" }, TAG_GLOBAL, true },
- { "clamp", TYPE_UVEC2, { TYPE_UVEC2, TYPE_UINT, TYPE_UINT, TYPE_VOID }, { "x", "minVal", "maxVal" }, TAG_GLOBAL, true },
- { "clamp", TYPE_UVEC3, { TYPE_UVEC3, TYPE_UINT, TYPE_UINT, TYPE_VOID }, { "x", "minVal", "maxVal" }, TAG_GLOBAL, true },
- { "clamp", TYPE_UVEC4, { TYPE_UVEC4, TYPE_UINT, TYPE_UINT, TYPE_VOID }, { "x", "minVal", "maxVal" }, TAG_GLOBAL, true },
+ { "clamp", TYPE_UINT, { TYPE_UINT, TYPE_UINT, TYPE_UINT, TYPE_VOID }, { "x", "minVal", "maxVal" }, TAG_GLOBAL, false },
+ { "clamp", TYPE_UVEC2, { TYPE_UVEC2, TYPE_UVEC2, TYPE_UVEC2, TYPE_VOID }, { "x", "minVal", "maxVal" }, TAG_GLOBAL, false },
+ { "clamp", TYPE_UVEC3, { TYPE_UVEC3, TYPE_UVEC3, TYPE_UVEC3, TYPE_VOID }, { "x", "minVal", "maxVal" }, TAG_GLOBAL, false },
+ { "clamp", TYPE_UVEC4, { TYPE_UVEC4, TYPE_UVEC4, TYPE_UVEC4, TYPE_VOID }, { "x", "minVal", "maxVal" }, TAG_GLOBAL, false },
+ { "clamp", TYPE_UVEC2, { TYPE_UVEC2, TYPE_UINT, TYPE_UINT, TYPE_VOID }, { "x", "minVal", "maxVal" }, TAG_GLOBAL, false },
+ { "clamp", TYPE_UVEC3, { TYPE_UVEC3, TYPE_UINT, TYPE_UINT, TYPE_VOID }, { "x", "minVal", "maxVal" }, TAG_GLOBAL, false },
+ { "clamp", TYPE_UVEC4, { TYPE_UVEC4, TYPE_UINT, TYPE_UINT, TYPE_VOID }, { "x", "minVal", "maxVal" }, TAG_GLOBAL, false },
// mix
@@ -2339,31 +2339,31 @@ const ShaderLanguage::BuiltinFuncDef ShaderLanguage::builtin_func_defs[] = {
// floatBitsToInt
- { "floatBitsToInt", TYPE_INT, { TYPE_FLOAT, TYPE_VOID }, { "x" }, TAG_GLOBAL, true },
- { "floatBitsToInt", TYPE_IVEC2, { TYPE_VEC2, TYPE_VOID }, { "x" }, TAG_GLOBAL, true },
- { "floatBitsToInt", TYPE_IVEC3, { TYPE_VEC3, TYPE_VOID }, { "x" }, TAG_GLOBAL, true },
- { "floatBitsToInt", TYPE_IVEC4, { TYPE_VEC4, TYPE_VOID }, { "x" }, TAG_GLOBAL, true },
+ { "floatBitsToInt", TYPE_INT, { TYPE_FLOAT, TYPE_VOID }, { "x" }, TAG_GLOBAL, false },
+ { "floatBitsToInt", TYPE_IVEC2, { TYPE_VEC2, TYPE_VOID }, { "x" }, TAG_GLOBAL, false },
+ { "floatBitsToInt", TYPE_IVEC3, { TYPE_VEC3, TYPE_VOID }, { "x" }, TAG_GLOBAL, false },
+ { "floatBitsToInt", TYPE_IVEC4, { TYPE_VEC4, TYPE_VOID }, { "x" }, TAG_GLOBAL, false },
// floatBitsToUint
- { "floatBitsToUint", TYPE_UINT, { TYPE_FLOAT, TYPE_VOID }, { "x" }, TAG_GLOBAL, true },
- { "floatBitsToUint", TYPE_UVEC2, { TYPE_VEC2, TYPE_VOID }, { "x" }, TAG_GLOBAL, true },
- { "floatBitsToUint", TYPE_UVEC3, { TYPE_VEC3, TYPE_VOID }, { "x" }, TAG_GLOBAL, true },
- { "floatBitsToUint", TYPE_UVEC4, { TYPE_VEC4, TYPE_VOID }, { "x" }, TAG_GLOBAL, true },
+ { "floatBitsToUint", TYPE_UINT, { TYPE_FLOAT, TYPE_VOID }, { "x" }, TAG_GLOBAL, false },
+ { "floatBitsToUint", TYPE_UVEC2, { TYPE_VEC2, TYPE_VOID }, { "x" }, TAG_GLOBAL, false },
+ { "floatBitsToUint", TYPE_UVEC3, { TYPE_VEC3, TYPE_VOID }, { "x" }, TAG_GLOBAL, false },
+ { "floatBitsToUint", TYPE_UVEC4, { TYPE_VEC4, TYPE_VOID }, { "x" }, TAG_GLOBAL, false },
// intBitsToFloat
- { "intBitsToFloat", TYPE_FLOAT, { TYPE_INT, TYPE_VOID }, { "x" }, TAG_GLOBAL, true },
- { "intBitsToFloat", TYPE_VEC2, { TYPE_IVEC2, TYPE_VOID }, { "x" }, TAG_GLOBAL, true },
- { "intBitsToFloat", TYPE_VEC3, { TYPE_IVEC3, TYPE_VOID }, { "x" }, TAG_GLOBAL, true },
- { "intBitsToFloat", TYPE_VEC4, { TYPE_IVEC4, TYPE_VOID }, { "x" }, TAG_GLOBAL, true },
+ { "intBitsToFloat", TYPE_FLOAT, { TYPE_INT, TYPE_VOID }, { "x" }, TAG_GLOBAL, false },
+ { "intBitsToFloat", TYPE_VEC2, { TYPE_IVEC2, TYPE_VOID }, { "x" }, TAG_GLOBAL, false },
+ { "intBitsToFloat", TYPE_VEC3, { TYPE_IVEC3, TYPE_VOID }, { "x" }, TAG_GLOBAL, false },
+ { "intBitsToFloat", TYPE_VEC4, { TYPE_IVEC4, TYPE_VOID }, { "x" }, TAG_GLOBAL, false },
// uintBitsToFloat
- { "uintBitsToFloat", TYPE_FLOAT, { TYPE_UINT, TYPE_VOID }, { "x" }, TAG_GLOBAL, true },
- { "uintBitsToFloat", TYPE_VEC2, { TYPE_UVEC2, TYPE_VOID }, { "x" }, TAG_GLOBAL, true },
- { "uintBitsToFloat", TYPE_VEC3, { TYPE_UVEC3, TYPE_VOID }, { "x" }, TAG_GLOBAL, true },
- { "uintBitsToFloat", TYPE_VEC4, { TYPE_UVEC4, TYPE_VOID }, { "x" }, TAG_GLOBAL, true },
+ { "uintBitsToFloat", TYPE_FLOAT, { TYPE_UINT, TYPE_VOID }, { "x" }, TAG_GLOBAL, false },
+ { "uintBitsToFloat", TYPE_VEC2, { TYPE_UVEC2, TYPE_VOID }, { "x" }, TAG_GLOBAL, false },
+ { "uintBitsToFloat", TYPE_VEC3, { TYPE_UVEC3, TYPE_VOID }, { "x" }, TAG_GLOBAL, false },
+ { "uintBitsToFloat", TYPE_VEC4, { TYPE_UVEC4, TYPE_VOID }, { "x" }, TAG_GLOBAL, false },
// Built-ins - geometric functions.
// length
@@ -2452,9 +2452,9 @@ const ShaderLanguage::BuiltinFuncDef ShaderLanguage::builtin_func_defs[] = {
{ "lessThan", TYPE_BVEC3, { TYPE_IVEC3, TYPE_IVEC3, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, false },
{ "lessThan", TYPE_BVEC4, { TYPE_IVEC4, TYPE_IVEC4, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, false },
- { "lessThan", TYPE_BVEC2, { TYPE_UVEC2, TYPE_UVEC2, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, true },
- { "lessThan", TYPE_BVEC3, { TYPE_UVEC3, TYPE_UVEC3, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, true },
- { "lessThan", TYPE_BVEC4, { TYPE_UVEC4, TYPE_UVEC4, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, true },
+ { "lessThan", TYPE_BVEC3, { TYPE_UVEC3, TYPE_UVEC3, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, false },
+ { "lessThan", TYPE_BVEC4, { TYPE_UVEC4, TYPE_UVEC4, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, false },
+ { "lessThan", TYPE_BVEC2, { TYPE_UVEC2, TYPE_UVEC2, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, false },
// greaterThan
@@ -2466,9 +2466,9 @@ const ShaderLanguage::BuiltinFuncDef ShaderLanguage::builtin_func_defs[] = {
{ "greaterThan", TYPE_BVEC3, { TYPE_IVEC3, TYPE_IVEC3, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, false },
{ "greaterThan", TYPE_BVEC4, { TYPE_IVEC4, TYPE_IVEC4, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, false },
- { "greaterThan", TYPE_BVEC2, { TYPE_UVEC2, TYPE_UVEC2, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, true },
- { "greaterThan", TYPE_BVEC3, { TYPE_UVEC3, TYPE_UVEC3, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, true },
- { "greaterThan", TYPE_BVEC4, { TYPE_UVEC4, TYPE_UVEC4, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, true },
+ { "greaterThan", TYPE_BVEC2, { TYPE_UVEC2, TYPE_UVEC2, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, false },
+ { "greaterThan", TYPE_BVEC3, { TYPE_UVEC3, TYPE_UVEC3, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, false },
+ { "greaterThan", TYPE_BVEC4, { TYPE_UVEC4, TYPE_UVEC4, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, false },
// lessThanEqual
@@ -2480,9 +2480,9 @@ const ShaderLanguage::BuiltinFuncDef ShaderLanguage::builtin_func_defs[] = {
{ "lessThanEqual", TYPE_BVEC3, { TYPE_IVEC3, TYPE_IVEC3, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, false },
{ "lessThanEqual", TYPE_BVEC4, { TYPE_IVEC4, TYPE_IVEC4, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, false },
- { "lessThanEqual", TYPE_BVEC2, { TYPE_UVEC2, TYPE_UVEC2, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, true },
- { "lessThanEqual", TYPE_BVEC3, { TYPE_UVEC3, TYPE_UVEC3, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, true },
- { "lessThanEqual", TYPE_BVEC4, { TYPE_UVEC4, TYPE_UVEC4, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, true },
+ { "lessThanEqual", TYPE_BVEC2, { TYPE_UVEC2, TYPE_UVEC2, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, false },
+ { "lessThanEqual", TYPE_BVEC3, { TYPE_UVEC3, TYPE_UVEC3, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, false },
+ { "lessThanEqual", TYPE_BVEC4, { TYPE_UVEC4, TYPE_UVEC4, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, false },
// greaterThanEqual
@@ -2494,9 +2494,9 @@ const ShaderLanguage::BuiltinFuncDef ShaderLanguage::builtin_func_defs[] = {
{ "greaterThanEqual", TYPE_BVEC3, { TYPE_IVEC3, TYPE_IVEC3, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, false },
{ "greaterThanEqual", TYPE_BVEC4, { TYPE_IVEC4, TYPE_IVEC4, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, false },
- { "greaterThanEqual", TYPE_BVEC2, { TYPE_UVEC2, TYPE_UVEC2, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, true },
- { "greaterThanEqual", TYPE_BVEC3, { TYPE_UVEC3, TYPE_UVEC3, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, true },
- { "greaterThanEqual", TYPE_BVEC4, { TYPE_UVEC4, TYPE_UVEC4, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, true },
+ { "greaterThanEqual", TYPE_BVEC2, { TYPE_UVEC2, TYPE_UVEC2, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, false },
+ { "greaterThanEqual", TYPE_BVEC3, { TYPE_UVEC3, TYPE_UVEC3, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, false },
+ { "greaterThanEqual", TYPE_BVEC4, { TYPE_UVEC4, TYPE_UVEC4, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, false },
// equal
@@ -2508,9 +2508,9 @@ const ShaderLanguage::BuiltinFuncDef ShaderLanguage::builtin_func_defs[] = {
{ "equal", TYPE_BVEC3, { TYPE_IVEC3, TYPE_IVEC3, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, false },
{ "equal", TYPE_BVEC4, { TYPE_IVEC4, TYPE_IVEC4, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, false },
- { "equal", TYPE_BVEC2, { TYPE_UVEC2, TYPE_UVEC2, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, true },
- { "equal", TYPE_BVEC3, { TYPE_UVEC3, TYPE_UVEC3, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, true },
- { "equal", TYPE_BVEC4, { TYPE_UVEC4, TYPE_UVEC4, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, true },
+ { "equal", TYPE_BVEC2, { TYPE_UVEC2, TYPE_UVEC2, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, false },
+ { "equal", TYPE_BVEC3, { TYPE_UVEC3, TYPE_UVEC3, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, false },
+ { "equal", TYPE_BVEC4, { TYPE_UVEC4, TYPE_UVEC4, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, false },
{ "equal", TYPE_BVEC2, { TYPE_BVEC2, TYPE_BVEC2, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, false },
{ "equal", TYPE_BVEC3, { TYPE_BVEC3, TYPE_BVEC3, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, false },
@@ -2526,9 +2526,9 @@ const ShaderLanguage::BuiltinFuncDef ShaderLanguage::builtin_func_defs[] = {
{ "notEqual", TYPE_BVEC3, { TYPE_IVEC3, TYPE_IVEC3, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, false },
{ "notEqual", TYPE_BVEC4, { TYPE_IVEC4, TYPE_IVEC4, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, false },
- { "notEqual", TYPE_BVEC2, { TYPE_UVEC2, TYPE_UVEC2, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, true },
- { "notEqual", TYPE_BVEC3, { TYPE_UVEC3, TYPE_UVEC3, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, true },
- { "notEqual", TYPE_BVEC4, { TYPE_UVEC4, TYPE_UVEC4, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, true },
+ { "notEqual", TYPE_BVEC2, { TYPE_UVEC2, TYPE_UVEC2, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, false },
+ { "notEqual", TYPE_BVEC3, { TYPE_UVEC3, TYPE_UVEC3, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, false },
+ { "notEqual", TYPE_BVEC4, { TYPE_UVEC4, TYPE_UVEC4, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, false },
{ "notEqual", TYPE_BVEC2, { TYPE_BVEC2, TYPE_BVEC2, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, false },
{ "notEqual", TYPE_BVEC3, { TYPE_BVEC3, TYPE_BVEC3, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, false },
@@ -2555,38 +2555,38 @@ const ShaderLanguage::BuiltinFuncDef ShaderLanguage::builtin_func_defs[] = {
// Built-ins: texture functions.
// textureSize
- { "textureSize", TYPE_IVEC2, { TYPE_SAMPLER2D, TYPE_INT, TYPE_VOID }, { "sampler", "lod" }, TAG_GLOBAL, true },
- { "textureSize", TYPE_IVEC2, { TYPE_ISAMPLER2D, TYPE_INT, TYPE_VOID }, { "sampler", "lod" }, TAG_GLOBAL, true },
- { "textureSize", TYPE_IVEC2, { TYPE_USAMPLER2D, TYPE_INT, TYPE_VOID }, { "sampler", "lod" }, TAG_GLOBAL, true },
- { "textureSize", TYPE_IVEC3, { TYPE_SAMPLER2DARRAY, TYPE_INT, TYPE_VOID }, { "sampler", "lod" }, TAG_GLOBAL, true },
- { "textureSize", TYPE_IVEC3, { TYPE_ISAMPLER2DARRAY, TYPE_INT, TYPE_VOID }, { "sampler", "lod" }, TAG_GLOBAL, true },
- { "textureSize", TYPE_IVEC3, { TYPE_USAMPLER2DARRAY, TYPE_INT, TYPE_VOID }, { "sampler", "lod" }, TAG_GLOBAL, true },
- { "textureSize", TYPE_IVEC3, { TYPE_SAMPLER3D, TYPE_INT, TYPE_VOID }, { "sampler", "lod" }, TAG_GLOBAL, true },
- { "textureSize", TYPE_IVEC3, { TYPE_ISAMPLER3D, TYPE_INT, TYPE_VOID }, { "sampler", "lod" }, TAG_GLOBAL, true },
- { "textureSize", TYPE_IVEC3, { TYPE_USAMPLER3D, TYPE_INT, TYPE_VOID }, { "sampler", "lod" }, TAG_GLOBAL, true },
- { "textureSize", TYPE_IVEC2, { TYPE_SAMPLERCUBE, TYPE_INT, TYPE_VOID }, { "sampler", "lod" }, TAG_GLOBAL, true },
- { "textureSize", TYPE_IVEC2, { TYPE_SAMPLERCUBEARRAY, TYPE_INT, TYPE_VOID }, { "sampler", "lod" }, TAG_GLOBAL, true },
+ { "textureSize", TYPE_IVEC2, { TYPE_SAMPLER2D, TYPE_INT, TYPE_VOID }, { "sampler", "lod" }, TAG_GLOBAL, false },
+ { "textureSize", TYPE_IVEC2, { TYPE_ISAMPLER2D, TYPE_INT, TYPE_VOID }, { "sampler", "lod" }, TAG_GLOBAL, false },
+ { "textureSize", TYPE_IVEC2, { TYPE_USAMPLER2D, TYPE_INT, TYPE_VOID }, { "sampler", "lod" }, TAG_GLOBAL, false },
+ { "textureSize", TYPE_IVEC3, { TYPE_SAMPLER2DARRAY, TYPE_INT, TYPE_VOID }, { "sampler", "lod" }, TAG_GLOBAL, false },
+ { "textureSize", TYPE_IVEC3, { TYPE_ISAMPLER2DARRAY, TYPE_INT, TYPE_VOID }, { "sampler", "lod" }, TAG_GLOBAL, false },
+ { "textureSize", TYPE_IVEC3, { TYPE_USAMPLER2DARRAY, TYPE_INT, TYPE_VOID }, { "sampler", "lod" }, TAG_GLOBAL, false },
+ { "textureSize", TYPE_IVEC3, { TYPE_SAMPLER3D, TYPE_INT, TYPE_VOID }, { "sampler", "lod" }, TAG_GLOBAL, false },
+ { "textureSize", TYPE_IVEC3, { TYPE_ISAMPLER3D, TYPE_INT, TYPE_VOID }, { "sampler", "lod" }, TAG_GLOBAL, false },
+ { "textureSize", TYPE_IVEC3, { TYPE_USAMPLER3D, TYPE_INT, TYPE_VOID }, { "sampler", "lod" }, TAG_GLOBAL, false },
+ { "textureSize", TYPE_IVEC2, { TYPE_SAMPLERCUBE, TYPE_INT, TYPE_VOID }, { "sampler", "lod" }, TAG_GLOBAL, false },
+ { "textureSize", TYPE_IVEC2, { TYPE_SAMPLERCUBEARRAY, TYPE_INT, TYPE_VOID }, { "sampler", "lod" }, TAG_GLOBAL, false },
// texture
{ "texture", TYPE_VEC4, { TYPE_SAMPLER2D, TYPE_VEC2, TYPE_VOID }, { "sampler", "coords" }, TAG_GLOBAL, false },
{ "texture", TYPE_VEC4, { TYPE_SAMPLER2D, TYPE_VEC2, TYPE_FLOAT, TYPE_VOID }, { "sampler", "coords", "bias" }, TAG_GLOBAL, false },
- { "texture", TYPE_UVEC4, { TYPE_USAMPLER2D, TYPE_VEC2, TYPE_VOID }, { "sampler", "coords" }, TAG_GLOBAL, true },
- { "texture", TYPE_UVEC4, { TYPE_USAMPLER2D, TYPE_VEC2, TYPE_FLOAT, TYPE_VOID }, { "sampler", "coords", "bias" }, TAG_GLOBAL, true },
- { "texture", TYPE_IVEC4, { TYPE_ISAMPLER2D, TYPE_VEC2, TYPE_VOID }, { "sampler", "coords" }, TAG_GLOBAL, true },
- { "texture", TYPE_IVEC4, { TYPE_ISAMPLER2D, TYPE_VEC2, TYPE_FLOAT, TYPE_VOID }, { "sampler", "coords", "bias" }, TAG_GLOBAL, true },
+ { "texture", TYPE_UVEC4, { TYPE_USAMPLER2D, TYPE_VEC2, TYPE_VOID }, { "sampler", "coords" }, TAG_GLOBAL, false },
+ { "texture", TYPE_UVEC4, { TYPE_USAMPLER2D, TYPE_VEC2, TYPE_FLOAT, TYPE_VOID }, { "sampler", "coords", "bias" }, TAG_GLOBAL, false },
+ { "texture", TYPE_IVEC4, { TYPE_ISAMPLER2D, TYPE_VEC2, TYPE_VOID }, { "sampler", "coords" }, TAG_GLOBAL, false },
+ { "texture", TYPE_IVEC4, { TYPE_ISAMPLER2D, TYPE_VEC2, TYPE_FLOAT, TYPE_VOID }, { "sampler", "coords", "bias" }, TAG_GLOBAL, false },
{ "texture", TYPE_VEC4, { TYPE_SAMPLER2DARRAY, TYPE_VEC3, TYPE_VOID }, { "sampler", "coords" }, TAG_GLOBAL, false },
{ "texture", TYPE_VEC4, { TYPE_SAMPLER2DARRAY, TYPE_VEC3, TYPE_FLOAT, TYPE_VOID }, { "sampler", "coords", "bias" }, TAG_GLOBAL, false },
- { "texture", TYPE_UVEC4, { TYPE_USAMPLER2DARRAY, TYPE_VEC3, TYPE_VOID }, { "sampler", "coords" }, TAG_GLOBAL, true },
- { "texture", TYPE_UVEC4, { TYPE_USAMPLER2DARRAY, TYPE_VEC3, TYPE_FLOAT, TYPE_VOID }, { "sampler", "coords", "bias" }, TAG_GLOBAL, true },
- { "texture", TYPE_IVEC4, { TYPE_ISAMPLER2DARRAY, TYPE_VEC3, TYPE_VOID }, { "sampler", "coords" }, TAG_GLOBAL, true },
- { "texture", TYPE_IVEC4, { TYPE_ISAMPLER2DARRAY, TYPE_VEC3, TYPE_FLOAT, TYPE_VOID }, { "sampler", "coords", "bias" }, TAG_GLOBAL, true },
+ { "texture", TYPE_UVEC4, { TYPE_USAMPLER2DARRAY, TYPE_VEC3, TYPE_VOID }, { "sampler", "coords" }, TAG_GLOBAL, false },
+ { "texture", TYPE_UVEC4, { TYPE_USAMPLER2DARRAY, TYPE_VEC3, TYPE_FLOAT, TYPE_VOID }, { "sampler", "coords", "bias" }, TAG_GLOBAL, false },
+ { "texture", TYPE_IVEC4, { TYPE_ISAMPLER2DARRAY, TYPE_VEC3, TYPE_VOID }, { "sampler", "coords" }, TAG_GLOBAL, false },
+ { "texture", TYPE_IVEC4, { TYPE_ISAMPLER2DARRAY, TYPE_VEC3, TYPE_FLOAT, TYPE_VOID }, { "sampler", "coords", "bias" }, TAG_GLOBAL, false },
{ "texture", TYPE_VEC4, { TYPE_SAMPLER3D, TYPE_VEC3, TYPE_VOID }, { "sampler", "coords" }, TAG_GLOBAL, false },
{ "texture", TYPE_VEC4, { TYPE_SAMPLER3D, TYPE_VEC3, TYPE_FLOAT, TYPE_VOID }, { "sampler", "coords", "bias" }, TAG_GLOBAL, false },
- { "texture", TYPE_UVEC4, { TYPE_USAMPLER3D, TYPE_VEC3, TYPE_VOID }, { "sampler", "coords" }, TAG_GLOBAL, true },
- { "texture", TYPE_UVEC4, { TYPE_USAMPLER3D, TYPE_VEC3, TYPE_FLOAT, TYPE_VOID }, { "sampler", "coords", "bias" }, TAG_GLOBAL, true },
- { "texture", TYPE_IVEC4, { TYPE_ISAMPLER3D, TYPE_VEC3, TYPE_VOID }, { "sampler", "coords" }, TAG_GLOBAL, true },
- { "texture", TYPE_IVEC4, { TYPE_ISAMPLER3D, TYPE_VEC3, TYPE_FLOAT, TYPE_VOID }, { "sampler", "coords", "bias" }, TAG_GLOBAL, true },
+ { "texture", TYPE_UVEC4, { TYPE_USAMPLER3D, TYPE_VEC3, TYPE_VOID }, { "sampler", "coords" }, TAG_GLOBAL, false },
+ { "texture", TYPE_UVEC4, { TYPE_USAMPLER3D, TYPE_VEC3, TYPE_FLOAT, TYPE_VOID }, { "sampler", "coords", "bias" }, TAG_GLOBAL, false },
+ { "texture", TYPE_IVEC4, { TYPE_ISAMPLER3D, TYPE_VEC3, TYPE_VOID }, { "sampler", "coords" }, TAG_GLOBAL, false },
+ { "texture", TYPE_IVEC4, { TYPE_ISAMPLER3D, TYPE_VEC3, TYPE_FLOAT, TYPE_VOID }, { "sampler", "coords", "bias" }, TAG_GLOBAL, false },
{ "texture", TYPE_VEC4, { TYPE_SAMPLERCUBE, TYPE_VEC3, TYPE_VOID }, { "sampler", "coords" }, TAG_GLOBAL, false },
{ "texture", TYPE_VEC4, { TYPE_SAMPLERCUBE, TYPE_VEC3, TYPE_FLOAT, TYPE_VOID }, { "sampler", "coords", "bias" }, TAG_GLOBAL, false },
{ "texture", TYPE_VEC4, { TYPE_SAMPLERCUBEARRAY, TYPE_VEC4, TYPE_VOID }, { "sampler", "coords" }, TAG_GLOBAL, false },
@@ -2594,119 +2594,119 @@ const ShaderLanguage::BuiltinFuncDef ShaderLanguage::builtin_func_defs[] = {
// textureProj
- { "textureProj", TYPE_VEC4, { TYPE_SAMPLER2D, TYPE_VEC3, TYPE_VOID }, { "sampler", "coords" }, TAG_GLOBAL, true },
- { "textureProj", TYPE_VEC4, { TYPE_SAMPLER2D, TYPE_VEC4, TYPE_VOID }, { "sampler", "coords" }, TAG_GLOBAL, true },
- { "textureProj", TYPE_VEC4, { TYPE_SAMPLER2D, TYPE_VEC3, TYPE_FLOAT, TYPE_VOID }, { "sampler", "coords", "bias" }, TAG_GLOBAL, true },
- { "textureProj", TYPE_VEC4, { TYPE_SAMPLER2D, TYPE_VEC4, TYPE_FLOAT, TYPE_VOID }, { "sampler", "coords", "bias" }, TAG_GLOBAL, true },
- { "textureProj", TYPE_IVEC4, { TYPE_ISAMPLER2D, TYPE_VEC3, TYPE_VOID }, { "sampler", "coords" }, TAG_GLOBAL, true },
- { "textureProj", TYPE_IVEC4, { TYPE_ISAMPLER2D, TYPE_VEC4, TYPE_VOID }, { "sampler", "coords" }, TAG_GLOBAL, true },
- { "textureProj", TYPE_IVEC4, { TYPE_ISAMPLER2D, TYPE_VEC3, TYPE_FLOAT, TYPE_VOID }, { "sampler", "coords", "bias" }, TAG_GLOBAL, true },
- { "textureProj", TYPE_IVEC4, { TYPE_ISAMPLER2D, TYPE_VEC4, TYPE_FLOAT, TYPE_VOID }, { "sampler", "coords", "bias" }, TAG_GLOBAL, true },
- { "textureProj", TYPE_UVEC4, { TYPE_USAMPLER2D, TYPE_VEC3, TYPE_VOID }, { "sampler", "coords" }, TAG_GLOBAL, true },
- { "textureProj", TYPE_UVEC4, { TYPE_USAMPLER2D, TYPE_VEC4, TYPE_VOID }, { "sampler", "coords" }, TAG_GLOBAL, true },
- { "textureProj", TYPE_UVEC4, { TYPE_USAMPLER2D, TYPE_VEC3, TYPE_FLOAT, TYPE_VOID }, { "sampler", "coords", "bias" }, TAG_GLOBAL, true },
- { "textureProj", TYPE_UVEC4, { TYPE_USAMPLER2D, TYPE_VEC4, TYPE_FLOAT, TYPE_VOID }, { "sampler", "coords", "bias" }, TAG_GLOBAL, true },
- { "textureProj", TYPE_VEC4, { TYPE_SAMPLER3D, TYPE_VEC4, TYPE_VOID }, { "sampler", "coords" }, TAG_GLOBAL, true },
- { "textureProj", TYPE_VEC4, { TYPE_SAMPLER3D, TYPE_VEC4, TYPE_FLOAT, TYPE_VOID }, { "sampler", "coords", "bias" }, TAG_GLOBAL, true },
- { "textureProj", TYPE_IVEC4, { TYPE_ISAMPLER3D, TYPE_VEC4, TYPE_VOID }, { "sampler", "coords" }, TAG_GLOBAL, true },
- { "textureProj", TYPE_IVEC4, { TYPE_ISAMPLER3D, TYPE_VEC4, TYPE_FLOAT, TYPE_VOID }, { "sampler", "coords", "bias" }, TAG_GLOBAL, true },
- { "textureProj", TYPE_UVEC4, { TYPE_USAMPLER3D, TYPE_VEC4, TYPE_VOID }, { "sampler", "coords" }, TAG_GLOBAL, true },
- { "textureProj", TYPE_UVEC4, { TYPE_USAMPLER3D, TYPE_VEC4, TYPE_FLOAT, TYPE_VOID }, { "sampler", "coords", "bias" }, TAG_GLOBAL, true },
+ { "textureProj", TYPE_VEC4, { TYPE_SAMPLER2D, TYPE_VEC3, TYPE_VOID }, { "sampler", "coords" }, TAG_GLOBAL, false },
+ { "textureProj", TYPE_VEC4, { TYPE_SAMPLER2D, TYPE_VEC4, TYPE_VOID }, { "sampler", "coords" }, TAG_GLOBAL, false },
+ { "textureProj", TYPE_VEC4, { TYPE_SAMPLER2D, TYPE_VEC3, TYPE_FLOAT, TYPE_VOID }, { "sampler", "coords", "bias" }, TAG_GLOBAL, false },
+ { "textureProj", TYPE_VEC4, { TYPE_SAMPLER2D, TYPE_VEC4, TYPE_FLOAT, TYPE_VOID }, { "sampler", "coords", "bias" }, TAG_GLOBAL, false },
+ { "textureProj", TYPE_IVEC4, { TYPE_ISAMPLER2D, TYPE_VEC3, TYPE_VOID }, { "sampler", "coords" }, TAG_GLOBAL, false },
+ { "textureProj", TYPE_IVEC4, { TYPE_ISAMPLER2D, TYPE_VEC4, TYPE_VOID }, { "sampler", "coords" }, TAG_GLOBAL, false },
+ { "textureProj", TYPE_IVEC4, { TYPE_ISAMPLER2D, TYPE_VEC3, TYPE_FLOAT, TYPE_VOID }, { "sampler", "coords", "bias" }, TAG_GLOBAL, false },
+ { "textureProj", TYPE_IVEC4, { TYPE_ISAMPLER2D, TYPE_VEC4, TYPE_FLOAT, TYPE_VOID }, { "sampler", "coords", "bias" }, TAG_GLOBAL, false },
+ { "textureProj", TYPE_UVEC4, { TYPE_USAMPLER2D, TYPE_VEC3, TYPE_VOID }, { "sampler", "coords" }, TAG_GLOBAL, false },
+ { "textureProj", TYPE_UVEC4, { TYPE_USAMPLER2D, TYPE_VEC4, TYPE_VOID }, { "sampler", "coords" }, TAG_GLOBAL, false },
+ { "textureProj", TYPE_UVEC4, { TYPE_USAMPLER2D, TYPE_VEC3, TYPE_FLOAT, TYPE_VOID }, { "sampler", "coords", "bias" }, TAG_GLOBAL, false },
+ { "textureProj", TYPE_UVEC4, { TYPE_USAMPLER2D, TYPE_VEC4, TYPE_FLOAT, TYPE_VOID }, { "sampler", "coords", "bias" }, TAG_GLOBAL, false },
+ { "textureProj", TYPE_VEC4, { TYPE_SAMPLER3D, TYPE_VEC4, TYPE_VOID }, { "sampler", "coords" }, TAG_GLOBAL, false },
+ { "textureProj", TYPE_VEC4, { TYPE_SAMPLER3D, TYPE_VEC4, TYPE_FLOAT, TYPE_VOID }, { "sampler", "coords", "bias" }, TAG_GLOBAL, false },
+ { "textureProj", TYPE_IVEC4, { TYPE_ISAMPLER3D, TYPE_VEC4, TYPE_VOID }, { "sampler", "coords" }, TAG_GLOBAL, false },
+ { "textureProj", TYPE_IVEC4, { TYPE_ISAMPLER3D, TYPE_VEC4, TYPE_FLOAT, TYPE_VOID }, { "sampler", "coords", "bias" }, TAG_GLOBAL, false },
+ { "textureProj", TYPE_UVEC4, { TYPE_USAMPLER3D, TYPE_VEC4, TYPE_VOID }, { "sampler", "coords" }, TAG_GLOBAL, false },
+ { "textureProj", TYPE_UVEC4, { TYPE_USAMPLER3D, TYPE_VEC4, TYPE_FLOAT, TYPE_VOID }, { "sampler", "coords", "bias" }, TAG_GLOBAL, false },
// textureLod
{ "textureLod", TYPE_VEC4, { TYPE_SAMPLER2D, TYPE_VEC2, TYPE_FLOAT, TYPE_VOID }, { "sampler", "coords", "lod" }, TAG_GLOBAL, false },
- { "textureLod", TYPE_IVEC4, { TYPE_ISAMPLER2D, TYPE_VEC2, TYPE_FLOAT, TYPE_VOID }, { "sampler", "coords", "lod" }, TAG_GLOBAL, true },
- { "textureLod", TYPE_UVEC4, { TYPE_USAMPLER2D, TYPE_VEC2, TYPE_FLOAT, TYPE_VOID }, { "sampler", "coords", "lod" }, TAG_GLOBAL, true },
+ { "textureLod", TYPE_IVEC4, { TYPE_ISAMPLER2D, TYPE_VEC2, TYPE_FLOAT, TYPE_VOID }, { "sampler", "coords", "lod" }, TAG_GLOBAL, false },
+ { "textureLod", TYPE_UVEC4, { TYPE_USAMPLER2D, TYPE_VEC2, TYPE_FLOAT, TYPE_VOID }, { "sampler", "coords", "lod" }, TAG_GLOBAL, false },
{ "textureLod", TYPE_VEC4, { TYPE_SAMPLER2DARRAY, TYPE_VEC3, TYPE_FLOAT, TYPE_VOID }, { "sampler", "coords", "lod" }, TAG_GLOBAL, false },
- { "textureLod", TYPE_IVEC4, { TYPE_ISAMPLER2DARRAY, TYPE_VEC3, TYPE_FLOAT, TYPE_VOID }, { "sampler", "coords", "lod" }, TAG_GLOBAL, true },
- { "textureLod", TYPE_UVEC4, { TYPE_USAMPLER2DARRAY, TYPE_VEC3, TYPE_FLOAT, TYPE_VOID }, { "sampler", "coords", "lod" }, TAG_GLOBAL, true },
+ { "textureLod", TYPE_IVEC4, { TYPE_ISAMPLER2DARRAY, TYPE_VEC3, TYPE_FLOAT, TYPE_VOID }, { "sampler", "coords", "lod" }, TAG_GLOBAL, false },
+ { "textureLod", TYPE_UVEC4, { TYPE_USAMPLER2DARRAY, TYPE_VEC3, TYPE_FLOAT, TYPE_VOID }, { "sampler", "coords", "lod" }, TAG_GLOBAL, false },
{ "textureLod", TYPE_VEC4, { TYPE_SAMPLER3D, TYPE_VEC3, TYPE_FLOAT, TYPE_VOID }, { "sampler", "coords", "lod" }, TAG_GLOBAL, false },
- { "textureLod", TYPE_IVEC4, { TYPE_ISAMPLER3D, TYPE_VEC3, TYPE_FLOAT, TYPE_VOID }, { "sampler", "coords", "lod" }, TAG_GLOBAL, true },
- { "textureLod", TYPE_UVEC4, { TYPE_USAMPLER3D, TYPE_VEC3, TYPE_FLOAT, TYPE_VOID }, { "sampler", "coords", "lod" }, TAG_GLOBAL, true },
+ { "textureLod", TYPE_IVEC4, { TYPE_ISAMPLER3D, TYPE_VEC3, TYPE_FLOAT, TYPE_VOID }, { "sampler", "coords", "lod" }, TAG_GLOBAL, false },
+ { "textureLod", TYPE_UVEC4, { TYPE_USAMPLER3D, TYPE_VEC3, TYPE_FLOAT, TYPE_VOID }, { "sampler", "coords", "lod" }, TAG_GLOBAL, false },
{ "textureLod", TYPE_VEC4, { TYPE_SAMPLERCUBE, TYPE_VEC3, TYPE_FLOAT, TYPE_VOID }, { "sampler", "coords", "lod" }, TAG_GLOBAL, false },
{ "textureLod", TYPE_VEC4, { TYPE_SAMPLERCUBEARRAY, TYPE_VEC4, TYPE_FLOAT, TYPE_VOID }, { "sampler", "coords", "lod" }, TAG_GLOBAL, false },
// texelFetch
- { "texelFetch", TYPE_VEC4, { TYPE_SAMPLER2D, TYPE_IVEC2, TYPE_INT, TYPE_VOID }, { "sampler", "coords", "lod" }, TAG_GLOBAL, true },
- { "texelFetch", TYPE_IVEC4, { TYPE_ISAMPLER2D, TYPE_IVEC2, TYPE_INT, TYPE_VOID }, { "sampler", "coords", "lod" }, TAG_GLOBAL, true },
- { "texelFetch", TYPE_UVEC4, { TYPE_USAMPLER2D, TYPE_IVEC2, TYPE_INT, TYPE_VOID }, { "sampler", "coords", "lod" }, TAG_GLOBAL, true },
- { "texelFetch", TYPE_VEC4, { TYPE_SAMPLER2DARRAY, TYPE_IVEC3, TYPE_INT, TYPE_VOID }, { "sampler", "coords", "lod" }, TAG_GLOBAL, true },
- { "texelFetch", TYPE_IVEC4, { TYPE_ISAMPLER2DARRAY, TYPE_IVEC3, TYPE_INT, TYPE_VOID }, { "sampler", "coords", "lod" }, TAG_GLOBAL, true },
- { "texelFetch", TYPE_UVEC4, { TYPE_USAMPLER2DARRAY, TYPE_IVEC3, TYPE_INT, TYPE_VOID }, { "sampler", "coords", "lod" }, TAG_GLOBAL, true },
- { "texelFetch", TYPE_VEC4, { TYPE_SAMPLER3D, TYPE_IVEC3, TYPE_INT, TYPE_VOID }, { "sampler", "coords", "lod" }, TAG_GLOBAL, true },
- { "texelFetch", TYPE_IVEC4, { TYPE_ISAMPLER3D, TYPE_IVEC3, TYPE_INT, TYPE_VOID }, { "sampler", "coords", "lod" }, TAG_GLOBAL, true },
- { "texelFetch", TYPE_UVEC4, { TYPE_USAMPLER3D, TYPE_IVEC3, TYPE_INT, TYPE_VOID }, { "sampler", "coords", "lod" }, TAG_GLOBAL, true },
+ { "texelFetch", TYPE_VEC4, { TYPE_SAMPLER2D, TYPE_IVEC2, TYPE_INT, TYPE_VOID }, { "sampler", "coords", "lod" }, TAG_GLOBAL, false },
+ { "texelFetch", TYPE_IVEC4, { TYPE_ISAMPLER2D, TYPE_IVEC2, TYPE_INT, TYPE_VOID }, { "sampler", "coords", "lod" }, TAG_GLOBAL, false },
+ { "texelFetch", TYPE_UVEC4, { TYPE_USAMPLER2D, TYPE_IVEC2, TYPE_INT, TYPE_VOID }, { "sampler", "coords", "lod" }, TAG_GLOBAL, false },
+ { "texelFetch", TYPE_VEC4, { TYPE_SAMPLER2DARRAY, TYPE_IVEC3, TYPE_INT, TYPE_VOID }, { "sampler", "coords", "lod" }, TAG_GLOBAL, false },
+ { "texelFetch", TYPE_IVEC4, { TYPE_ISAMPLER2DARRAY, TYPE_IVEC3, TYPE_INT, TYPE_VOID }, { "sampler", "coords", "lod" }, TAG_GLOBAL, false },
+ { "texelFetch", TYPE_UVEC4, { TYPE_USAMPLER2DARRAY, TYPE_IVEC3, TYPE_INT, TYPE_VOID }, { "sampler", "coords", "lod" }, TAG_GLOBAL, false },
+ { "texelFetch", TYPE_VEC4, { TYPE_SAMPLER3D, TYPE_IVEC3, TYPE_INT, TYPE_VOID }, { "sampler", "coords", "lod" }, TAG_GLOBAL, false },
+ { "texelFetch", TYPE_IVEC4, { TYPE_ISAMPLER3D, TYPE_IVEC3, TYPE_INT, TYPE_VOID }, { "sampler", "coords", "lod" }, TAG_GLOBAL, false },
+ { "texelFetch", TYPE_UVEC4, { TYPE_USAMPLER3D, TYPE_IVEC3, TYPE_INT, TYPE_VOID }, { "sampler", "coords", "lod" }, TAG_GLOBAL, false },
// textureProjLod
- { "textureProjLod", TYPE_VEC4, { TYPE_SAMPLER2D, TYPE_VEC3, TYPE_FLOAT, TYPE_VOID }, { "sampler", "coords", "lod" }, TAG_GLOBAL, true },
- { "textureProjLod", TYPE_VEC4, { TYPE_SAMPLER2D, TYPE_VEC4, TYPE_FLOAT, TYPE_VOID }, { "sampler", "coords", "lod" }, TAG_GLOBAL, true },
- { "textureProjLod", TYPE_IVEC4, { TYPE_ISAMPLER2D, TYPE_VEC3, TYPE_FLOAT, TYPE_VOID }, { "sampler", "coords", "lod" }, TAG_GLOBAL, true },
- { "textureProjLod", TYPE_IVEC4, { TYPE_ISAMPLER2D, TYPE_VEC4, TYPE_FLOAT, TYPE_VOID }, { "sampler", "coords", "lod" }, TAG_GLOBAL, true },
- { "textureProjLod", TYPE_UVEC4, { TYPE_USAMPLER2D, TYPE_VEC3, TYPE_FLOAT, TYPE_VOID }, { "sampler", "coords", "lod" }, TAG_GLOBAL, true },
- { "textureProjLod", TYPE_UVEC4, { TYPE_USAMPLER2D, TYPE_VEC4, TYPE_FLOAT, TYPE_VOID }, { "sampler", "coords", "lod" }, TAG_GLOBAL, true },
- { "textureProjLod", TYPE_VEC4, { TYPE_SAMPLER3D, TYPE_VEC4, TYPE_FLOAT, TYPE_VOID }, { "sampler", "coords", "lod" }, TAG_GLOBAL, true },
- { "textureProjLod", TYPE_IVEC4, { TYPE_ISAMPLER3D, TYPE_VEC4, TYPE_FLOAT, TYPE_VOID }, { "sampler", "coords", "lod" }, TAG_GLOBAL, true },
- { "textureProjLod", TYPE_UVEC4, { TYPE_USAMPLER3D, TYPE_VEC4, TYPE_FLOAT, TYPE_VOID }, { "sampler", "coords", "lod" }, TAG_GLOBAL, true },
+ { "textureProjLod", TYPE_VEC4, { TYPE_SAMPLER2D, TYPE_VEC3, TYPE_FLOAT, TYPE_VOID }, { "sampler", "coords", "lod" }, TAG_GLOBAL, false },
+ { "textureProjLod", TYPE_VEC4, { TYPE_SAMPLER2D, TYPE_VEC4, TYPE_FLOAT, TYPE_VOID }, { "sampler", "coords", "lod" }, TAG_GLOBAL, false },
+ { "textureProjLod", TYPE_IVEC4, { TYPE_ISAMPLER2D, TYPE_VEC3, TYPE_FLOAT, TYPE_VOID }, { "sampler", "coords", "lod" }, TAG_GLOBAL, false },
+ { "textureProjLod", TYPE_IVEC4, { TYPE_ISAMPLER2D, TYPE_VEC4, TYPE_FLOAT, TYPE_VOID }, { "sampler", "coords", "lod" }, TAG_GLOBAL, false },
+ { "textureProjLod", TYPE_UVEC4, { TYPE_USAMPLER2D, TYPE_VEC3, TYPE_FLOAT, TYPE_VOID }, { "sampler", "coords", "lod" }, TAG_GLOBAL, false },
+ { "textureProjLod", TYPE_UVEC4, { TYPE_USAMPLER2D, TYPE_VEC4, TYPE_FLOAT, TYPE_VOID }, { "sampler", "coords", "lod" }, TAG_GLOBAL, false },
+ { "textureProjLod", TYPE_VEC4, { TYPE_SAMPLER3D, TYPE_VEC4, TYPE_FLOAT, TYPE_VOID }, { "sampler", "coords", "lod" }, TAG_GLOBAL, false },
+ { "textureProjLod", TYPE_IVEC4, { TYPE_ISAMPLER3D, TYPE_VEC4, TYPE_FLOAT, TYPE_VOID }, { "sampler", "coords", "lod" }, TAG_GLOBAL, false },
+ { "textureProjLod", TYPE_UVEC4, { TYPE_USAMPLER3D, TYPE_VEC4, TYPE_FLOAT, TYPE_VOID }, { "sampler", "coords", "lod" }, TAG_GLOBAL, false },
// textureGrad
- { "textureGrad", TYPE_VEC4, { TYPE_SAMPLER2D, TYPE_VEC2, TYPE_VEC2, TYPE_VEC2, TYPE_VOID }, { "sampler", "coords", "dPdx", "dPdy" }, TAG_GLOBAL, true },
- { "textureGrad", TYPE_IVEC4, { TYPE_ISAMPLER2D, TYPE_VEC2, TYPE_VEC2, TYPE_VEC2, TYPE_VOID }, { "sampler", "coords", "dPdx", "dPdy" }, TAG_GLOBAL, true },
- { "textureGrad", TYPE_UVEC4, { TYPE_USAMPLER2D, TYPE_VEC2, TYPE_VEC2, TYPE_VEC2, TYPE_VOID }, { "sampler", "coords", "dPdx", "dPdy" }, TAG_GLOBAL, true },
- { "textureGrad", TYPE_VEC4, { TYPE_SAMPLER2DARRAY, TYPE_VEC3, TYPE_VEC2, TYPE_VEC2, TYPE_VOID }, { "sampler", "coords", "dPdx", "dPdy" }, TAG_GLOBAL, true },
- { "textureGrad", TYPE_IVEC4, { TYPE_ISAMPLER2DARRAY, TYPE_VEC3, TYPE_VEC2, TYPE_VEC2, TYPE_VOID }, { "sampler", "coords", "dPdx", "dPdy" }, TAG_GLOBAL, true },
- { "textureGrad", TYPE_UVEC4, { TYPE_USAMPLER2DARRAY, TYPE_VEC3, TYPE_VEC2, TYPE_VEC2, TYPE_VOID }, { "sampler", "coords", "dPdx", "dPdy" }, TAG_GLOBAL, true },
- { "textureGrad", TYPE_VEC4, { TYPE_SAMPLER3D, TYPE_VEC3, TYPE_VEC3, TYPE_VEC3, TYPE_VOID }, { "sampler", "coords", "dPdx", "dPdy" }, TAG_GLOBAL, true },
- { "textureGrad", TYPE_IVEC4, { TYPE_ISAMPLER3D, TYPE_VEC3, TYPE_VEC3, TYPE_VEC3, TYPE_VOID }, { "sampler", "coords", "dPdx", "dPdy" }, TAG_GLOBAL, true },
- { "textureGrad", TYPE_UVEC4, { TYPE_USAMPLER3D, TYPE_VEC3, TYPE_VEC3, TYPE_VEC3, TYPE_VOID }, { "sampler", "coords", "dPdx", "dPdy" }, TAG_GLOBAL, true },
- { "textureGrad", TYPE_VEC4, { TYPE_SAMPLERCUBE, TYPE_VEC3, TYPE_VEC3, TYPE_VEC3, TYPE_VOID }, { "sampler", "coords", "dPdx", "dPdy" }, TAG_GLOBAL, true },
- { "textureGrad", TYPE_VEC4, { TYPE_SAMPLERCUBEARRAY, TYPE_VEC4, TYPE_VEC3, TYPE_VEC3, TYPE_VOID }, { "sampler", "coords", "dPdx", "dPdy" }, TAG_GLOBAL, true },
+ { "textureGrad", TYPE_VEC4, { TYPE_SAMPLER2D, TYPE_VEC2, TYPE_VEC2, TYPE_VEC2, TYPE_VOID }, { "sampler", "coords", "dPdx", "dPdy" }, TAG_GLOBAL, false },
+ { "textureGrad", TYPE_IVEC4, { TYPE_ISAMPLER2D, TYPE_VEC2, TYPE_VEC2, TYPE_VEC2, TYPE_VOID }, { "sampler", "coords", "dPdx", "dPdy" }, TAG_GLOBAL, false },
+ { "textureGrad", TYPE_UVEC4, { TYPE_USAMPLER2D, TYPE_VEC2, TYPE_VEC2, TYPE_VEC2, TYPE_VOID }, { "sampler", "coords", "dPdx", "dPdy" }, TAG_GLOBAL, false },
+ { "textureGrad", TYPE_VEC4, { TYPE_SAMPLER2DARRAY, TYPE_VEC3, TYPE_VEC2, TYPE_VEC2, TYPE_VOID }, { "sampler", "coords", "dPdx", "dPdy" }, TAG_GLOBAL, false },
+ { "textureGrad", TYPE_IVEC4, { TYPE_ISAMPLER2DARRAY, TYPE_VEC3, TYPE_VEC2, TYPE_VEC2, TYPE_VOID }, { "sampler", "coords", "dPdx", "dPdy" }, TAG_GLOBAL, false },
+ { "textureGrad", TYPE_UVEC4, { TYPE_USAMPLER2DARRAY, TYPE_VEC3, TYPE_VEC2, TYPE_VEC2, TYPE_VOID }, { "sampler", "coords", "dPdx", "dPdy" }, TAG_GLOBAL, false },
+ { "textureGrad", TYPE_VEC4, { TYPE_SAMPLER3D, TYPE_VEC3, TYPE_VEC3, TYPE_VEC3, TYPE_VOID }, { "sampler", "coords", "dPdx", "dPdy" }, TAG_GLOBAL, false },
+ { "textureGrad", TYPE_IVEC4, { TYPE_ISAMPLER3D, TYPE_VEC3, TYPE_VEC3, TYPE_VEC3, TYPE_VOID }, { "sampler", "coords", "dPdx", "dPdy" }, TAG_GLOBAL, false },
+ { "textureGrad", TYPE_UVEC4, { TYPE_USAMPLER3D, TYPE_VEC3, TYPE_VEC3, TYPE_VEC3, TYPE_VOID }, { "sampler", "coords", "dPdx", "dPdy" }, TAG_GLOBAL, false },
+ { "textureGrad", TYPE_VEC4, { TYPE_SAMPLERCUBE, TYPE_VEC3, TYPE_VEC3, TYPE_VEC3, TYPE_VOID }, { "sampler", "coords", "dPdx", "dPdy" }, TAG_GLOBAL, false },
+ { "textureGrad", TYPE_VEC4, { TYPE_SAMPLERCUBEARRAY, TYPE_VEC4, TYPE_VEC3, TYPE_VEC3, TYPE_VOID }, { "sampler", "coords", "dPdx", "dPdy" }, TAG_GLOBAL, false },
// textureGather
- { "textureGather", TYPE_VEC4, { TYPE_SAMPLER2D, TYPE_VEC2, TYPE_VOID }, { "sampler", "coords" }, TAG_GLOBAL, true },
- { "textureGather", TYPE_IVEC4, { TYPE_ISAMPLER2D, TYPE_VEC2, TYPE_VOID }, { "sampler", "coords" }, TAG_GLOBAL, true },
- { "textureGather", TYPE_UVEC4, { TYPE_USAMPLER2D, TYPE_VEC2, TYPE_VOID }, { "sampler", "coords" }, TAG_GLOBAL, true },
- { "textureGather", TYPE_VEC4, { TYPE_SAMPLER2D, TYPE_VEC2, TYPE_INT, TYPE_VOID }, { "sampler", "coords", "comp" }, TAG_GLOBAL, true },
- { "textureGather", TYPE_IVEC4, { TYPE_ISAMPLER2D, TYPE_VEC2, TYPE_INT, TYPE_VOID }, { "sampler", "coords", "comp" }, TAG_GLOBAL, true },
- { "textureGather", TYPE_UVEC4, { TYPE_USAMPLER2D, TYPE_VEC2, TYPE_INT, TYPE_VOID }, { "sampler", "coords", "comp" }, TAG_GLOBAL, true },
- { "textureGather", TYPE_VEC4, { TYPE_SAMPLER2DARRAY, TYPE_VEC3, TYPE_VOID }, { "sampler", "coords" }, TAG_GLOBAL, true },
- { "textureGather", TYPE_IVEC4, { TYPE_ISAMPLER2DARRAY, TYPE_VEC3, TYPE_VOID }, { "sampler", "coords" }, TAG_GLOBAL, true },
- { "textureGather", TYPE_UVEC4, { TYPE_USAMPLER2DARRAY, TYPE_VEC3, TYPE_VOID }, { "sampler", "coords" }, TAG_GLOBAL, true },
- { "textureGather", TYPE_VEC4, { TYPE_SAMPLER2DARRAY, TYPE_VEC3, TYPE_INT, TYPE_VOID }, { "sampler", "coords", "comp" }, TAG_GLOBAL, true },
- { "textureGather", TYPE_IVEC4, { TYPE_ISAMPLER2DARRAY, TYPE_VEC3, TYPE_INT, TYPE_VOID }, { "sampler", "coords", "comp" }, TAG_GLOBAL, true },
- { "textureGather", TYPE_UVEC4, { TYPE_USAMPLER2DARRAY, TYPE_VEC3, TYPE_INT, TYPE_VOID }, { "sampler", "coords", "comp" }, TAG_GLOBAL, true },
- { "textureGather", TYPE_VEC4, { TYPE_SAMPLERCUBE, TYPE_VEC3, TYPE_VOID }, { "sampler", "coords" }, TAG_GLOBAL, true },
- { "textureGather", TYPE_VEC4, { TYPE_SAMPLERCUBE, TYPE_VEC3, TYPE_INT, TYPE_VOID }, { "sampler", "coords", "comp" }, TAG_GLOBAL, true },
+ { "textureGather", TYPE_VEC4, { TYPE_SAMPLER2D, TYPE_VEC2, TYPE_VOID }, { "sampler", "coords" }, TAG_GLOBAL, false },
+ { "textureGather", TYPE_IVEC4, { TYPE_ISAMPLER2D, TYPE_VEC2, TYPE_VOID }, { "sampler", "coords" }, TAG_GLOBAL, false },
+ { "textureGather", TYPE_UVEC4, { TYPE_USAMPLER2D, TYPE_VEC2, TYPE_VOID }, { "sampler", "coords" }, TAG_GLOBAL, false },
+ { "textureGather", TYPE_VEC4, { TYPE_SAMPLER2D, TYPE_VEC2, TYPE_INT, TYPE_VOID }, { "sampler", "coords", "comp" }, TAG_GLOBAL, false },
+ { "textureGather", TYPE_IVEC4, { TYPE_ISAMPLER2D, TYPE_VEC2, TYPE_INT, TYPE_VOID }, { "sampler", "coords", "comp" }, TAG_GLOBAL, false },
+ { "textureGather", TYPE_UVEC4, { TYPE_USAMPLER2D, TYPE_VEC2, TYPE_INT, TYPE_VOID }, { "sampler", "coords", "comp" }, TAG_GLOBAL, false },
+ { "textureGather", TYPE_VEC4, { TYPE_SAMPLER2DARRAY, TYPE_VEC3, TYPE_VOID }, { "sampler", "coords" }, TAG_GLOBAL, false },
+ { "textureGather", TYPE_IVEC4, { TYPE_ISAMPLER2DARRAY, TYPE_VEC3, TYPE_VOID }, { "sampler", "coords" }, TAG_GLOBAL, false },
+ { "textureGather", TYPE_UVEC4, { TYPE_USAMPLER2DARRAY, TYPE_VEC3, TYPE_VOID }, { "sampler", "coords" }, TAG_GLOBAL, false },
+ { "textureGather", TYPE_VEC4, { TYPE_SAMPLER2DARRAY, TYPE_VEC3, TYPE_INT, TYPE_VOID }, { "sampler", "coords", "comp" }, TAG_GLOBAL, false },
+ { "textureGather", TYPE_IVEC4, { TYPE_ISAMPLER2DARRAY, TYPE_VEC3, TYPE_INT, TYPE_VOID }, { "sampler", "coords", "comp" }, TAG_GLOBAL, false },
+ { "textureGather", TYPE_UVEC4, { TYPE_USAMPLER2DARRAY, TYPE_VEC3, TYPE_INT, TYPE_VOID }, { "sampler", "coords", "comp" }, TAG_GLOBAL, false },
+ { "textureGather", TYPE_VEC4, { TYPE_SAMPLERCUBE, TYPE_VEC3, TYPE_VOID }, { "sampler", "coords" }, TAG_GLOBAL, false },
+ { "textureGather", TYPE_VEC4, { TYPE_SAMPLERCUBE, TYPE_VEC3, TYPE_INT, TYPE_VOID }, { "sampler", "coords", "comp" }, TAG_GLOBAL, false },
// dFdx
- { "dFdx", TYPE_FLOAT, { TYPE_FLOAT, TYPE_VOID }, { "p" }, TAG_GLOBAL, true },
- { "dFdx", TYPE_VEC2, { TYPE_VEC2, TYPE_VOID }, { "p" }, TAG_GLOBAL, true },
- { "dFdx", TYPE_VEC3, { TYPE_VEC3, TYPE_VOID }, { "p" }, TAG_GLOBAL, true },
- { "dFdx", TYPE_VEC4, { TYPE_VEC4, TYPE_VOID }, { "p" }, TAG_GLOBAL, true },
+ { "dFdx", TYPE_FLOAT, { TYPE_FLOAT, TYPE_VOID }, { "p" }, TAG_GLOBAL, false },
+ { "dFdx", TYPE_VEC2, { TYPE_VEC2, TYPE_VOID }, { "p" }, TAG_GLOBAL, false },
+ { "dFdx", TYPE_VEC3, { TYPE_VEC3, TYPE_VOID }, { "p" }, TAG_GLOBAL, false },
+ { "dFdx", TYPE_VEC4, { TYPE_VEC4, TYPE_VOID }, { "p" }, TAG_GLOBAL, false },
// dFdy
- { "dFdy", TYPE_FLOAT, { TYPE_FLOAT, TYPE_VOID }, { "p" }, TAG_GLOBAL, true },
- { "dFdy", TYPE_VEC2, { TYPE_VEC2, TYPE_VOID }, { "p" }, TAG_GLOBAL, true },
- { "dFdy", TYPE_VEC3, { TYPE_VEC3, TYPE_VOID }, { "p" }, TAG_GLOBAL, true },
- { "dFdy", TYPE_VEC4, { TYPE_VEC4, TYPE_VOID }, { "p" }, TAG_GLOBAL, true },
+ { "dFdy", TYPE_FLOAT, { TYPE_FLOAT, TYPE_VOID }, { "p" }, TAG_GLOBAL, false },
+ { "dFdy", TYPE_VEC2, { TYPE_VEC2, TYPE_VOID }, { "p" }, TAG_GLOBAL, false },
+ { "dFdy", TYPE_VEC3, { TYPE_VEC3, TYPE_VOID }, { "p" }, TAG_GLOBAL, false },
+ { "dFdy", TYPE_VEC4, { TYPE_VEC4, TYPE_VOID }, { "p" }, TAG_GLOBAL, false },
// fwidth
- { "fwidth", TYPE_FLOAT, { TYPE_FLOAT, TYPE_VOID }, { "p" }, TAG_GLOBAL, true },
- { "fwidth", TYPE_VEC2, { TYPE_VEC2, TYPE_VOID }, { "p" }, TAG_GLOBAL, true },
- { "fwidth", TYPE_VEC3, { TYPE_VEC3, TYPE_VOID }, { "p" }, TAG_GLOBAL, true },
- { "fwidth", TYPE_VEC4, { TYPE_VEC4, TYPE_VOID }, { "p" }, TAG_GLOBAL, true },
+ { "fwidth", TYPE_FLOAT, { TYPE_FLOAT, TYPE_VOID }, { "p" }, TAG_GLOBAL, false },
+ { "fwidth", TYPE_VEC2, { TYPE_VEC2, TYPE_VOID }, { "p" }, TAG_GLOBAL, false },
+ { "fwidth", TYPE_VEC3, { TYPE_VEC3, TYPE_VOID }, { "p" }, TAG_GLOBAL, false },
+ { "fwidth", TYPE_VEC4, { TYPE_VEC4, TYPE_VOID }, { "p" }, TAG_GLOBAL, false },
// Sub-functions.
// array
- { "length", TYPE_INT, { TYPE_VOID }, { "" }, TAG_ARRAY, true },
+ { "length", TYPE_INT, { TYPE_VOID }, { "" }, TAG_ARRAY, false },
// Modern functions.
// fma
@@ -2718,17 +2718,17 @@ const ShaderLanguage::BuiltinFuncDef ShaderLanguage::builtin_func_defs[] = {
// Packing/Unpacking functions.
- { "packHalf2x16", TYPE_UINT, { TYPE_VEC2, TYPE_VOID }, { "v" }, TAG_GLOBAL, true },
- { "packUnorm2x16", TYPE_UINT, { TYPE_VEC2, TYPE_VOID }, { "v" }, TAG_GLOBAL, true },
- { "packSnorm2x16", TYPE_UINT, { TYPE_VEC2, TYPE_VOID }, { "v" }, TAG_GLOBAL, true },
- { "packUnorm4x8", TYPE_UINT, { TYPE_VEC4, TYPE_VOID }, { "v" }, TAG_GLOBAL, true },
- { "packSnorm4x8", TYPE_UINT, { TYPE_VEC4, TYPE_VOID }, { "v" }, TAG_GLOBAL, true },
+ { "packHalf2x16", TYPE_UINT, { TYPE_VEC2, TYPE_VOID }, { "v" }, TAG_GLOBAL, false },
+ { "packUnorm2x16", TYPE_UINT, { TYPE_VEC2, TYPE_VOID }, { "v" }, TAG_GLOBAL, false },
+ { "packSnorm2x16", TYPE_UINT, { TYPE_VEC2, TYPE_VOID }, { "v" }, TAG_GLOBAL, false },
+ { "packUnorm4x8", TYPE_UINT, { TYPE_VEC4, TYPE_VOID }, { "v" }, TAG_GLOBAL, false },
+ { "packSnorm4x8", TYPE_UINT, { TYPE_VEC4, TYPE_VOID }, { "v" }, TAG_GLOBAL, false },
- { "unpackHalf2x16", TYPE_VEC2, { TYPE_UINT, TYPE_VOID }, { "v" }, TAG_GLOBAL, true },
- { "unpackUnorm2x16", TYPE_VEC2, { TYPE_UINT, TYPE_VOID }, { "v" }, TAG_GLOBAL, true },
- { "unpackSnorm2x16", TYPE_VEC2, { TYPE_UINT, TYPE_VOID }, { "v" }, TAG_GLOBAL, true },
- { "unpackUnorm4x8", TYPE_VEC4, { TYPE_UINT, TYPE_VOID }, { "v" }, TAG_GLOBAL, true },
- { "unpackSnorm4x8", TYPE_VEC4, { TYPE_UINT, TYPE_VOID }, { "v" }, TAG_GLOBAL, true },
+ { "unpackHalf2x16", TYPE_VEC2, { TYPE_UINT, TYPE_VOID }, { "v" }, TAG_GLOBAL, false },
+ { "unpackUnorm2x16", TYPE_VEC2, { TYPE_UINT, TYPE_VOID }, { "v" }, TAG_GLOBAL, false },
+ { "unpackSnorm2x16", TYPE_VEC2, { TYPE_UINT, TYPE_VOID }, { "v" }, TAG_GLOBAL, false },
+ { "unpackUnorm4x8", TYPE_VEC4, { TYPE_UINT, TYPE_VOID }, { "v" }, TAG_GLOBAL, false },
+ { "unpackSnorm4x8", TYPE_VEC4, { TYPE_UINT, TYPE_VOID }, { "v" }, TAG_GLOBAL, false },
// bitfieldExtract
@@ -6653,10 +6653,6 @@ Error ShaderLanguage::_parse_block(BlockNode *p_block, const FunctionInfo &p_fun
DataType type = is_struct ? TYPE_STRUCT : get_token_datatype(tk.type);
- if (_validate_datatype(type) != OK) {
- return ERR_PARSE_ERROR;
- }
-
if (precision != PRECISION_DEFAULT && _validate_precision(type, precision) != OK) {
return ERR_PARSE_ERROR;
}
@@ -6753,11 +6749,6 @@ Error ShaderLanguage::_parse_block(BlockNode *p_block, const FunctionInfo &p_fun
tk = _get_token();
if (tk.type == TK_BRACKET_OPEN) {
- if (RenderingServer::get_singleton()->is_low_end() && is_const) {
- _set_error(RTR("Local const arrays are only supported on high-end platforms."));
- return ERR_PARSE_ERROR;
- }
-
Error error = _parse_array_size(p_block, p_function_info, false, &decl.size_expression, &var.array_size, &unknown_size);
if (error != OK) {
return error;
@@ -6777,11 +6768,6 @@ Error ShaderLanguage::_parse_block(BlockNode *p_block, const FunctionInfo &p_fun
bool full_def = false;
if (tk.type == TK_OP_ASSIGN) {
- if (RenderingServer::get_singleton()->is_low_end()) {
- _set_error(RTR("Array initialization is only supported on high-end platforms."));
- return ERR_PARSE_ERROR;
- }
-
TkPos prev_pos = _get_tkpos();
tk = _get_token();
@@ -7088,11 +7074,6 @@ Error ShaderLanguage::_parse_block(BlockNode *p_block, const FunctionInfo &p_fun
_set_tkpos(pos); //rollback
}
} else if (tk.type == TK_CF_SWITCH) {
- if (RenderingServer::get_singleton()->is_low_end()) {
- _set_error(vformat(RTR("The '%s' operator is only supported on high-end platforms."), "switch"));
- return ERR_PARSE_ERROR;
- }
-
// switch() {}
tk = _get_token();
if (tk.type != TK_PARENTHESIS_OPEN) {
@@ -7696,35 +7677,6 @@ Error ShaderLanguage::_validate_precision(DataType p_type, DataPrecision p_preci
return OK;
}
-Error ShaderLanguage::_validate_datatype(DataType p_type) {
- if (RenderingServer::get_singleton()->is_low_end()) {
- bool invalid_type = false;
-
- switch (p_type) {
- case TYPE_UINT:
- case TYPE_UVEC2:
- case TYPE_UVEC3:
- case TYPE_UVEC4:
- case TYPE_ISAMPLER2D:
- case TYPE_USAMPLER2D:
- case TYPE_ISAMPLER3D:
- case TYPE_USAMPLER3D:
- case TYPE_USAMPLER2DARRAY:
- case TYPE_ISAMPLER2DARRAY:
- invalid_type = true;
- break;
- default:
- break;
- }
-
- if (invalid_type) {
- _set_error(vformat(RTR("The \"%s\" type is only supported on high-end platforms."), get_datatype_name(p_type)));
- return ERR_UNAVAILABLE;
- }
- }
- return OK;
-}
-
Error ShaderLanguage::_parse_shader(const HashMap<StringName, FunctionInfo> &p_functions, const Vector<ModeInfo> &p_render_modes, const HashSet<String> &p_shader_types) {
Token tk = _get_token();
TkPos prev_pos;
@@ -8265,9 +8217,6 @@ Error ShaderLanguage::_parse_shader(const HashMap<StringName, FunctionInfo> &p_f
++texture_binding;
}
uniform.order = -1;
- if (_validate_datatype(type) != OK) {
- return ERR_PARSE_ERROR;
- }
} else {
if (uniform_scope == ShaderNode::Uniform::SCOPE_INSTANCE && (type == TYPE_MAT2 || type == TYPE_MAT3 || type == TYPE_MAT4)) {
_set_error(vformat(RTR("The '%s' qualifier is not supported for matrix types."), "SCOPE_INSTANCE"));
@@ -8743,10 +8692,6 @@ Error ShaderLanguage::_parse_shader(const HashMap<StringName, FunctionInfo> &p_f
bool fixed_array_size = false;
if (tk.type == TK_BRACKET_OPEN) {
- if (is_constant && RenderingServer::get_singleton()->is_low_end()) {
- _set_error(RTR("Global constant arrays are only supported on high-end platforms."));
- return ERR_PARSE_ERROR;
- }
Error error = _parse_array_size(nullptr, constants, !is_constant, nullptr, &array_size, &unknown_size);
if (error != OK) {
return error;
@@ -8791,10 +8736,6 @@ Error ShaderLanguage::_parse_shader(const HashMap<StringName, FunctionInfo> &p_f
constant.array_size = array_size;
if (tk.type == TK_BRACKET_OPEN) {
- if (RenderingServer::get_singleton()->is_low_end()) {
- _set_error(RTR("Global const arrays are only supported on high-end platforms."));
- return ERR_PARSE_ERROR;
- }
Error error = _parse_array_size(nullptr, constants, false, nullptr, &constant.array_size, &unknown_size);
if (error != OK) {
return error;
@@ -9262,9 +9203,6 @@ Error ShaderLanguage::_parse_shader(const HashMap<StringName, FunctionInfo> &p_f
param_type = TYPE_STRUCT;
} else {
param_type = get_token_datatype(tk.type);
- if (_validate_datatype(param_type) != OK) {
- return ERR_PARSE_ERROR;
- }
if (param_type == TYPE_VOID) {
_set_error(RTR("Void type not allowed as argument."));
return ERR_PARSE_ERROR;
diff --git a/servers/rendering/shader_language.h b/servers/rendering/shader_language.h
index a4226a9764..2b147fbeb1 100644
--- a/servers/rendering/shader_language.h
+++ b/servers/rendering/shader_language.h
@@ -1049,7 +1049,6 @@ private:
static bool is_const_suffix_lut_initialized;
Error _validate_precision(DataType p_type, DataPrecision p_precision);
- Error _validate_datatype(DataType p_type);
bool _compare_datatypes(DataType p_datatype_a, String p_datatype_name_a, int p_array_size_a, DataType p_datatype_b, String p_datatype_name_b, int p_array_size_b);
bool _compare_datatypes_in_nodes(Node *a, Node *b);
diff --git a/servers/text/text_server_extension.cpp b/servers/text/text_server_extension.cpp
index 005cb68302..e9a558ac5f 100644
--- a/servers/text/text_server_extension.cpp
+++ b/servers/text/text_server_extension.cpp
@@ -55,6 +55,11 @@ void TextServerExtension::_bind_methods() {
GDVIRTUAL_BIND(font_set_data, "font_rid", "data");
GDVIRTUAL_BIND(font_set_data_ptr, "font_rid", "data_ptr", "data_size");
+ GDVIRTUAL_BIND(font_set_face_index, "font_rid", "face_index");
+ GDVIRTUAL_BIND(font_get_face_index, "font_rid");
+
+ GDVIRTUAL_BIND(font_get_face_count, "font_rid");
+
GDVIRTUAL_BIND(font_set_style, "font_rid", "style");
GDVIRTUAL_BIND(font_get_style, "font_rid");
@@ -413,6 +418,26 @@ void TextServerExtension::font_set_data_ptr(const RID &p_font_rid, const uint8_t
GDVIRTUAL_CALL(font_set_data_ptr, p_font_rid, p_data_ptr, p_data_size);
}
+void TextServerExtension::font_set_face_index(const RID &p_font_rid, int64_t p_index) {
+ GDVIRTUAL_CALL(font_set_face_index, p_font_rid, p_index);
+}
+
+int64_t TextServerExtension::font_get_face_index(const RID &p_font_rid) const {
+ int64_t ret;
+ if (GDVIRTUAL_CALL(font_get_face_index, p_font_rid, ret)) {
+ return ret;
+ }
+ return 0;
+}
+
+int64_t TextServerExtension::font_get_face_count(const RID &p_font_rid) const {
+ int64_t ret;
+ if (GDVIRTUAL_CALL(font_get_face_count, p_font_rid, ret)) {
+ return ret;
+ }
+ return 0;
+}
+
void TextServerExtension::font_set_style(const RID &p_font_rid, int64_t /*FontStyle*/ p_style) {
GDVIRTUAL_CALL(font_set_style, p_font_rid, p_style);
}
diff --git a/servers/text/text_server_extension.h b/servers/text/text_server_extension.h
index 7b7fc61ed7..9ca0939247 100644
--- a/servers/text/text_server_extension.h
+++ b/servers/text/text_server_extension.h
@@ -84,6 +84,14 @@ public:
GDVIRTUAL2(font_set_data, RID, const PackedByteArray &);
GDVIRTUAL3(font_set_data_ptr, RID, GDNativeConstPtr<const uint8_t>, int64_t);
+ virtual void font_set_face_index(const RID &p_font_rid, int64_t p_index) override;
+ virtual int64_t font_get_face_index(const RID &p_font_rid) const override;
+ GDVIRTUAL2(font_set_face_index, RID, int64_t);
+ GDVIRTUAL1RC(int64_t, font_get_face_index, RID);
+
+ virtual int64_t font_get_face_count(const RID &p_font_rid) const override;
+ GDVIRTUAL1RC(int64_t, font_get_face_count, RID);
+
virtual void font_set_style(const RID &p_font_rid, int64_t /*FontStyle*/ p_style) override;
virtual int64_t /*FontStyle*/ font_get_style(const RID &p_font_rid) const override;
GDVIRTUAL2(font_set_style, RID, int64_t);
diff --git a/servers/text_server.cpp b/servers/text_server.cpp
index 20e62037e6..41d9c74d82 100644
--- a/servers/text_server.cpp
+++ b/servers/text_server.cpp
@@ -208,6 +208,11 @@ void TextServer::_bind_methods() {
ClassDB::bind_method(D_METHOD("font_set_data", "font_rid", "data"), &TextServer::font_set_data);
+ ClassDB::bind_method(D_METHOD("font_set_face_index", "font_rid", "face_index"), &TextServer::font_set_face_index);
+ ClassDB::bind_method(D_METHOD("font_get_face_index", "font_rid"), &TextServer::font_get_face_index);
+
+ ClassDB::bind_method(D_METHOD("font_get_face_count", "font_rid"), &TextServer::font_get_face_count);
+
ClassDB::bind_method(D_METHOD("font_set_style", "font_rid", "style"), &TextServer::font_set_style);
ClassDB::bind_method(D_METHOD("font_get_style", "font_rid"), &TextServer::font_get_style);
diff --git a/servers/text_server.h b/servers/text_server.h
index f96146a549..a67ad8fc9e 100644
--- a/servers/text_server.h
+++ b/servers/text_server.h
@@ -189,6 +189,11 @@ public:
virtual void font_set_data(const RID &p_font_rid, const PackedByteArray &p_data) = 0;
virtual void font_set_data_ptr(const RID &p_font_rid, const uint8_t *p_data_ptr, int64_t p_data_size) = 0;
+ virtual void font_set_face_index(const RID &p_font_rid, int64_t p_index) = 0;
+ virtual int64_t font_get_face_index(const RID &p_font_rid) const = 0;
+
+ virtual int64_t font_get_face_count(const RID &p_font_rid) const = 0;
+
virtual void font_set_style(const RID &p_font_rid, int64_t /*FontStyle*/ p_style) = 0;
virtual int64_t /*FontStyle*/ font_get_style(const RID &p_font_rid) const = 0;
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;