diff options
76 files changed, 2110 insertions, 719 deletions
diff --git a/core/core_bind.cpp b/core/core_bind.cpp index 892b74c26a..8308c4fe53 100644 --- a/core/core_bind.cpp +++ b/core/core_bind.cpp @@ -483,6 +483,10 @@ void OS::dump_resources_to_file(const String &p_file) { ::OS::get_singleton()->dump_resources_to_file(p_file.utf8().get_data()); } +Error OS::move_to_trash(const String &p_path) const { + return ::OS::get_singleton()->move_to_trash(p_path); +} + String OS::get_user_data_dir() const { return ::OS::get_singleton()->get_user_data_dir(); } @@ -597,6 +601,7 @@ void OS::_bind_methods() { ClassDB::bind_method(D_METHOD("get_static_memory_usage"), &OS::get_static_memory_usage); ClassDB::bind_method(D_METHOD("get_static_memory_peak_usage"), &OS::get_static_memory_peak_usage); + ClassDB::bind_method(D_METHOD("move_to_trash", "path"), &OS::move_to_trash); ClassDB::bind_method(D_METHOD("get_user_data_dir"), &OS::get_user_data_dir); ClassDB::bind_method(D_METHOD("get_system_dir", "dir", "shared_storage"), &OS::get_system_dir, DEFVAL(true)); ClassDB::bind_method(D_METHOD("get_config_dir"), &OS::get_config_dir); diff --git a/core/core_bind.h b/core/core_bind.h index 591cacdabb..bc68be3f62 100644 --- a/core/core_bind.h +++ b/core/core_bind.h @@ -235,6 +235,7 @@ public: String get_system_dir(SystemDir p_dir, bool p_shared_storage = true) const; + Error move_to_trash(const String &p_path) const; String get_user_data_dir() const; String get_config_dir() const; String get_data_dir() const; diff --git a/core/templates/oa_hash_map.h b/core/templates/oa_hash_map.h index e4d9323c45..25c21d1802 100644 --- a/core/templates/oa_hash_map.h +++ b/core/templates/oa_hash_map.h @@ -246,13 +246,17 @@ public: return false; } - /** - * returns true if the value was found, false otherwise. - * - * if r_data is not nullptr then the value will be written to the object - * it points to. - */ - TValue *lookup_ptr(const TKey &p_key) const { + const TValue *lookup_ptr(const TKey &p_key) const { + uint32_t pos = 0; + bool exists = _lookup_pos(p_key, pos); + + if (exists) { + return &values[pos]; + } + return nullptr; + } + + TValue *lookup_ptr(const TKey &p_key) { uint32_t pos = 0; bool exists = _lookup_pos(p_key, pos); diff --git a/doc/classes/Directory.xml b/doc/classes/Directory.xml index 7d72cd867c..bd16fd3936 100644 --- a/doc/classes/Directory.xml +++ b/doc/classes/Directory.xml @@ -196,7 +196,8 @@ <return type="int" enum="Error" /> <argument index="0" name="path" type="String" /> <description> - Deletes the target file or an empty directory. The argument can be relative to the current directory, or an absolute path. If the target directory is not empty, the operation will fail. + Permanently deletes the target file or an empty directory. The argument can be relative to the current directory, or an absolute path. If the target directory is not empty, the operation will fail. + If you don't want to delete the file/directory permanently, use [method OS.move_to_trash] instead. Returns one of the [enum Error] code constants ([code]OK[/code] on success). </description> </method> diff --git a/doc/classes/MultiplayerAPI.xml b/doc/classes/MultiplayerAPI.xml index ac17886183..059d147979 100644 --- a/doc/classes/MultiplayerAPI.xml +++ b/doc/classes/MultiplayerAPI.xml @@ -6,7 +6,7 @@ <description> This class implements the high-level multiplayer API. See also [MultiplayerPeer]. By default, [SceneTree] has a reference to this class that is used to provide multiplayer capabilities (i.e. RPCs) across the whole scene. - It is possible to override the MultiplayerAPI instance used by specific Nodes by setting the [member Node.custom_multiplayer] property, effectively allowing to run both client and server in the same scene. + It is possible to override the MultiplayerAPI instance used by specific tree branches by calling the [method SceneTree.set_multiplayer] method, effectively allowing to run both client and server in the same scene. [b]Note:[/b] The high-level multiplayer API protocol is an implementation detail and isn't meant to be used by non-Godot servers. It may change without notice. [b]Note:[/b] When exporting to Android, make sure to enable the [code]INTERNET[/code] permission in the Android export preset before exporting the project or using one-click deploy. Otherwise, network communication of any kind will be blocked by Android. </description> @@ -53,7 +53,7 @@ <method name="poll"> <return type="void" /> <description> - Method used for polling the MultiplayerAPI. You only need to worry about this if you are using [member Node.custom_multiplayer] override or you set [member SceneTree.multiplayer_poll] to [code]false[/code]. By default, [SceneTree] will poll its MultiplayerAPI for you. + Method used for polling the MultiplayerAPI. You only need to worry about this if you set [member SceneTree.multiplayer_poll] to [code]false[/code]. By default, [SceneTree] will poll its MultiplayerAPI(s) for you. [b]Note:[/b] This method results in RPCs being called, so they will be executed in the same context of this function (e.g. [code]_process[/code], [code]physics[/code], [Thread]). </description> </method> diff --git a/doc/classes/Node.xml b/doc/classes/Node.xml index 75f16e0c1c..c9795856d5 100644 --- a/doc/classes/Node.xml +++ b/doc/classes/Node.xml @@ -193,28 +193,45 @@ [b]Note:[/b] It will not work properly if the node contains a script with constructor arguments (i.e. needs to supply arguments to [method Object._init] method). In that case, the node will be duplicated without a script. </description> </method> - <method name="find_nodes" qualifiers="const"> + <method name="find_child" qualifiers="const"> + <return type="Node" /> + <argument index="0" name="pattern" type="String" /> + <argument index="1" name="recursive" type="bool" default="true" /> + <argument index="2" name="owned" type="bool" default="true" /> + <description> + Finds the first descendant of this node whose name matches [code]pattern[/code] as in [method String.match]. + [code]pattern[/code] does not match against the full path, just against individual node names. It is case-sensitive, with [code]"*"[/code] matching zero or more characters and [code]"?"[/code] matching any single character except [code]"."[/code]). + If [code]recursive[/code] is [code]true[/code], all child nodes are included, even if deeply nested. Nodes are checked in tree order, so this node's first direct child is checked first, then its own direct children, etc., before moving to the second direct child, and so on. If [code]recursive[/code] is [code]false[/code], only this node's direct children are matched. + If [code]owned[/code] is [code]true[/code], this method only finds nodes who have an assigned [member Node.owner]. This is especially important for scenes instantiated through a script, because those scenes don't have an owner. + Returns [code]null[/code] if no matching [Node] is found. + [b]Note:[/b] As this method walks through all the descendants of the node, it is the slowest way to get a reference to another node. Whenever possible, consider using [method get_node] with unique names instead (see [member unique_name_in_owner]), or caching the node references into variable. + [b]Note:[/b] To find all descendant nodes matching a pattern or a class type, see [method find_children]. + </description> + </method> + <method name="find_children" qualifiers="const"> <return type="Node[]" /> - <argument index="0" name="mask" type="String" /> + <argument index="0" name="pattern" type="String" /> <argument index="1" name="type" type="String" default="""" /> <argument index="2" name="recursive" type="bool" default="true" /> <argument index="3" name="owned" type="bool" default="true" /> <description> - Finds descendants of this node whose, name matches [code]mask[/code] as in [method String.match], and/or type matches [code]type[/code] as in [method Object.is_class]. - [code]mask[/code] does not match against the full path, just against individual node names. It is case-sensitive, with [code]"*"[/code] matching zero or more characters and [code]"?"[/code] matching any single character except [code]"."[/code]). - [code]type[/code] will check equality or inheritance. It is case-sensitive, [code]"Object"[/code] will match a node whose type is [code]"Node"[/code] but not the other way around. - If [code]owned[/code] is [code]true[/code], this method only finds nodes whose owner is this node. This is especially important for scenes instantiated through a script, because those scenes don't have an owner. - Returns an empty array, if no matching nodes are found. - [b]Note:[/b] As this method walks through all the descendants of the node, it is the slowest way to get references to other nodes. To avoid using [method find_nodes] too often, consider caching the node references into variables. + Finds descendants of this node whose name matches [code]pattern[/code] as in [method String.match], and/or type matches [code]type[/code] as in [method Object.is_class]. + [code]pattern[/code] does not match against the full path, just against individual node names. It is case-sensitive, with [code]"*"[/code] matching zero or more characters and [code]"?"[/code] matching any single character except [code]"."[/code]). + [code]type[/code] will check equality or inheritance, and is case-sensitive. [code]"Object"[/code] will match a node whose type is [code]"Node"[/code] but not the other way around. + If [code]recursive[/code] is [code]true[/code], all child nodes are included, even if deeply nested. Nodes are checked in tree order, so this node's first direct child is checked first, then its own direct children, etc., before moving to the second direct child, and so on. If [code]recursive[/code] is [code]false[/code], only this node's direct children are matched. + If [code]owned[/code] is [code]true[/code], this method only finds nodes who have an assigned [member Node.owner]. This is especially important for scenes instantiated through a script, because those scenes don't have an owner. + Returns an empty array if no matching nodes are found. + [b]Note:[/b] As this method walks through all the descendants of the node, it is the slowest way to get references to other nodes. Whenever possible, consider caching the node references into variables. + [b]Note:[/b] If you only want to find the first descendant node that matches a pattern, see [method find_child]. </description> </method> <method name="find_parent" qualifiers="const"> <return type="Node" /> - <argument index="0" name="mask" type="String" /> + <argument index="0" name="pattern" type="String" /> <description> - Finds the first parent of the current node whose name matches [code]mask[/code] as in [method String.match] (i.e. case-sensitive, but [code]"*"[/code] matches zero or more characters and [code]"?"[/code] matches any single character except [code]"."[/code]). - [b]Note:[/b] It does not match against the full path, just against individual node names. - [b]Note:[/b] As this method walks upwards in the scene tree, it can be slow in large, deeply nested scene trees. Whenever possible, consider using [method get_node] instead. To avoid using [method find_parent] too often, consider caching the node reference into a variable. + Finds the first parent of the current node whose name matches [code]pattern[/code] as in [method String.match]. + [code]pattern[/code] does not match against the full path, just against individual node names. It is case-sensitive, with [code]"*"[/code] matching zero or more characters and [code]"?"[/code] matching any single character except [code]"."[/code]). + [b]Note:[/b] As this method walks upwards in the scene tree, it can be slow in large, deeply nested scene trees. Whenever possible, consider using [method get_node] with unique names instead (see [member unique_name_in_owner]), or caching the node references into variable. </description> </method> <method name="get_child" qualifiers="const"> @@ -492,12 +509,6 @@ Returns [code]true[/code] if the node is processing unhandled key input (see [method set_process_unhandled_key_input]). </description> </method> - <method name="is_unique_name_in_owner" qualifiers="const"> - <return type="bool" /> - <description> - Returns whether the node is an unique name for all the other nodes owned by its [member owner]. - </description> - </method> <method name="move_child"> <return type="void" /> <argument index="0" name="child_node" type="Node" /> @@ -725,13 +736,6 @@ Sets whether this is an instance load placeholder. See [InstancePlaceholder]. </description> </method> - <method name="set_unique_name_in_owner"> - <return type="void" /> - <argument index="0" name="enable" type="bool" /> - <description> - Sets this node's name as the unique name in its [member owner]. This allows the node to be accessed as [code]%Name[/code] instead of the full path, from any node within that scene. - </description> - </method> <method name="update_configuration_warnings"> <return type="void" /> <description> @@ -741,14 +745,11 @@ </method> </methods> <members> - <member name="custom_multiplayer" type="MultiplayerAPI" setter="set_custom_multiplayer" getter="get_custom_multiplayer"> - The override to the default [MultiplayerAPI]. Set to [code]null[/code] to use the default [SceneTree] one. - </member> <member name="editor_description" type="String" setter="set_editor_description" getter="get_editor_description" default=""""> Add a custom description to a node. It will be displayed in a tooltip when hovered in editor's scene tree. </member> <member name="multiplayer" type="MultiplayerAPI" setter="" getter="get_multiplayer"> - The [MultiplayerAPI] instance associated with this node. Either the [member custom_multiplayer], or the default SceneTree one (if inside tree). + The [MultiplayerAPI] instance associated with this node. See [method SceneTree.get_multiplayer]. </member> <member name="name" type="StringName" setter="set_name" getter="get_name"> The name of the node. This name is unique among the siblings (other child nodes from the same parent). When set to an existing name, the node will be automatically renamed. @@ -767,6 +768,10 @@ <member name="scene_file_path" type="String" setter="set_scene_file_path" getter="get_scene_file_path"> If a scene is instantiated from a file, its topmost node contains the absolute file path from which it was loaded in [member scene_file_path] (e.g. [code]res://levels/1.tscn[/code]). Otherwise, [member scene_file_path] is set to an empty string. </member> + <member name="unique_name_in_owner" type="bool" setter="set_unique_name_in_owner" getter="is_unique_name_in_owner" default="false"> + Sets this node's name as a unique name in its [member owner]. This allows the node to be accessed as [code]%Name[/code] instead of the full path, from any node within that scene. + If another node with the same owner already had that name declared as unique, that other node's name will no longer be set as having a unique name. + </member> </members> <signals> <signal name="child_entered_tree"> diff --git a/doc/classes/OS.xml b/doc/classes/OS.xml index b2e325d226..f45bee4db4 100644 --- a/doc/classes/OS.xml +++ b/doc/classes/OS.xml @@ -455,6 +455,14 @@ [b]Note:[/b] This method is implemented on Android, iOS, Linux, macOS and Windows. </description> </method> + <method name="move_to_trash" qualifiers="const"> + <return type="int" enum="Error" /> + <argument index="0" name="path" type="String" /> + <description> + Moves the file or directory to the system's recycle bin. See also [method Directory.remove]. + [b]Note:[/b] If the user has disabled the recycle bin on their system, the file will be permanently deleted instead. + </description> + </method> <method name="open_midi_inputs"> <return type="void" /> <description> diff --git a/doc/classes/ProjectSettings.xml b/doc/classes/ProjectSettings.xml index ee32677b3a..7c6d6d1c10 100644 --- a/doc/classes/ProjectSettings.xml +++ b/doc/classes/ProjectSettings.xml @@ -578,9 +578,19 @@ <member name="gui/theme/default_font_antialiased" type="bool" setter="" getter="" default="true"> If set to [code]true[/code], default font uses 8-bit anitialiased glyph rendering. See [member FontData.antialiased]. </member> + <member name="gui/theme/default_font_generate_mipmaps" type="bool" setter="" getter="" default="false"> + If set to [code]true[/code], the default font will have mipmaps generated. This prevents text from looking grainy when a [Control] is scaled down, or when a [Label3D] is viewed from a long distance (if [member Label3D.texture_filter] is set to a mode that displays mipmaps). + Enabling [member gui/theme/default_font_generate_mipmaps] increases font generation time and memory usage. Only enable this setting if you actually need it. + [b]Note:[/b] This setting does not affect custom [Font]s used within the project. + </member> <member name="gui/theme/default_font_hinting" type="int" setter="" getter="" default="1"> Default font hinting mode. See [member FontData.hinting]. </member> + <member name="gui/theme/default_font_multichannel_signed_distance_field" type="bool" setter="" getter="" default="false"> + If set to [code]true[/code], the default font will use multichannel signed distance field (MSDF) for crisp rendering at any size. Since this approach does not rely on rasterizing the font every time its size changes, this allows for resizing the font in real-time without any performance penalty. Text will also not look grainy for [Control]s that are scaled down (or for [Label3D]s viewed from a long distance). + MSDF font rendering can be combined with [member gui/theme/default_font_generate_mipmaps] to further improve font rendering quality when scaled down. + [b]Note:[/b] This setting does not affect custom [Font]s used within the project. + </member> <member name="gui/theme/default_font_subpixel_positioning" type="int" setter="" getter="" default="1"> Default font glyph sub-pixel positioning mode. See [member FontData.subpixel_positioning]. </member> diff --git a/doc/classes/SceneTree.xml b/doc/classes/SceneTree.xml index 77023d2126..ddff766b17 100644 --- a/doc/classes/SceneTree.xml +++ b/doc/classes/SceneTree.xml @@ -99,6 +99,13 @@ Returns the current frame number, i.e. the total frame count since the application started. </description> </method> + <method name="get_multiplayer" qualifiers="const"> + <return type="MultiplayerAPI" /> + <argument index="0" name="for_path" type="NodePath" default="NodePath("")" /> + <description> + Return the [MultiplayerAPI] configured for the given path, or the default one if [code]for_path[/code] is empty. + </description> + </method> <method name="get_node_count" qualifiers="const"> <return type="int" /> <description> @@ -193,6 +200,14 @@ Sets the given [code]property[/code] to [code]value[/code] on all members of the given group, respecting the given [enum GroupCallFlags]. </description> </method> + <method name="set_multiplayer"> + <return type="void" /> + <argument index="0" name="multiplayer" type="MultiplayerAPI" /> + <argument index="1" name="root_path" type="NodePath" default="NodePath("")" /> + <description> + Sets a custom [MultiplayerAPI] with the given [code]root_path[/code] (controlling also the relative subpaths), or override the default one if [code]root_path[/code] is empty. + </description> + </method> <method name="set_quit_on_go_back"> <return type="void" /> <argument index="0" name="enabled" type="bool" /> @@ -215,9 +230,6 @@ <member name="edited_scene_root" type="Node" setter="set_edited_scene_root" getter="get_edited_scene_root"> The root of the edited scene. </member> - <member name="multiplayer" type="MultiplayerAPI" setter="set_multiplayer" getter="get_multiplayer"> - The default [MultiplayerAPI] instance for this [SceneTree]. - </member> <member name="multiplayer_poll" type="bool" setter="set_multiplayer_poll_enabled" getter="is_multiplayer_poll_enabled" default="true"> If [code]true[/code] (default value), enables automatic polling of the [MultiplayerAPI] for this SceneTree during [signal process_frame]. If [code]false[/code], you need to manually call [method MultiplayerAPI.poll] to process network packets and deliver RPCs. This allows running RPCs in a different loop (e.g. physics, thread, specific time step) and for manual [Mutex] protection when accessing the [MultiplayerAPI] from threads. diff --git a/drivers/gles3/rasterizer_scene_gles3.cpp b/drivers/gles3/rasterizer_scene_gles3.cpp index 1382573461..08d6dd25cf 100644 --- a/drivers/gles3/rasterizer_scene_gles3.cpp +++ b/drivers/gles3/rasterizer_scene_gles3.cpp @@ -411,7 +411,7 @@ void RasterizerSceneGLES3::voxel_gi_set_quality(RS::VoxelGIQuality) { void RasterizerSceneGLES3::render_scene(RID p_render_buffers, const CameraData *p_camera_data, const PagedArray<GeometryInstance *> &p_instances, const PagedArray<RID> &p_lights, const PagedArray<RID> &p_reflection_probes, const PagedArray<RID> &p_voxel_gi_instances, const PagedArray<RID> &p_decals, const PagedArray<RID> &p_lightmaps, const PagedArray<RID> &p_fog_volumes, RID p_environment, RID p_camera_effects, RID p_shadow_atlas, RID p_occluder_debug_tex, RID p_reflection_atlas, RID p_reflection_probe, int p_reflection_probe_pass, float p_screen_mesh_lod_threshold, const RenderShadowData *p_render_shadows, int p_render_shadow_count, const RenderSDFGIData *p_render_sdfgi_regions, int p_render_sdfgi_region_count, const RenderSDFGIUpdateData *p_sdfgi_update_data, RendererScene::RenderInfo *r_render_info) { } -void RasterizerSceneGLES3::render_material(const Transform3D &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, const PagedArray<GeometryInstance *> &p_instances, RID p_framebuffer, const Rect2i &p_region) { +void RasterizerSceneGLES3::render_material(const Transform3D &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_orthogonal, const PagedArray<GeometryInstance *> &p_instances, RID p_framebuffer, const Rect2i &p_region) { } void RasterizerSceneGLES3::render_particle_collider_heightfield(RID p_collider, const Transform3D &p_transform, const PagedArray<GeometryInstance *> &p_instances) { diff --git a/drivers/gles3/rasterizer_scene_gles3.h b/drivers/gles3/rasterizer_scene_gles3.h index 12bb21a5a0..1c78c66c20 100644 --- a/drivers/gles3/rasterizer_scene_gles3.h +++ b/drivers/gles3/rasterizer_scene_gles3.h @@ -196,7 +196,7 @@ public: void voxel_gi_set_quality(RS::VoxelGIQuality) override; void render_scene(RID p_render_buffers, const CameraData *p_camera_data, const PagedArray<GeometryInstance *> &p_instances, const PagedArray<RID> &p_lights, const PagedArray<RID> &p_reflection_probes, const PagedArray<RID> &p_voxel_gi_instances, const PagedArray<RID> &p_decals, const PagedArray<RID> &p_lightmaps, const PagedArray<RID> &p_fog_volumes, RID p_environment, RID p_camera_effects, RID p_shadow_atlas, RID p_occluder_debug_tex, RID p_reflection_atlas, RID p_reflection_probe, int p_reflection_probe_pass, float p_screen_mesh_lod_threshold, const RenderShadowData *p_render_shadows, int p_render_shadow_count, const RenderSDFGIData *p_render_sdfgi_regions, int p_render_sdfgi_region_count, const RenderSDFGIUpdateData *p_sdfgi_update_data = nullptr, RendererScene::RenderInfo *r_render_info = nullptr) override; - void render_material(const Transform3D &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, const PagedArray<GeometryInstance *> &p_instances, RID p_framebuffer, const Rect2i &p_region) override; + void render_material(const Transform3D &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_orthogonal, const PagedArray<GeometryInstance *> &p_instances, RID p_framebuffer, const Rect2i &p_region) override; void render_particle_collider_heightfield(RID p_collider, const Transform3D &p_transform, const PagedArray<GeometryInstance *> &p_instances) override; void set_scene_pass(uint64_t p_pass) override; diff --git a/editor/editor_inspector.cpp b/editor/editor_inspector.cpp index bd9b0ae1c8..5d47b87fbf 100644 --- a/editor/editor_inspector.cpp +++ b/editor/editor_inspector.cpp @@ -3515,7 +3515,9 @@ void EditorInspector::_notification(int p_what) { get_v_scroll_bar()->call_deferred(SNAME("set_value"), update_scroll_request); update_scroll_request = -1; } - if (refresh_countdown > 0) { + if (update_tree_pending) { + refresh_countdown = float(EditorSettings::get_singleton()->get("docks/property_editor/auto_refresh_interval")); + } else if (refresh_countdown > 0) { refresh_countdown -= get_process_delta_time(); if (refresh_countdown <= 0) { for (const KeyValue<StringName, List<EditorProperty *>> &F : editor_property_map) { diff --git a/editor/editor_node.cpp b/editor/editor_node.cpp index 3cc4821f95..db6bf4f816 100644 --- a/editor/editor_node.cpp +++ b/editor/editor_node.cpp @@ -134,6 +134,7 @@ #include "editor/plugins/asset_library_editor_plugin.h" #include "editor/plugins/audio_stream_editor_plugin.h" #include "editor/plugins/audio_stream_randomizer_editor_plugin.h" +#include "editor/plugins/bit_map_editor_plugin.h" #include "editor/plugins/camera_3d_editor_plugin.h" #include "editor/plugins/canvas_item_editor_plugin.h" #include "editor/plugins/collision_polygon_2d_editor_plugin.h" @@ -171,6 +172,7 @@ #include "editor/plugins/physical_bone_3d_editor_plugin.h" #include "editor/plugins/polygon_2d_editor_plugin.h" #include "editor/plugins/polygon_3d_editor_plugin.h" +#include "editor/plugins/ray_cast_2d_editor_plugin.h" #include "editor/plugins/replication_editor_plugin.h" #include "editor/plugins/resource_preloader_editor_plugin.h" #include "editor/plugins/root_motion_editor_plugin.h" @@ -4094,22 +4096,28 @@ Ref<Texture2D> EditorNode::get_class_icon(const String &p_class, const String &p ERR_FAIL_COND_V_MSG(p_class.is_empty(), nullptr, "Class name cannot be empty."); if (ScriptServer::is_global_class(p_class)) { - Ref<ImageTexture> icon; - Ref<Script> script = EditorNode::get_editor_data().script_class_load_script(p_class); - StringName name = p_class; - - while (script.is_valid()) { - name = EditorNode::get_editor_data().script_class_get_name(script->get_path()); - String current_icon_path = EditorNode::get_editor_data().script_class_get_icon_path(name); - icon = _load_custom_class_icon(current_icon_path); + String class_name = p_class; + Ref<Script> script = EditorNode::get_editor_data().script_class_load_script(class_name); + + while (true) { + String icon_path = EditorNode::get_editor_data().script_class_get_icon_path(class_name); + Ref<Texture> icon = _load_custom_class_icon(icon_path); if (icon.is_valid()) { - return icon; + return icon; // Current global class has icon. } - script = script->get_base_script(); - } - if (icon.is_null()) { - icon = gui_base->get_theme_icon(ScriptServer::get_global_class_base(name), SNAME("EditorIcons")); + // Find next global class along the inheritance chain. + do { + Ref<Script> base_script = script->get_base_script(); + if (base_script.is_null()) { + // We've reached a native class, use its icon. + String base_type; + script->get_language()->get_global_class_name(script->get_path(), &base_type); + return gui_base->get_theme_icon(base_type, "EditorIcons"); + } + script = base_script; + class_name = EditorNode::get_editor_data().script_class_get_name(script->get_path()); + } while (class_name.is_empty()); } } @@ -7066,6 +7074,8 @@ EditorNode::EditorNode() { add_editor_plugin(memnew(TextControlEditorPlugin)); add_editor_plugin(memnew(ControlEditorPlugin)); add_editor_plugin(memnew(GradientTexture2DEditorPlugin)); + add_editor_plugin(memnew(BitMapEditorPlugin)); + add_editor_plugin(memnew(RayCast2DEditorPlugin)); for (int i = 0; i < EditorPlugins::get_plugin_count(); i++) { add_editor_plugin(EditorPlugins::create(i)); @@ -7084,6 +7094,7 @@ EditorNode::EditorNode() { resource_preview->add_preview_generator(Ref<EditorMeshPreviewPlugin>(memnew(EditorMeshPreviewPlugin))); resource_preview->add_preview_generator(Ref<EditorBitmapPreviewPlugin>(memnew(EditorBitmapPreviewPlugin))); resource_preview->add_preview_generator(Ref<EditorFontPreviewPlugin>(memnew(EditorFontPreviewPlugin))); + resource_preview->add_preview_generator(Ref<EditorGradientPreviewPlugin>(memnew(EditorGradientPreviewPlugin))); { Ref<StandardMaterial3DConversionPlugin> spatial_mat_convert; diff --git a/editor/editor_properties.cpp b/editor/editor_properties.cpp index 677d22cb62..581a807e27 100644 --- a/editor/editor_properties.cpp +++ b/editor/editor_properties.cpp @@ -3361,10 +3361,8 @@ struct EditorPropertyRangeHint { static EditorPropertyRangeHint _parse_range_hint(PropertyHint p_hint, const String &p_hint_text, double p_default_step) { EditorPropertyRangeHint hint; hint.step = p_default_step; - bool degrees = false; - + Vector<String> slices = p_hint_text.split(","); if (p_hint == PROPERTY_HINT_RANGE) { - Vector<String> slices = p_hint_text.split(","); ERR_FAIL_COND_V_MSG(slices.size() < 2, hint, vformat("Invalid PROPERTY_HINT_RANGE with hint \"%s\": Missing required min and/or max values.", p_hint_text)); @@ -3381,11 +3379,7 @@ static EditorPropertyRangeHint _parse_range_hint(PropertyHint p_hint, const Stri hint.hide_slider = false; for (int i = 2; i < slices.size(); i++) { String slice = slices[i].strip_edges(); - if (slice == "radians") { - hint.radians = true; - } else if (slice == "degrees") { - degrees = true; - } else if (slice == "or_greater") { + if (slice == "or_greater") { hint.greater = true; } else if (slice == "or_lesser") { hint.lesser = true; @@ -3393,11 +3387,20 @@ static EditorPropertyRangeHint _parse_range_hint(PropertyHint p_hint, const Stri hint.hide_slider = true; } else if (slice == "exp") { hint.exp_range = true; - } else if (slice.begins_with("suffix:")) { - hint.suffix = " " + slice.replace_first("suffix:", "").strip_edges(); } } } + bool degrees = false; + for (int i = 0; i < slices.size(); i++) { + String slice = slices[i].strip_edges(); + if (slice == "radians") { + hint.radians = true; + } else if (slice == "degrees") { + degrees = true; + } else if (slice.begins_with("suffix:")) { + hint.suffix = " " + slice.replace_first("suffix:", "").strip_edges(); + } + } if ((hint.radians || degrees) && hint.suffix.is_empty()) { hint.suffix = U"\u00B0"; diff --git a/editor/editor_properties_array_dict.cpp b/editor/editor_properties_array_dict.cpp index f59ba66862..ffbe50285c 100644 --- a/editor/editor_properties_array_dict.cpp +++ b/editor/editor_properties_array_dict.cpp @@ -209,46 +209,13 @@ void EditorPropertyArray::_object_id_selected(const StringName &p_property, Obje void EditorPropertyArray::update_property() { Variant array = get_edited_object()->get(get_edited_property()); - String arrtype = ""; - switch (array_type) { - case Variant::ARRAY: { - arrtype = "Array"; - } break; - - // Arrays. - case Variant::PACKED_BYTE_ARRAY: { - arrtype = "PackedByteArray"; - } break; - case Variant::PACKED_INT32_ARRAY: { - arrtype = "PackedInt32Array"; - } break; - case Variant::PACKED_FLOAT32_ARRAY: { - arrtype = "PackedFloat32Array"; - } break; - case Variant::PACKED_INT64_ARRAY: { - arrtype = "PackedInt64Array"; - } break; - case Variant::PACKED_FLOAT64_ARRAY: { - arrtype = "PackedFloat64Array"; - } break; - case Variant::PACKED_STRING_ARRAY: { - arrtype = "PackedStringArray"; - } break; - case Variant::PACKED_VECTOR2_ARRAY: { - arrtype = "PackedVector2Array"; - } break; - case Variant::PACKED_VECTOR3_ARRAY: { - arrtype = "PackedVector3Array"; - } break; - case Variant::PACKED_COLOR_ARRAY: { - arrtype = "PackedColorArray"; - } break; - default: { - } + String array_type_name = Variant::get_type_name(array_type); + if (array_type == Variant::ARRAY && subtype != Variant::NIL) { + array_type_name = vformat("%s[%s]", array_type_name, Variant::get_type_name(subtype)); } if (array.get_type() == Variant::NIL) { - edit->set_text(String("(Nil) ") + arrtype); + edit->set_text(vformat(TTR("(Nil) %s"), array_type_name)); edit->set_pressed(false); if (vbox) { set_bottom_editor(nullptr); @@ -264,7 +231,7 @@ void EditorPropertyArray::update_property() { page_index = MIN(page_index, max_page); int offset = page_index * page_length; - edit->set_text(arrtype + " (size " + itos(size) + ")"); + edit->set_text(vformat(TTR("%s (size %s)"), array_type_name, itos(size))); bool unfolded = get_edited_object()->editor_is_section_unfolded(get_edited_property()); if (edit->is_pressed() != unfolded) { diff --git a/editor/editor_resource_picker.cpp b/editor/editor_resource_picker.cpp index a1d09d4df3..3c68a715c3 100644 --- a/editor/editor_resource_picker.cpp +++ b/editor/editor_resource_picker.cpp @@ -90,7 +90,8 @@ void EditorResourcePicker::_update_resource_preview(const String &p_path, const if (p_preview.is_valid()) { preview_rect->set_offset(SIDE_LEFT, assign_button->get_icon()->get_width() + assign_button->get_theme_stylebox(SNAME("normal"))->get_default_margin(SIDE_LEFT) + get_theme_constant(SNAME("h_separation"), SNAME("Button"))); - if (Ref<GradientTexture1D>(edited_resource).is_valid()) { + // Resource-specific stretching. + if (Ref<GradientTexture1D>(edited_resource).is_valid() || Ref<Gradient>(edited_resource).is_valid()) { preview_rect->set_stretch_mode(TextureRect::STRETCH_SCALE); assign_button->set_custom_minimum_size(Size2(1, 1)); } else { diff --git a/editor/editor_run.cpp b/editor/editor_run.cpp index 574acdff1c..6a2ff50ee0 100644 --- a/editor/editor_run.cpp +++ b/editor/editor_run.cpp @@ -98,67 +98,79 @@ Error EditorRun::run(const String &p_scene) { screen_rect.position = DisplayServer::get_singleton()->screen_get_position(screen); screen_rect.size = DisplayServer::get_singleton()->screen_get_size(screen); - Size2 window_size; - window_size.x = ProjectSettings::get_singleton()->get("display/window/size/viewport_width"); - window_size.y = ProjectSettings::get_singleton()->get("display/window/size/viewport_height"); - - Size2 desired_size; - desired_size.x = ProjectSettings::get_singleton()->get("display/window/size/window_width_override"); - desired_size.y = ProjectSettings::get_singleton()->get("display/window/size/window_height_override"); - if (desired_size.x > 0 && desired_size.y > 0) { - window_size = desired_size; - } - int window_placement = EditorSettings::get_singleton()->get("run/window_placement/rect"); - if (DisplayServer::get_singleton()->has_feature(DisplayServer::FEATURE_HIDPI)) { - bool hidpi_proj = ProjectSettings::get_singleton()->get("display/window/dpi/allow_hidpi"); - int display_scale = 1; + if (screen_rect != Rect2()) { + Size2 window_size; + window_size.x = ProjectSettings::get_singleton()->get("display/window/size/viewport_width"); + window_size.y = ProjectSettings::get_singleton()->get("display/window/size/viewport_height"); + + Size2 desired_size; + desired_size.x = ProjectSettings::get_singleton()->get("display/window/size/window_width_override"); + desired_size.y = ProjectSettings::get_singleton()->get("display/window/size/window_height_override"); + if (desired_size.x > 0 && desired_size.y > 0) { + window_size = desired_size; + } - if (OS::get_singleton()->is_hidpi_allowed()) { - if (hidpi_proj) { - display_scale = 1; // Both editor and project runs in hiDPI mode, do not scale. - } else { - display_scale = DisplayServer::get_singleton()->screen_get_max_scale(); // Editor is in hiDPI mode, project is not, scale down. - } - } else { - if (hidpi_proj) { - display_scale = (1.f / DisplayServer::get_singleton()->screen_get_max_scale()); // Editor is not in hiDPI mode, project is, scale up. + if (DisplayServer::get_singleton()->has_feature(DisplayServer::FEATURE_HIDPI)) { + bool hidpi_proj = ProjectSettings::get_singleton()->get("display/window/dpi/allow_hidpi"); + int display_scale = 1; + + if (OS::get_singleton()->is_hidpi_allowed()) { + if (hidpi_proj) { + display_scale = 1; // Both editor and project runs in hiDPI mode, do not scale. + } else { + display_scale = DisplayServer::get_singleton()->screen_get_max_scale(); // Editor is in hiDPI mode, project is not, scale down. + } } else { - display_scale = 1; // Both editor and project runs in lowDPI mode, do not scale. + if (hidpi_proj) { + display_scale = (1.f / DisplayServer::get_singleton()->screen_get_max_scale()); // Editor is not in hiDPI mode, project is, scale up. + } else { + display_scale = 1; // Both editor and project runs in lowDPI mode, do not scale. + } } + screen_rect.position /= display_scale; + screen_rect.size /= display_scale; } - screen_rect.position /= display_scale; - screen_rect.size /= display_scale; - } - switch (window_placement) { - case 0: { // top left - args.push_back("--position"); - args.push_back(itos(screen_rect.position.x) + "," + itos(screen_rect.position.y)); - } break; - case 1: { // centered - Vector2 pos = (screen_rect.position) + ((screen_rect.size - window_size) / 2).floor(); - args.push_back("--position"); - args.push_back(itos(pos.x) + "," + itos(pos.y)); - } break; - case 2: { // custom pos - Vector2 pos = EditorSettings::get_singleton()->get("run/window_placement/rect_custom_position"); - pos += screen_rect.position; - args.push_back("--position"); - args.push_back(itos(pos.x) + "," + itos(pos.y)); - } break; - case 3: { // force maximized - Vector2 pos = screen_rect.position; - args.push_back("--position"); - args.push_back(itos(pos.x) + "," + itos(pos.y)); - args.push_back("--maximized"); - } break; - case 4: { // force fullscreen - Vector2 pos = screen_rect.position; - args.push_back("--position"); - args.push_back(itos(pos.x) + "," + itos(pos.y)); - args.push_back("--fullscreen"); - } break; + switch (window_placement) { + case 0: { // top left + args.push_back("--position"); + args.push_back(itos(screen_rect.position.x) + "," + itos(screen_rect.position.y)); + } break; + case 1: { // centered + Vector2 pos = (screen_rect.position) + ((screen_rect.size - window_size) / 2).floor(); + args.push_back("--position"); + args.push_back(itos(pos.x) + "," + itos(pos.y)); + } break; + case 2: { // custom pos + Vector2 pos = EditorSettings::get_singleton()->get("run/window_placement/rect_custom_position"); + pos += screen_rect.position; + args.push_back("--position"); + args.push_back(itos(pos.x) + "," + itos(pos.y)); + } break; + case 3: { // force maximized + Vector2 pos = screen_rect.position; + args.push_back("--position"); + args.push_back(itos(pos.x) + "," + itos(pos.y)); + args.push_back("--maximized"); + } break; + case 4: { // force fullscreen + Vector2 pos = screen_rect.position; + args.push_back("--position"); + args.push_back(itos(pos.x) + "," + itos(pos.y)); + args.push_back("--fullscreen"); + } break; + } + } else { + // Unable to get screen info, skip setting position. + switch (window_placement) { + case 3: { // force maximized + args.push_back("--maximized"); + } break; + case 4: { // force fullscreen + args.push_back("--fullscreen"); + } break; + } } List<String> breakpoints; diff --git a/editor/editor_settings.cpp b/editor/editor_settings.cpp index 48f04694aa..bdabff20f9 100644 --- a/editor/editor_settings.cpp +++ b/editor/editor_settings.cpp @@ -1365,6 +1365,12 @@ float EditorSettings::get_auto_display_scale() const { return DisplayServer::get_singleton()->screen_get_max_scale(); #else const int screen = DisplayServer::get_singleton()->window_get_current_screen(); + + if (DisplayServer::get_singleton()->screen_get_size(screen) == Vector2i()) { + // Invalid screen size, skip. + return 1.0; + } + // Use the smallest dimension to use a correct display scale on portrait displays. const int smallest_dimension = MIN(DisplayServer::get_singleton()->screen_get_size(screen).x, DisplayServer::get_singleton()->screen_get_size(screen).y); if (DisplayServer::get_singleton()->screen_get_dpi(screen) >= 192 && smallest_dimension >= 1400) { diff --git a/editor/import/resource_importer_texture.cpp b/editor/import/resource_importer_texture.cpp index de51a28c5a..8c038d0311 100644 --- a/editor/import/resource_importer_texture.cpp +++ b/editor/import/resource_importer_texture.cpp @@ -221,6 +221,7 @@ void ResourceImporterTexture::get_import_options(const String &p_path, List<Impo r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL, "process/premult_alpha"), false)); r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL, "process/normal_map_invert_y"), false)); r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL, "process/hdr_as_srgb"), false)); + r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL, "process/hdr_clamp_exposure"), false)); r_options->push_back(ImportOption(PropertyInfo(Variant::INT, "process/size_limit", PROPERTY_HINT_RANGE, "0,4096,1"), 0)); r_options->push_back(ImportOption(PropertyInfo(Variant::INT, "detect_3d/compress_to", PROPERTY_HINT_ENUM, "Disabled,VRAM Compressed,Basis Universal"), (p_preset == PRESET_DETECT) ? 1 : 0)); @@ -414,6 +415,7 @@ Error ResourceImporterTexture::import(const String &p_source_file, const String const bool stream = false; const int size_limit = p_options["process/size_limit"]; const bool hdr_as_srgb = p_options["process/hdr_as_srgb"]; + const bool hdr_clamp_exposure = p_options["process/hdr_clamp_exposure"]; const int normal = p_options["compress/normal_map"]; const int hdr_compression = p_options["compress/hdr_compression"]; const int bptc_ldr = p_options["compress/bptc_ldr"]; @@ -485,6 +487,34 @@ Error ResourceImporterTexture::import(const String &p_source_file, const String } } + if (hdr_clamp_exposure) { + // Clamp HDR exposure following Filament's tonemapping formula. + // This can be used to reduce fireflies in environment maps or reduce the influence + // of the sun from an HDRI panorama on environment lighting (when a DirectionalLight3D is used instead). + const int height = image->get_height(); + const int width = image->get_width(); + + // These values are chosen arbitrarily and seem to produce good results with 4,096 samples. + const float linear = 4096.0; + const float compressed = 16384.0; + + for (int i = 0; i < width; i++) { + for (int j = 0; j < height; j++) { + const Color color = image->get_pixel(i, j); + const float luma = color.get_luminance(); + + Color clamped_color; + if (luma <= linear) { + clamped_color = color; + } else { + clamped_color = (color / luma) * ((linear * linear - compressed * luma) / (2 * linear - compressed - luma)); + } + + image->set_pixel(i, j, clamped_color); + } + } + } + if (compress_mode == COMPRESS_BASIS_UNIVERSAL && image->get_format() >= Image::FORMAT_RF) { //basis universal does not support float formats, fall back compress_mode = COMPRESS_VRAM_COMPRESSED; diff --git a/editor/import/scene_import_settings.cpp b/editor/import/scene_import_settings.cpp index 4e53a644ee..b08622b910 100644 --- a/editor/import/scene_import_settings.cpp +++ b/editor/import/scene_import_settings.cpp @@ -423,7 +423,7 @@ void SceneImportSettings::_update_view_gizmos() { continue; } - TypedArray<Node> descendants = mesh_node->find_nodes("collider_view", "MeshInstance3D"); + TypedArray<Node> descendants = mesh_node->find_children("collider_view", "MeshInstance3D"); CRASH_COND_MSG(descendants.is_empty(), "This is unreachable, since the collider view is always created even when the collision is not used! If this is triggered there is a bug on the function `_fill_scene`."); diff --git a/editor/plugins/bit_map_editor_plugin.cpp b/editor/plugins/bit_map_editor_plugin.cpp new file mode 100644 index 0000000000..9003c4480b --- /dev/null +++ b/editor/plugins/bit_map_editor_plugin.cpp @@ -0,0 +1,86 @@ +/*************************************************************************/ +/* bit_map_editor_plugin.cpp */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#include "bit_map_editor_plugin.h" + +#include "editor/editor_scale.h" + +void BitMapEditor::setup(const Ref<BitMap> &p_bitmap) { + Ref<ImageTexture> texture; + texture.instantiate(); + texture->create_from_image(p_bitmap->convert_to_image()); + texture_rect->set_texture(texture); + + size_label->set_text(vformat(String::utf8("%s×%s"), p_bitmap->get_size().width, p_bitmap->get_size().height)); +} + +BitMapEditor::BitMapEditor() { + texture_rect = memnew(TextureRect); + texture_rect->set_stretch_mode(TextureRect::STRETCH_KEEP_ASPECT_CENTERED); + texture_rect->set_texture_filter(TEXTURE_FILTER_NEAREST); + texture_rect->set_custom_minimum_size(Size2(0, 250) * EDSCALE); + add_child(texture_rect); + + size_label = memnew(Label); + size_label->set_horizontal_alignment(HORIZONTAL_ALIGNMENT_RIGHT); + add_child(size_label); + + // Reduce extra padding on top and bottom of size label. + Ref<StyleBoxEmpty> stylebox; + stylebox.instantiate(); + stylebox->set_default_margin(SIDE_RIGHT, 4 * EDSCALE); + size_label->add_theme_style_override("normal", stylebox); +} + +/////////////////////// + +bool EditorInspectorPluginBitMap::can_handle(Object *p_object) { + return Object::cast_to<BitMap>(p_object) != nullptr; +} + +void EditorInspectorPluginBitMap::parse_begin(Object *p_object) { + BitMap *bitmap = Object::cast_to<BitMap>(p_object); + if (!bitmap) { + return; + } + Ref<BitMap> bm(bitmap); + + BitMapEditor *editor = memnew(BitMapEditor); + editor->setup(bm); + add_custom_control(editor); +} + +/////////////////////// + +BitMapEditorPlugin::BitMapEditorPlugin() { + Ref<EditorInspectorPluginBitMap> plugin; + plugin.instantiate(); + add_inspector_plugin(plugin); +} diff --git a/editor/plugins/bit_map_editor_plugin.h b/editor/plugins/bit_map_editor_plugin.h new file mode 100644 index 0000000000..c883e5542f --- /dev/null +++ b/editor/plugins/bit_map_editor_plugin.h @@ -0,0 +1,64 @@ +/*************************************************************************/ +/* bit_map_editor_plugin.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#ifndef BIT_MAP_PREVIEW_EDITOR_PLUGIN_H +#define BIT_MAP_PREVIEW_EDITOR_PLUGIN_H + +#include "editor/editor_plugin.h" +#include "scene/resources/bit_map.h" + +class BitMapEditor : public VBoxContainer { + GDCLASS(BitMapEditor, VBoxContainer); + + TextureRect *texture_rect = nullptr; + Label *size_label = nullptr; + +public: + void setup(const Ref<BitMap> &p_bitmap); + + BitMapEditor(); +}; + +class EditorInspectorPluginBitMap : public EditorInspectorPlugin { + GDCLASS(EditorInspectorPluginBitMap, EditorInspectorPlugin); + +public: + virtual bool can_handle(Object *p_object) override; + virtual void parse_begin(Object *p_object) override; +}; + +class BitMapEditorPlugin : public EditorPlugin { + GDCLASS(BitMapEditorPlugin, EditorPlugin); + +public: + BitMapEditorPlugin(); +}; + +#endif // BIT_MAP_PREVIEW_EDITOR_PLUGIN_H diff --git a/editor/plugins/editor_preview_plugins.cpp b/editor/plugins/editor_preview_plugins.cpp index b8556220d2..a160ca463b 100644 --- a/editor/plugins/editor_preview_plugins.cpp +++ b/editor/plugins/editor_preview_plugins.cpp @@ -904,3 +904,34 @@ EditorFontPreviewPlugin::~EditorFontPreviewPlugin() { RS::get_singleton()->free(canvas); RS::get_singleton()->free(viewport); } + +//////////////////////////////////////////////////////////////////////////// + +static const real_t GRADIENT_PREVIEW_TEXTURE_SCALE_FACTOR = 4.0; + +bool EditorGradientPreviewPlugin::handles(const String &p_type) const { + return ClassDB::is_parent_class(p_type, "Gradient"); +} + +bool EditorGradientPreviewPlugin::generate_small_preview_automatically() const { + return true; +} + +Ref<Texture2D> EditorGradientPreviewPlugin::generate(const RES &p_from, const Size2 &p_size) const { + Ref<Gradient> gradient = p_from; + if (gradient.is_valid()) { + Ref<GradientTexture1D> ptex; + ptex.instantiate(); + ptex->set_width(p_size.width * GRADIENT_PREVIEW_TEXTURE_SCALE_FACTOR * EDSCALE); + ptex->set_gradient(gradient); + + Ref<ImageTexture> itex; + itex.instantiate(); + itex->create_from_image(ptex->get_image()); + return itex; + } + return Ref<Texture2D>(); +} + +EditorGradientPreviewPlugin::EditorGradientPreviewPlugin() { +} diff --git a/editor/plugins/editor_preview_plugins.h b/editor/plugins/editor_preview_plugins.h index 803f03f17e..73eb90dd86 100644 --- a/editor/plugins/editor_preview_plugins.h +++ b/editor/plugins/editor_preview_plugins.h @@ -182,4 +182,15 @@ public: EditorTileMapPatternPreviewPlugin(); ~EditorTileMapPatternPreviewPlugin(); }; + +class EditorGradientPreviewPlugin : public EditorResourcePreviewGenerator { + GDCLASS(EditorGradientPreviewPlugin, EditorResourcePreviewGenerator); + +public: + virtual bool handles(const String &p_type) const override; + virtual bool generate_small_preview_automatically() const override; + virtual Ref<Texture2D> generate(const RES &p_from, const Size2 &p_size) const override; + + EditorGradientPreviewPlugin(); +}; #endif // EDITORPREVIEWPLUGINS_H diff --git a/editor/plugins/ray_cast_2d_editor_plugin.cpp b/editor/plugins/ray_cast_2d_editor_plugin.cpp new file mode 100644 index 0000000000..6f247a37ef --- /dev/null +++ b/editor/plugins/ray_cast_2d_editor_plugin.cpp @@ -0,0 +1,151 @@ +/*************************************************************************/ +/* ray_cast_2d_editor_plugin.cpp */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#include "ray_cast_2d_editor_plugin.h" + +#include "canvas_item_editor_plugin.h" +#include "editor/editor_node.h" + +void RayCast2DEditor::_notification(int p_what) { + switch (p_what) { + case NOTIFICATION_ENTER_TREE: { + get_tree()->connect("node_removed", callable_mp(this, &RayCast2DEditor::_node_removed)); + } break; + + case NOTIFICATION_EXIT_TREE: { + get_tree()->disconnect("node_removed", callable_mp(this, &RayCast2DEditor::_node_removed)); + } break; + } +} + +void RayCast2DEditor::_node_removed(Node *p_node) { + if (p_node == node) { + node = nullptr; + } +} + +bool RayCast2DEditor::forward_canvas_gui_input(const Ref<InputEvent> &p_event) { + if (!node || !node->is_visible_in_tree()) { + return false; + } + + Transform2D xform = canvas_item_editor->get_canvas_transform() * node->get_global_transform(); + + Ref<InputEventMouseButton> mb = p_event; + if (mb.is_valid() && mb->get_button_index() == MouseButton::LEFT) { + if (mb->is_pressed()) { + if (xform.xform(node->get_target_position()).distance_to(mb->get_position()) < 8) { + pressed = true; + original_target_position = node->get_target_position(); + + return true; + } else { + pressed = false; + + return false; + } + } else if (pressed) { + undo_redo->create_action(TTR("Set target_position")); + undo_redo->add_do_method(node, "set_target_position", node->get_target_position()); + undo_redo->add_do_method(canvas_item_editor, "update_viewport"); + undo_redo->add_undo_method(node, "set_target_position", original_target_position); + undo_redo->add_undo_method(canvas_item_editor, "update_viewport"); + undo_redo->commit_action(); + + pressed = false; + + return true; + } + } + + Ref<InputEventMouseMotion> mm = p_event; + if (mm.is_valid() && pressed) { + Vector2 point = canvas_item_editor->snap_point(canvas_item_editor->get_canvas_transform().affine_inverse().xform(mm->get_position())); + point = node->get_global_transform().affine_inverse().xform(point); + + node->set_target_position(point); + canvas_item_editor->update_viewport(); + node->notify_property_list_changed(); + + return true; + } + + return false; +} + +void RayCast2DEditor::forward_canvas_draw_over_viewport(Control *p_overlay) { + if (!node || !node->is_visible_in_tree()) { + return; + } + + Transform2D gt = canvas_item_editor->get_canvas_transform() * node->get_global_transform(); + + const Ref<Texture2D> handle = get_theme_icon(SNAME("EditorHandle"), SNAME("EditorIcons")); + p_overlay->draw_texture(handle, gt.xform(node->get_target_position()) - handle->get_size() / 2); +} + +void RayCast2DEditor::edit(Node *p_node) { + if (!canvas_item_editor) { + canvas_item_editor = CanvasItemEditor::get_singleton(); + } + + if (p_node) { + node = Object::cast_to<RayCast2D>(p_node); + } else { + node = nullptr; + } + + canvas_item_editor->update_viewport(); +} + +RayCast2DEditor::RayCast2DEditor() { + undo_redo = EditorNode::get_singleton()->get_undo_redo(); +} + +/////////////////////// + +void RayCast2DEditorPlugin::edit(Object *p_object) { + ray_cast_2d_editor->edit(Object::cast_to<RayCast2D>(p_object)); +} + +bool RayCast2DEditorPlugin::handles(Object *p_object) const { + return Object::cast_to<RayCast2D>(p_object) != nullptr; +} + +void RayCast2DEditorPlugin::make_visible(bool p_visible) { + if (!p_visible) { + edit(nullptr); + } +} + +RayCast2DEditorPlugin::RayCast2DEditorPlugin() { + ray_cast_2d_editor = memnew(RayCast2DEditor); + EditorNode::get_singleton()->get_gui_base()->add_child(ray_cast_2d_editor); +} diff --git a/editor/plugins/ray_cast_2d_editor_plugin.h b/editor/plugins/ray_cast_2d_editor_plugin.h new file mode 100644 index 0000000000..74628da0e4 --- /dev/null +++ b/editor/plugins/ray_cast_2d_editor_plugin.h @@ -0,0 +1,79 @@ +/*************************************************************************/ +/* ray_cast_2d_editor_plugin.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#ifndef RAY_CAST_2D_EDITOR_PLUGIN_H +#define RAY_CAST_2D_EDITOR_PLUGIN_H + +#include "editor/editor_plugin.h" +#include "scene/2d/ray_cast_2d.h" + +class CanvasItemEditor; + +class RayCast2DEditor : public Control { + GDCLASS(RayCast2DEditor, Control); + + UndoRedo *undo_redo = nullptr; + CanvasItemEditor *canvas_item_editor = nullptr; + RayCast2D *node; + + bool pressed = false; + Point2 original_target_position; + +protected: + void _notification(int p_what); + void _node_removed(Node *p_node); + +public: + bool forward_canvas_gui_input(const Ref<InputEvent> &p_event); + void forward_canvas_draw_over_viewport(Control *p_overlay); + void edit(Node *p_node); + + RayCast2DEditor(); +}; + +class RayCast2DEditorPlugin : public EditorPlugin { + GDCLASS(RayCast2DEditorPlugin, EditorPlugin); + + RayCast2DEditor *ray_cast_2d_editor = nullptr; + +public: + virtual bool forward_canvas_gui_input(const Ref<InputEvent> &p_event) override { return ray_cast_2d_editor->forward_canvas_gui_input(p_event); } + virtual void forward_canvas_draw_over_viewport(Control *p_overlay) override { ray_cast_2d_editor->forward_canvas_draw_over_viewport(p_overlay); } + + virtual String get_name() const override { return "RayCast2D"; } + bool has_main_screen() const override { return false; } + virtual void edit(Object *p_object) override; + virtual bool handles(Object *p_object) const override; + virtual void make_visible(bool visible) override; + + RayCast2DEditorPlugin(); +}; + +#endif // RAY_CAST_2D_EDITOR_PLUGIN_H diff --git a/editor/project_manager.cpp b/editor/project_manager.cpp index 81df7ee30a..82aa4ead6f 100644 --- a/editor/project_manager.cpp +++ b/editor/project_manager.cpp @@ -2877,17 +2877,15 @@ ProjectManager::ProjectManager() { Vector2i screen_size = DisplayServer::get_singleton()->screen_get_size(); Vector2i screen_position = DisplayServer::get_singleton()->screen_get_position(); - // Consider the editor display scale. - window_size.x = round((float)window_size.x * scale_factor); - window_size.y = round((float)window_size.y * scale_factor); - - // Make the window centered on the screen. - Vector2i window_position; - window_position.x = screen_position.x + (screen_size.x - window_size.x) / 2; - window_position.y = screen_position.y + (screen_size.y - window_size.y) / 2; + window_size *= scale_factor; DisplayServer::get_singleton()->window_set_size(window_size); - DisplayServer::get_singleton()->window_set_position(window_position); + if (screen_size != Vector2i()) { + Vector2i window_position; + window_position.x = screen_position.x + (screen_size.x - window_size.x) / 2; + window_position.y = screen_position.y + (screen_size.y - window_size.y) / 2; + DisplayServer::get_singleton()->window_set_position(window_position); + } } OS::get_singleton()->set_low_processor_usage_mode(true); diff --git a/main/main.cpp b/main/main.cpp index f20ec94fa5..755924929c 100644 --- a/main/main.cpp +++ b/main/main.cpp @@ -120,10 +120,10 @@ static RenderingServer *rendering_server = nullptr; static CameraServer *camera_server = nullptr; static XRServer *xr_server = nullptr; static TextServerManager *tsman = nullptr; -static PhysicsServer3D *physics_server = nullptr; -static PhysicsServer2D *physics_2d_server = nullptr; -static NavigationServer3D *navigation_server = nullptr; -static NavigationServer2D *navigation_2d_server = nullptr; +static PhysicsServer3D *physics_server_3d = nullptr; +static PhysicsServer2D *physics_server_2d = nullptr; +static NavigationServer3D *navigation_server_3d = nullptr; +static NavigationServer2D *navigation_server_2d = nullptr; // We error out if setup2() doesn't turn this true static bool _start_success = false; @@ -204,32 +204,32 @@ static String get_full_version_string() { // to have less code in main.cpp. void initialize_physics() { /// 3D Physics Server - physics_server = PhysicsServer3DManager::new_server( + physics_server_3d = PhysicsServer3DManager::new_server( ProjectSettings::get_singleton()->get(PhysicsServer3DManager::setting_property_name)); - if (!physics_server) { + if (!physics_server_3d) { // Physics server not found, Use the default physics - physics_server = PhysicsServer3DManager::new_default_server(); + physics_server_3d = PhysicsServer3DManager::new_default_server(); } - ERR_FAIL_COND(!physics_server); - physics_server->init(); + ERR_FAIL_COND(!physics_server_3d); + physics_server_3d->init(); /// 2D Physics server - physics_2d_server = PhysicsServer2DManager::new_server( + physics_server_2d = PhysicsServer2DManager::new_server( ProjectSettings::get_singleton()->get(PhysicsServer2DManager::setting_property_name)); - if (!physics_2d_server) { + if (!physics_server_2d) { // Physics server not found, Use the default physics - physics_2d_server = PhysicsServer2DManager::new_default_server(); + physics_server_2d = PhysicsServer2DManager::new_default_server(); } - ERR_FAIL_COND(!physics_2d_server); - physics_2d_server->init(); + ERR_FAIL_COND(!physics_server_2d); + physics_server_2d->init(); } void finalize_physics() { - physics_server->finish(); - memdelete(physics_server); + physics_server_3d->finish(); + memdelete(physics_server_3d); - physics_2d_server->finish(); - memdelete(physics_2d_server); + physics_server_2d->finish(); + memdelete(physics_server_2d); } void finalize_display() { @@ -240,18 +240,18 @@ void finalize_display() { } void initialize_navigation_server() { - ERR_FAIL_COND(navigation_server != nullptr); + ERR_FAIL_COND(navigation_server_3d != nullptr); - navigation_server = NavigationServer3DManager::new_default_server(); - navigation_2d_server = memnew(NavigationServer2D); + navigation_server_3d = NavigationServer3DManager::new_default_server(); + navigation_server_2d = memnew(NavigationServer2D); } void finalize_navigation_server() { - memdelete(navigation_server); - navigation_server = nullptr; + memdelete(navigation_server_3d); + navigation_server_3d = nullptr; - memdelete(navigation_2d_server); - navigation_2d_server = nullptr; + memdelete(navigation_server_2d); + navigation_server_2d = nullptr; } //#define DEBUG_INIT diff --git a/modules/gdscript/gdscript.cpp b/modules/gdscript/gdscript.cpp index 59254fc3ad..55c7ace938 100644 --- a/modules/gdscript/gdscript.cpp +++ b/modules/gdscript/gdscript.cpp @@ -1032,7 +1032,13 @@ Error GDScript::load_source_code(const String &p_path) { Error err; Ref<FileAccess> f = FileAccess::open(p_path, FileAccess::READ, &err); if (err) { - ERR_FAIL_COND_V(err, err); + const char *err_name; + if (err < 0 || err >= ERR_MAX) { + err_name = "(invalid error code)"; + } else { + err_name = error_names[err]; + } + ERR_FAIL_COND_V_MSG(err, err, "Attempt to open script '" + p_path + "' resulted in error '" + err_name + "'."); } uint64_t len = f->get_length(); diff --git a/modules/navigation/nav_map.cpp b/modules/navigation/nav_map.cpp index a6df6bb72c..cbc0adc574 100644 --- a/modules/navigation/nav_map.cpp +++ b/modules/navigation/nav_map.cpp @@ -30,7 +30,6 @@ #include "nav_map.h" -#include "core/os/threaded_array_processor.h" #include "nav_region.h" #include "rvo_agent.h" @@ -674,7 +673,10 @@ void NavMap::compute_single_step(uint32_t index, RvoAgent **agent) { void NavMap::step(real_t p_deltatime) { deltatime = p_deltatime; if (controlled_agents.size() > 0) { - thread_process_array( + if (step_work_pool.get_thread_count() == 0) { + step_work_pool.init(); + } + step_work_pool.do_work( controlled_agents.size(), this, &NavMap::compute_single_step, @@ -719,3 +721,10 @@ void NavMap::clip_path(const std::vector<gd::NavigationPoly> &p_navigation_polys } } } + +NavMap::NavMap() { +} + +NavMap::~NavMap() { + step_work_pool.finish(); +} diff --git a/modules/navigation/nav_map.h b/modules/navigation/nav_map.h index f46297a7ce..5232e42bed 100644 --- a/modules/navigation/nav_map.h +++ b/modules/navigation/nav_map.h @@ -35,6 +35,7 @@ #include "core/math/math_defs.h" #include "core/templates/map.h" +#include "core/templates/thread_work_pool.h" #include "nav_utils.h" #include <KdTree.h> @@ -80,8 +81,12 @@ class NavMap : public NavRid { /// Change the id each time the map is updated. uint32_t map_update_id = 0; + /// Pooled threads for computing steps + ThreadWorkPool step_work_pool; + public: - NavMap() {} + NavMap(); + ~NavMap(); void set_up(Vector3 p_up); Vector3 get_up() const { diff --git a/modules/noise/SCsub b/modules/noise/SCsub index 3e8395b9b1..1430aa0c4e 100644 --- a/modules/noise/SCsub +++ b/modules/noise/SCsub @@ -27,6 +27,7 @@ env.modules_sources += thirdparty_obj module_obj = [] env_noise.add_source_files(module_obj, "*.cpp") +env_noise.add_source_files(module_obj, "editor/*.cpp") env.modules_sources += module_obj # Needed to force rebuilding the module files when the thirdparty library is updated. diff --git a/modules/noise/doc_classes/FastNoiseLite.xml b/modules/noise/doc_classes/FastNoiseLite.xml index b6d91850c4..6ca4ba2d46 100644 --- a/modules/noise/doc_classes/FastNoiseLite.xml +++ b/modules/noise/doc_classes/FastNoiseLite.xml @@ -16,12 +16,9 @@ <member name="cellular_jitter" type="float" setter="set_cellular_jitter" getter="get_cellular_jitter" default="0.45"> Maximum distance a point can move off of its grid position. Set to [code]0[/code] for an even grid. </member> - <member name="cellular_return_type" type="int" setter="set_cellular_return_type" getter="get_cellular_return_type" enum="FastNoiseLite.CellularReturnType" default="0"> + <member name="cellular_return_type" type="int" setter="set_cellular_return_type" getter="get_cellular_return_type" enum="FastNoiseLite.CellularReturnType" default="1"> Return type from cellular noise calculations. See [enum CellularReturnType]. </member> - <member name="color_ramp" type="Gradient" setter="set_color_ramp" getter="get_color_ramp"> - A [Gradient] which is used to map the luminance of each pixel to a color value. - </member> <member name="domain_warp_amplitude" type="float" setter="set_domain_warp_amplitude" getter="get_domain_warp_amplitude" default="30.0"> Sets the maximum warp distance from the origin. </member> @@ -69,9 +66,6 @@ <member name="frequency" type="float" setter="set_frequency" getter="get_frequency" default="0.01"> The frequency for all noise types. Low frequency results in smooth noise while high frequency results in rougher, more granular noise. </member> - <member name="in_3d_space" type="bool" setter="set_in_3d_space" getter="is_in_3d_space" default="false"> - Determines whether the noise image returned by [method Noise.get_image] is calculated in 3d space. May result in reduced contrast. - </member> <member name="noise_type" type="int" setter="set_noise_type" getter="get_noise_type" enum="FastNoiseLite.NoiseType" default="1"> The noise algorithm used. See [enum NoiseType]. </member> diff --git a/modules/noise/doc_classes/Noise.xml b/modules/noise/doc_classes/Noise.xml index db0dec18d2..5af204575c 100644 --- a/modules/noise/doc_classes/Noise.xml +++ b/modules/noise/doc_classes/Noise.xml @@ -11,23 +11,24 @@ <tutorials> </tutorials> <methods> - <method name="get_image"> + <method name="get_image" qualifiers="const"> <return type="Image" /> <argument index="0" name="width" type="int" /> <argument index="1" name="height" type="int" /> <argument index="2" name="invert" type="bool" default="false" /> + <argument index="3" name="in_3d_space" type="bool" default="false" /> <description> Returns a 2D [Image] noise image. </description> </method> - <method name="get_noise_1d"> + <method name="get_noise_1d" qualifiers="const"> <return type="float" /> <argument index="0" name="x" type="float" /> <description> Returns the 1D noise value at the given (x) coordinate. </description> </method> - <method name="get_noise_2d"> + <method name="get_noise_2d" qualifiers="const"> <return type="float" /> <argument index="0" name="x" type="float" /> <argument index="1" name="y" type="float" /> @@ -35,14 +36,14 @@ Returns the 2D noise value at the given position. </description> </method> - <method name="get_noise_2dv"> + <method name="get_noise_2dv" qualifiers="const"> <return type="float" /> <argument index="0" name="v" type="Vector2" /> <description> Returns the 2D noise value at the given position. </description> </method> - <method name="get_noise_3d"> + <method name="get_noise_3d" qualifiers="const"> <return type="float" /> <argument index="0" name="x" type="float" /> <argument index="1" name="y" type="float" /> @@ -51,19 +52,20 @@ Returns the 3D noise value at the given position. </description> </method> - <method name="get_noise_3dv"> + <method name="get_noise_3dv" qualifiers="const"> <return type="float" /> <argument index="0" name="v" type="Vector3" /> <description> Returns the 3D noise value at the given position. </description> </method> - <method name="get_seamless_image"> + <method name="get_seamless_image" qualifiers="const"> <return type="Image" /> <argument index="0" name="width" type="int" /> <argument index="1" name="height" type="int" /> <argument index="2" name="invert" type="bool" default="false" /> - <argument index="3" name="skirt" type="float" default="0.1" /> + <argument index="3" name="in_3d_space" type="bool" default="false" /> + <argument index="4" name="skirt" type="float" default="0.1" /> <description> Returns a seamless 2D [Image] noise image. </description> diff --git a/modules/noise/doc_classes/NoiseTexture.xml b/modules/noise/doc_classes/NoiseTexture.xml index 63630eccde..62a223b387 100644 --- a/modules/noise/doc_classes/NoiseTexture.xml +++ b/modules/noise/doc_classes/NoiseTexture.xml @@ -24,9 +24,20 @@ <member name="bump_strength" type="float" setter="set_bump_strength" getter="get_bump_strength" default="8.0"> Strength of the bump maps used in this texture. A higher value will make the bump maps appear larger while a lower value will make them appear softer. </member> + <member name="color_ramp" type="Gradient" setter="set_color_ramp" getter="get_color_ramp"> + A [Gradient] which is used to map the luminance of each pixel to a color value. + </member> + <member name="generate_mipmaps" type="bool" setter="set_generate_mipmaps" getter="is_generating_mipmaps" default="true"> + Determines whether mipmaps are generated for this texture. + Enabling this results in less texture aliasing, but the noise texture generation may take longer. + Requires (anisotropic) mipmap filtering to be enabled for a material to have an effect. + </member> <member name="height" type="int" setter="set_height" getter="get_height" default="512"> Height of the generated texture. </member> + <member name="in_3d_space" type="bool" setter="set_in_3d_space" getter="is_in_3d_space" default="false"> + Determines whether the noise image is calculated in 3D space. May result in reduced contrast. + </member> <member name="invert" type="bool" setter="set_invert" getter="get_invert" default="false"> If [code]true[/code], inverts the noise texture. White becomes black, black becomes white. </member> diff --git a/modules/noise/editor/noise_editor_plugin.cpp b/modules/noise/editor/noise_editor_plugin.cpp new file mode 100644 index 0000000000..32c3f0aad4 --- /dev/null +++ b/modules/noise/editor/noise_editor_plugin.cpp @@ -0,0 +1,149 @@ +/*************************************************************************/ +/* noise_editor_plugin.cpp */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#include "noise_editor_plugin.h" + +#ifdef TOOLS_ENABLED + +#include "editor/editor_scale.h" + +#include "modules/noise/noise.h" +#include "modules/noise/noise_texture.h" + +class NoisePreview : public Control { + GDCLASS(NoisePreview, Control) + + static const int PREVIEW_HEIGHT = 150; + static const int PADDING_3D_SPACE_SWITCH = 2; + + Ref<Noise> _noise; + Size2i _preview_texture_size; + + TextureRect *_texture_rect = nullptr; + Button *_3d_space_switch = nullptr; + +public: + NoisePreview() { + set_custom_minimum_size(Size2(0, EDSCALE * PREVIEW_HEIGHT)); + + _texture_rect = memnew(TextureRect); + _texture_rect->set_anchors_and_offsets_preset(Control::PRESET_WIDE); + _texture_rect->set_stretch_mode(TextureRect::STRETCH_KEEP_ASPECT_COVERED); + add_child(_texture_rect); + + _3d_space_switch = memnew(Button); + _3d_space_switch->set_text(TTR("3D")); + _3d_space_switch->set_tooltip(TTR("Toggles whether the noise preview is computed in 3D space.")); + _3d_space_switch->set_toggle_mode(true); + _3d_space_switch->set_offset(SIDE_LEFT, PADDING_3D_SPACE_SWITCH); + _3d_space_switch->set_offset(SIDE_TOP, PADDING_3D_SPACE_SWITCH); + _3d_space_switch->connect("pressed", callable_mp(this, &NoisePreview::_on_3d_button_pressed)); + add_child(_3d_space_switch); + } + + void set_noise(Ref<Noise> noise) { + if (_noise == noise) { + return; + } + _noise = noise; + if (_noise.is_valid()) { + if (_noise->has_meta("_preview_in_3d_space_")) { + _3d_space_switch->set_pressed(true); + } + + update_preview(); + } + } + +private: + void _on_3d_button_pressed() { + if (_3d_space_switch->is_pressed()) { + _noise->set_meta("_preview_in_3d_space_", true); + } else { + _noise->remove_meta("_preview_in_3d_space_"); + } + } + + void _notification(int p_what) { + switch (p_what) { + case NOTIFICATION_RESIZED: { + _preview_texture_size = get_size(); + update_preview(); + } break; + } + } + + void update_preview() { + if (MIN(_preview_texture_size.width, _preview_texture_size.height) > 0) { + Ref<NoiseTexture> tex; + tex.instantiate(); + tex->set_width(_preview_texture_size.width); + tex->set_height(_preview_texture_size.height); + tex->set_in_3d_space(_3d_space_switch->is_pressed()); + tex->set_noise(_noise); + _texture_rect->set_texture(tex); + } + } +}; + +///////////////////////////////////////////////////////////////////////////////// + +class NoiseEditorInspectorPlugin : public EditorInspectorPlugin { + GDCLASS(NoiseEditorInspectorPlugin, EditorInspectorPlugin) +public: + bool can_handle(Object *p_object) override { + return Object::cast_to<Noise>(p_object) != nullptr; + } + + void parse_begin(Object *p_object) override { + Noise *noise_ptr = Object::cast_to<Noise>(p_object); + if (noise_ptr) { + Ref<Noise> noise(noise_ptr); + + NoisePreview *viewer = memnew(NoisePreview); + viewer->set_noise(noise); + add_custom_control(viewer); + } + } +}; + +///////////////////////////////////////////////////////////////////////////////// + +String NoiseEditorPlugin::get_name() const { + return Noise::get_class_static(); +} + +NoiseEditorPlugin::NoiseEditorPlugin() { + Ref<NoiseEditorInspectorPlugin> plugin; + plugin.instantiate(); + add_inspector_plugin(plugin); +} + +#endif // TOOLS_ENABLED diff --git a/modules/noise/editor/noise_editor_plugin.h b/modules/noise/editor/noise_editor_plugin.h new file mode 100644 index 0000000000..55a01deb2d --- /dev/null +++ b/modules/noise/editor/noise_editor_plugin.h @@ -0,0 +1,49 @@ +/*************************************************************************/ +/* noise_editor_plugin.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#ifndef NOISE_EDITOR_PLUGIN_H +#define NOISE_EDITOR_PLUGIN_H + +#ifdef TOOLS_ENABLED + +#include "editor/editor_plugin.h" + +class NoiseEditorPlugin : public EditorPlugin { + GDCLASS(NoiseEditorPlugin, EditorPlugin) + +public: + String get_name() const override; + + NoiseEditorPlugin(); +}; + +#endif // TOOLS_ENABLED + +#endif // NOISE_EDITOR_PLUGIN_H diff --git a/modules/noise/fastnoise_lite.cpp b/modules/noise/fastnoise_lite.cpp index 9497fe6a7e..a8d38dee62 100644 --- a/modules/noise/fastnoise_lite.cpp +++ b/modules/noise/fastnoise_lite.cpp @@ -31,31 +31,29 @@ #include "fastnoise_lite.h" FastNoiseLite::FastNoiseLite() { - // Most defaults copied from the library. - set_noise_type(TYPE_SIMPLEX_SMOOTH); - set_seed(0); - set_frequency(0.01); - set_in_3d_space(false); - - set_fractal_type(FRACTAL_FBM); - set_fractal_octaves(5); - set_fractal_lacunarity(2.0); - set_fractal_gain(0.5); - set_fractal_weighted_strength(0.0); - set_fractal_ping_pong_strength(2.0); - - set_cellular_distance_function(DISTANCE_EUCLIDEAN); - set_cellular_return_type(RETURN_CELL_VALUE); - set_cellular_jitter(0.45); - - set_domain_warp_enabled(false); - set_domain_warp_type(DOMAIN_WARP_SIMPLEX); - set_domain_warp_amplitude(30.0); - set_domain_warp_frequency(0.05); - set_domain_warp_fractal_type(DOMAIN_WARP_FRACTAL_PROGRESSIVE); - set_domain_warp_fractal_octaves(5); - set_domain_warp_fractal_lacunarity(6); - set_domain_warp_fractal_gain(0.5); + _noise.SetNoiseType((_FastNoiseLite::NoiseType)noise_type); + _noise.SetSeed(seed); + _noise.SetFrequency(frequency); + + _noise.SetFractalType((_FastNoiseLite::FractalType)fractal_type); + _noise.SetFractalOctaves(fractal_octaves); + _noise.SetFractalLacunarity(fractal_lacunarity); + _noise.SetFractalGain(fractal_gain); + _noise.SetFractalWeightedStrength(fractal_weighted_strength); + _noise.SetFractalPingPongStrength(fractal_ping_pong_strength); + + _noise.SetCellularDistanceFunction((_FastNoiseLite::CellularDistanceFunction)cellular_distance_function); + _noise.SetCellularReturnType((_FastNoiseLite::CellularReturnType)cellular_return_type); + _noise.SetCellularJitter(cellular_jitter); + + _domain_warp_noise.SetDomainWarpType((_FastNoiseLite::DomainWarpType)domain_warp_type); + _domain_warp_noise.SetSeed(seed); + _domain_warp_noise.SetDomainWarpAmp(domain_warp_amplitude); + _domain_warp_noise.SetFrequency(domain_warp_frequency); + _domain_warp_noise.SetFractalType(_FastNoiseLite::FractalType_None); + _domain_warp_noise.SetFractalOctaves(domain_warp_fractal_octaves); + _domain_warp_noise.SetFractalLacunarity(domain_warp_fractal_lacunarity); + _domain_warp_noise.SetFractalGain(domain_warp_fractal_gain); } FastNoiseLite::~FastNoiseLite() { @@ -77,6 +75,7 @@ FastNoiseLite::NoiseType FastNoiseLite::get_noise_type() const { void FastNoiseLite::set_seed(int p_seed) { seed = p_seed; _noise.SetSeed(p_seed); + _domain_warp_noise.SetSeed(p_seed); emit_changed(); } @@ -94,14 +93,6 @@ real_t FastNoiseLite::get_frequency() const { return frequency; } -void FastNoiseLite::set_in_3d_space(bool p_enable) { - in_3d_space = p_enable; - emit_changed(); -} -bool FastNoiseLite::is_in_3d_space() const { - return in_3d_space; -} - void FastNoiseLite::set_offset(Vector3 p_offset) { offset = p_offset; emit_changed(); @@ -111,46 +102,6 @@ Vector3 FastNoiseLite::get_offset() const { return offset; } -void FastNoiseLite::set_color_ramp(const Ref<Gradient> &p_gradient) { - color_ramp = p_gradient; - if (color_ramp.is_valid()) { - color_ramp->connect(SNAME("changed"), callable_mp(this, &FastNoiseLite::_changed)); - emit_changed(); - } -} - -Ref<Gradient> FastNoiseLite::get_color_ramp() const { - return color_ramp; -} - -// Noise functions. - -real_t FastNoiseLite::get_noise_1d(real_t p_x) { - return get_noise_2d(p_x, 0.0); -} - -real_t FastNoiseLite::get_noise_2dv(Vector2 p_v) { - return get_noise_2d(p_v.x, p_v.y); -} - -real_t FastNoiseLite::get_noise_2d(real_t p_x, real_t p_y) { - if (domain_warp_enabled) { - _domain_warp_noise.DomainWarp(p_x, p_y); - } - return _noise.GetNoise(p_x + offset.x, p_y + offset.y); -} - -real_t FastNoiseLite::get_noise_3dv(Vector3 p_v) { - return get_noise_3d(p_v.x, p_v.y, p_v.z); -} - -real_t FastNoiseLite::get_noise_3d(real_t p_x, real_t p_y, real_t p_z) { - if (domain_warp_enabled) { - _domain_warp_noise.DomainWarp(p_x, p_y, p_z); - } - return _noise.GetNoise(p_x + offset.x, p_y + offset.y, p_z + offset.z); -} - // Fractal. void FastNoiseLite::set_fractal_type(FractalType p_type) { @@ -204,12 +155,12 @@ real_t FastNoiseLite::get_fractal_weighted_strength() const { } void FastNoiseLite::set_fractal_ping_pong_strength(real_t p_ping_pong_strength) { - fractal_pinp_pong_strength = p_ping_pong_strength; + fractal_ping_pong_strength = p_ping_pong_strength; _noise.SetFractalPingPongStrength(p_ping_pong_strength); emit_changed(); } real_t FastNoiseLite::get_fractal_ping_pong_strength() const { - return fractal_pinp_pong_strength; + return fractal_ping_pong_strength; } // Cellular. @@ -237,7 +188,6 @@ real_t FastNoiseLite::get_cellular_jitter() const { void FastNoiseLite::set_cellular_return_type(CellularReturnType p_ret) { cellular_return_type = p_ret; _noise.SetCellularReturnType((_FastNoiseLite::CellularReturnType)p_ret); - emit_changed(); } @@ -345,68 +295,32 @@ real_t FastNoiseLite::get_domain_warp_fractal_gain() const { return domain_warp_fractal_gain; } -// Textures. +// Noise interface functions. -Ref<Image> FastNoiseLite::get_image(int p_width, int p_height, bool p_invert) { - bool grayscale = color_ramp.is_null(); - - Vector<uint8_t> data; - data.resize(p_width * p_height * (grayscale ? 1 : 4)); - - uint8_t *wd8 = data.ptrw(); +real_t FastNoiseLite::get_noise_1d(real_t p_x) const { + return get_noise_2d(p_x, 0.0); +} - // Get all values and identify min/max values. - Vector<real_t> values; - values.resize(p_width * p_height); - real_t min_val = 100; - real_t max_val = -100; +real_t FastNoiseLite::get_noise_2dv(Vector2 p_v) const { + return get_noise_2d(p_v.x, p_v.y); +} - for (int y = 0, i = 0; y < p_height; y++) { - for (int x = 0; x < p_width; x++, i++) { - values.set(i, is_in_3d_space() ? get_noise_3d(x, y, 0.0) : get_noise_2d(x, y)); - if (values[i] > max_val) { - max_val = values[i]; - } - if (values[i] < min_val) { - min_val = values[i]; - } - } +real_t FastNoiseLite::get_noise_2d(real_t p_x, real_t p_y) const { + if (domain_warp_enabled) { + _domain_warp_noise.DomainWarp(p_x, p_y); } + return _noise.GetNoise(p_x + offset.x, p_y + offset.y); +} - // Normalize values and write to texture. - uint8_t value; - for (int i = 0, x = 0; i < p_height; i++) { - for (int j = 0; j < p_width; j++, x++) { - if (max_val == min_val) { - value = 0; - } else { - value = uint8_t(CLAMP((values[x] - min_val) / (max_val - min_val) * 255.f, 0, 255)); - } - if (p_invert) { - value = 255 - value; - } - if (grayscale) { - wd8[x] = value; - } else { - float luminance = value / 255.0; - Color ramp_color = color_ramp->get_color_at_offset(luminance); - wd8[x * 4 + 0] = uint8_t(CLAMP(ramp_color.r * 255, 0, 255)); - wd8[x * 4 + 1] = uint8_t(CLAMP(ramp_color.g * 255, 0, 255)); - wd8[x * 4 + 2] = uint8_t(CLAMP(ramp_color.b * 255, 0, 255)); - wd8[x * 4 + 3] = uint8_t(CLAMP(ramp_color.a * 255, 0, 255)); - } - } - } - if (grayscale) { - return memnew(Image(p_width, p_height, false, Image::FORMAT_L8, data)); - } else { - return memnew(Image(p_width, p_height, false, Image::FORMAT_RGBA8, data)); - } +real_t FastNoiseLite::get_noise_3dv(Vector3 p_v) const { + return get_noise_3d(p_v.x, p_v.y, p_v.z); } -Ref<Image> FastNoiseLite::get_seamless_image(int p_width, int p_height, bool p_invert, real_t p_blend_skirt) { - // Just return parent function. This is here only so Godot will properly document this function. - return Noise::get_seamless_image(p_width, p_height, p_invert, p_blend_skirt); +real_t FastNoiseLite::get_noise_3d(real_t p_x, real_t p_y, real_t p_z) const { + if (domain_warp_enabled) { + _domain_warp_noise.DomainWarp(p_x, p_y, p_z); + } + return _noise.GetNoise(p_x + offset.x, p_y + offset.y, p_z + offset.z); } void FastNoiseLite::_changed() { @@ -418,108 +332,103 @@ void FastNoiseLite::_bind_methods() { ClassDB::bind_method(D_METHOD("set_noise_type", "type"), &FastNoiseLite::set_noise_type); ClassDB::bind_method(D_METHOD("get_noise_type"), &FastNoiseLite::get_noise_type); - ADD_PROPERTY(PropertyInfo(Variant::INT, "noise_type", PROPERTY_HINT_ENUM, "Simplex,Simplex Smooth,Cellular,Perlin,Value Cubic,Value"), "set_noise_type", "get_noise_type"); ClassDB::bind_method(D_METHOD("set_seed", "seed"), &FastNoiseLite::set_seed); ClassDB::bind_method(D_METHOD("get_seed"), &FastNoiseLite::get_seed); - ADD_PROPERTY(PropertyInfo(Variant::INT, "seed"), "set_seed", "get_seed"); ClassDB::bind_method(D_METHOD("set_frequency", "freq"), &FastNoiseLite::set_frequency); ClassDB::bind_method(D_METHOD("get_frequency"), &FastNoiseLite::get_frequency); - ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "frequency", PROPERTY_HINT_RANGE, ".001,1"), "set_frequency", "get_frequency"); - - ClassDB::bind_method(D_METHOD("set_in_3d_space", "enable"), &FastNoiseLite::set_in_3d_space); - ClassDB::bind_method(D_METHOD("is_in_3d_space"), &FastNoiseLite::is_in_3d_space); - ADD_PROPERTY(PropertyInfo(Variant::BOOL, "in_3d_space"), "set_in_3d_space", "is_in_3d_space"); ClassDB::bind_method(D_METHOD("set_offset", "offset"), &FastNoiseLite::set_offset); ClassDB::bind_method(D_METHOD("get_offset"), &FastNoiseLite::get_offset); - ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "offset", PROPERTY_HINT_RANGE, "-999999999,999999999,1"), "set_offset", "get_offset"); - - ClassDB::bind_method(D_METHOD("set_color_ramp", "gradient"), &FastNoiseLite::set_color_ramp); - ClassDB::bind_method(D_METHOD("get_color_ramp"), &FastNoiseLite::get_color_ramp); - ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "color_ramp", PROPERTY_HINT_RESOURCE_TYPE, "Gradient"), "set_color_ramp", "get_color_ramp"); // Fractal. - ADD_GROUP("Fractal", "fractal_"); ClassDB::bind_method(D_METHOD("set_fractal_type", "type"), &FastNoiseLite::set_fractal_type); ClassDB::bind_method(D_METHOD("get_fractal_type"), &FastNoiseLite::get_fractal_type); - ADD_PROPERTY(PropertyInfo(Variant::INT, "fractal_type", PROPERTY_HINT_ENUM, "None,FBM,Ridged,Ping-Pong"), "set_fractal_type", "get_fractal_type"); ClassDB::bind_method(D_METHOD("set_fractal_octaves", "octave_count"), &FastNoiseLite::set_fractal_octaves); ClassDB::bind_method(D_METHOD("get_fractal_octaves"), &FastNoiseLite::get_fractal_octaves); - ADD_PROPERTY(PropertyInfo(Variant::INT, "fractal_octaves", PROPERTY_HINT_RANGE, "1,10,1"), "set_fractal_octaves", "get_fractal_octaves"); ClassDB::bind_method(D_METHOD("set_fractal_lacunarity", "lacunarity"), &FastNoiseLite::set_fractal_lacunarity); ClassDB::bind_method(D_METHOD("get_fractal_lacunarity"), &FastNoiseLite::get_fractal_lacunarity); - ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "fractal_lacunarity"), "set_fractal_lacunarity", "get_fractal_lacunarity"); ClassDB::bind_method(D_METHOD("set_fractal_gain", "gain"), &FastNoiseLite::set_fractal_gain); ClassDB::bind_method(D_METHOD("get_fractal_gain"), &FastNoiseLite::get_fractal_gain); - ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "fractal_gain"), "set_fractal_gain", "get_fractal_gain"); ClassDB::bind_method(D_METHOD("set_fractal_weighted_strength", "weighted_strength"), &FastNoiseLite::set_fractal_weighted_strength); ClassDB::bind_method(D_METHOD("get_fractal_weighted_strength"), &FastNoiseLite::get_fractal_weighted_strength); - ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "fractal_weighted_strength", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_fractal_weighted_strength", "get_fractal_weighted_strength"); ClassDB::bind_method(D_METHOD("set_fractal_ping_pong_strength", "ping_pong_strength"), &FastNoiseLite::set_fractal_ping_pong_strength); ClassDB::bind_method(D_METHOD("get_fractal_ping_pong_strength"), &FastNoiseLite::get_fractal_ping_pong_strength); - ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "fractal_ping_pong_strength"), "set_fractal_ping_pong_strength", "get_fractal_ping_pong_strength"); // Cellular. - ADD_GROUP("Cellular", "cellular_"); ClassDB::bind_method(D_METHOD("set_cellular_distance_function", "func"), &FastNoiseLite::set_cellular_distance_function); ClassDB::bind_method(D_METHOD("get_cellular_distance_function"), &FastNoiseLite::get_cellular_distance_function); - ADD_PROPERTY(PropertyInfo(Variant::INT, "cellular_distance_function", PROPERTY_HINT_ENUM, "Euclidean,Euclidean Squared,Manhattan,Hybrid"), "set_cellular_distance_function", "get_cellular_distance_function"); ClassDB::bind_method(D_METHOD("set_cellular_jitter", "jitter"), &FastNoiseLite::set_cellular_jitter); ClassDB::bind_method(D_METHOD("get_cellular_jitter"), &FastNoiseLite::get_cellular_jitter); - ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "cellular_jitter"), "set_cellular_jitter", "get_cellular_jitter"); ClassDB::bind_method(D_METHOD("set_cellular_return_type", "ret"), &FastNoiseLite::set_cellular_return_type); ClassDB::bind_method(D_METHOD("get_cellular_return_type"), &FastNoiseLite::get_cellular_return_type); - ADD_PROPERTY(PropertyInfo(Variant::INT, "cellular_return_type", PROPERTY_HINT_ENUM, "Cell Value,Distance,Distance2,Distance2Add,Distance2Sub,Distance2Mul,Distance2Div"), "set_cellular_return_type", "get_cellular_return_type"); // Domain warp. - ADD_GROUP("Domain Warp", "domain_warp_"); - ClassDB::bind_method(D_METHOD("set_domain_warp_enabled", "domain_warp_enabled"), &FastNoiseLite::set_domain_warp_enabled); ClassDB::bind_method(D_METHOD("is_domain_warp_enabled"), &FastNoiseLite::is_domain_warp_enabled); - ADD_PROPERTY(PropertyInfo(Variant::BOOL, "domain_warp_enabled"), "set_domain_warp_enabled", "is_domain_warp_enabled"); ClassDB::bind_method(D_METHOD("set_domain_warp_type", "domain_warp_type"), &FastNoiseLite::set_domain_warp_type); ClassDB::bind_method(D_METHOD("get_domain_warp_type"), &FastNoiseLite::get_domain_warp_type); - ADD_PROPERTY(PropertyInfo(Variant::INT, "domain_warp_type", PROPERTY_HINT_ENUM, "Simplex,Simplex Reduced,Basic Grid"), "set_domain_warp_type", "get_domain_warp_type"); ClassDB::bind_method(D_METHOD("set_domain_warp_amplitude", "domain_warp_amplitude"), &FastNoiseLite::set_domain_warp_amplitude); ClassDB::bind_method(D_METHOD("get_domain_warp_amplitude"), &FastNoiseLite::get_domain_warp_amplitude); - ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "domain_warp_amplitude"), "set_domain_warp_amplitude", "get_domain_warp_amplitude"); ClassDB::bind_method(D_METHOD("set_domain_warp_frequency", "domain_warp_frequency"), &FastNoiseLite::set_domain_warp_frequency); ClassDB::bind_method(D_METHOD("get_domain_warp_frequency"), &FastNoiseLite::get_domain_warp_frequency); - ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "domain_warp_frequency"), "set_domain_warp_frequency", "get_domain_warp_frequency"); ClassDB::bind_method(D_METHOD("set_domain_warp_fractal_type", "domain_warp_fractal_type"), &FastNoiseLite::set_domain_warp_fractal_type); ClassDB::bind_method(D_METHOD("get_domain_warp_fractal_type"), &FastNoiseLite::get_domain_warp_fractal_type); - ADD_PROPERTY(PropertyInfo(Variant::INT, "domain_warp_fractal_type", PROPERTY_HINT_ENUM, "None,Progressive,Independent"), "set_domain_warp_fractal_type", "get_domain_warp_fractal_type"); ClassDB::bind_method(D_METHOD("set_domain_warp_fractal_octaves", "domain_warp_octave_count"), &FastNoiseLite::set_domain_warp_fractal_octaves); ClassDB::bind_method(D_METHOD("get_domain_warp_fractal_octaves"), &FastNoiseLite::get_domain_warp_fractal_octaves); - ADD_PROPERTY(PropertyInfo(Variant::INT, "domain_warp_fractal_octaves", PROPERTY_HINT_RANGE, "1,10,1"), "set_domain_warp_fractal_octaves", "get_domain_warp_fractal_octaves"); ClassDB::bind_method(D_METHOD("set_domain_warp_fractal_lacunarity", "domain_warp_lacunarity"), &FastNoiseLite::set_domain_warp_fractal_lacunarity); ClassDB::bind_method(D_METHOD("get_domain_warp_fractal_lacunarity"), &FastNoiseLite::get_domain_warp_fractal_lacunarity); - ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "domain_warp_fractal_lacunarity"), "set_domain_warp_fractal_lacunarity", "get_domain_warp_fractal_lacunarity"); ClassDB::bind_method(D_METHOD("set_domain_warp_fractal_gain", "domain_warp_gain"), &FastNoiseLite::set_domain_warp_fractal_gain); ClassDB::bind_method(D_METHOD("get_domain_warp_fractal_gain"), &FastNoiseLite::get_domain_warp_fractal_gain); - ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "domain_warp_fractal_gain"), "set_domain_warp_fractal_gain", "get_domain_warp_fractal_gain"); ClassDB::bind_method(D_METHOD("_changed"), &FastNoiseLite::_changed); + ADD_PROPERTY(PropertyInfo(Variant::INT, "noise_type", PROPERTY_HINT_ENUM, "Simplex,Simplex Smooth,Cellular,Perlin,Value Cubic,Value"), "set_noise_type", "get_noise_type"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "seed"), "set_seed", "get_seed"); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "frequency", PROPERTY_HINT_RANGE, ".001,1"), "set_frequency", "get_frequency"); + ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "offset", PROPERTY_HINT_RANGE, "-999999999,999999999,0.01"), "set_offset", "get_offset"); + + ADD_GROUP("Fractal", "fractal_"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "fractal_type", PROPERTY_HINT_ENUM, "None,FBM,Ridged,Ping-Pong"), "set_fractal_type", "get_fractal_type"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "fractal_octaves", PROPERTY_HINT_RANGE, "1,10,1"), "set_fractal_octaves", "get_fractal_octaves"); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "fractal_lacunarity"), "set_fractal_lacunarity", "get_fractal_lacunarity"); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "fractal_gain"), "set_fractal_gain", "get_fractal_gain"); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "fractal_weighted_strength", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_fractal_weighted_strength", "get_fractal_weighted_strength"); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "fractal_ping_pong_strength"), "set_fractal_ping_pong_strength", "get_fractal_ping_pong_strength"); + + ADD_GROUP("Cellular", "cellular_"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "cellular_distance_function", PROPERTY_HINT_ENUM, "Euclidean,Euclidean Squared,Manhattan,Hybrid"), "set_cellular_distance_function", "get_cellular_distance_function"); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "cellular_jitter"), "set_cellular_jitter", "get_cellular_jitter"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "cellular_return_type", PROPERTY_HINT_ENUM, "Cell Value,Distance,Distance2,Distance2Add,Distance2Sub,Distance2Mul,Distance2Div"), "set_cellular_return_type", "get_cellular_return_type"); + + ADD_GROUP("Domain Warp", "domain_warp_"); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "domain_warp_enabled"), "set_domain_warp_enabled", "is_domain_warp_enabled"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "domain_warp_type", PROPERTY_HINT_ENUM, "Simplex,Simplex Reduced,Basic Grid"), "set_domain_warp_type", "get_domain_warp_type"); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "domain_warp_amplitude"), "set_domain_warp_amplitude", "get_domain_warp_amplitude"); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "domain_warp_frequency"), "set_domain_warp_frequency", "get_domain_warp_frequency"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "domain_warp_fractal_type", PROPERTY_HINT_ENUM, "None,Progressive,Independent"), "set_domain_warp_fractal_type", "get_domain_warp_fractal_type"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "domain_warp_fractal_octaves", PROPERTY_HINT_RANGE, "1,10,1"), "set_domain_warp_fractal_octaves", "get_domain_warp_fractal_octaves"); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "domain_warp_fractal_lacunarity"), "set_domain_warp_fractal_lacunarity", "get_domain_warp_fractal_lacunarity"); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "domain_warp_fractal_gain"), "set_domain_warp_fractal_gain", "get_domain_warp_fractal_gain"); + BIND_ENUM_CONSTANT(TYPE_VALUE); BIND_ENUM_CONSTANT(TYPE_VALUE_CUBIC); BIND_ENUM_CONSTANT(TYPE_PERLIN); diff --git a/modules/noise/fastnoise_lite.h b/modules/noise/fastnoise_lite.h index 4635e26d28..0a4251868b 100644 --- a/modules/noise/fastnoise_lite.h +++ b/modules/noise/fastnoise_lite.h @@ -99,36 +99,33 @@ private: _FastNoiseLite _domain_warp_noise; Vector3 offset; - NoiseType noise_type; - Ref<Gradient> color_ramp; + NoiseType noise_type = TYPE_SIMPLEX_SMOOTH; - int seed; - real_t frequency; - bool in_3d_space; + int seed = 0; + real_t frequency = 0.01; // Fractal specific. - FractalType fractal_type; - int fractal_octaves; - real_t fractal_lacunarity; - real_t fractal_gain; - real_t fractal_weighted_strength; - real_t fractal_pinp_pong_strength; + FractalType fractal_type = FRACTAL_FBM; + int fractal_octaves = 5; + real_t fractal_lacunarity = 2; + real_t fractal_gain = 0.5; + real_t fractal_weighted_strength = 0; + real_t fractal_ping_pong_strength = 2; // Cellular specific. - CellularDistanceFunction cellular_distance_function; - CellularReturnType cellular_return_type; - real_t cellular_jitter; + CellularDistanceFunction cellular_distance_function = DISTANCE_EUCLIDEAN; + CellularReturnType cellular_return_type = RETURN_DISTANCE; + real_t cellular_jitter = 0.45; // Domain warp specific. - bool domain_warp_enabled; - DomainWarpType domain_warp_type; - real_t domain_warp_frequency; - real_t domain_warp_amplitude; - - DomainWarpFractalType domain_warp_fractal_type; - int domain_warp_fractal_octaves; - real_t domain_warp_fractal_lacunarity; - real_t domain_warp_fractal_gain; + bool domain_warp_enabled = false; + DomainWarpType domain_warp_type = DOMAIN_WARP_SIMPLEX; + real_t domain_warp_amplitude = 30.0; + real_t domain_warp_frequency = 0.05; + DomainWarpFractalType domain_warp_fractal_type = DOMAIN_WARP_FRACTAL_PROGRESSIVE; + int domain_warp_fractal_octaves = 5; + real_t domain_warp_fractal_lacunarity = 6; + real_t domain_warp_fractal_gain = 0.5; public: FastNoiseLite(); @@ -145,15 +142,9 @@ public: void set_frequency(real_t p_freq); real_t get_frequency() const; - void set_in_3d_space(bool p_enable); - bool is_in_3d_space() const; - void set_offset(Vector3 p_offset); Vector3 get_offset() const; - void set_color_ramp(const Ref<Gradient> &p_gradient); - Ref<Gradient> get_color_ramp() const; - // Fractal specific. void set_fractal_type(FractalType p_type); @@ -212,17 +203,13 @@ public: real_t get_domain_warp_fractal_gain() const; // Interface methods. + real_t get_noise_1d(real_t p_x) const override; - Ref<Image> get_image(int p_width, int p_height, bool p_invert = false) override; - Ref<Image> get_seamless_image(int p_width, int p_height, bool p_invert = false, real_t p_blend_skirt = 0.1) override; - - real_t get_noise_1d(real_t p_x) override; - - real_t get_noise_2dv(Vector2 p_v) override; - real_t get_noise_2d(real_t p_x, real_t p_y) override; + real_t get_noise_2dv(Vector2 p_v) const override; + real_t get_noise_2d(real_t p_x, real_t p_y) const override; - real_t get_noise_3dv(Vector3 p_v) override; - real_t get_noise_3d(real_t p_x, real_t p_y, real_t p_z) override; + real_t get_noise_3dv(Vector3 p_v) const override; + real_t get_noise_3d(real_t p_x, real_t p_y, real_t p_z) const override; void _changed(); }; diff --git a/modules/noise/noise.cpp b/modules/noise/noise.cpp index 430e8c87cf..ad3df0a016 100644 --- a/modules/noise/noise.cpp +++ b/modules/noise/noise.cpp @@ -30,13 +30,13 @@ #include "noise.h" -Ref<Image> Noise::get_seamless_image(int p_width, int p_height, bool p_invert, real_t p_blend_skirt) { +Ref<Image> Noise::get_seamless_image(int p_width, int p_height, bool p_invert, bool p_in_3d_space, real_t p_blend_skirt) const { int skirt_width = p_width * p_blend_skirt; int skirt_height = p_height * p_blend_skirt; int src_width = p_width + skirt_width; int src_height = p_height + skirt_height; - Ref<Image> src = get_image(src_width, src_height, p_invert); + Ref<Image> src = get_image(src_width, src_height, p_invert, p_in_3d_space); bool grayscale = (src->get_format() == Image::FORMAT_L8); if (grayscale) { return _generate_seamless_image<uint8_t>(src, p_width, p_height, p_invert, p_blend_skirt); @@ -54,6 +54,50 @@ uint8_t Noise::_alpha_blend<uint8_t>(uint8_t p_bg, uint8_t p_fg, int p_alpha) co return (uint8_t)((alpha * p_fg + inv_alpha * p_bg) >> 8); } +Ref<Image> Noise::get_image(int p_width, int p_height, bool p_invert, bool p_in_3d_space) const { + Vector<uint8_t> data; + data.resize(p_width * p_height); + + uint8_t *wd8 = data.ptrw(); + + // Get all values and identify min/max values. + Vector<real_t> values; + values.resize(p_width * p_height); + real_t min_val = 1000; + real_t max_val = -1000; + + for (int y = 0, i = 0; y < p_height; y++) { + for (int x = 0; x < p_width; x++, i++) { + values.set(i, p_in_3d_space ? get_noise_3d(x, y, 0.0) : get_noise_2d(x, y)); + if (values[i] > max_val) { + max_val = values[i]; + } + if (values[i] < min_val) { + min_val = values[i]; + } + } + } + + // Normalize values and write to texture. + uint8_t value; + for (int i = 0, x = 0; i < p_height; i++) { + for (int j = 0; j < p_width; j++, x++) { + if (max_val == min_val) { + value = 0; + } else { + value = uint8_t(CLAMP((values[x] - min_val) / (max_val - min_val) * 255.f, 0, 255)); + } + if (p_invert) { + value = 255 - value; + } + + wd8[x] = value; + } + } + + return memnew(Image(p_width, p_height, false, Image::FORMAT_L8, data)); +} + void Noise::_bind_methods() { // Noise functions. ClassDB::bind_method(D_METHOD("get_noise_1d", "x"), &Noise::get_noise_1d); @@ -63,6 +107,6 @@ void Noise::_bind_methods() { ClassDB::bind_method(D_METHOD("get_noise_3dv", "v"), &Noise::get_noise_3dv); // Textures. - ClassDB::bind_method(D_METHOD("get_image", "width", "height", "invert"), &Noise::get_image, DEFVAL(false)); - ClassDB::bind_method(D_METHOD("get_seamless_image", "width", "height", "invert", "skirt"), &Noise::get_seamless_image, DEFVAL(false), DEFVAL(0.1)); + ClassDB::bind_method(D_METHOD("get_image", "width", "height", "invert", "in_3d_space"), &Noise::get_image, DEFVAL(false), DEFVAL(false)); + ClassDB::bind_method(D_METHOD("get_seamless_image", "width", "height", "invert", "in_3d_space", "skirt"), &Noise::get_seamless_image, DEFVAL(false), DEFVAL(false), DEFVAL(0.1)); } diff --git a/modules/noise/noise.h b/modules/noise/noise.h index 853c24b485..8083334388 100644 --- a/modules/noise/noise.h +++ b/modules/noise/noise.h @@ -81,7 +81,7 @@ class Noise : public Resource { }; template <typename T> - Ref<Image> _generate_seamless_image(Ref<Image> p_src, int p_width, int p_height, bool p_invert, real_t p_blend_skirt) { + Ref<Image> _generate_seamless_image(Ref<Image> p_src, int p_width, int p_height, bool p_invert, real_t p_blend_skirt) const { /* To make a seamless image, we swap the quadrants so the edges are perfect matches. We initially get a 10% larger image so we have an overlap we can use to blend over the seams. @@ -225,16 +225,16 @@ public: // Virtual destructor so we can delete any Noise derived object when referenced as a Noise*. virtual ~Noise() {} - virtual real_t get_noise_1d(real_t p_x) = 0; + virtual real_t get_noise_1d(real_t p_x) const = 0; - virtual real_t get_noise_2dv(Vector2 p_v) = 0; - virtual real_t get_noise_2d(real_t p_x, real_t p_y) = 0; + virtual real_t get_noise_2dv(Vector2 p_v) const = 0; + virtual real_t get_noise_2d(real_t p_x, real_t p_y) const = 0; - virtual real_t get_noise_3dv(Vector3 p_v) = 0; - virtual real_t get_noise_3d(real_t p_x, real_t p_y, real_t p_z) = 0; + virtual real_t get_noise_3dv(Vector3 p_v) const = 0; + virtual real_t get_noise_3d(real_t p_x, real_t p_y, real_t p_z) const = 0; - virtual Ref<Image> get_image(int p_width, int p_height, bool p_invert = false) = 0; - virtual Ref<Image> get_seamless_image(int p_width, int p_height, bool p_invert = false, real_t p_blend_skirt = 0.1); + virtual Ref<Image> get_image(int p_width, int p_height, bool p_invert = false, bool p_in_3d_space = false) const; + virtual Ref<Image> get_seamless_image(int p_width, int p_height, bool p_invert = false, bool p_in_3d_space = false, real_t p_blend_skirt = 0.1) const; }; #endif // NOISE_H diff --git a/modules/noise/noise_texture.cpp b/modules/noise/noise_texture.cpp index 276335797a..2b35e00906 100644 --- a/modules/noise/noise_texture.cpp +++ b/modules/noise/noise_texture.cpp @@ -47,15 +47,22 @@ NoiseTexture::~NoiseTexture() { } void NoiseTexture::_bind_methods() { + ClassDB::bind_method(D_METHOD("_update_texture"), &NoiseTexture::_update_texture); + ClassDB::bind_method(D_METHOD("_generate_texture"), &NoiseTexture::_generate_texture); + ClassDB::bind_method(D_METHOD("_thread_done", "image"), &NoiseTexture::_thread_done); + ClassDB::bind_method(D_METHOD("set_width", "width"), &NoiseTexture::set_width); ClassDB::bind_method(D_METHOD("set_height", "height"), &NoiseTexture::set_height); - ClassDB::bind_method(D_METHOD("set_noise", "noise"), &NoiseTexture::set_noise); - ClassDB::bind_method(D_METHOD("get_noise"), &NoiseTexture::get_noise); - ClassDB::bind_method(D_METHOD("set_invert", "invert"), &NoiseTexture::set_invert); ClassDB::bind_method(D_METHOD("get_invert"), &NoiseTexture::get_invert); + ClassDB::bind_method(D_METHOD("set_in_3d_space", "enable"), &NoiseTexture::set_in_3d_space); + ClassDB::bind_method(D_METHOD("is_in_3d_space"), &NoiseTexture::is_in_3d_space); + + ClassDB::bind_method(D_METHOD("set_generate_mipmaps", "invert"), &NoiseTexture::set_generate_mipmaps); + ClassDB::bind_method(D_METHOD("is_generating_mipmaps"), &NoiseTexture::is_generating_mipmaps); + ClassDB::bind_method(D_METHOD("set_seamless", "seamless"), &NoiseTexture::set_seamless); ClassDB::bind_method(D_METHOD("get_seamless"), &NoiseTexture::get_seamless); @@ -68,17 +75,22 @@ void NoiseTexture::_bind_methods() { ClassDB::bind_method(D_METHOD("set_bump_strength", "bump_strength"), &NoiseTexture::set_bump_strength); ClassDB::bind_method(D_METHOD("get_bump_strength"), &NoiseTexture::get_bump_strength); - ClassDB::bind_method(D_METHOD("_update_texture"), &NoiseTexture::_update_texture); - ClassDB::bind_method(D_METHOD("_generate_texture"), &NoiseTexture::_generate_texture); - ClassDB::bind_method(D_METHOD("_thread_done", "image"), &NoiseTexture::_thread_done); + ClassDB::bind_method(D_METHOD("set_color_ramp", "gradient"), &NoiseTexture::set_color_ramp); + ClassDB::bind_method(D_METHOD("get_color_ramp"), &NoiseTexture::get_color_ramp); + + 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::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"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "seamless"), "set_seamless", "get_seamless"); ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "seamless_blend_skirt", PROPERTY_HINT_RANGE, "0.05,1,0.001"), "set_seamless_blend_skirt", "get_seamless_blend_skirt"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "as_normal_map"), "set_as_normal_map", "is_normal_map"); ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "bump_strength", PROPERTY_HINT_RANGE, "0,32,0.1,or_greater"), "set_bump_strength", "get_bump_strength"); + ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "color_ramp", PROPERTY_HINT_RESOURCE_TYPE, "Gradient"), "set_color_ramp", "get_color_ramp"); ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "noise", PROPERTY_HINT_RESOURCE_TYPE, "Noise"), "set_noise", "get_noise"); } @@ -143,18 +155,42 @@ Ref<Image> NoiseTexture::_generate_texture() { Ref<Image> image; if (seamless) { - image = ref_noise->get_seamless_image(size.x, size.y, invert, seamless_blend_skirt); + image = ref_noise->get_seamless_image(size.x, size.y, invert, in_3d_space, seamless_blend_skirt); } else { - image = ref_noise->get_image(size.x, size.y, invert); + image = ref_noise->get_image(size.x, size.y, invert, in_3d_space); + } + if (color_ramp.is_valid()) { + image = _modulate_with_gradient(image, color_ramp); } - if (as_normal_map) { image->bump_map_to_normal_map(bump_strength); } + if (generate_mipmaps) { + image->generate_mipmaps(); + } return image; } +Ref<Image> NoiseTexture::_modulate_with_gradient(Ref<Image> p_image, Ref<Gradient> p_gradient) { + int width = p_image->get_width(); + int height = p_image->get_height(); + + Ref<Image> new_image; + new_image.instantiate(); + new_image->create(width, height, false, Image::FORMAT_RGBA8); + + for (int row = 0; row < height; row++) { + for (int col = 0; col < width; col++) { + Color pixel_color = p_image->get_pixel(col, row); + Color ramp_color = color_ramp->get_color_at_offset(pixel_color.get_luminance()); + new_image->set_pixel(col, row, ramp_color); + } + } + + return new_image; +} + void NoiseTexture::_update_texture() { bool use_thread = true; if (first_time) { @@ -227,6 +263,29 @@ bool NoiseTexture::get_invert() const { return invert; } +void NoiseTexture::set_in_3d_space(bool p_enable) { + if (p_enable == in_3d_space) { + return; + } + in_3d_space = p_enable; + _queue_update(); +} +bool NoiseTexture::is_in_3d_space() const { + return in_3d_space; +} + +void NoiseTexture::set_generate_mipmaps(bool p_enable) { + if (p_enable == generate_mipmaps) { + return; + } + generate_mipmaps = p_enable; + _queue_update(); +} + +bool NoiseTexture::is_generating_mipmaps() const { + return generate_mipmaps; +} + void NoiseTexture::set_seamless(bool p_seamless) { if (p_seamless == seamless) { return; @@ -278,6 +337,24 @@ float NoiseTexture::get_bump_strength() { return bump_strength; } +void NoiseTexture::set_color_ramp(const Ref<Gradient> &p_gradient) { + if (p_gradient == color_ramp) { + return; + } + if (color_ramp.is_valid()) { + color_ramp->disconnect(CoreStringNames::get_singleton()->changed, callable_mp(this, &NoiseTexture::_queue_update)); + } + color_ramp = p_gradient; + if (color_ramp.is_valid()) { + color_ramp->connect(CoreStringNames::get_singleton()->changed, callable_mp(this, &NoiseTexture::_queue_update)); + } + _queue_update(); +} + +Ref<Gradient> NoiseTexture::get_color_ramp() const { + return color_ramp; +} + int NoiseTexture::get_width() const { return size.x; } diff --git a/modules/noise/noise_texture.h b/modules/noise/noise_texture.h index 2a94df39d4..6c088562a1 100644 --- a/modules/noise/noise_texture.h +++ b/modules/noise/noise_texture.h @@ -51,15 +51,18 @@ private: mutable RID texture; uint32_t flags = 0; - Ref<Noise> noise; + Size2i size = Size2i(512, 512); bool invert = false; - Vector2i size = Vector2i(512, 512); - Vector2 noise_offset; + bool in_3d_space = false; + bool generate_mipmaps = true; bool seamless = false; real_t seamless_blend_skirt = 0.1; bool as_normal_map = false; float bump_strength = 8.0; + Ref<Gradient> color_ramp; + Ref<Noise> noise; + void _thread_done(const Ref<Image> &p_image); static void _thread_function(void *p_ud); @@ -68,6 +71,8 @@ private: void _update_texture(); void _set_texture_image(const Ref<Image> &p_image); + Ref<Image> _modulate_with_gradient(Ref<Image> p_image, Ref<Gradient> p_gradient); + protected: static void _bind_methods(); virtual void _validate_property(PropertyInfo &property) const override; @@ -82,6 +87,12 @@ public: void set_invert(bool p_invert); bool get_invert() const; + void set_in_3d_space(bool p_enable); + bool is_in_3d_space() const; + + void set_generate_mipmaps(bool p_enable); + bool is_generating_mipmaps() const; + void set_seamless(bool p_seamless); bool get_seamless(); @@ -94,6 +105,9 @@ public: void set_bump_strength(float p_bump_strength); float get_bump_strength(); + void set_color_ramp(const Ref<Gradient> &p_gradient); + Ref<Gradient> get_color_ramp() const; + int get_width() const override; int get_height() const override; diff --git a/modules/noise/register_types.cpp b/modules/noise/register_types.cpp index 81bb0317c1..3623da3bb9 100644 --- a/modules/noise/register_types.cpp +++ b/modules/noise/register_types.cpp @@ -34,10 +34,19 @@ #include "noise.h" #include "noise_texture.h" +#ifdef TOOLS_ENABLED +#include "editor/editor_plugin.h" +#include "editor/noise_editor_plugin.h" +#endif + void register_noise_types() { GDREGISTER_CLASS(NoiseTexture); GDREGISTER_ABSTRACT_CLASS(Noise); GDREGISTER_CLASS(FastNoiseLite); + +#ifdef TOOLS_ENABLED + EditorPlugins::add_by_type<NoiseEditorPlugin>(); +#endif } void unregister_noise_types() { diff --git a/platform/iphone/ios.h b/platform/iphone/ios.h index 03e663b05c..0607d7b395 100644 --- a/platform/iphone/ios.h +++ b/platform/iphone/ios.h @@ -32,15 +32,26 @@ #define IOS_H #include "core/object/class_db.h" +#import <CoreHaptics/CoreHaptics.h> class iOS : public Object { GDCLASS(iOS, Object); static void _bind_methods(); +private: + CHHapticEngine *haptic_engine API_AVAILABLE(ios(13)) = nullptr; + + CHHapticEngine *get_haptic_engine_instance() API_AVAILABLE(ios(13)); + void start_haptic_engine(); + void stop_haptic_engine(); + public: static void alert(const char *p_alert, const char *p_title); + bool supports_haptic_engine(); + void vibrate_haptic_engine(float p_duration_seconds); + String get_model() const; String get_rate_url(int p_app_id) const; diff --git a/platform/iphone/ios.mm b/platform/iphone/ios.mm index ad1ea70c10..cca28cc055 100644 --- a/platform/iphone/ios.mm +++ b/platform/iphone/ios.mm @@ -32,11 +32,110 @@ #import "app_delegate.h" #import "view_controller.h" + +#import <CoreHaptics/CoreHaptics.h> #import <UIKit/UIKit.h> #include <sys/sysctl.h> void iOS::_bind_methods() { ClassDB::bind_method(D_METHOD("get_rate_url", "app_id"), &iOS::get_rate_url); + ClassDB::bind_method(D_METHOD("supports_haptic_engine"), &iOS::supports_haptic_engine); + ClassDB::bind_method(D_METHOD("start_haptic_engine"), &iOS::start_haptic_engine); + ClassDB::bind_method(D_METHOD("stop_haptic_engine"), &iOS::stop_haptic_engine); +}; + +bool iOS::supports_haptic_engine() { + if (@available(iOS 13, *)) { + id<CHHapticDeviceCapability> capabilities = [CHHapticEngine capabilitiesForHardware]; + return capabilities.supportsHaptics; + } + + return false; +} + +CHHapticEngine *iOS::get_haptic_engine_instance() API_AVAILABLE(ios(13)) { + if (haptic_engine == nullptr) { + NSError *error = nullptr; + haptic_engine = [[CHHapticEngine alloc] initAndReturnError:&error]; + + if (!error) { + [haptic_engine setAutoShutdownEnabled:true]; + } else { + haptic_engine = nullptr; + NSLog(@"Could not initialize haptic engine: %@", error); + } + } + + return haptic_engine; +} + +void iOS::vibrate_haptic_engine(float p_duration_seconds) API_AVAILABLE(ios(13)) { + if (@available(iOS 13, *)) { // We need the @available check every time to make the compiler happy... + if (supports_haptic_engine()) { + CHHapticEngine *haptic_engine = get_haptic_engine_instance(); + if (haptic_engine) { + NSDictionary *hapticDict = @{ + CHHapticPatternKeyPattern : @[ + @{CHHapticPatternKeyEvent : @{ + CHHapticPatternKeyEventType : CHHapticEventTypeHapticTransient, + CHHapticPatternKeyTime : @(CHHapticTimeImmediate), + CHHapticPatternKeyEventDuration : @(p_duration_seconds) + }, + }, + ], + }; + + NSError *error; + CHHapticPattern *pattern = [[CHHapticPattern alloc] initWithDictionary:hapticDict error:&error]; + + [[haptic_engine createPlayerWithPattern:pattern error:&error] startAtTime:0 error:&error]; + + NSLog(@"Could not vibrate using haptic engine: %@", error); + } + + return; + } + } + + NSLog(@"Haptic engine is not supported in this version of iOS"); +} + +void iOS::start_haptic_engine() { + if (@available(iOS 13, *)) { + if (supports_haptic_engine()) { + CHHapticEngine *haptic_engine = get_haptic_engine_instance(); + if (haptic_engine) { + [haptic_engine startWithCompletionHandler:^(NSError *returnedError) { + if (returnedError) { + NSLog(@"Could not start haptic engine: %@", returnedError); + } + }]; + } + + return; + } + } + + NSLog(@"Haptic engine is not supported in this version of iOS"); +} + +void iOS::stop_haptic_engine() { + if (@available(iOS 13, *)) { + if (supports_haptic_engine()) { + CHHapticEngine *haptic_engine = get_haptic_engine_instance(); + if (haptic_engine) { + [haptic_engine stopWithCompletionHandler:^(NSError *returnedError) { + if (returnedError) { + NSLog(@"Could not stop haptic engine: %@", returnedError); + } + }]; + } + + return; + } + } + + NSLog(@"Haptic engine is not supported in this version of iOS"); } void iOS::alert(const char *p_alert, const char *p_title) { diff --git a/platform/iphone/os_iphone.mm b/platform/iphone/os_iphone.mm index ea1bc0ef64..f7974c4b3d 100644 --- a/platform/iphone/os_iphone.mm +++ b/platform/iphone/os_iphone.mm @@ -298,8 +298,12 @@ String OSIPhone::get_processor_name() const { } void OSIPhone::vibrate_handheld(int p_duration_ms) { - // iOS does not support duration for vibration - AudioServicesPlaySystemSound(kSystemSoundID_Vibrate); + if (ios->supports_haptic_engine()) { + ios->vibrate_haptic_engine((float)p_duration_ms / 1000.f); + } else { + // iOS <13 does not support duration for vibration + AudioServicesPlaySystemSound(kSystemSoundID_Vibrate); + } } bool OSIPhone::_check_internal_feature_support(const String &p_feature) { diff --git a/platform/linuxbsd/display_server_x11.cpp b/platform/linuxbsd/display_server_x11.cpp index 7da30ac363..acc7d1bc30 100644 --- a/platform/linuxbsd/display_server_x11.cpp +++ b/platform/linuxbsd/display_server_x11.cpp @@ -670,17 +670,17 @@ void DisplayServerX11::_clipboard_transfer_ownership(Atom p_source, Window x11_w int DisplayServerX11::get_screen_count() const { _THREAD_SAFE_METHOD_ + int count = 0; // Using Xinerama Extension int event_base, error_base; - const Bool ext_okay = XineramaQueryExtension(x11_display, &event_base, &error_base); - if (!ext_okay) { - return 0; + if (XineramaQueryExtension(x11_display, &event_base, &error_base)) { + XineramaScreenInfo *xsi = XineramaQueryScreens(x11_display, &count); + XFree(xsi); + } else { + count = XScreenCount(x11_display); } - int count; - XineramaScreenInfo *xsi = XineramaQueryScreens(x11_display, &count); - XFree(xsi); return count; } @@ -712,6 +712,19 @@ Rect2i DisplayServerX11::_screen_get_rect(int p_screen) const { if (xsi) { XFree(xsi); } + } else { + int count = XScreenCount(x11_display); + if (p_screen < count) { + Window root = XRootWindow(x11_display, p_screen); + XWindowAttributes xwa; + XGetWindowAttributes(x11_display, root, &xwa); + rect.position.x = xwa.x; + rect.position.y = xwa.y; + rect.size.width = xwa.width; + rect.size.height = xwa.height; + } else { + ERR_PRINT("Invalid screen index: " + itos(p_screen) + "(count: " + itos(count) + ")."); + } } return rect; diff --git a/scene/main/node.cpp b/scene/main/node.cpp index 1cfe54155a..f1c0260dd5 100644 --- a/scene/main/node.cpp +++ b/scene/main/node.cpp @@ -653,21 +653,10 @@ void Node::rpcp(int p_peer_id, const StringName &p_method, const Variant **p_arg } Ref<MultiplayerAPI> Node::get_multiplayer() const { - if (multiplayer.is_valid()) { - return multiplayer; - } if (!is_inside_tree()) { return Ref<MultiplayerAPI>(); } - return get_tree()->get_multiplayer(); -} - -Ref<MultiplayerAPI> Node::get_custom_multiplayer() const { - return multiplayer; -} - -void Node::set_custom_multiplayer(Ref<MultiplayerAPI> p_multiplayer) { - multiplayer = p_multiplayer; + return get_tree()->get_multiplayer(get_path()); } Vector<Multiplayer::RPCConfig> Node::get_node_rpc_methods() const { @@ -1373,9 +1362,39 @@ bool Node::has_node(const NodePath &p_path) const { return get_node_or_null(p_path) != nullptr; } -TypedArray<Node> Node::find_nodes(const String &p_mask, const String &p_type, bool p_recursive, bool p_owned) const { +// Finds the first child node (in tree order) whose name matches the given pattern. +// Can be recursive or not, and limited to owned nodes. +Node *Node::find_child(const String &p_pattern, bool p_recursive, bool p_owned) const { + ERR_FAIL_COND_V(p_pattern.is_empty(), nullptr); + + Node *const *cptr = data.children.ptr(); + int ccount = data.children.size(); + for (int i = 0; i < ccount; i++) { + if (p_owned && !cptr[i]->data.owner) { + continue; + } + if (cptr[i]->data.name.operator String().match(p_pattern)) { + return cptr[i]; + } + + if (!p_recursive) { + continue; + } + + Node *ret = cptr[i]->find_child(p_pattern, true, p_owned); + if (ret) { + return ret; + } + } + return nullptr; +} + +// Finds child nodes based on their name using pattern matching, or class name, +// or both (either pattern or type can be left empty). +// Can be recursive or not, and limited to owned nodes. +TypedArray<Node> Node::find_children(const String &p_pattern, const String &p_type, bool p_recursive, bool p_owned) const { TypedArray<Node> ret; - ERR_FAIL_COND_V(p_mask.is_empty() && p_type.is_empty(), ret); + ERR_FAIL_COND_V(p_pattern.is_empty() && p_type.is_empty(), ret); Node *const *cptr = data.children.ptr(); int ccount = data.children.size(); @@ -1384,8 +1403,8 @@ TypedArray<Node> Node::find_nodes(const String &p_mask, const String &p_type, bo continue; } - if (!p_mask.is_empty()) { - if (!cptr[i]->data.name.operator String().match(p_mask)) { + if (!p_pattern.is_empty()) { + if (!cptr[i]->data.name.operator String().match(p_pattern)) { continue; } else if (p_type.is_empty()) { ret.append(cptr[i]); @@ -1407,7 +1426,7 @@ TypedArray<Node> Node::find_nodes(const String &p_mask, const String &p_type, bo } if (p_recursive) { - ret.append_array(cptr[i]->find_nodes(p_mask, p_type, true, p_owned)); + ret.append_array(cptr[i]->find_children(p_pattern, p_type, true, p_owned)); } } @@ -1418,10 +1437,10 @@ Node *Node::get_parent() const { return data.parent; } -Node *Node::find_parent(const String &p_mask) const { +Node *Node::find_parent(const String &p_pattern) const { Node *p = data.parent; while (p) { - if (p->data.name.operator String().match(p_mask)) { + if (p->data.name.operator String().match(p_pattern)) { return p; } p = p->data.parent; @@ -1542,7 +1561,9 @@ void Node::_acquire_unique_name_in_owner() { StringName key = StringName(UNIQUE_NODE_PREFIX + data.name.operator String()); Node **which = data.owner->data.owned_unique_nodes.getptr(key); if (which != nullptr && *which != this) { - WARN_PRINT(vformat(RTR("Setting node name '%s' to be unique within scene for '%s', but it's already claimed by '%s'. This node is no longer set unique."), get_name(), is_inside_tree() ? get_path() : data.owner->get_path_to(this), is_inside_tree() ? (*which)->get_path() : data.owner->get_path_to(*which))); + String which_path = is_inside_tree() ? (*which)->get_path() : data.owner->get_path_to(*which); + WARN_PRINT(vformat(RTR("Setting node name '%s' to be unique within scene for '%s', but it's already claimed by '%s'.\n'%s' is no longer set as having a unique name."), + get_name(), is_inside_tree() ? get_path() : data.owner->get_path_to(this), which_path, which_path)); data.unique_name_in_owner = false; return; } @@ -2780,8 +2801,9 @@ void Node::_bind_methods() { ClassDB::bind_method(D_METHOD("get_node", "path"), &Node::get_node); ClassDB::bind_method(D_METHOD("get_node_or_null", "path"), &Node::get_node_or_null); ClassDB::bind_method(D_METHOD("get_parent"), &Node::get_parent); - ClassDB::bind_method(D_METHOD("find_nodes", "mask", "type", "recursive", "owned"), &Node::find_nodes, DEFVAL(""), DEFVAL(true), DEFVAL(true)); - ClassDB::bind_method(D_METHOD("find_parent", "mask"), &Node::find_parent); + ClassDB::bind_method(D_METHOD("find_child", "pattern", "recursive", "owned"), &Node::find_child, DEFVAL(true), DEFVAL(true)); + ClassDB::bind_method(D_METHOD("find_children", "pattern", "type", "recursive", "owned"), &Node::find_children, DEFVAL(""), DEFVAL(true), DEFVAL(true)); + ClassDB::bind_method(D_METHOD("find_parent", "pattern"), &Node::find_parent); ClassDB::bind_method(D_METHOD("has_node_and_resource", "path"), &Node::has_node_and_resource); ClassDB::bind_method(D_METHOD("get_node_and_resource", "path"), &Node::_get_node_and_resource); @@ -2859,8 +2881,6 @@ void Node::_bind_methods() { ClassDB::bind_method(D_METHOD("is_multiplayer_authority"), &Node::is_multiplayer_authority); ClassDB::bind_method(D_METHOD("get_multiplayer"), &Node::get_multiplayer); - ClassDB::bind_method(D_METHOD("get_custom_multiplayer"), &Node::get_custom_multiplayer); - ClassDB::bind_method(D_METHOD("set_custom_multiplayer", "api"), &Node::set_custom_multiplayer); ClassDB::bind_method(D_METHOD("rpc_config", "method", "rpc_mode", "call_local", "transfer_mode", "channel"), &Node::rpc_config, DEFVAL(false), DEFVAL(Multiplayer::TRANSFER_MODE_RELIABLE), DEFVAL(0)); ClassDB::bind_method(D_METHOD("set_editor_description", "editor_description"), &Node::set_editor_description); @@ -2872,8 +2892,6 @@ void Node::_bind_methods() { ClassDB::bind_method(D_METHOD("set_unique_name_in_owner", "enable"), &Node::set_unique_name_in_owner); ClassDB::bind_method(D_METHOD("is_unique_name_in_owner"), &Node::is_unique_name_in_owner); - ADD_PROPERTY(PropertyInfo(Variant::BOOL, "unique_name_in_owner", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR | PROPERTY_USAGE_INTERNAL), "set_unique_name_in_owner", "is_unique_name_in_owner"); - #ifdef TOOLS_ENABLED ClassDB::bind_method(D_METHOD("_set_property_pinned", "property", "pinned"), &Node::set_property_pinned); #endif @@ -2964,10 +2982,10 @@ void Node::_bind_methods() { ADD_SIGNAL(MethodInfo("child_exited_tree", PropertyInfo(Variant::OBJECT, "node", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_DEFAULT, "Node"))); ADD_PROPERTY(PropertyInfo(Variant::STRING_NAME, "name", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NONE), "set_name", "get_name"); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "unique_name_in_owner", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR), "set_unique_name_in_owner", "is_unique_name_in_owner"); ADD_PROPERTY(PropertyInfo(Variant::STRING, "scene_file_path", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NONE), "set_scene_file_path", "get_scene_file_path"); ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "owner", PROPERTY_HINT_RESOURCE_TYPE, "Node", PROPERTY_USAGE_NONE), "set_owner", "get_owner"); ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "multiplayer", PROPERTY_HINT_RESOURCE_TYPE, "MultiplayerAPI", PROPERTY_USAGE_NONE), "", "get_multiplayer"); - ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "custom_multiplayer", PROPERTY_HINT_RESOURCE_TYPE, "MultiplayerAPI", PROPERTY_USAGE_NONE), "set_custom_multiplayer", "get_custom_multiplayer"); ADD_GROUP("Process", "process_"); ADD_PROPERTY(PropertyInfo(Variant::INT, "process_mode", PROPERTY_HINT_ENUM, "Inherit,Pausable,When Paused,Always,Disabled"), "set_process_mode", "get_process_mode"); diff --git a/scene/main/node.h b/scene/main/node.h index 0973baf793..fb84aabb62 100644 --- a/scene/main/node.h +++ b/scene/main/node.h @@ -310,12 +310,13 @@ public: bool has_node(const NodePath &p_path) const; Node *get_node(const NodePath &p_path) const; Node *get_node_or_null(const NodePath &p_path) const; - TypedArray<Node> find_nodes(const String &p_mask, const String &p_type = "", bool p_recursive = true, bool p_owned = true) const; + Node *find_child(const String &p_pattern, bool p_recursive = true, bool p_owned = true) const; + TypedArray<Node> find_children(const String &p_pattern, const String &p_type = "", bool p_recursive = true, bool p_owned = true) const; bool has_node_and_resource(const NodePath &p_path) const; Node *get_node_and_resource(const NodePath &p_path, RES &r_res, Vector<StringName> &r_leftover_subpath, bool p_last_is_property = true) const; Node *get_parent() const; - Node *find_parent(const String &p_mask) const; + Node *find_parent(const String &p_pattern) const; _FORCE_INLINE_ SceneTree *get_tree() const { ERR_FAIL_COND_V(!data.tree, nullptr); @@ -514,8 +515,6 @@ public: void rpcp(int p_peer_id, const StringName &p_method, const Variant **p_arg, int p_argcount); Ref<MultiplayerAPI> get_multiplayer() const; - Ref<MultiplayerAPI> get_custom_multiplayer() const; - void set_custom_multiplayer(Ref<MultiplayerAPI> p_multiplayer); Node(); ~Node(); diff --git a/scene/main/scene_tree.cpp b/scene/main/scene_tree.cpp index 151239c9e7..d42c2aadad 100644 --- a/scene/main/scene_tree.cpp +++ b/scene/main/scene_tree.cpp @@ -438,6 +438,10 @@ bool SceneTree::process(double p_time) { if (multiplayer_poll) { multiplayer->poll(); + const NodePath *rpath = nullptr; + while ((rpath = custom_multiplayers.next(rpath))) { + custom_multiplayers[*rpath]->poll(); + } } emit_signal(SNAME("process_frame")); @@ -1133,8 +1137,51 @@ Array SceneTree::get_processed_tweens() { return ret; } -Ref<MultiplayerAPI> SceneTree::get_multiplayer() const { - return multiplayer; +Ref<MultiplayerAPI> SceneTree::get_multiplayer(const NodePath &p_for_path) const { + Ref<MultiplayerAPI> out = multiplayer; + const NodePath *spath = nullptr; + while ((spath = custom_multiplayers.next(spath))) { + const Vector<StringName> snames = (*spath).get_names(); + const Vector<StringName> tnames = p_for_path.get_names(); + if (tnames.size() < snames.size()) { + continue; + } + const StringName *sptr = snames.ptr(); + const StringName *nptr = tnames.ptr(); + bool valid = true; + for (int i = 0; i < snames.size(); i++) { + if (sptr[i] != nptr[i]) { + valid = false; + break; + } + } + if (valid) { + out = custom_multiplayers[*spath]; + break; + } + } + return out; +} + +void SceneTree::set_multiplayer(Ref<MultiplayerAPI> p_multiplayer, const NodePath &p_root_path) { + if (p_root_path.is_empty()) { + ERR_FAIL_COND(!p_multiplayer.is_valid()); + if (multiplayer.is_valid()) { + multiplayer->set_root_path(NodePath()); + } + multiplayer = p_multiplayer; + multiplayer->set_root_path("/" + root->get_name()); + } else { + if (p_multiplayer.is_valid()) { + custom_multiplayers[p_root_path] = p_multiplayer; + p_multiplayer->set_root_path(p_root_path); + } else { + if (custom_multiplayers.has(p_root_path)) { + custom_multiplayers[p_root_path]->set_root_path(NodePath()); + custom_multiplayers.erase(p_root_path); + } + } + } } void SceneTree::set_multiplayer_poll_enabled(bool p_enabled) { @@ -1145,13 +1192,6 @@ bool SceneTree::is_multiplayer_poll_enabled() const { return multiplayer_poll; } -void SceneTree::set_multiplayer(Ref<MultiplayerAPI> p_multiplayer) { - ERR_FAIL_COND(!p_multiplayer.is_valid()); - - multiplayer = p_multiplayer; - multiplayer->set_root_path("/" + root->get_name()); -} - void SceneTree::_bind_methods() { ClassDB::bind_method(D_METHOD("get_root"), &SceneTree::get_root); ClassDB::bind_method(D_METHOD("has_group", "name"), &SceneTree::has_group); @@ -1214,8 +1254,8 @@ void SceneTree::_bind_methods() { ClassDB::bind_method(D_METHOD("_change_scene"), &SceneTree::_change_scene); - ClassDB::bind_method(D_METHOD("set_multiplayer", "multiplayer"), &SceneTree::set_multiplayer); - ClassDB::bind_method(D_METHOD("get_multiplayer"), &SceneTree::get_multiplayer); + ClassDB::bind_method(D_METHOD("set_multiplayer", "multiplayer", "root_path"), &SceneTree::set_multiplayer, DEFVAL(NodePath())); + ClassDB::bind_method(D_METHOD("get_multiplayer", "for_path"), &SceneTree::get_multiplayer, DEFVAL(NodePath())); ClassDB::bind_method(D_METHOD("set_multiplayer_poll_enabled", "enabled"), &SceneTree::set_multiplayer_poll_enabled); ClassDB::bind_method(D_METHOD("is_multiplayer_poll_enabled"), &SceneTree::is_multiplayer_poll_enabled); @@ -1225,7 +1265,6 @@ void SceneTree::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "edited_scene_root", PROPERTY_HINT_RESOURCE_TYPE, "Node", PROPERTY_USAGE_NONE), "set_edited_scene_root", "get_edited_scene_root"); ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "current_scene", PROPERTY_HINT_RESOURCE_TYPE, "Node", PROPERTY_USAGE_NONE), "set_current_scene", "get_current_scene"); ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "root", PROPERTY_HINT_RESOURCE_TYPE, "Node", PROPERTY_USAGE_NONE), "", "get_root"); - ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "multiplayer", PROPERTY_HINT_RESOURCE_TYPE, "MultiplayerAPI", PROPERTY_USAGE_NONE), "set_multiplayer", "get_multiplayer"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "multiplayer_poll"), "set_multiplayer_poll_enabled", "is_multiplayer_poll_enabled"); ADD_SIGNAL(MethodInfo("tree_changed")); diff --git a/scene/main/scene_tree.h b/scene/main/scene_tree.h index 705ca6ebd3..9d7757e0a3 100644 --- a/scene/main/scene_tree.h +++ b/scene/main/scene_tree.h @@ -159,6 +159,7 @@ private: ///network/// Ref<MultiplayerAPI> multiplayer; + HashMap<NodePath, Ref<MultiplayerAPI>> custom_multiplayers; bool multiplayer_poll = true; static SceneTree *singleton; @@ -351,10 +352,10 @@ public: //network API - Ref<MultiplayerAPI> get_multiplayer() const; + Ref<MultiplayerAPI> get_multiplayer(const NodePath &p_for_path = NodePath()) const; + void set_multiplayer(Ref<MultiplayerAPI> p_multiplayer, const NodePath &p_root_path = NodePath()); void set_multiplayer_poll_enabled(bool p_enabled); bool is_multiplayer_poll_enabled() const; - void set_multiplayer(Ref<MultiplayerAPI> p_multiplayer); static void add_idle_callback(IdleCallback p_callback); diff --git a/scene/main/window.cpp b/scene/main/window.cpp index 8b1a4680d2..6feccb7eec 100644 --- a/scene/main/window.cpp +++ b/scene/main/window.cpp @@ -1045,7 +1045,9 @@ void Window::popup_centered_clamped(const Size2i &p_size, float p_fallback_ratio Rect2i popup_rect; popup_rect.size = Vector2i(MIN(size_ratio.x, p_size.x), MIN(size_ratio.y, p_size.y)); - popup_rect.position = parent_rect.position + (parent_rect.size - popup_rect.size) / 2; + if (parent_rect != Rect2()) { + popup_rect.position = parent_rect.position + (parent_rect.size - popup_rect.size) / 2; + } popup(popup_rect); } @@ -1069,7 +1071,10 @@ void Window::popup_centered(const Size2i &p_minsize) { Size2 contents_minsize = _get_contents_minimum_size(); popup_rect.size.x = MAX(p_minsize.x, contents_minsize.x); popup_rect.size.y = MAX(p_minsize.y, contents_minsize.y); - popup_rect.position = parent_rect.position + (parent_rect.size - popup_rect.size) / 2; + + if (parent_rect != Rect2()) { + popup_rect.position = parent_rect.position + (parent_rect.size - popup_rect.size) / 2; + } popup(popup_rect); } @@ -1091,8 +1096,10 @@ void Window::popup_centered_ratio(float p_ratio) { } Rect2i popup_rect; - popup_rect.size = parent_rect.size * p_ratio; - popup_rect.position = parent_rect.position + (parent_rect.size - popup_rect.size) / 2; + if (parent_rect != Rect2()) { + popup_rect.size = parent_rect.size * p_ratio; + popup_rect.position = parent_rect.position + (parent_rect.size - popup_rect.size) / 2; + } popup(popup_rect); } diff --git a/scene/register_scene_types.cpp b/scene/register_scene_types.cpp index e421cdc1f8..6c0192cf44 100644 --- a/scene/register_scene_types.cpp +++ b/scene/register_scene_types.cpp @@ -1109,6 +1109,9 @@ void initialize_theme() { TextServer::SubpixelPositioning font_subpixel_positioning = (TextServer::SubpixelPositioning)(int)GLOBAL_DEF_RST("gui/theme/default_font_subpixel_positioning", TextServer::SUBPIXEL_POSITIONING_AUTO); ProjectSettings::get_singleton()->set_custom_property_info("gui/theme/default_font_subpixel_positioning", PropertyInfo(Variant::INT, "gui/theme/default_font_subpixel_positioning", PROPERTY_HINT_ENUM, "Disabled,Auto,One half of a pixel,One quarter of a pixel", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_RESTART_IF_CHANGED)); + const bool font_msdf = GLOBAL_DEF_RST("gui/theme/default_font_multichannel_signed_distance_field", false); + const bool font_generate_mipmaps = GLOBAL_DEF_RST("gui/theme/default_font_generate_mipmaps", false); + Ref<Font> font; if (!font_path.is_empty()) { font = ResourceLoader::load(font_path); @@ -1119,7 +1122,7 @@ void initialize_theme() { // Always make the default theme to avoid invalid default font/icon/style in the given theme. if (RenderingServer::get_singleton()) { - make_default_theme(default_theme_scale, font, font_subpixel_positioning, font_hinting, font_antialiased); + make_default_theme(default_theme_scale, font, font_subpixel_positioning, font_hinting, font_antialiased, font_msdf, font_generate_mipmaps); } if (!theme_path.is_empty()) { diff --git a/scene/resources/default_theme/default_theme.cpp b/scene/resources/default_theme/default_theme.cpp index f059ec2cf6..271cf61171 100644 --- a/scene/resources/default_theme/default_theme.cpp +++ b/scene/resources/default_theme/default_theme.cpp @@ -1026,7 +1026,7 @@ void fill_default_theme(Ref<Theme> &theme, const Ref<Font> &default_font, const default_style = make_flat_stylebox(Color(1, 0.365, 0.365), 4, 4, 4, 4, 0, false, 2); } -void make_default_theme(float p_scale, Ref<Font> p_font, TextServer::SubpixelPositioning p_subpixel, TextServer::Hinting p_hinting, bool p_aa) { +void make_default_theme(float p_scale, Ref<Font> p_font, TextServer::SubpixelPositioning p_font_subpixel, TextServer::Hinting p_font_hinting, bool p_font_antialiased, bool p_font_msdf, bool p_font_generate_mipmaps) { Ref<Theme> t; t.instantiate(); @@ -1051,9 +1051,12 @@ void make_default_theme(float p_scale, Ref<Font> p_font, TextServer::SubpixelPos Ref<FontData> dynamic_font_data; dynamic_font_data.instantiate(); dynamic_font_data->set_data_ptr(_font_OpenSans_SemiBold, _font_OpenSans_SemiBold_size); - dynamic_font_data->set_subpixel_positioning(p_subpixel); - dynamic_font_data->set_hinting(p_hinting); - dynamic_font_data->set_antialiased(p_aa); + dynamic_font_data->set_subpixel_positioning(p_font_subpixel); + dynamic_font_data->set_hinting(p_font_hinting); + dynamic_font_data->set_antialiased(p_font_antialiased); + dynamic_font_data->set_multichannel_signed_distance_field(p_font_msdf); + dynamic_font_data->set_generate_mipmaps(p_font_generate_mipmaps); + dynamic_font->add_data(dynamic_font_data); default_font = dynamic_font; diff --git a/scene/resources/default_theme/default_theme.h b/scene/resources/default_theme/default_theme.h index a9e21dda3f..f777330a07 100644 --- a/scene/resources/default_theme/default_theme.h +++ b/scene/resources/default_theme/default_theme.h @@ -36,7 +36,7 @@ const int default_font_size = 16; void fill_default_theme(Ref<Theme> &theme, const Ref<Font> &default_font, const Ref<Font> &bold_font, const Ref<Font> &bold_italics_font, const Ref<Font> &italics_font, Ref<Texture2D> &default_icon, Ref<StyleBox> &default_style, float p_scale); -void make_default_theme(float p_scale, Ref<Font> p_font, TextServer::SubpixelPositioning p_subpixel, TextServer::Hinting p_hinting, bool p_aa); +void make_default_theme(float p_scale, Ref<Font> p_font, TextServer::SubpixelPositioning p_font_subpixel = TextServer::SUBPIXEL_POSITIONING_AUTO, TextServer::Hinting p_font_hinting = TextServer::HINTING_LIGHT, bool p_font_antialiased = true, bool p_font_msdf = false, bool p_font_generate_mipmaps = false); void clear_default_theme(); #endif diff --git a/servers/physics_server_2d_wrap_mt.cpp b/servers/physics_server_2d_wrap_mt.cpp index 02223b83f0..699f515270 100644 --- a/servers/physics_server_2d_wrap_mt.cpp +++ b/servers/physics_server_2d_wrap_mt.cpp @@ -37,7 +37,7 @@ void PhysicsServer2DWrapMT::thread_exit() { } void PhysicsServer2DWrapMT::thread_step(real_t p_delta) { - physics_2d_server->step(p_delta); + physics_server_2d->step(p_delta); step_sem.post(); } @@ -50,7 +50,7 @@ void PhysicsServer2DWrapMT::_thread_callback(void *_instance) { void PhysicsServer2DWrapMT::thread_loop() { server_thread = Thread::get_caller_id(); - physics_2d_server->init(); + physics_server_2d->init(); exit.clear(); step_thread_up.set(); @@ -61,7 +61,7 @@ void PhysicsServer2DWrapMT::thread_loop() { command_queue.flush_all(); // flush all - physics_2d_server->finish(); + physics_server_2d->finish(); } /* EVENT QUEUING */ @@ -71,7 +71,7 @@ void PhysicsServer2DWrapMT::step(real_t p_step) { command_queue.push(this, &PhysicsServer2DWrapMT::thread_step, p_step); } else { command_queue.flush_all(); //flush all pending from other threads - physics_2d_server->step(p_step); + physics_server_2d->step(p_step); } } @@ -83,15 +83,15 @@ void PhysicsServer2DWrapMT::sync() { step_sem.wait(); //must not wait if a step was not issued } } - physics_2d_server->sync(); + physics_server_2d->sync(); } void PhysicsServer2DWrapMT::flush_queries() { - physics_2d_server->flush_queries(); + physics_server_2d->flush_queries(); } void PhysicsServer2DWrapMT::end_sync() { - physics_2d_server->end_sync(); + physics_server_2d->end_sync(); } void PhysicsServer2DWrapMT::init() { @@ -102,7 +102,7 @@ void PhysicsServer2DWrapMT::init() { OS::get_singleton()->delay_usec(1000); } } else { - physics_2d_server->init(); + physics_server_2d->init(); } } @@ -111,13 +111,13 @@ void PhysicsServer2DWrapMT::finish() { command_queue.push(this, &PhysicsServer2DWrapMT::thread_exit); thread.wait_to_finish(); } else { - physics_2d_server->finish(); + physics_server_2d->finish(); } } PhysicsServer2DWrapMT::PhysicsServer2DWrapMT(PhysicsServer2D *p_contained, bool p_create_thread) : command_queue(p_create_thread) { - physics_2d_server = p_contained; + physics_server_2d = p_contained; create_thread = p_create_thread; pool_max_size = GLOBAL_GET("memory/limits/multithreaded_server/rid_pool_prealloc"); @@ -132,6 +132,6 @@ PhysicsServer2DWrapMT::PhysicsServer2DWrapMT(PhysicsServer2D *p_contained, bool } PhysicsServer2DWrapMT::~PhysicsServer2DWrapMT() { - memdelete(physics_2d_server); + memdelete(physics_server_2d); //finish(); } diff --git a/servers/physics_server_2d_wrap_mt.h b/servers/physics_server_2d_wrap_mt.h index aa3a8bc04a..ddb071f603 100644 --- a/servers/physics_server_2d_wrap_mt.h +++ b/servers/physics_server_2d_wrap_mt.h @@ -44,7 +44,7 @@ #endif class PhysicsServer2DWrapMT : public PhysicsServer2D { - mutable PhysicsServer2D *physics_2d_server; + mutable PhysicsServer2D *physics_server_2d; mutable CommandQueueMT command_queue; @@ -71,7 +71,7 @@ class PhysicsServer2DWrapMT : public PhysicsServer2D { public: #define ServerName PhysicsServer2D #define ServerNameWrapMT PhysicsServer2DWrapMT -#define server_name physics_2d_server +#define server_name physics_server_2d #define WRITE_ACTION #include "servers/server_wrap_mt_common.h" @@ -96,7 +96,7 @@ public: //these work well, but should be used from the main thread only bool shape_collide(RID p_shape_A, const Transform2D &p_xform_A, const Vector2 &p_motion_A, RID p_shape_B, const Transform2D &p_xform_B, const Vector2 &p_motion_B, Vector2 *r_results, int p_result_max, int &r_result_count) override { ERR_FAIL_COND_V(main_thread != Thread::get_caller_id(), false); - return physics_2d_server->shape_collide(p_shape_A, p_xform_A, p_motion_A, p_shape_B, p_xform_B, p_motion_B, r_results, p_result_max, r_result_count); + return physics_server_2d->shape_collide(p_shape_A, p_xform_A, p_motion_A, p_shape_B, p_xform_B, p_motion_B, r_results, p_result_max, r_result_count); } /* SPACE API */ @@ -111,18 +111,18 @@ public: // this function only works on physics process, errors and returns null otherwise PhysicsDirectSpaceState2D *space_get_direct_state(RID p_space) override { ERR_FAIL_COND_V(main_thread != Thread::get_caller_id(), nullptr); - return physics_2d_server->space_get_direct_state(p_space); + return physics_server_2d->space_get_direct_state(p_space); } FUNC2(space_set_debug_contacts, RID, int); virtual Vector<Vector2> space_get_contacts(RID p_space) const override { ERR_FAIL_COND_V(main_thread != Thread::get_caller_id(), Vector<Vector2>()); - return physics_2d_server->space_get_contacts(p_space); + return physics_server_2d->space_get_contacts(p_space); } virtual int space_get_contact_count(RID p_space) const override { ERR_FAIL_COND_V(main_thread != Thread::get_caller_id(), 0); - return physics_2d_server->space_get_contact_count(p_space); + return physics_server_2d->space_get_contact_count(p_space); } /* AREA API */ @@ -250,20 +250,20 @@ public: FUNC3(body_set_force_integration_callback, RID, const Callable &, const Variant &); bool body_collide_shape(RID p_body, int p_body_shape, RID p_shape, const Transform2D &p_shape_xform, const Vector2 &p_motion, Vector2 *r_results, int p_result_max, int &r_result_count) override { - return physics_2d_server->body_collide_shape(p_body, p_body_shape, p_shape, p_shape_xform, p_motion, r_results, p_result_max, r_result_count); + return physics_server_2d->body_collide_shape(p_body, p_body_shape, p_shape, p_shape_xform, p_motion, r_results, p_result_max, r_result_count); } FUNC2(body_set_pickable, RID, bool); bool body_test_motion(RID p_body, const MotionParameters &p_parameters, MotionResult *r_result = nullptr) override { ERR_FAIL_COND_V(main_thread != Thread::get_caller_id(), false); - return physics_2d_server->body_test_motion(p_body, p_parameters, r_result); + return physics_server_2d->body_test_motion(p_body, p_parameters, r_result); } // this function only works on physics process, errors and returns null otherwise PhysicsDirectBodyState2D *body_get_direct_state(RID p_body) override { ERR_FAIL_COND_V(main_thread != Thread::get_caller_id(), nullptr); - return physics_2d_server->body_get_direct_state(p_body); + return physics_server_2d->body_get_direct_state(p_body); } /* JOINT API */ @@ -309,11 +309,11 @@ public: virtual void finish() override; virtual bool is_flushing_queries() const override { - return physics_2d_server->is_flushing_queries(); + return physics_server_2d->is_flushing_queries(); } int get_process_info(ProcessInfo p_info) override { - return physics_2d_server->get_process_info(p_info); + return physics_server_2d->get_process_info(p_info); } PhysicsServer2DWrapMT(PhysicsServer2D *p_contained, bool p_create_thread); diff --git a/servers/physics_server_3d_wrap_mt.cpp b/servers/physics_server_3d_wrap_mt.cpp index 822ca44b72..7faa193ec2 100644 --- a/servers/physics_server_3d_wrap_mt.cpp +++ b/servers/physics_server_3d_wrap_mt.cpp @@ -37,7 +37,7 @@ void PhysicsServer3DWrapMT::thread_exit() { } void PhysicsServer3DWrapMT::thread_step(real_t p_delta) { - physics_3d_server->step(p_delta); + physics_server_3d->step(p_delta); step_sem.post(); } @@ -50,7 +50,7 @@ void PhysicsServer3DWrapMT::_thread_callback(void *_instance) { void PhysicsServer3DWrapMT::thread_loop() { server_thread = Thread::get_caller_id(); - physics_3d_server->init(); + physics_server_3d->init(); exit = false; step_thread_up = true; @@ -61,7 +61,7 @@ void PhysicsServer3DWrapMT::thread_loop() { command_queue.flush_all(); // flush all - physics_3d_server->finish(); + physics_server_3d->finish(); } /* EVENT QUEUING */ @@ -71,7 +71,7 @@ void PhysicsServer3DWrapMT::step(real_t p_step) { command_queue.push(this, &PhysicsServer3DWrapMT::thread_step, p_step); } else { command_queue.flush_all(); //flush all pending from other threads - physics_3d_server->step(p_step); + physics_server_3d->step(p_step); } } @@ -83,15 +83,15 @@ void PhysicsServer3DWrapMT::sync() { step_sem.wait(); //must not wait if a step was not issued } } - physics_3d_server->sync(); + physics_server_3d->sync(); } void PhysicsServer3DWrapMT::flush_queries() { - physics_3d_server->flush_queries(); + physics_server_3d->flush_queries(); } void PhysicsServer3DWrapMT::end_sync() { - physics_3d_server->end_sync(); + physics_server_3d->end_sync(); } void PhysicsServer3DWrapMT::init() { @@ -102,7 +102,7 @@ void PhysicsServer3DWrapMT::init() { OS::get_singleton()->delay_usec(1000); } } else { - physics_3d_server->init(); + physics_server_3d->init(); } } @@ -111,13 +111,13 @@ void PhysicsServer3DWrapMT::finish() { command_queue.push(this, &PhysicsServer3DWrapMT::thread_exit); thread.wait_to_finish(); } else { - physics_3d_server->finish(); + physics_server_3d->finish(); } } PhysicsServer3DWrapMT::PhysicsServer3DWrapMT(PhysicsServer3D *p_contained, bool p_create_thread) : command_queue(p_create_thread) { - physics_3d_server = p_contained; + physics_server_3d = p_contained; create_thread = p_create_thread; pool_max_size = GLOBAL_GET("memory/limits/multithreaded_server/rid_pool_prealloc"); @@ -132,6 +132,6 @@ PhysicsServer3DWrapMT::PhysicsServer3DWrapMT(PhysicsServer3D *p_contained, bool } PhysicsServer3DWrapMT::~PhysicsServer3DWrapMT() { - memdelete(physics_3d_server); + memdelete(physics_server_3d); //finish(); } diff --git a/servers/physics_server_3d_wrap_mt.h b/servers/physics_server_3d_wrap_mt.h index e44f82672d..d4a4ad3132 100644 --- a/servers/physics_server_3d_wrap_mt.h +++ b/servers/physics_server_3d_wrap_mt.h @@ -43,7 +43,7 @@ #endif class PhysicsServer3DWrapMT : public PhysicsServer3D { - mutable PhysicsServer3D *physics_3d_server; + mutable PhysicsServer3D *physics_server_3d; mutable CommandQueueMT command_queue; @@ -70,7 +70,7 @@ class PhysicsServer3DWrapMT : public PhysicsServer3D { public: #define ServerName PhysicsServer3D #define ServerNameWrapMT PhysicsServer3DWrapMT -#define server_name physics_3d_server +#define server_name physics_server_3d #define WRITE_ACTION #include "servers/server_wrap_mt_common.h" @@ -100,7 +100,7 @@ public: //these work well, but should be used from the main thread only bool shape_collide(RID p_shape_A, const Transform &p_xform_A, const Vector3 &p_motion_A, RID p_shape_B, const Transform &p_xform_B, const Vector3 &p_motion_B, Vector3 *r_results, int p_result_max, int &r_result_count) { ERR_FAIL_COND_V(main_thread != Thread::get_caller_id(), false); - return physics_3d_server->shape_collide(p_shape_A, p_xform_A, p_motion_A, p_shape_B, p_xform_B, p_motion_B, r_results, p_result_max, r_result_count); + return physics_server_3d->shape_collide(p_shape_A, p_xform_A, p_motion_A, p_shape_B, p_xform_B, p_motion_B, r_results, p_result_max, r_result_count); } #endif /* SPACE API */ @@ -115,18 +115,18 @@ public: // this function only works on physics process, errors and returns null otherwise PhysicsDirectSpaceState3D *space_get_direct_state(RID p_space) override { ERR_FAIL_COND_V(main_thread != Thread::get_caller_id(), nullptr); - return physics_3d_server->space_get_direct_state(p_space); + return physics_server_3d->space_get_direct_state(p_space); } FUNC2(space_set_debug_contacts, RID, int); virtual Vector<Vector3> space_get_contacts(RID p_space) const override { ERR_FAIL_COND_V(main_thread != Thread::get_caller_id(), Vector<Vector3>()); - return physics_3d_server->space_get_contacts(p_space); + return physics_server_3d->space_get_contacts(p_space); } virtual int space_get_contact_count(RID p_space) const override { ERR_FAIL_COND_V(main_thread != Thread::get_caller_id(), 0); - return physics_3d_server->space_get_contact_count(p_space); + return physics_server_3d->space_get_contact_count(p_space); } /* AREA API */ @@ -256,13 +256,13 @@ public: bool body_test_motion(RID p_body, const MotionParameters &p_parameters, MotionResult *r_result = nullptr) override { ERR_FAIL_COND_V(main_thread != Thread::get_caller_id(), false); - return physics_3d_server->body_test_motion(p_body, p_parameters, r_result); + return physics_server_3d->body_test_motion(p_body, p_parameters, r_result); } // this function only works on physics process, errors and returns null otherwise PhysicsDirectBodyState3D *body_get_direct_state(RID p_body) override { ERR_FAIL_COND_V(main_thread != Thread::get_caller_id(), nullptr); - return physics_3d_server->body_get_direct_state(p_body); + return physics_server_3d->body_get_direct_state(p_body); } /* SOFT BODY API */ @@ -385,11 +385,11 @@ public: virtual void finish() override; virtual bool is_flushing_queries() const override { - return physics_3d_server->is_flushing_queries(); + return physics_server_3d->is_flushing_queries(); } int get_process_info(ProcessInfo p_info) override { - return physics_3d_server->get_process_info(p_info); + return physics_server_3d->get_process_info(p_info); } PhysicsServer3DWrapMT(PhysicsServer3D *p_contained, bool p_create_thread); diff --git a/servers/register_server_types.cpp b/servers/register_server_types.cpp index 9843492316..f02bf80645 100644 --- a/servers/register_server_types.cpp +++ b/servers/register_server_types.cpp @@ -85,17 +85,17 @@ ShaderTypes *shader_types = nullptr; PhysicsServer3D *_createGodotPhysics3DCallback() { bool using_threads = GLOBAL_GET("physics/3d/run_on_separate_thread"); - PhysicsServer3D *physics_server = memnew(GodotPhysicsServer3D(using_threads)); + PhysicsServer3D *physics_server_3d = memnew(GodotPhysicsServer3D(using_threads)); - return memnew(PhysicsServer3DWrapMT(physics_server, using_threads)); + return memnew(PhysicsServer3DWrapMT(physics_server_3d, using_threads)); } PhysicsServer2D *_createGodotPhysics2DCallback() { bool using_threads = GLOBAL_GET("physics/2d/run_on_separate_thread"); - PhysicsServer2D *physics_server = memnew(GodotPhysicsServer2D(using_threads)); + PhysicsServer2D *physics_server_2d = memnew(GodotPhysicsServer2D(using_threads)); - return memnew(PhysicsServer2DWrapMT(physics_server, using_threads)); + return memnew(PhysicsServer2DWrapMT(physics_server_2d, using_threads)); } static bool has_server_feature_callback(const String &p_feature) { diff --git a/servers/rendering/dummy/rasterizer_scene_dummy.h b/servers/rendering/dummy/rasterizer_scene_dummy.h index 3855222554..fa58322ea8 100644 --- a/servers/rendering/dummy/rasterizer_scene_dummy.h +++ b/servers/rendering/dummy/rasterizer_scene_dummy.h @@ -184,7 +184,7 @@ public: void voxel_gi_set_quality(RS::VoxelGIQuality) override {} void render_scene(RID p_render_buffers, const CameraData *p_camera_data, const PagedArray<GeometryInstance *> &p_instances, const PagedArray<RID> &p_lights, const PagedArray<RID> &p_reflection_probes, const PagedArray<RID> &p_voxel_gi_instances, const PagedArray<RID> &p_decals, const PagedArray<RID> &p_lightmaps, const PagedArray<RID> &p_fog_volumes, RID p_environment, RID p_camera_effects, RID p_shadow_atlas, RID p_occluder_debug_tex, RID p_reflection_atlas, RID p_reflection_probe, int p_reflection_probe_pass, float p_screen_mesh_lod_threshold, const RenderShadowData *p_render_shadows, int p_render_shadow_count, const RenderSDFGIData *p_render_sdfgi_regions, int p_render_sdfgi_region_count, const RenderSDFGIUpdateData *p_sdfgi_update_data = nullptr, RendererScene::RenderInfo *r_info = nullptr) override {} - void render_material(const Transform3D &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, const PagedArray<GeometryInstance *> &p_instances, RID p_framebuffer, const Rect2i &p_region) override {} + void render_material(const Transform3D &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_orthogonal, const PagedArray<GeometryInstance *> &p_instances, RID p_framebuffer, const Rect2i &p_region) override {} void render_particle_collider_heightfield(RID p_collider, const Transform3D &p_transform, const PagedArray<GeometryInstance *> &p_instances) override {} void set_scene_pass(uint64_t p_pass) override {} diff --git a/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.cpp b/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.cpp index 93baa9a96f..3be15db9e8 100644 --- a/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.cpp +++ b/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.cpp @@ -1124,7 +1124,7 @@ void RenderForwardClustered::_fill_render_list(RenderListType p_render_list, con distance = -distance_max; } - if (p_render_data->cam_ortogonal) { + if (p_render_data->cam_orthogonal) { distance = 1.0; } @@ -1815,7 +1815,7 @@ void RenderForwardClustered::_render_particle_collider_heightfield(RID p_fb, con RD::get_singleton()->draw_command_end_label(); } -void RenderForwardClustered::_render_material(const Transform3D &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, const PagedArray<GeometryInstance *> &p_instances, RID p_framebuffer, const Rect2i &p_region) { +void RenderForwardClustered::_render_material(const Transform3D &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_orthogonal, const PagedArray<GeometryInstance *> &p_instances, RID p_framebuffer, const Rect2i &p_region) { RENDER_TIMESTAMP("Setup Rendering 3D Material"); RD::get_singleton()->draw_command_begin_label("Render 3D Material"); diff --git a/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.h b/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.h index 37366d3e14..c30499da29 100644 --- a/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.h +++ b/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.h @@ -611,7 +611,7 @@ protected: virtual void _render_shadow_process() override; virtual void _render_shadow_end(uint32_t p_barrier = RD::BARRIER_MASK_ALL) override; - virtual void _render_material(const Transform3D &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, const PagedArray<GeometryInstance *> &p_instances, RID p_framebuffer, const Rect2i &p_region) override; + virtual void _render_material(const Transform3D &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_orthogonal, const PagedArray<GeometryInstance *> &p_instances, RID p_framebuffer, const Rect2i &p_region) override; virtual void _render_uv2(const PagedArray<GeometryInstance *> &p_instances, RID p_framebuffer, const Rect2i &p_region) override; virtual void _render_sdfgi(RID p_render_buffers, const Vector3i &p_from, const Vector3i &p_size, const AABB &p_bounds, const PagedArray<GeometryInstance *> &p_instances, const RID &p_albedo_texture, const RID &p_emission_texture, const RID &p_emission_aniso_texture, const RID &p_geom_facing_texture) override; virtual void _render_particle_collider_heightfield(RID p_fb, const Transform3D &p_cam_transform, const CameraMatrix &p_cam_projection, const PagedArray<GeometryInstance *> &p_instances) override; diff --git a/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.cpp b/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.cpp index ade2b976c8..d9c339097a 100644 --- a/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.cpp +++ b/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.cpp @@ -977,7 +977,7 @@ void RenderForwardMobile::_render_shadow_end(uint32_t p_barrier) { /* */ -void RenderForwardMobile::_render_material(const Transform3D &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, const PagedArray<GeometryInstance *> &p_instances, RID p_framebuffer, const Rect2i &p_region) { +void RenderForwardMobile::_render_material(const Transform3D &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_orthogonal, const PagedArray<GeometryInstance *> &p_instances, RID p_framebuffer, const Rect2i &p_region) { RENDER_TIMESTAMP("Setup Rendering 3D Material"); RD::get_singleton()->draw_command_begin_label("Render 3D Material"); @@ -1441,7 +1441,7 @@ void RenderForwardMobile::_fill_render_list(RenderListType p_render_list, const distance = -distance_max; } - if (p_render_data->cam_ortogonal) { + if (p_render_data->cam_orthogonal) { distance = 1.0; } diff --git a/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.h b/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.h index 0ddfe89eea..0a7e973120 100644 --- a/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.h +++ b/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.h @@ -214,7 +214,7 @@ protected: virtual void _render_shadow_process() override; virtual void _render_shadow_end(uint32_t p_barrier = RD::BARRIER_MASK_ALL) override; - virtual void _render_material(const Transform3D &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, const PagedArray<GeometryInstance *> &p_instances, RID p_framebuffer, const Rect2i &p_region) override; + virtual void _render_material(const Transform3D &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_orthogonal, const PagedArray<GeometryInstance *> &p_instances, RID p_framebuffer, const Rect2i &p_region) override; virtual void _render_uv2(const PagedArray<GeometryInstance *> &p_instances, RID p_framebuffer, const Rect2i &p_region) override; virtual void _render_sdfgi(RID p_render_buffers, const Vector3i &p_from, const Vector3i &p_size, const AABB &p_bounds, const PagedArray<GeometryInstance *> &p_instances, const RID &p_albedo_texture, const RID &p_emission_texture, const RID &p_emission_aniso_texture, const RID &p_geom_facing_texture) override; virtual void _render_particle_collider_heightfield(RID p_fb, const Transform3D &p_cam_transform, const CameraMatrix &p_cam_projection, const PagedArray<GeometryInstance *> &p_instances) override; diff --git a/servers/rendering/renderer_rd/renderer_scene_render_rd.cpp b/servers/rendering/renderer_rd/renderer_scene_render_rd.cpp index bdbc228bde..b1dab1f02a 100644 --- a/servers/rendering/renderer_rd/renderer_scene_render_rd.cpp +++ b/servers/rendering/renderer_rd/renderer_scene_render_rd.cpp @@ -2391,7 +2391,7 @@ void RendererSceneRenderRD::_render_buffers_post_process_and_tonemap(const Rende float bokeh_size = camfx->dof_blur_amount * 64.0; if (can_use_storage) { - storage->get_effects()->bokeh_dof(buffers, camfx->dof_blur_far_enabled, camfx->dof_blur_far_distance, camfx->dof_blur_far_transition, camfx->dof_blur_near_enabled, camfx->dof_blur_near_distance, camfx->dof_blur_near_transition, bokeh_size, dof_blur_bokeh_shape, dof_blur_quality, dof_blur_use_jitter, p_render_data->z_near, p_render_data->z_far, p_render_data->cam_ortogonal); + storage->get_effects()->bokeh_dof(buffers, camfx->dof_blur_far_enabled, camfx->dof_blur_far_distance, camfx->dof_blur_far_transition, camfx->dof_blur_near_enabled, camfx->dof_blur_near_distance, camfx->dof_blur_near_transition, bokeh_size, dof_blur_bokeh_shape, dof_blur_quality, dof_blur_use_jitter, p_render_data->z_near, p_render_data->z_far, p_render_data->cam_orthogonal); } else { // Set framebuffers. buffers.base_fb = rb->texture_fb; @@ -2406,7 +2406,7 @@ void RendererSceneRenderRD::_render_buffers_post_process_and_tonemap(const Rende // Set weight buffers. buffers.base_weight_fb = rb->base_weight_fb; - storage->get_effects()->bokeh_dof_raster(buffers, camfx->dof_blur_far_enabled, camfx->dof_blur_far_distance, camfx->dof_blur_far_transition, camfx->dof_blur_near_enabled, camfx->dof_blur_near_distance, camfx->dof_blur_near_transition, bokeh_size, dof_blur_bokeh_shape, dof_blur_quality, p_render_data->z_near, p_render_data->z_far, p_render_data->cam_ortogonal); + storage->get_effects()->bokeh_dof_raster(buffers, camfx->dof_blur_far_enabled, camfx->dof_blur_far_distance, camfx->dof_blur_far_transition, camfx->dof_blur_near_enabled, camfx->dof_blur_near_distance, camfx->dof_blur_near_transition, bokeh_size, dof_blur_bokeh_shape, dof_blur_quality, p_render_data->z_near, p_render_data->z_far, p_render_data->cam_orthogonal); } RD::get_singleton()->draw_command_end_label(); } @@ -4998,7 +4998,7 @@ void RendererSceneRenderRD::render_scene(RID p_render_buffers, const CameraData render_data.cam_transform = p_camera_data->main_transform; render_data.cam_projection = p_camera_data->main_projection; render_data.view_projection[0] = p_camera_data->main_projection; - render_data.cam_ortogonal = p_camera_data->is_ortogonal; + render_data.cam_orthogonal = p_camera_data->is_orthogonal; render_data.view_count = p_camera_data->view_count; for (uint32_t v = 0; v < p_camera_data->view_count; v++) { @@ -5327,8 +5327,8 @@ void RendererSceneRenderRD::_render_shadow_pass(RID p_light, RID p_shadow_atlas, } } -void RendererSceneRenderRD::render_material(const Transform3D &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, const PagedArray<GeometryInstance *> &p_instances, RID p_framebuffer, const Rect2i &p_region) { - _render_material(p_cam_transform, p_cam_projection, p_cam_ortogonal, p_instances, p_framebuffer, p_region); +void RendererSceneRenderRD::render_material(const Transform3D &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_orthogonal, const PagedArray<GeometryInstance *> &p_instances, RID p_framebuffer, const Rect2i &p_region) { + _render_material(p_cam_transform, p_cam_projection, p_cam_orthogonal, p_instances, p_framebuffer, p_region); } void RendererSceneRenderRD::render_particle_collider_heightfield(RID p_collider, const Transform3D &p_transform, const PagedArray<GeometryInstance *> &p_instances) { diff --git a/servers/rendering/renderer_rd/renderer_scene_render_rd.h b/servers/rendering/renderer_rd/renderer_scene_render_rd.h index b2c8daffb1..a36df15023 100644 --- a/servers/rendering/renderer_rd/renderer_scene_render_rd.h +++ b/servers/rendering/renderer_rd/renderer_scene_render_rd.h @@ -50,7 +50,7 @@ struct RenderDataRD { Transform3D cam_transform = Transform3D(); CameraMatrix cam_projection = CameraMatrix(); - bool cam_ortogonal = false; + bool cam_orthogonal = false; // For stereo rendering uint32_t view_count = 1; @@ -113,7 +113,7 @@ protected: virtual void _render_shadow_process() = 0; virtual void _render_shadow_end(uint32_t p_barrier = RD::BARRIER_MASK_ALL) = 0; - virtual void _render_material(const Transform3D &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, const PagedArray<GeometryInstance *> &p_instances, RID p_framebuffer, const Rect2i &p_region) = 0; + virtual void _render_material(const Transform3D &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_orthogonal, const PagedArray<GeometryInstance *> &p_instances, RID p_framebuffer, const Rect2i &p_region) = 0; virtual void _render_uv2(const PagedArray<GeometryInstance *> &p_instances, RID p_framebuffer, const Rect2i &p_region) = 0; virtual void _render_sdfgi(RID p_render_buffers, const Vector3i &p_from, const Vector3i &p_size, const AABB &p_bounds, const PagedArray<GeometryInstance *> &p_instances, const RID &p_albedo_texture, const RID &p_emission_texture, const RID &p_emission_aniso_texture, const RID &p_geom_facing_texture) = 0; virtual void _render_particle_collider_heightfield(RID p_fb, const Transform3D &p_cam_transform, const CameraMatrix &p_cam_projection, const PagedArray<GeometryInstance *> &p_instances) = 0; @@ -1411,7 +1411,7 @@ public: virtual void render_scene(RID p_render_buffers, const CameraData *p_camera_data, const PagedArray<GeometryInstance *> &p_instances, const PagedArray<RID> &p_lights, const PagedArray<RID> &p_reflection_probes, const PagedArray<RID> &p_voxel_gi_instances, const PagedArray<RID> &p_decals, const PagedArray<RID> &p_lightmaps, const PagedArray<RID> &p_fog_volumes, RID p_environment, RID p_camera_effects, RID p_shadow_atlas, RID p_occluder_debug_tex, RID p_reflection_atlas, RID p_reflection_probe, int p_reflection_probe_pass, float p_screen_mesh_lod_threshold, const RenderShadowData *p_render_shadows, int p_render_shadow_count, const RenderSDFGIData *p_render_sdfgi_regions, int p_render_sdfgi_region_count, const RenderSDFGIUpdateData *p_sdfgi_update_data = nullptr, RendererScene::RenderInfo *r_render_info = nullptr) override; - virtual void render_material(const Transform3D &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, const PagedArray<GeometryInstance *> &p_instances, RID p_framebuffer, const Rect2i &p_region) override; + virtual void render_material(const Transform3D &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_orthogonal, const PagedArray<GeometryInstance *> &p_instances, RID p_framebuffer, const Rect2i &p_region) override; virtual void render_particle_collider_heightfield(RID p_collider, const Transform3D &p_transform, const PagedArray<GeometryInstance *> &p_instances) override; diff --git a/servers/rendering/renderer_scene_cull.cpp b/servers/rendering/renderer_scene_cull.cpp index 55193a45f0..528f381139 100644 --- a/servers/rendering/renderer_scene_cull.cpp +++ b/servers/rendering/renderer_scene_cull.cpp @@ -2444,7 +2444,7 @@ void RendererSceneCull::render_camera(RID p_render_buffers, RID p_camera, RID p_ Transform3D transform = camera->transform; CameraMatrix projection; bool vaspect = camera->vaspect; - bool is_ortogonal = false; + bool is_orthogonal = false; switch (camera->type) { case Camera::ORTHOGONAL: { @@ -2454,7 +2454,7 @@ void RendererSceneCull::render_camera(RID p_render_buffers, RID p_camera, RID p_ camera->znear, camera->zfar, camera->vaspect); - is_ortogonal = true; + is_orthogonal = true; } break; case Camera::PERSPECTIVE: { projection.set_perspective( @@ -2476,7 +2476,7 @@ void RendererSceneCull::render_camera(RID p_render_buffers, RID p_camera, RID p_ } break; } - camera_data.set_camera(transform, projection, is_ortogonal, vaspect); + camera_data.set_camera(transform, projection, is_orthogonal, vaspect); } else { // Setup our camera for our XR interface. // We can support multiple views here each with their own camera @@ -2510,7 +2510,7 @@ void RendererSceneCull::render_camera(RID p_render_buffers, RID p_camera, RID p_ RENDER_TIMESTAMP("Update Occlusion Buffer") // For now just cull on the first camera - RendererSceneOcclusionCull::get_singleton()->buffer_update(p_viewport, camera_data.main_transform, camera_data.main_projection, camera_data.is_ortogonal, RendererThreadPool::singleton->thread_work_pool); + RendererSceneOcclusionCull::get_singleton()->buffer_update(p_viewport, camera_data.main_transform, camera_data.main_projection, camera_data.is_orthogonal, RendererThreadPool::singleton->thread_work_pool); _render_scene(&camera_data, p_render_buffers, environment, camera->effects, camera->visible_layers, p_scenario, p_viewport, p_shadow_atlas, RID(), -1, p_screen_mesh_lod_threshold, true, r_render_info); #endif @@ -2920,7 +2920,7 @@ void RendererSceneCull::_render_scene(const RendererSceneRender::CameraData *p_c RENDER_TIMESTAMP("Cull 3D Scene"); - //rasterizer->set_camera(p_camera_data->main_transform, p_camera_data.main_projection, p_camera_data.is_ortogonal); + //rasterizer->set_camera(p_camera_data->main_transform, p_camera_data.main_projection, p_camera_data.is_orthogonal); /* STEP 2 - CULL */ @@ -2959,7 +2959,7 @@ void RendererSceneCull::_render_scene(const RendererSceneRender::CameraData *p_c scene_render->set_directional_shadow_count(lights_with_shadow.size()); for (int i = 0; i < lights_with_shadow.size(); i++) { - _light_instance_setup_directional_shadow(i, lights_with_shadow[i], p_camera_data->main_transform, p_camera_data->main_projection, p_camera_data->is_ortogonal, p_camera_data->vaspect); + _light_instance_setup_directional_shadow(i, lights_with_shadow[i], p_camera_data->main_transform, p_camera_data->main_projection, p_camera_data->is_orthogonal, p_camera_data->vaspect); } } @@ -3097,7 +3097,7 @@ void RendererSceneCull::_render_scene(const RendererSceneRender::CameraData *p_c ins->transform.origin + cam_xf.basis.get_axis(0) * radius }; - if (!p_camera_data->is_ortogonal) { + if (!p_camera_data->is_orthogonal) { //if using perspetive, map them to near plane for (int j = 0; j < 2; j++) { if (p.distance_to(points[j]) < 0) { @@ -3125,7 +3125,7 @@ void RendererSceneCull::_render_scene(const RendererSceneRender::CameraData *p_c base + cam_xf.basis.get_axis(0) * w }; - if (!p_camera_data->is_ortogonal) { + if (!p_camera_data->is_orthogonal) { //if using perspetive, map them to near plane for (int j = 0; j < 2; j++) { if (p.distance_to(points[j]) < 0) { @@ -3156,7 +3156,7 @@ void RendererSceneCull::_render_scene(const RendererSceneRender::CameraData *p_c if (redraw && max_shadows_used < MAX_UPDATE_SHADOWS) { //must redraw! RENDER_TIMESTAMP("> Render Light3D " + itos(i)); - light->shadow_dirty = _light_instance_update_shadow(ins, p_camera_data->main_transform, p_camera_data->main_projection, p_camera_data->is_ortogonal, p_camera_data->vaspect, p_shadow_atlas, scenario, p_screen_mesh_lod_threshold); + light->shadow_dirty = _light_instance_update_shadow(ins, p_camera_data->main_transform, p_camera_data->main_projection, p_camera_data->is_orthogonal, p_camera_data->vaspect, p_shadow_atlas, scenario, p_screen_mesh_lod_threshold); RENDER_TIMESTAMP("< Render Light3D " + itos(i)); } else { light->shadow_dirty = redraw; @@ -3229,7 +3229,7 @@ void RendererSceneCull::_render_scene(const RendererSceneRender::CameraData *p_c render_sdfgi_data[i].instances.clear(); } - // virtual void render_scene(RID p_render_buffers, const Transform3D &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, const PagedArray<GeometryInstance *> &p_instances, const PagedArray<RID> &p_lights, const PagedArray<RID> &p_reflection_probes, const PagedArray<RID> &p_voxel_gi_instances, const PagedArray<RID> &p_decals, const PagedArray<RID> &p_lightmaps, RID p_environment, RID p_camera_effects, RID p_shadow_atlas, RID p_reflection_atlas, RID p_reflection_probe, int p_reflection_probe_pass, float p_screen_mesh_lod_threshold,const RenderShadowData *p_render_shadows,int p_render_shadow_count,const RenderSDFGIData *p_render_sdfgi_regions,int p_render_sdfgi_region_count,const RenderSDFGIStaticLightData *p_render_sdfgi_static_lights=nullptr) = 0; + // virtual void render_scene(RID p_render_buffers, const Transform3D &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_orthogonal, const PagedArray<GeometryInstance *> &p_instances, const PagedArray<RID> &p_lights, const PagedArray<RID> &p_reflection_probes, const PagedArray<RID> &p_voxel_gi_instances, const PagedArray<RID> &p_decals, const PagedArray<RID> &p_lightmaps, RID p_environment, RID p_camera_effects, RID p_shadow_atlas, RID p_reflection_atlas, RID p_reflection_probe, int p_reflection_probe_pass, float p_screen_mesh_lod_threshold,const RenderShadowData *p_render_shadows,int p_render_shadow_count,const RenderSDFGIData *p_render_sdfgi_regions,int p_render_sdfgi_region_count,const RenderSDFGIStaticLightData *p_render_sdfgi_static_lights=nullptr) = 0; } RID RendererSceneCull::_render_get_environment(RID p_camera, RID p_scenario) { diff --git a/servers/rendering/renderer_scene_render.cpp b/servers/rendering/renderer_scene_render.cpp index c802f72fdf..fadece317a 100644 --- a/servers/rendering/renderer_scene_render.cpp +++ b/servers/rendering/renderer_scene_render.cpp @@ -30,9 +30,9 @@ #include "renderer_scene_render.h" -void RendererSceneRender::CameraData::set_camera(const Transform3D p_transform, const CameraMatrix p_projection, bool p_is_ortogonal, bool p_vaspect) { +void RendererSceneRender::CameraData::set_camera(const Transform3D p_transform, const CameraMatrix p_projection, bool p_is_orthogonal, bool p_vaspect) { view_count = 1; - is_ortogonal = p_is_ortogonal; + is_orthogonal = p_is_orthogonal; vaspect = p_vaspect; main_transform = p_transform; @@ -42,11 +42,11 @@ void RendererSceneRender::CameraData::set_camera(const Transform3D p_transform, view_projection[0] = p_projection; } -void RendererSceneRender::CameraData::set_multiview_camera(uint32_t p_view_count, const Transform3D *p_transforms, const CameraMatrix *p_projections, bool p_is_ortogonal, bool p_vaspect) { +void RendererSceneRender::CameraData::set_multiview_camera(uint32_t p_view_count, const Transform3D *p_transforms, const CameraMatrix *p_projections, bool p_is_orthogonal, bool p_vaspect) { ERR_FAIL_COND_MSG(p_view_count != 2, "Incorrect view count for stereoscopic view"); view_count = p_view_count; - is_ortogonal = p_is_ortogonal; + is_orthogonal = p_is_orthogonal; vaspect = p_vaspect; Vector<Plane> planes[2]; diff --git a/servers/rendering/renderer_scene_render.h b/servers/rendering/renderer_scene_render.h index 0b8734e68c..d43bfb170e 100644 --- a/servers/rendering/renderer_scene_render.h +++ b/servers/rendering/renderer_scene_render.h @@ -234,7 +234,7 @@ public: struct CameraData { // flags uint32_t view_count; - bool is_ortogonal; + bool is_orthogonal; bool vaspect; // Main/center projection @@ -244,13 +244,13 @@ public: Transform3D view_offset[RendererSceneRender::MAX_RENDER_VIEWS]; CameraMatrix view_projection[RendererSceneRender::MAX_RENDER_VIEWS]; - void set_camera(const Transform3D p_transform, const CameraMatrix p_projection, bool p_is_ortogonal, bool p_vaspect); - void set_multiview_camera(uint32_t p_view_count, const Transform3D *p_transforms, const CameraMatrix *p_projections, bool p_is_ortogonal, bool p_vaspect); + void set_camera(const Transform3D p_transform, const CameraMatrix p_projection, bool p_is_orthogonal, bool p_vaspect); + void set_multiview_camera(uint32_t p_view_count, const Transform3D *p_transforms, const CameraMatrix *p_projections, bool p_is_orthogonal, bool p_vaspect); }; virtual void render_scene(RID p_render_buffers, const CameraData *p_camera_data, const PagedArray<GeometryInstance *> &p_instances, const PagedArray<RID> &p_lights, const PagedArray<RID> &p_reflection_probes, const PagedArray<RID> &p_voxel_gi_instances, const PagedArray<RID> &p_decals, const PagedArray<RID> &p_lightmaps, const PagedArray<RID> &p_fog_volumes, RID p_environment, RID p_camera_effects, RID p_shadow_atlas, RID p_occluder_debug_tex, RID p_reflection_atlas, RID p_reflection_probe, int p_reflection_probe_pass, float p_screen_mesh_lod_threshold, const RenderShadowData *p_render_shadows, int p_render_shadow_count, const RenderSDFGIData *p_render_sdfgi_regions, int p_render_sdfgi_region_count, const RenderSDFGIUpdateData *p_sdfgi_update_data = nullptr, RendererScene::RenderInfo *r_render_info = nullptr) = 0; - virtual void render_material(const Transform3D &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, const PagedArray<GeometryInstance *> &p_instances, RID p_framebuffer, const Rect2i &p_region) = 0; + virtual void render_material(const Transform3D &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_orthogonal, const PagedArray<GeometryInstance *> &p_instances, RID p_framebuffer, const Rect2i &p_region) = 0; virtual void render_particle_collider_heightfield(RID p_collider, const Transform3D &p_transform, const PagedArray<GeometryInstance *> &p_instances) = 0; virtual void set_scene_pass(uint64_t p_pass) = 0; diff --git a/servers/rendering/shader_language.cpp b/servers/rendering/shader_language.cpp index af5da6ae6f..54d1a6fd8d 100644 --- a/servers/rendering/shader_language.cpp +++ b/servers/rendering/shader_language.cpp @@ -4670,16 +4670,18 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons expr = _parse_array_constructor(p_block, p_function_info); } else { DataType datatype; - DataPrecision precision; - bool precision_defined = false; + DataPrecision precision = PRECISION_DEFAULT; if (is_token_precision(tk.type)) { precision = get_token_precision(tk.type); - precision_defined = true; tk = _get_token(); } datatype = get_token_datatype(tk.type); + if (precision != PRECISION_DEFAULT && _validate_precision(datatype, precision) != OK) { + return nullptr; + } + tk = _get_token(); if (tk.type == TK_BRACKET_OPEN) { @@ -4697,7 +4699,7 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons OperatorNode *func = alloc_node<OperatorNode>(); func->op = OP_CONSTRUCT; - if (precision_defined) { + if (precision != PRECISION_DEFAULT) { func->return_precision_cache = precision; } @@ -6426,10 +6428,6 @@ Error ShaderLanguage::_parse_block(BlockNode *p_block, const FunctionInfo &p_fun if (!is_struct) { is_struct = shader->structs.has(tk.text); // check again. } - if (is_struct && precision != PRECISION_DEFAULT) { - _set_error(RTR("The precision modifier cannot be used on structs.")); - return ERR_PARSE_ERROR; - } if (!is_token_nonvoid_datatype(tk.type)) { _set_error(RTR("Expected variable type after precision modifier.")); return ERR_PARSE_ERROR; @@ -6449,6 +6447,10 @@ Error ShaderLanguage::_parse_block(BlockNode *p_block, const FunctionInfo &p_fun return ERR_PARSE_ERROR; } + if (precision != PRECISION_DEFAULT && _validate_precision(type, precision) != OK) { + return ERR_PARSE_ERROR; + } + int array_size = 0; bool fixed_array_size = false; bool first = true; @@ -6600,10 +6602,6 @@ Error ShaderLanguage::_parse_block(BlockNode *p_block, const FunctionInfo &p_fun if (is_token_precision(tk.type)) { precision2 = get_token_precision(tk.type); tk = _get_token(); - if (shader->structs.has(tk.text)) { - _set_error(RTR("The precision modifier cannot be used on structs.")); - return ERR_PARSE_ERROR; - } if (!is_token_nonvoid_datatype(tk.type)) { _set_error(RTR("Expected data type after precision modifier.")); return ERR_PARSE_ERROR; @@ -6624,6 +6622,10 @@ Error ShaderLanguage::_parse_block(BlockNode *p_block, const FunctionInfo &p_fun type2 = get_token_datatype(tk.type); } + if (precision2 != PRECISION_DEFAULT && _validate_precision(type2, precision2) != OK) { + return ERR_PARSE_ERROR; + } + int array_size2 = 0; tk = _get_token(); @@ -7427,6 +7429,25 @@ String ShaderLanguage::_get_qualifier_str(ArgumentQualifier p_qualifier) const { return ""; } +Error ShaderLanguage::_validate_precision(DataType p_type, DataPrecision p_precision) { + switch (p_type) { + case TYPE_STRUCT: { + _set_error(RTR("The precision modifier cannot be used on structs.")); + return FAILED; + } break; + case TYPE_BOOL: + case TYPE_BVEC2: + case TYPE_BVEC3: + case TYPE_BVEC4: { + _set_error(RTR("The precision modifier cannot be used on boolean types.")); + return FAILED; + } break; + default: + break; + } + return OK; +} + Error ShaderLanguage::_validate_datatype(DataType p_type) { if (RenderingServer::get_singleton()->is_low_end()) { bool invalid_type = false; @@ -7608,8 +7629,7 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct } StringName struct_name = ""; bool struct_dt = false; - bool use_precision = false; - DataPrecision precision = DataPrecision::PRECISION_DEFAULT; + DataPrecision precision = PRECISION_DEFAULT; if (tk.type == TK_STRUCT) { _set_error(RTR("Nested structs are not allowed.")); @@ -7618,7 +7638,6 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct if (is_token_precision(tk.type)) { precision = get_token_precision(tk.type); - use_precision = true; tk = _get_token(); } @@ -7630,10 +7649,6 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct } #endif // DEBUG_ENABLED struct_dt = true; - if (use_precision) { - _set_error(RTR("The precision modifier cannot be used on structs.")); - return ERR_PARSE_ERROR; - } } if (!is_token_datatype(tk.type) && !struct_dt) { @@ -7642,6 +7657,10 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct } else { type = struct_dt ? TYPE_STRUCT : get_token_datatype(tk.type); + if (precision != PRECISION_DEFAULT && _validate_precision(type, precision) != OK) { + return ERR_PARSE_ERROR; + } + if (type == TYPE_VOID || is_sampler_type(type)) { _set_error(vformat(RTR("A '%s' data type is not allowed here."), get_datatype_name(type))); return ERR_PARSE_ERROR; @@ -7762,7 +7781,6 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct } } - bool precision_defined = false; DataPrecision precision = PRECISION_DEFAULT; DataInterpolation interpolation = INTERPOLATION_SMOOTH; DataType type; @@ -7781,16 +7799,11 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct if (is_token_precision(tk.type)) { precision = get_token_precision(tk.type); - precision_defined = true; tk = _get_token(); } if (shader->structs.has(tk.text)) { if (uniform) { - if (precision_defined) { - _set_error(RTR("The precision modifier cannot be used on structs.")); - return ERR_PARSE_ERROR; - } _set_error(vformat(RTR("The '%s' data type is not supported for uniforms."), "struct")); return ERR_PARSE_ERROR; } else { @@ -7806,6 +7819,10 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct type = get_token_datatype(tk.type); + if (precision != PRECISION_DEFAULT && _validate_precision(type, precision) != OK) { + return ERR_PARSE_ERROR; + } + if (type == TYPE_VOID) { _set_error(vformat(RTR("The '%s' data type is not allowed here."), "void")); return ERR_PARSE_ERROR; @@ -8249,10 +8266,6 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct } if (shader->structs.has(tk.text)) { - if (precision != PRECISION_DEFAULT) { - _set_error(RTR("The precision modifier cannot be used on structs.")); - return ERR_PARSE_ERROR; - } is_struct = true; struct_name = tk.text; } else { @@ -8276,6 +8289,11 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct } else { type = get_token_datatype(tk.type); } + + if (precision != PRECISION_DEFAULT && _validate_precision(type, precision) != OK) { + return ERR_PARSE_ERROR; + } + prev_pos = _get_tkpos(); tk = _get_token(); @@ -8652,44 +8670,41 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct break; } - bool is_const = false; + bool param_is_const = false; if (tk.type == TK_CONST) { - is_const = true; + param_is_const = true; tk = _get_token(); } - ArgumentQualifier qualifier = ARGUMENT_QUALIFIER_IN; - + ArgumentQualifier param_qualifier = ARGUMENT_QUALIFIER_IN; if (tk.type == TK_ARG_IN) { - qualifier = ARGUMENT_QUALIFIER_IN; + param_qualifier = ARGUMENT_QUALIFIER_IN; tk = _get_token(); } else if (tk.type == TK_ARG_OUT) { - if (is_const) { + if (param_is_const) { _set_error(vformat(RTR("The '%s' qualifier cannot be used within a function parameter declared with '%s'."), "out", "const")); return ERR_PARSE_ERROR; } - qualifier = ARGUMENT_QUALIFIER_OUT; + param_qualifier = ARGUMENT_QUALIFIER_OUT; tk = _get_token(); } else if (tk.type == TK_ARG_INOUT) { - if (is_const) { + if (param_is_const) { _set_error(vformat(RTR("The '%s' qualifier cannot be used within a function parameter declared with '%s'."), "inout", "const")); return ERR_PARSE_ERROR; } - qualifier = ARGUMENT_QUALIFIER_INOUT; + param_qualifier = ARGUMENT_QUALIFIER_INOUT; tk = _get_token(); } - DataType ptype; - StringName pname; + DataType param_type; + StringName param_name; StringName param_struct_name; - DataPrecision pprecision = PRECISION_DEFAULT; - bool use_precision = false; + DataPrecision param_precision = PRECISION_DEFAULT; int arg_array_size = 0; if (is_token_precision(tk.type)) { - pprecision = get_token_precision(tk.type); + param_precision = get_token_precision(tk.type); tk = _get_token(); - use_precision = true; } is_struct = false; @@ -8702,10 +8717,6 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct used_structs[param_struct_name].used = true; } #endif // DEBUG_ENABLED - if (use_precision) { - _set_error(RTR("The precision modifier cannot be used on structs.")); - return ERR_PARSE_ERROR; - } } if (!is_struct && !is_token_datatype(tk.type)) { @@ -8713,7 +8724,7 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct return ERR_PARSE_ERROR; } - if (qualifier == ARGUMENT_QUALIFIER_OUT || qualifier == ARGUMENT_QUALIFIER_INOUT) { + if (param_qualifier == ARGUMENT_QUALIFIER_OUT || param_qualifier == ARGUMENT_QUALIFIER_INOUT) { if (is_sampler_type(get_token_datatype(tk.type))) { _set_error(RTR("Opaque types cannot be output parameters.")); return ERR_PARSE_ERROR; @@ -8721,18 +8732,22 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct } if (is_struct) { - ptype = TYPE_STRUCT; + param_type = TYPE_STRUCT; } else { - ptype = get_token_datatype(tk.type); - if (_validate_datatype(ptype) != OK) { + param_type = get_token_datatype(tk.type); + if (_validate_datatype(param_type) != OK) { return ERR_PARSE_ERROR; } - if (ptype == TYPE_VOID) { + if (param_type == TYPE_VOID) { _set_error(RTR("Void type not allowed as argument.")); return ERR_PARSE_ERROR; } } + if (param_precision != PRECISION_DEFAULT && _validate_precision(param_type, param_precision) != OK) { + return ERR_PARSE_ERROR; + } + tk = _get_token(); if (tk.type == TK_BRACKET_OPEN) { @@ -8747,32 +8762,32 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct return ERR_PARSE_ERROR; } - pname = tk.text; + param_name = tk.text; ShaderLanguage::IdentifierType itype; - if (_find_identifier(func_node->body, false, builtins, pname, (ShaderLanguage::DataType *)nullptr, &itype)) { + if (_find_identifier(func_node->body, false, builtins, param_name, (ShaderLanguage::DataType *)nullptr, &itype)) { if (itype != IDENTIFIER_FUNCTION) { - _set_redefinition_error(String(pname)); + _set_redefinition_error(String(param_name)); return ERR_PARSE_ERROR; } } - if (has_builtin(p_functions, pname)) { - _set_redefinition_error(String(pname)); + if (has_builtin(p_functions, param_name)) { + _set_redefinition_error(String(param_name)); return ERR_PARSE_ERROR; } FunctionNode::Argument arg; - arg.type = ptype; - arg.name = pname; + arg.type = param_type; + arg.name = param_name; arg.type_str = param_struct_name; - arg.precision = pprecision; - arg.qualifier = qualifier; + arg.precision = param_precision; + arg.qualifier = param_qualifier; arg.tex_argument_check = false; arg.tex_builtin_check = false; arg.tex_argument_filter = FILTER_DEFAULT; arg.tex_argument_repeat = REPEAT_DEFAULT; - arg.is_const = is_const; + arg.is_const = param_is_const; tk = _get_token(); if (tk.type == TK_BRACKET_OPEN) { diff --git a/servers/rendering/shader_language.h b/servers/rendering/shader_language.h index 66ae220edf..de6d912a4f 100644 --- a/servers/rendering/shader_language.h +++ b/servers/rendering/shader_language.h @@ -1038,6 +1038,7 @@ 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/tests/test_main.cpp b/tests/test_main.cpp index dc28a98c97..a059949105 100644 --- a/tests/test_main.cpp +++ b/tests/test_main.cpp @@ -160,10 +160,10 @@ struct GodotTestCaseListener : public doctest::IReporter { SignalWatcher *signal_watcher = nullptr; - PhysicsServer3D *physics_3d_server = nullptr; - PhysicsServer2D *physics_2d_server = nullptr; - NavigationServer3D *navigation_3d_server = nullptr; - NavigationServer2D *navigation_2d_server = nullptr; + PhysicsServer3D *physics_server_3d = nullptr; + PhysicsServer2D *physics_server_2d = nullptr; + NavigationServer3D *navigation_server_3d = nullptr; + NavigationServer2D *navigation_server_2d = nullptr; void test_case_start(const doctest::TestCaseData &p_in) override { SignalWatcher::get_singleton()->_clear_signals(); @@ -190,19 +190,19 @@ struct GodotTestCaseListener : public doctest::IReporter { RenderingServerDefault::get_singleton()->init(); RenderingServerDefault::get_singleton()->set_render_loop_enabled(false); - physics_3d_server = PhysicsServer3DManager::new_default_server(); - physics_3d_server->init(); + physics_server_3d = PhysicsServer3DManager::new_default_server(); + physics_server_3d->init(); - physics_2d_server = PhysicsServer2DManager::new_default_server(); - physics_2d_server->init(); + physics_server_2d = PhysicsServer2DManager::new_default_server(); + physics_server_2d->init(); - navigation_3d_server = NavigationServer3DManager::new_default_server(); - navigation_2d_server = memnew(NavigationServer2D); + navigation_server_3d = NavigationServer3DManager::new_default_server(); + navigation_server_2d = memnew(NavigationServer2D); memnew(InputMap); InputMap::get_singleton()->load_default(); - make_default_theme(1.0, Ref<Font>(), TextServer::SUBPIXEL_POSITIONING_AUTO, TextServer::HINTING_LIGHT, true); + make_default_theme(1.0, Ref<Font>()); memnew(SceneTree); SceneTree::get_singleton()->initialize(); @@ -225,26 +225,26 @@ struct GodotTestCaseListener : public doctest::IReporter { clear_default_theme(); - if (navigation_3d_server) { - memdelete(navigation_3d_server); - navigation_3d_server = nullptr; + if (navigation_server_3d) { + memdelete(navigation_server_3d); + navigation_server_3d = nullptr; } - if (navigation_2d_server) { - memdelete(navigation_2d_server); - navigation_2d_server = nullptr; + if (navigation_server_2d) { + memdelete(navigation_server_2d); + navigation_server_2d = nullptr; } - if (physics_3d_server) { - physics_3d_server->finish(); - memdelete(physics_3d_server); - physics_3d_server = nullptr; + if (physics_server_3d) { + physics_server_3d->finish(); + memdelete(physics_server_3d); + physics_server_3d = nullptr; } - if (physics_2d_server) { - physics_2d_server->finish(); - memdelete(physics_2d_server); - physics_2d_server = nullptr; + if (physics_server_2d) { + physics_server_2d->finish(); + memdelete(physics_server_2d); + physics_server_2d = nullptr; } if (Input::get_singleton()) { diff --git a/thirdparty/noise/FastNoiseLite.h b/thirdparty/noise/FastNoiseLite.h index 3db344c149..8015bf636a 100644 --- a/thirdparty/noise/FastNoiseLite.h +++ b/thirdparty/noise/FastNoiseLite.h @@ -295,7 +295,7 @@ public: /// Noise output bounded between -1...1 /// </returns> template <typename FNfloat> - float GetNoise(FNfloat x, FNfloat y) + float GetNoise(FNfloat x, FNfloat y) const { Arguments_must_be_floating_point_values<FNfloat>(); @@ -321,7 +321,7 @@ public: /// Noise output bounded between -1...1 /// </returns> template <typename FNfloat> - float GetNoise(FNfloat x, FNfloat y, FNfloat z) + float GetNoise(FNfloat x, FNfloat y, FNfloat z) const { Arguments_must_be_floating_point_values<FNfloat>(); @@ -350,7 +350,7 @@ public: /// noise = GetNoise(x, y)</code> /// </example> template <typename FNfloat> - void DomainWarp(FNfloat& x, FNfloat& y) + void DomainWarp(FNfloat& x, FNfloat& y) const { Arguments_must_be_floating_point_values<FNfloat>(); @@ -377,7 +377,7 @@ public: /// noise = GetNoise(x, y, z)</code> /// </example> template <typename FNfloat> - void DomainWarp(FNfloat& x, FNfloat& y, FNfloat& z) + void DomainWarp(FNfloat& x, FNfloat& y, FNfloat& z) const { Arguments_must_be_floating_point_values<FNfloat>(); @@ -528,7 +528,7 @@ private: } - float GradCoord(int seed, int xPrimed, int yPrimed, float xd, float yd) + float GradCoord(int seed, int xPrimed, int yPrimed, float xd, float yd) const { int hash = Hash(seed, xPrimed, yPrimed); hash ^= hash >> 15; @@ -541,7 +541,7 @@ private: } - float GradCoord(int seed, int xPrimed, int yPrimed, int zPrimed, float xd, float yd, float zd) + float GradCoord(int seed, int xPrimed, int yPrimed, int zPrimed, float xd, float yd, float zd) const { int hash = Hash(seed, xPrimed, yPrimed, zPrimed); hash ^= hash >> 15; @@ -555,7 +555,7 @@ private: } - void GradCoordOut(int seed, int xPrimed, int yPrimed, float& xo, float& yo) + void GradCoordOut(int seed, int xPrimed, int yPrimed, float& xo, float& yo) const { int hash = Hash(seed, xPrimed, yPrimed) & (255 << 1); @@ -564,7 +564,7 @@ private: } - void GradCoordOut(int seed, int xPrimed, int yPrimed, int zPrimed, float& xo, float& yo, float& zo) + void GradCoordOut(int seed, int xPrimed, int yPrimed, int zPrimed, float& xo, float& yo, float& zo) const { int hash = Hash(seed, xPrimed, yPrimed, zPrimed) & (255 << 2); @@ -574,7 +574,7 @@ private: } - void GradCoordDual(int seed, int xPrimed, int yPrimed, float xd, float yd, float& xo, float& yo) + void GradCoordDual(int seed, int xPrimed, int yPrimed, float xd, float yd, float& xo, float& yo) const { int hash = Hash(seed, xPrimed, yPrimed); int index1 = hash & (127 << 1); @@ -592,7 +592,7 @@ private: } - void GradCoordDual(int seed, int xPrimed, int yPrimed, int zPrimed, float xd, float yd, float zd, float& xo, float& yo, float& zo) + void GradCoordDual(int seed, int xPrimed, int yPrimed, int zPrimed, float xd, float yd, float zd, float& xo, float& yo, float& zo) const { int hash = Hash(seed, xPrimed, yPrimed, zPrimed); int index1 = hash & (63 << 2); @@ -616,7 +616,7 @@ private: // Generic noise gen template <typename FNfloat> - float GenNoiseSingle(int seed, FNfloat x, FNfloat y) + float GenNoiseSingle(int seed, FNfloat x, FNfloat y) const { switch (mNoiseType) { @@ -638,7 +638,7 @@ private: } template <typename FNfloat> - float GenNoiseSingle(int seed, FNfloat x, FNfloat y, FNfloat z) + float GenNoiseSingle(int seed, FNfloat x, FNfloat y, FNfloat z) const { switch (mNoiseType) { @@ -663,7 +663,7 @@ private: // Noise Coordinate Transforms (frequency, and possible skew or rotation) template <typename FNfloat> - void TransformNoiseCoordinate(FNfloat& x, FNfloat& y) + void TransformNoiseCoordinate(FNfloat& x, FNfloat& y) const { x *= mFrequency; y *= mFrequency; @@ -686,7 +686,7 @@ private: } template <typename FNfloat> - void TransformNoiseCoordinate(FNfloat& x, FNfloat& y, FNfloat& z) + void TransformNoiseCoordinate(FNfloat& x, FNfloat& y, FNfloat& z) const { x *= mFrequency; y *= mFrequency; @@ -757,7 +757,7 @@ private: // Domain Warp Coordinate Transforms template <typename FNfloat> - void TransformDomainWarpCoordinate(FNfloat& x, FNfloat& y) + void TransformDomainWarpCoordinate(FNfloat& x, FNfloat& y) const { switch (mDomainWarpType) { @@ -777,7 +777,7 @@ private: } template <typename FNfloat> - void TransformDomainWarpCoordinate(FNfloat& x, FNfloat& y, FNfloat& z) + void TransformDomainWarpCoordinate(FNfloat& x, FNfloat& y, FNfloat& z) const { switch (mWarpTransformType3D) { @@ -844,7 +844,7 @@ private: // Fractal FBm template <typename FNfloat> - float GenFractalFBm(FNfloat x, FNfloat y) + float GenFractalFBm(FNfloat x, FNfloat y) const { int seed = mSeed; float sum = 0; @@ -865,7 +865,7 @@ private: } template <typename FNfloat> - float GenFractalFBm(FNfloat x, FNfloat y, FNfloat z) + float GenFractalFBm(FNfloat x, FNfloat y, FNfloat z) const { int seed = mSeed; float sum = 0; @@ -890,7 +890,7 @@ private: // Fractal Ridged template <typename FNfloat> - float GenFractalRidged(FNfloat x, FNfloat y) + float GenFractalRidged(FNfloat x, FNfloat y) const { int seed = mSeed; float sum = 0; @@ -911,7 +911,7 @@ private: } template <typename FNfloat> - float GenFractalRidged(FNfloat x, FNfloat y, FNfloat z) + float GenFractalRidged(FNfloat x, FNfloat y, FNfloat z) const { int seed = mSeed; float sum = 0; @@ -936,7 +936,7 @@ private: // Fractal PingPong template <typename FNfloat> - float GenFractalPingPong(FNfloat x, FNfloat y) + float GenFractalPingPong(FNfloat x, FNfloat y) const { int seed = mSeed; float sum = 0; @@ -957,7 +957,7 @@ private: } template <typename FNfloat> - float GenFractalPingPong(FNfloat x, FNfloat y, FNfloat z) + float GenFractalPingPong(FNfloat x, FNfloat y, FNfloat z) const { int seed = mSeed; float sum = 0; @@ -982,7 +982,7 @@ private: // Simplex/OpenSimplex2 Noise template <typename FNfloat> - float SingleSimplex(int seed, FNfloat x, FNfloat y) + float SingleSimplex(int seed, FNfloat x, FNfloat y) const { // 2D OpenSimplex2 case uses the same algorithm as ordinary Simplex. @@ -1053,7 +1053,7 @@ private: } template <typename FNfloat> - float SingleOpenSimplex2(int seed, FNfloat x, FNfloat y, FNfloat z) + float SingleOpenSimplex2(int seed, FNfloat x, FNfloat y, FNfloat z) const { // 3D OpenSimplex2 case uses two offset rotated cube grids. @@ -1155,7 +1155,7 @@ private: // OpenSimplex2S Noise template <typename FNfloat> - float SingleOpenSimplex2S(int seed, FNfloat x, FNfloat y) + float SingleOpenSimplex2S(int seed, FNfloat x, FNfloat y) const { // 2D OpenSimplex2S case is a modified 2D simplex noise. @@ -1286,7 +1286,7 @@ private: } template <typename FNfloat> - float SingleOpenSimplex2S(int seed, FNfloat x, FNfloat y, FNfloat z) + float SingleOpenSimplex2S(int seed, FNfloat x, FNfloat y, FNfloat z) const { // 3D OpenSimplex2S case uses two offset rotated cube grids. @@ -1482,7 +1482,7 @@ private: // Cellular Noise template <typename FNfloat> - float SingleCellular(int seed, FNfloat x, FNfloat y) + float SingleCellular(int seed, FNfloat x, FNfloat y) const { int xr = FastRound(x); int yr = FastRound(y); @@ -1612,7 +1612,7 @@ private: } template <typename FNfloat> - float SingleCellular(int seed, FNfloat x, FNfloat y, FNfloat z) + float SingleCellular(int seed, FNfloat x, FNfloat y, FNfloat z) const { int xr = FastRound(x); int yr = FastRound(y); @@ -1769,7 +1769,7 @@ private: // Perlin Noise template <typename FNfloat> - float SinglePerlin(int seed, FNfloat x, FNfloat y) + float SinglePerlin(int seed, FNfloat x, FNfloat y) const { int x0 = FastFloor(x); int y0 = FastFloor(y); @@ -1794,7 +1794,7 @@ private: } template <typename FNfloat> - float SinglePerlin(int seed, FNfloat x, FNfloat y, FNfloat z) + float SinglePerlin(int seed, FNfloat x, FNfloat y, FNfloat z) const { int x0 = FastFloor(x); int y0 = FastFloor(y); @@ -1833,7 +1833,7 @@ private: // Value Cubic Noise template <typename FNfloat> - float SingleValueCubic(int seed, FNfloat x, FNfloat y) + float SingleValueCubic(int seed, FNfloat x, FNfloat y) const { int x1 = FastFloor(x); int y1 = FastFloor(y); @@ -1863,7 +1863,7 @@ private: } template <typename FNfloat> - float SingleValueCubic(int seed, FNfloat x, FNfloat y, FNfloat z) + float SingleValueCubic(int seed, FNfloat x, FNfloat y, FNfloat z) const { int x1 = FastFloor(x); int y1 = FastFloor(y); @@ -1920,7 +1920,7 @@ private: // Value Noise template <typename FNfloat> - float SingleValue(int seed, FNfloat x, FNfloat y) + float SingleValue(int seed, FNfloat x, FNfloat y) const { int x0 = FastFloor(x); int y0 = FastFloor(y); @@ -1940,7 +1940,7 @@ private: } template <typename FNfloat> - float SingleValue(int seed, FNfloat x, FNfloat y, FNfloat z) + float SingleValue(int seed, FNfloat x, FNfloat y, FNfloat z) const { int x0 = FastFloor(x); int y0 = FastFloor(y); @@ -1972,7 +1972,7 @@ private: // Domain Warp template <typename FNfloat> - void DoSingleDomainWarp(int seed, float amp, float freq, FNfloat x, FNfloat y, FNfloat& xr, FNfloat& yr) + void DoSingleDomainWarp(int seed, float amp, float freq, FNfloat x, FNfloat y, FNfloat& xr, FNfloat& yr) const { switch (mDomainWarpType) { @@ -1989,7 +1989,7 @@ private: } template <typename FNfloat> - void DoSingleDomainWarp(int seed, float amp, float freq, FNfloat x, FNfloat y, FNfloat z, FNfloat& xr, FNfloat& yr, FNfloat& zr) + void DoSingleDomainWarp(int seed, float amp, float freq, FNfloat x, FNfloat y, FNfloat z, FNfloat& xr, FNfloat& yr, FNfloat& zr) const { switch (mDomainWarpType) { @@ -2009,7 +2009,7 @@ private: // Domain Warp Single Wrapper template <typename FNfloat> - void DomainWarpSingle(FNfloat& x, FNfloat& y) + void DomainWarpSingle(FNfloat& x, FNfloat& y) const { int seed = mSeed; float amp = mDomainWarpAmp * mFractalBounding; @@ -2023,7 +2023,7 @@ private: } template <typename FNfloat> - void DomainWarpSingle(FNfloat& x, FNfloat& y, FNfloat& z) + void DomainWarpSingle(FNfloat& x, FNfloat& y, FNfloat& z) const { int seed = mSeed; float amp = mDomainWarpAmp * mFractalBounding; @@ -2041,7 +2041,7 @@ private: // Domain Warp Fractal Progressive template <typename FNfloat> - void DomainWarpFractalProgressive(FNfloat& x, FNfloat& y) + void DomainWarpFractalProgressive(FNfloat& x, FNfloat& y) const { int seed = mSeed; float amp = mDomainWarpAmp * mFractalBounding; @@ -2062,7 +2062,7 @@ private: } template <typename FNfloat> - void DomainWarpFractalProgressive(FNfloat& x, FNfloat& y, FNfloat& z) + void DomainWarpFractalProgressive(FNfloat& x, FNfloat& y, FNfloat& z) const { int seed = mSeed; float amp = mDomainWarpAmp * mFractalBounding; @@ -2087,7 +2087,7 @@ private: // Domain Warp Fractal Independant template <typename FNfloat> - void DomainWarpFractalIndependent(FNfloat& x, FNfloat& y) + void DomainWarpFractalIndependent(FNfloat& x, FNfloat& y) const { FNfloat xs = x; FNfloat ys = y; @@ -2108,7 +2108,7 @@ private: } template <typename FNfloat> - void DomainWarpFractalIndependent(FNfloat& x, FNfloat& y, FNfloat& z) + void DomainWarpFractalIndependent(FNfloat& x, FNfloat& y, FNfloat& z) const { FNfloat xs = x; FNfloat ys = y; @@ -2133,7 +2133,7 @@ private: // Domain Warp Basic Grid template <typename FNfloat> - void SingleDomainWarpBasicGrid(int seed, float warpAmp, float frequency, FNfloat x, FNfloat y, FNfloat& xr, FNfloat& yr) + void SingleDomainWarpBasicGrid(int seed, float warpAmp, float frequency, FNfloat x, FNfloat y, FNfloat& xr, FNfloat& yr) const { FNfloat xf = x * frequency; FNfloat yf = y * frequency; @@ -2166,7 +2166,7 @@ private: } template <typename FNfloat> - void SingleDomainWarpBasicGrid(int seed, float warpAmp, float frequency, FNfloat x, FNfloat y, FNfloat z, FNfloat& xr, FNfloat& yr, FNfloat& zr) + void SingleDomainWarpBasicGrid(int seed, float warpAmp, float frequency, FNfloat x, FNfloat y, FNfloat z, FNfloat& xr, FNfloat& yr, FNfloat& zr) const { FNfloat xf = x * frequency; FNfloat yf = y * frequency; @@ -2228,7 +2228,7 @@ private: // Domain Warp Simplex/OpenSimplex2 template <typename FNfloat> - void SingleDomainWarpSimplexGradient(int seed, float warpAmp, float frequency, FNfloat x, FNfloat y, FNfloat& xr, FNfloat& yr, bool outGradOnly) + void SingleDomainWarpSimplexGradient(int seed, float warpAmp, float frequency, FNfloat x, FNfloat y, FNfloat& xr, FNfloat& yr, bool outGradOnly) const { const float SQRT3 = 1.7320508075688772935274463415059f; const float G2 = (3 - SQRT3) / 6; @@ -2326,7 +2326,7 @@ private: } template <typename FNfloat> - void SingleDomainWarpOpenSimplex2Gradient(int seed, float warpAmp, float frequency, FNfloat x, FNfloat y, FNfloat z, FNfloat& xr, FNfloat& yr, FNfloat& zr, bool outGradOnly) + void SingleDomainWarpOpenSimplex2Gradient(int seed, float warpAmp, float frequency, FNfloat x, FNfloat y, FNfloat z, FNfloat& xr, FNfloat& yr, FNfloat& zr, bool outGradOnly) const { x *= frequency; y *= frequency; diff --git a/thirdparty/noise/patches/FastNoiseLite.patch b/thirdparty/noise/patches/FastNoiseLite.patch index acb1edfd73..41ec943077 100644 --- a/thirdparty/noise/patches/FastNoiseLite.patch +++ b/thirdparty/noise/patches/FastNoiseLite.patch @@ -16,3 +16,417 @@ -#endif +} +#endif // namespace fastnoiselite +@@ -295,7 +295,7 @@ public: + /// Noise output bounded between -1...1 + /// </returns> + template <typename FNfloat> +- float GetNoise(FNfloat x, FNfloat y) ++ float GetNoise(FNfloat x, FNfloat y) const + { + Arguments_must_be_floating_point_values<FNfloat>(); + +@@ -321,7 +321,7 @@ public: + /// Noise output bounded between -1...1 + /// </returns> + template <typename FNfloat> +- float GetNoise(FNfloat x, FNfloat y, FNfloat z) ++ float GetNoise(FNfloat x, FNfloat y, FNfloat z) const + { + Arguments_must_be_floating_point_values<FNfloat>(); + +@@ -350,7 +350,7 @@ public: + /// noise = GetNoise(x, y)</code> + /// </example> + template <typename FNfloat> +- void DomainWarp(FNfloat& x, FNfloat& y) ++ void DomainWarp(FNfloat& x, FNfloat& y) const + { + Arguments_must_be_floating_point_values<FNfloat>(); + +@@ -377,7 +377,7 @@ public: + /// noise = GetNoise(x, y, z)</code> + /// </example> + template <typename FNfloat> +- void DomainWarp(FNfloat& x, FNfloat& y, FNfloat& z) ++ void DomainWarp(FNfloat& x, FNfloat& y, FNfloat& z) const + { + Arguments_must_be_floating_point_values<FNfloat>(); + +@@ -528,7 +528,7 @@ private: + } + + +- float GradCoord(int seed, int xPrimed, int yPrimed, float xd, float yd) ++ float GradCoord(int seed, int xPrimed, int yPrimed, float xd, float yd) const + { + int hash = Hash(seed, xPrimed, yPrimed); + hash ^= hash >> 15; +@@ -541,7 +541,7 @@ private: + } + + +- float GradCoord(int seed, int xPrimed, int yPrimed, int zPrimed, float xd, float yd, float zd) ++ float GradCoord(int seed, int xPrimed, int yPrimed, int zPrimed, float xd, float yd, float zd) const + { + int hash = Hash(seed, xPrimed, yPrimed, zPrimed); + hash ^= hash >> 15; +@@ -555,7 +555,7 @@ private: + } + + +- void GradCoordOut(int seed, int xPrimed, int yPrimed, float& xo, float& yo) ++ void GradCoordOut(int seed, int xPrimed, int yPrimed, float& xo, float& yo) const + { + int hash = Hash(seed, xPrimed, yPrimed) & (255 << 1); + +@@ -564,7 +564,7 @@ private: + } + + +- void GradCoordOut(int seed, int xPrimed, int yPrimed, int zPrimed, float& xo, float& yo, float& zo) ++ void GradCoordOut(int seed, int xPrimed, int yPrimed, int zPrimed, float& xo, float& yo, float& zo) const + { + int hash = Hash(seed, xPrimed, yPrimed, zPrimed) & (255 << 2); + +@@ -574,7 +574,7 @@ private: + } + + +- void GradCoordDual(int seed, int xPrimed, int yPrimed, float xd, float yd, float& xo, float& yo) ++ void GradCoordDual(int seed, int xPrimed, int yPrimed, float xd, float yd, float& xo, float& yo) const + { + int hash = Hash(seed, xPrimed, yPrimed); + int index1 = hash & (127 << 1); +@@ -592,7 +592,7 @@ private: + } + + +- void GradCoordDual(int seed, int xPrimed, int yPrimed, int zPrimed, float xd, float yd, float zd, float& xo, float& yo, float& zo) ++ void GradCoordDual(int seed, int xPrimed, int yPrimed, int zPrimed, float xd, float yd, float zd, float& xo, float& yo, float& zo) const + { + int hash = Hash(seed, xPrimed, yPrimed, zPrimed); + int index1 = hash & (63 << 2); +@@ -616,7 +616,7 @@ private: + // Generic noise gen + + template <typename FNfloat> +- float GenNoiseSingle(int seed, FNfloat x, FNfloat y) ++ float GenNoiseSingle(int seed, FNfloat x, FNfloat y) const + { + switch (mNoiseType) + { +@@ -638,7 +638,7 @@ private: + } + + template <typename FNfloat> +- float GenNoiseSingle(int seed, FNfloat x, FNfloat y, FNfloat z) ++ float GenNoiseSingle(int seed, FNfloat x, FNfloat y, FNfloat z) const + { + switch (mNoiseType) + { +@@ -663,7 +663,7 @@ private: + // Noise Coordinate Transforms (frequency, and possible skew or rotation) + + template <typename FNfloat> +- void TransformNoiseCoordinate(FNfloat& x, FNfloat& y) ++ void TransformNoiseCoordinate(FNfloat& x, FNfloat& y) const + { + x *= mFrequency; + y *= mFrequency; +@@ -686,7 +686,7 @@ private: + } + + template <typename FNfloat> +- void TransformNoiseCoordinate(FNfloat& x, FNfloat& y, FNfloat& z) ++ void TransformNoiseCoordinate(FNfloat& x, FNfloat& y, FNfloat& z) const + { + x *= mFrequency; + y *= mFrequency; +@@ -757,7 +757,7 @@ private: + // Domain Warp Coordinate Transforms + + template <typename FNfloat> +- void TransformDomainWarpCoordinate(FNfloat& x, FNfloat& y) ++ void TransformDomainWarpCoordinate(FNfloat& x, FNfloat& y) const + { + switch (mDomainWarpType) + { +@@ -777,7 +777,7 @@ private: + } + + template <typename FNfloat> +- void TransformDomainWarpCoordinate(FNfloat& x, FNfloat& y, FNfloat& z) ++ void TransformDomainWarpCoordinate(FNfloat& x, FNfloat& y, FNfloat& z) const + { + switch (mWarpTransformType3D) + { +@@ -844,7 +844,7 @@ private: + // Fractal FBm + + template <typename FNfloat> +- float GenFractalFBm(FNfloat x, FNfloat y) ++ float GenFractalFBm(FNfloat x, FNfloat y) const + { + int seed = mSeed; + float sum = 0; +@@ -865,7 +865,7 @@ private: + } + + template <typename FNfloat> +- float GenFractalFBm(FNfloat x, FNfloat y, FNfloat z) ++ float GenFractalFBm(FNfloat x, FNfloat y, FNfloat z) const + { + int seed = mSeed; + float sum = 0; +@@ -890,7 +890,7 @@ private: + // Fractal Ridged + + template <typename FNfloat> +- float GenFractalRidged(FNfloat x, FNfloat y) ++ float GenFractalRidged(FNfloat x, FNfloat y) const + { + int seed = mSeed; + float sum = 0; +@@ -911,7 +911,7 @@ private: + } + + template <typename FNfloat> +- float GenFractalRidged(FNfloat x, FNfloat y, FNfloat z) ++ float GenFractalRidged(FNfloat x, FNfloat y, FNfloat z) const + { + int seed = mSeed; + float sum = 0; +@@ -936,7 +936,7 @@ private: + // Fractal PingPong + + template <typename FNfloat> +- float GenFractalPingPong(FNfloat x, FNfloat y) ++ float GenFractalPingPong(FNfloat x, FNfloat y) const + { + int seed = mSeed; + float sum = 0; +@@ -957,7 +957,7 @@ private: + } + + template <typename FNfloat> +- float GenFractalPingPong(FNfloat x, FNfloat y, FNfloat z) ++ float GenFractalPingPong(FNfloat x, FNfloat y, FNfloat z) const + { + int seed = mSeed; + float sum = 0; +@@ -982,7 +982,7 @@ private: + // Simplex/OpenSimplex2 Noise + + template <typename FNfloat> +- float SingleSimplex(int seed, FNfloat x, FNfloat y) ++ float SingleSimplex(int seed, FNfloat x, FNfloat y) const + { + // 2D OpenSimplex2 case uses the same algorithm as ordinary Simplex. + +@@ -1053,7 +1053,7 @@ private: + } + + template <typename FNfloat> +- float SingleOpenSimplex2(int seed, FNfloat x, FNfloat y, FNfloat z) ++ float SingleOpenSimplex2(int seed, FNfloat x, FNfloat y, FNfloat z) const + { + // 3D OpenSimplex2 case uses two offset rotated cube grids. + +@@ -1155,7 +1155,7 @@ private: + // OpenSimplex2S Noise + + template <typename FNfloat> +- float SingleOpenSimplex2S(int seed, FNfloat x, FNfloat y) ++ float SingleOpenSimplex2S(int seed, FNfloat x, FNfloat y) const + { + // 2D OpenSimplex2S case is a modified 2D simplex noise. + +@@ -1286,7 +1286,7 @@ private: + } + + template <typename FNfloat> +- float SingleOpenSimplex2S(int seed, FNfloat x, FNfloat y, FNfloat z) ++ float SingleOpenSimplex2S(int seed, FNfloat x, FNfloat y, FNfloat z) const + { + // 3D OpenSimplex2S case uses two offset rotated cube grids. + +@@ -1482,7 +1482,7 @@ private: + // Cellular Noise + + template <typename FNfloat> +- float SingleCellular(int seed, FNfloat x, FNfloat y) ++ float SingleCellular(int seed, FNfloat x, FNfloat y) const + { + int xr = FastRound(x); + int yr = FastRound(y); +@@ -1612,7 +1612,7 @@ private: + } + + template <typename FNfloat> +- float SingleCellular(int seed, FNfloat x, FNfloat y, FNfloat z) ++ float SingleCellular(int seed, FNfloat x, FNfloat y, FNfloat z) const + { + int xr = FastRound(x); + int yr = FastRound(y); +@@ -1769,7 +1769,7 @@ private: + // Perlin Noise + + template <typename FNfloat> +- float SinglePerlin(int seed, FNfloat x, FNfloat y) ++ float SinglePerlin(int seed, FNfloat x, FNfloat y) const + { + int x0 = FastFloor(x); + int y0 = FastFloor(y); +@@ -1794,7 +1794,7 @@ private: + } + + template <typename FNfloat> +- float SinglePerlin(int seed, FNfloat x, FNfloat y, FNfloat z) ++ float SinglePerlin(int seed, FNfloat x, FNfloat y, FNfloat z) const + { + int x0 = FastFloor(x); + int y0 = FastFloor(y); +@@ -1833,7 +1833,7 @@ private: + // Value Cubic Noise + + template <typename FNfloat> +- float SingleValueCubic(int seed, FNfloat x, FNfloat y) ++ float SingleValueCubic(int seed, FNfloat x, FNfloat y) const + { + int x1 = FastFloor(x); + int y1 = FastFloor(y); +@@ -1863,7 +1863,7 @@ private: + } + + template <typename FNfloat> +- float SingleValueCubic(int seed, FNfloat x, FNfloat y, FNfloat z) ++ float SingleValueCubic(int seed, FNfloat x, FNfloat y, FNfloat z) const + { + int x1 = FastFloor(x); + int y1 = FastFloor(y); +@@ -1920,7 +1920,7 @@ private: + // Value Noise + + template <typename FNfloat> +- float SingleValue(int seed, FNfloat x, FNfloat y) ++ float SingleValue(int seed, FNfloat x, FNfloat y) const + { + int x0 = FastFloor(x); + int y0 = FastFloor(y); +@@ -1940,7 +1940,7 @@ private: + } + + template <typename FNfloat> +- float SingleValue(int seed, FNfloat x, FNfloat y, FNfloat z) ++ float SingleValue(int seed, FNfloat x, FNfloat y, FNfloat z) const + { + int x0 = FastFloor(x); + int y0 = FastFloor(y); +@@ -1972,7 +1972,7 @@ private: + // Domain Warp + + template <typename FNfloat> +- void DoSingleDomainWarp(int seed, float amp, float freq, FNfloat x, FNfloat y, FNfloat& xr, FNfloat& yr) ++ void DoSingleDomainWarp(int seed, float amp, float freq, FNfloat x, FNfloat y, FNfloat& xr, FNfloat& yr) const + { + switch (mDomainWarpType) + { +@@ -1989,7 +1989,7 @@ private: + } + + template <typename FNfloat> +- void DoSingleDomainWarp(int seed, float amp, float freq, FNfloat x, FNfloat y, FNfloat z, FNfloat& xr, FNfloat& yr, FNfloat& zr) ++ void DoSingleDomainWarp(int seed, float amp, float freq, FNfloat x, FNfloat y, FNfloat z, FNfloat& xr, FNfloat& yr, FNfloat& zr) const + { + switch (mDomainWarpType) + { +@@ -2009,7 +2009,7 @@ private: + // Domain Warp Single Wrapper + + template <typename FNfloat> +- void DomainWarpSingle(FNfloat& x, FNfloat& y) ++ void DomainWarpSingle(FNfloat& x, FNfloat& y) const + { + int seed = mSeed; + float amp = mDomainWarpAmp * mFractalBounding; +@@ -2023,7 +2023,7 @@ private: + } + + template <typename FNfloat> +- void DomainWarpSingle(FNfloat& x, FNfloat& y, FNfloat& z) ++ void DomainWarpSingle(FNfloat& x, FNfloat& y, FNfloat& z) const + { + int seed = mSeed; + float amp = mDomainWarpAmp * mFractalBounding; +@@ -2041,7 +2041,7 @@ private: + // Domain Warp Fractal Progressive + + template <typename FNfloat> +- void DomainWarpFractalProgressive(FNfloat& x, FNfloat& y) ++ void DomainWarpFractalProgressive(FNfloat& x, FNfloat& y) const + { + int seed = mSeed; + float amp = mDomainWarpAmp * mFractalBounding; +@@ -2062,7 +2062,7 @@ private: + } + + template <typename FNfloat> +- void DomainWarpFractalProgressive(FNfloat& x, FNfloat& y, FNfloat& z) ++ void DomainWarpFractalProgressive(FNfloat& x, FNfloat& y, FNfloat& z) const + { + int seed = mSeed; + float amp = mDomainWarpAmp * mFractalBounding; +@@ -2087,7 +2087,7 @@ private: + // Domain Warp Fractal Independant + + template <typename FNfloat> +- void DomainWarpFractalIndependent(FNfloat& x, FNfloat& y) ++ void DomainWarpFractalIndependent(FNfloat& x, FNfloat& y) const + { + FNfloat xs = x; + FNfloat ys = y; +@@ -2108,7 +2108,7 @@ private: + } + + template <typename FNfloat> +- void DomainWarpFractalIndependent(FNfloat& x, FNfloat& y, FNfloat& z) ++ void DomainWarpFractalIndependent(FNfloat& x, FNfloat& y, FNfloat& z) const + { + FNfloat xs = x; + FNfloat ys = y; +@@ -2133,7 +2133,7 @@ private: + // Domain Warp Basic Grid + + template <typename FNfloat> +- void SingleDomainWarpBasicGrid(int seed, float warpAmp, float frequency, FNfloat x, FNfloat y, FNfloat& xr, FNfloat& yr) ++ void SingleDomainWarpBasicGrid(int seed, float warpAmp, float frequency, FNfloat x, FNfloat y, FNfloat& xr, FNfloat& yr) const + { + FNfloat xf = x * frequency; + FNfloat yf = y * frequency; +@@ -2166,7 +2166,7 @@ private: + } + + template <typename FNfloat> +- void SingleDomainWarpBasicGrid(int seed, float warpAmp, float frequency, FNfloat x, FNfloat y, FNfloat z, FNfloat& xr, FNfloat& yr, FNfloat& zr) ++ void SingleDomainWarpBasicGrid(int seed, float warpAmp, float frequency, FNfloat x, FNfloat y, FNfloat z, FNfloat& xr, FNfloat& yr, FNfloat& zr) const + { + FNfloat xf = x * frequency; + FNfloat yf = y * frequency; +@@ -2228,7 +2228,7 @@ private: + // Domain Warp Simplex/OpenSimplex2 + + template <typename FNfloat> +- void SingleDomainWarpSimplexGradient(int seed, float warpAmp, float frequency, FNfloat x, FNfloat y, FNfloat& xr, FNfloat& yr, bool outGradOnly) ++ void SingleDomainWarpSimplexGradient(int seed, float warpAmp, float frequency, FNfloat x, FNfloat y, FNfloat& xr, FNfloat& yr, bool outGradOnly) const + { + const float SQRT3 = 1.7320508075688772935274463415059f; + const float G2 = (3 - SQRT3) / 6; +@@ -2326,7 +2326,7 @@ private: + } + + template <typename FNfloat> +- void SingleDomainWarpOpenSimplex2Gradient(int seed, float warpAmp, float frequency, FNfloat x, FNfloat y, FNfloat z, FNfloat& xr, FNfloat& yr, FNfloat& zr, bool outGradOnly) ++ void SingleDomainWarpOpenSimplex2Gradient(int seed, float warpAmp, float frequency, FNfloat x, FNfloat y, FNfloat z, FNfloat& xr, FNfloat& yr, FNfloat& zr, bool outGradOnly) const + { + x *= frequency; + y *= frequency; |