diff options
111 files changed, 2421 insertions, 2586 deletions
diff --git a/COPYRIGHT.txt b/COPYRIGHT.txt index 4ba80941e0..49c602eb84 100644 --- a/COPYRIGHT.txt +++ b/COPYRIGHT.txt @@ -10,8 +10,9 @@ # all corresponding files (also recursively in subfolders), apart from those # with a more explicit copyright statement. # -# Licenses are given with their SPDX identifier, and are all included in -# plain text at the end of this file (in alphabetical order). +# Licenses are given with their debian/copyright short name (or SPDX identifier +# if no standard short name exists) and are all included in plain text at the +# end of this file (in alphabetical order). # # Disclaimer for thirdparty libraries: # ------------------------------------ @@ -139,7 +140,7 @@ Files: ./thirdparty/cvtt/ Comment: Convection Texture Tools Stand-Alone Kernels Copyright: 2018, Eric Lasota 2018, Microsoft Corp. -License: MIT +License: Expat Files: ./thirdparty/enet/ Comment: ENet @@ -373,7 +374,7 @@ Files: ./thirdparty/tinyexr/ Comment: TinyEXR Copyright: 2014-2017, Syoyo Fujita 2002, Industrial Light & Magic, a division of Lucas Digital Ltd. LLC -License: BSD-3-Clause +License: BSD-3-clause Files: ./thirdparty/zlib/ Comment: zlib @@ -383,7 +384,7 @@ License: Zlib Files: ./thirdparty/zstd/ Comment: Zstandard Copyright: 2016-2018, Facebook, Inc. -License: BSD-3-Clause +License: BSD-3-clause diff --git a/core/io/resource_loader.cpp b/core/io/resource_loader.cpp index c01aff9144..66dc9730c5 100644 --- a/core/io/resource_loader.cpp +++ b/core/io/resource_loader.cpp @@ -202,12 +202,32 @@ RES ResourceLoader::load(const String &p_path, const String &p_type_hint, bool p else local_path = ProjectSettings::get_singleton()->localize_path(p_path); - if (!p_no_cache && ResourceCache::has(local_path)) { + if (!p_no_cache) { + //lock first if possible + if (ResourceCache::lock) { + ResourceCache::lock->read_lock(); + } - print_verbose("Loading resource: " + local_path + " (cached)"); - if (r_error) - *r_error = OK; - return RES(ResourceCache::get(local_path)); + //get ptr + Resource **rptr = ResourceCache::resources.getptr(local_path); + + if (rptr) { + RES res(*rptr); + //it is possible this resource was just freed in a thread. If so, this referencing will not work and resource is considered not cached + if (res.is_valid()) { + //referencing is fine + if (r_error) + *r_error = OK; + if (ResourceCache::lock) { + ResourceCache::lock->read_unlock(); + } + print_verbose("Loading resource: " + local_path + " (cached)"); + return res; + } + } + if (ResourceCache::lock) { + ResourceCache::lock->read_unlock(); + } } bool xl_remapped = false; diff --git a/core/os/main_loop.cpp b/core/os/main_loop.cpp index c51801e3e2..6dba77ec9a 100644 --- a/core/os/main_loop.cpp +++ b/core/os/main_loop.cpp @@ -33,14 +33,14 @@ void MainLoop::_bind_methods() { - ClassDB::bind_method(D_METHOD("input_event", "ev"), &MainLoop::input_event); + ClassDB::bind_method(D_METHOD("input_event", "event"), &MainLoop::input_event); ClassDB::bind_method(D_METHOD("input_text", "text"), &MainLoop::input_text); ClassDB::bind_method(D_METHOD("init"), &MainLoop::init); ClassDB::bind_method(D_METHOD("iteration", "delta"), &MainLoop::iteration); ClassDB::bind_method(D_METHOD("idle", "delta"), &MainLoop::idle); ClassDB::bind_method(D_METHOD("finish"), &MainLoop::finish); - BIND_VMETHOD(MethodInfo("_input_event", PropertyInfo(Variant::OBJECT, "ev", PROPERTY_HINT_RESOURCE_TYPE, "InputEvent"))); + BIND_VMETHOD(MethodInfo("_input_event", PropertyInfo(Variant::OBJECT, "event", PROPERTY_HINT_RESOURCE_TYPE, "InputEvent"))); BIND_VMETHOD(MethodInfo("_input_text", PropertyInfo(Variant::STRING, "text"))); BIND_VMETHOD(MethodInfo("_initialize")); BIND_VMETHOD(MethodInfo("_iteration", PropertyInfo(Variant::REAL, "delta"))); diff --git a/core/os/os.cpp b/core/os/os.cpp index e90d714450..0e6251a4fb 100644 --- a/core/os/os.cpp +++ b/core/os/os.cpp @@ -632,10 +632,13 @@ void OS::center_window() { if (is_window_fullscreen()) return; + Point2 sp = get_screen_position(get_current_screen()); Size2 scr = get_screen_size(get_current_screen()); Size2 wnd = get_real_window_size(); - int x = scr.width / 2 - wnd.width / 2; - int y = scr.height / 2 - wnd.height / 2; + + int x = sp.width + (scr.width - wnd.width) / 2; + int y = sp.height + (scr.height - wnd.height) / 2; + set_window_position(Vector2(x, y)); } diff --git a/core/resource.cpp b/core/resource.cpp index 3078eb135a..f447f785b1 100644 --- a/core/resource.cpp +++ b/core/resource.cpp @@ -230,7 +230,7 @@ Ref<Resource> Resource::duplicate(bool p_subresources) const { Variant p = get(E->get().name); if ((p.get_type() == Variant::DICTIONARY || p.get_type() == Variant::ARRAY)) { - p = p.duplicate(p_subresources); //does not make a long of sense but should work? + r->set(E->get().name, p.duplicate(p_subresources)); } else if (p.get_type() == Variant::OBJECT && (p_subresources || (E->get().usage & PROPERTY_USAGE_DO_NOT_SHARE_ON_DUPLICATE))) { RES sr = p; diff --git a/doc/classes/@GlobalScope.xml b/doc/classes/@GlobalScope.xml index d2c6a853ad..5a53e7cb05 100644 --- a/doc/classes/@GlobalScope.xml +++ b/doc/classes/@GlobalScope.xml @@ -29,6 +29,8 @@ <member name="Geometry" type="Geometry" setter="" getter=""> [Geometry] singleton </member> + <member name="GodotSharp" type="GodotSharp" setter="" getter=""> + </member> <member name="IP" type="IP" setter="" getter=""> [IP] singleton </member> diff --git a/doc/classes/Area.xml b/doc/classes/Area.xml index 5c56b5e21b..970d09a2ac 100644 --- a/doc/classes/Area.xml +++ b/doc/classes/Area.xml @@ -142,14 +142,14 @@ </members> <signals> <signal name="area_entered"> - <argument index="0" name="area" type="Object"> + <argument index="0" name="area" type="Area"> </argument> <description> Emitted when another area enters. </description> </signal> <signal name="area_exited"> - <argument index="0" name="area" type="Object"> + <argument index="0" name="area" type="Area"> </argument> <description> Emitted when another area exits. @@ -158,7 +158,7 @@ <signal name="area_shape_entered"> <argument index="0" name="area_id" type="int"> </argument> - <argument index="1" name="area" type="Object"> + <argument index="1" name="area" type="Area"> </argument> <argument index="2" name="area_shape" type="int"> </argument> @@ -171,7 +171,7 @@ <signal name="area_shape_exited"> <argument index="0" name="area_id" type="int"> </argument> - <argument index="1" name="area" type="Object"> + <argument index="1" name="area" type="Area"> </argument> <argument index="2" name="area_shape" type="int"> </argument> @@ -182,14 +182,14 @@ </description> </signal> <signal name="body_entered"> - <argument index="0" name="body" type="Object"> + <argument index="0" name="body" type="Node"> </argument> <description> Emitted when a [PhysicsBody] object enters. </description> </signal> <signal name="body_exited"> - <argument index="0" name="body" type="Object"> + <argument index="0" name="body" type="Node"> </argument> <description> Emitted when a [PhysicsBody] object exits. @@ -198,7 +198,7 @@ <signal name="body_shape_entered"> <argument index="0" name="body_id" type="int"> </argument> - <argument index="1" name="body" type="Object"> + <argument index="1" name="body" type="Node"> </argument> <argument index="2" name="body_shape" type="int"> </argument> @@ -211,7 +211,7 @@ <signal name="body_shape_exited"> <argument index="0" name="body_id" type="int"> </argument> - <argument index="1" name="body" type="Object"> + <argument index="1" name="body" type="Node"> </argument> <argument index="2" name="body_shape" type="int"> </argument> diff --git a/doc/classes/Area2D.xml b/doc/classes/Area2D.xml index c50ccefc4c..b77a931201 100644 --- a/doc/classes/Area2D.xml +++ b/doc/classes/Area2D.xml @@ -130,14 +130,14 @@ </members> <signals> <signal name="area_entered"> - <argument index="0" name="area" type="Object"> + <argument index="0" name="area" type="Area2D"> </argument> <description> Emitted when another area enters. </description> </signal> <signal name="area_exited"> - <argument index="0" name="area" type="Object"> + <argument index="0" name="area" type="Area2D"> </argument> <description> Emitted when another area exits. @@ -146,7 +146,7 @@ <signal name="area_shape_entered"> <argument index="0" name="area_id" type="int"> </argument> - <argument index="1" name="area" type="Object"> + <argument index="1" name="area" type="Area2D"> </argument> <argument index="2" name="area_shape" type="int"> </argument> @@ -159,7 +159,7 @@ <signal name="area_shape_exited"> <argument index="0" name="area_id" type="int"> </argument> - <argument index="1" name="area" type="Object"> + <argument index="1" name="area" type="Area2D"> </argument> <argument index="2" name="area_shape" type="int"> </argument> @@ -170,14 +170,14 @@ </description> </signal> <signal name="body_entered"> - <argument index="0" name="body" type="Object"> + <argument index="0" name="body" type="PhysicsBody2D"> </argument> <description> Emitted when a [PhysicsBody2D] object enters. </description> </signal> <signal name="body_exited"> - <argument index="0" name="body" type="Object"> + <argument index="0" name="body" type="PhysicsBody2D"> </argument> <description> Emitted when a [PhysicsBody2D] object exits. @@ -186,7 +186,7 @@ <signal name="body_shape_entered"> <argument index="0" name="body_id" type="int"> </argument> - <argument index="1" name="body" type="Object"> + <argument index="1" name="body" type="PhysicsBody2D"> </argument> <argument index="2" name="body_shape" type="int"> </argument> @@ -199,7 +199,7 @@ <signal name="body_shape_exited"> <argument index="0" name="body_id" type="int"> </argument> - <argument index="1" name="body" type="Object"> + <argument index="1" name="body" type="PhysicsBody2D"> </argument> <argument index="2" name="body_shape" type="int"> </argument> diff --git a/doc/classes/Array.xml b/doc/classes/Array.xml index 162e2d3e05..7097fd8bf0 100644 --- a/doc/classes/Array.xml +++ b/doc/classes/Array.xml @@ -84,14 +84,14 @@ </description> </method> <method name="append"> - <argument index="0" name="value" type="var"> + <argument index="0" name="value" type="Variant"> </argument> <description> Append an element at the end of the array (alias of [method push_back]). </description> </method> <method name="back"> - <return type="var"> + <return type="Variant"> </return> <description> Returns the last element of the array if the array is not empty (size>0). @@ -100,7 +100,7 @@ <method name="bsearch"> <return type="int"> </return> - <argument index="0" name="value" type="var"> + <argument index="0" name="value" type="Variant"> </argument> <argument index="1" name="before" type="bool" default="True"> </argument> @@ -111,7 +111,7 @@ <method name="bsearch_custom"> <return type="int"> </return> - <argument index="0" name="value" type="var"> + <argument index="0" name="value" type="Variant"> </argument> <argument index="1" name="obj" type="Object"> </argument> @@ -131,7 +131,7 @@ <method name="count"> <return type="int"> </return> - <argument index="0" name="value" type="var"> + <argument index="0" name="value" type="Variant"> </argument> <description> Return the amount of times an element is in the array. @@ -155,7 +155,7 @@ </description> </method> <method name="erase"> - <argument index="0" name="value" type="var"> + <argument index="0" name="value" type="Variant"> </argument> <description> Remove the first occurrence of a value from the array. @@ -164,7 +164,7 @@ <method name="find"> <return type="int"> </return> - <argument index="0" name="what" type="var"> + <argument index="0" name="what" type="Variant"> </argument> <argument index="1" name="from" type="int" default="0"> </argument> @@ -175,14 +175,14 @@ <method name="find_last"> <return type="int"> </return> - <argument index="0" name="value" type="var"> + <argument index="0" name="value" type="Variant"> </argument> <description> Searches the array in reverse order for a value and returns its index or -1 if not found. </description> </method> <method name="front"> - <return type="var"> + <return type="Variant"> </return> <description> Returns the first element of the array if the array is not empty (size>0). @@ -191,7 +191,7 @@ <method name="has"> <return type="bool"> </return> - <argument index="0" name="value" type="var"> + <argument index="0" name="value" type="Variant"> </argument> <description> Return true if the array contains given value. @@ -213,7 +213,7 @@ <method name="insert"> <argument index="0" name="position" type="int"> </argument> - <argument index="1" name="value" type="var"> + <argument index="1" name="value" type="Variant"> </argument> <description> Insert a new element at a given position in the array. The position must be valid, or at the end of the array ([code]pos == size()[/code]). @@ -225,42 +225,42 @@ </description> </method> <method name="max"> - <return type="var"> + <return type="Variant"> </return> <description> Return maximum value contained in the array if all elements are of comparable types. If the elements can't be compared, [code]null[/code] is returned. </description> </method> <method name="min"> - <return type="var"> + <return type="Variant"> </return> <description> Return minimum value contained in the array if all elements are of comparable types. If the elements can't be compared, [code]null[/code] is returned. </description> </method> <method name="pop_back"> - <return type="var"> + <return type="Variant"> </return> <description> Remove the last element of the array. </description> </method> <method name="pop_front"> - <return type="var"> + <return type="Variant"> </return> <description> Remove the first element of the array. </description> </method> <method name="push_back"> - <argument index="0" name="value" type="var"> + <argument index="0" name="value" type="Variant"> </argument> <description> Append an element at the end of the array. </description> </method> <method name="push_front"> - <argument index="0" name="value" type="var"> + <argument index="0" name="value" type="Variant"> </argument> <description> Add an element at the beginning of the array. @@ -283,7 +283,7 @@ <method name="rfind"> <return type="int"> </return> - <argument index="0" name="what" type="var"> + <argument index="0" name="what" type="Variant"> </argument> <argument index="1" name="from" type="int" default="-1"> </argument> diff --git a/doc/classes/CollisionObject.xml b/doc/classes/CollisionObject.xml index 22b9725121..5e4e740498 100644 --- a/doc/classes/CollisionObject.xml +++ b/doc/classes/CollisionObject.xml @@ -191,9 +191,9 @@ </members> <signals> <signal name="input_event"> - <argument index="0" name="camera" type="Object"> + <argument index="0" name="camera" type="Node"> </argument> - <argument index="1" name="event" type="Object"> + <argument index="1" name="event" type="InputEvent"> </argument> <argument index="2" name="click_position" type="Vector3"> </argument> diff --git a/doc/classes/CollisionObject2D.xml b/doc/classes/CollisionObject2D.xml index 1ef72c0ca2..b507204f0d 100644 --- a/doc/classes/CollisionObject2D.xml +++ b/doc/classes/CollisionObject2D.xml @@ -204,9 +204,9 @@ </members> <signals> <signal name="input_event"> - <argument index="0" name="viewport" type="Object"> + <argument index="0" name="viewport" type="Node"> </argument> - <argument index="1" name="event" type="Object"> + <argument index="1" name="event" type="InputEvent"> </argument> <argument index="2" name="shape_idx" type="int"> </argument> diff --git a/doc/classes/Control.xml b/doc/classes/Control.xml index 8575a1f498..bbd0441a0b 100644 --- a/doc/classes/Control.xml +++ b/doc/classes/Control.xml @@ -723,7 +723,7 @@ </description> </signal> <signal name="gui_input"> - <argument index="0" name="ev" type="Object"> + <argument index="0" name="ev" type="InputEvent"> </argument> <description> Emitted when the node receives an [InputEvent]. diff --git a/doc/classes/Dictionary.xml b/doc/classes/Dictionary.xml index 800a76ccf1..06c996e13e 100644 --- a/doc/classes/Dictionary.xml +++ b/doc/classes/Dictionary.xml @@ -35,7 +35,7 @@ <method name="erase"> <return type="bool"> </return> - <argument index="0" name="key" type="var"> + <argument index="0" name="key" type="Variant"> </argument> <description> Erase a dictionary key/value pair by key. @@ -44,7 +44,7 @@ <method name="has"> <return type="bool"> </return> - <argument index="0" name="key" type="var"> + <argument index="0" name="key" type="Variant"> </argument> <description> Return true if the dictionary has a given key. diff --git a/doc/classes/EditorPlugin.xml b/doc/classes/EditorPlugin.xml index 5d2407adce..208780547e 100644 --- a/doc/classes/EditorPlugin.xml +++ b/doc/classes/EditorPlugin.xml @@ -445,13 +445,13 @@ </description> </signal> <signal name="resource_saved"> - <argument index="0" name="resource" type="Object"> + <argument index="0" name="resource" type="Resource"> </argument> <description> </description> </signal> <signal name="scene_changed"> - <argument index="0" name="scene_root" type="Object"> + <argument index="0" name="scene_root" type="Node"> </argument> <description> Emitted when user change scene. The argument is a root node of freshly opened scene. diff --git a/doc/classes/EditorProperty.xml b/doc/classes/EditorProperty.xml index 32d3a2703d..7d09554330 100644 --- a/doc/classes/EditorProperty.xml +++ b/doc/classes/EditorProperty.xml @@ -98,7 +98,7 @@ <signal name="resource_selected"> <argument index="0" name="path" type="String"> </argument> - <argument index="1" name="resource" type="Object"> + <argument index="1" name="resource" type="Resource"> </argument> <description> </description> diff --git a/doc/classes/GraphEdit.xml b/doc/classes/GraphEdit.xml index 48e3c295f1..ce0b619d67 100644 --- a/doc/classes/GraphEdit.xml +++ b/doc/classes/GraphEdit.xml @@ -247,7 +247,7 @@ </description> </signal> <signal name="node_selected"> - <argument index="0" name="node" type="Object"> + <argument index="0" name="node" type="Node"> </argument> <description> Emitted when a GraphNode is selected. diff --git a/doc/classes/Input.xml b/doc/classes/Input.xml index a4346c1485..1eb74446c6 100644 --- a/doc/classes/Input.xml +++ b/doc/classes/Input.xml @@ -293,6 +293,8 @@ </argument> <description> Set a custom mouse cursor image, which is only visible inside the game window. The hotspot can also be specified. Passing [code]null[/code] to the image parameter resets to the system cursor. See enum [code]CURSOR_*[/code] for the list of shapes. + [code]image[/code]'s size must be lower than 256x256. + [code]hotspot[/code] must be within [code]image[/code]'s size. </description> </method> <method name="set_default_cursor_shape"> diff --git a/doc/classes/ProjectSettings.xml b/doc/classes/ProjectSettings.xml index 0bda5909ed..ad8c5f68da 100644 --- a/doc/classes/ProjectSettings.xml +++ b/doc/classes/ProjectSettings.xml @@ -576,6 +576,14 @@ <member name="memory/limits/multithreaded_server/rid_pool_prealloc" type="int" setter="" getter=""> This is used by servers when used in multi threading mode (servers and visual). RIDs are preallocated to avoid stalling the server requesting them on threads. If servers get stalled too often when loading resources in a thread, increase this number. </member> + <member name="mono/debugger_agent/port" type="int" setter="" getter=""> + </member> + <member name="mono/debugger_agent/wait_for_debugger" type="bool" setter="" getter=""> + </member> + <member name="mono/debugger_agent/wait_timeout" type="int" setter="" getter=""> + </member> + <member name="mono/export/include_scripts_content" type="bool" setter="" getter=""> + </member> <member name="network/limits/debugger_stdout/max_chars_per_second" type="int" setter="" getter=""> Maximum amount of characters allowed to send as output from the debugger. Over this value, content is dropped. This helps not to stall the debugger connection. </member> diff --git a/doc/classes/RID.xml b/doc/classes/RID.xml index ee34560afd..9eb1462542 100644 --- a/doc/classes/RID.xml +++ b/doc/classes/RID.xml @@ -17,14 +17,14 @@ <argument index="0" name="from" type="Object"> </argument> <description> - Create a new RID instance with the ID of a given resource. When not handed a valid resource, silently stores the unused ID 0. + Creates a new RID instance with the ID of a given resource. When not handed a valid resource, silently stores the unused ID 0. </description> </method> <method name="get_id"> <return type="int"> </return> <description> - Retrieve the ID of the referenced resource. + Returns the ID of the referenced resource. </description> </method> </methods> diff --git a/doc/classes/RayCast.xml b/doc/classes/RayCast.xml index 910f5c8ad4..84c83d1282 100644 --- a/doc/classes/RayCast.xml +++ b/doc/classes/RayCast.xml @@ -6,6 +6,7 @@ <description> A RayCast represents a line from its origin to its destination position, [code]cast_to[/code]. It is used to query the 3D space in order to find the closest object along the path of the ray. RayCast can ignore some objects by adding them to the exception list via [code]add_exception[/code], by setting proper filtering with collision layers, or by filtering object types with type masks. + RayCast can be configured to report collisions with [Area]s ([member collide_with_areas]) and/or [PhysicsBody]s ([member collide_with_bodies]). Only enabled raycasts will be able to query the space and report collisions. RayCast calculates intersection every physics frame (see [Node]), and the result is cached so it can be used later until the next frame. If multiple queries are required between physics frames (or during the same frame) use [method force_raycast_update] after adjusting the raycast. </description> @@ -51,24 +52,14 @@ <return type="Object"> </return> <description> - Return the closest object the ray is pointing to. Note that this does not consider the length of the ray, so you must also use [method is_colliding] to check if the object returned is actually colliding with the ray. - Example: - [codeblock] - if RayCast.is_colliding(): - var collider = RayCast.get_collider() - [/codeblock] + Return the first object that the ray intersects, or [code]null[/code] if no object is intersecting the ray (i.e. [method is_colliding] returns [code]false[/code]). </description> </method> <method name="get_collider_shape" qualifiers="const"> <return type="int"> </return> <description> - Returns the collision shape of the closest object the ray is pointing to. Note that this does not consider the length of the ray, so you must also use [method is_colliding] to check if the object returned is actually colliding with the ray. - Example: - [codeblock] - if RayCast.is_colliding(): - var shape = RayCast.get_collider_shape() - [/codeblock] + Returns the shape ID of the first object that the ray intersects, or [code]0[/code] if no object is intersecting the ray (i.e. [method is_colliding] returns [code]false[/code]). </description> </method> <method name="get_collision_mask_bit" qualifiers="const"> @@ -98,7 +89,7 @@ <return type="bool"> </return> <description> - Return whether the closest object the ray is pointing to is colliding with the vector (considering the vector length). + Return whether any object is intersecting with the ray's vector (considering the vector length). </description> </method> <method name="remove_exception"> @@ -136,8 +127,10 @@ The ray's destination point, relative to the RayCast's [code]position[/code]. </member> <member name="collide_with_areas" type="bool" setter="set_collide_with_areas" getter="is_collide_with_areas_enabled"> + If [code]true[/code], collision with [Area]s will be reported. Default value: [code]false[/code]. </member> <member name="collide_with_bodies" type="bool" setter="set_collide_with_bodies" getter="is_collide_with_bodies_enabled"> + If [code]true[/code], collision with [PhysicsBody]s will be reported. Default value: [code]true[/code]. </member> <member name="collision_mask" type="int" setter="set_collision_mask" getter="get_collision_mask"> The ray's collision mask. Only objects in at least one collision layer enabled in the mask will be detected. diff --git a/doc/classes/RayCast2D.xml b/doc/classes/RayCast2D.xml index 8ba9ee2bcf..e4d1ecb7f8 100644 --- a/doc/classes/RayCast2D.xml +++ b/doc/classes/RayCast2D.xml @@ -6,6 +6,7 @@ <description> A RayCast represents a line from its origin to its destination position, [code]cast_to[/code]. It is used to query the 2D space in order to find the closest object along the path of the ray. RayCast2D can ignore some objects by adding them to the exception list via [code]add_exception[/code], by setting proper filtering with collision layers, or by filtering object types with type masks. + RayCast2D can be configured to report collisions with [Area2D]s ([member collide_with_areas]) and/or [PhysicsBody2D]s ([member collide_with_bodies]). Only enabled raycasts will be able to query the space and report collisions. RayCast2D calculates intersection every physics frame (see [Node]), and the result is cached so it can be used later until the next frame. If multiple queries are required between physics frames (or during the same frame) use [method force_raycast_update] after adjusting the raycast. </description> @@ -50,24 +51,14 @@ <return type="Object"> </return> <description> - Returns the closest object the ray is pointing to. Note that this does not consider the length of the ray, so you must also use [method is_colliding] to check if the object returned is actually colliding with the ray. - Example: - [codeblock] - if RayCast2D.is_colliding(): - var collider = RayCast2D.get_collider() - [/codeblock] + Return the first object that the ray intersects, or [code]null[/code] if no object is intersecting the ray (i.e. [method is_colliding] returns [code]false[/code]). </description> </method> <method name="get_collider_shape" qualifiers="const"> <return type="int"> </return> <description> - Returns the collision shape of the closest object the ray is pointing to. Note that this does not consider the length of the ray, so you must also use [method is_colliding] to check if the object returned is actually colliding with the ray. - Example: - [codeblock] - if RayCast2D.is_colliding(): - var shape = RayCast2D.get_collider_shape() - [/codeblock] + Returns the shape ID of the first object that the ray intersects, or [code]0[/code] if no object is intersecting the ray (i.e. [method is_colliding] returns [code]false[/code]). </description> </method> <method name="get_collision_mask_bit" qualifiers="const"> @@ -97,7 +88,7 @@ <return type="bool"> </return> <description> - Return whether the closest object the ray is pointing to is colliding with the vector (considering the vector length). + Return whether any object is intersecting with the ray's vector (considering the vector length). </description> </method> <method name="remove_exception"> @@ -135,8 +126,10 @@ The ray's destination point, relative to the RayCast's [code]position[/code]. </member> <member name="collide_with_areas" type="bool" setter="set_collide_with_areas" getter="is_collide_with_areas_enabled"> + If [code]true[/code], collision with [Area2D]s will be reported. Default value: [code]false[/code]. </member> <member name="collide_with_bodies" type="bool" setter="set_collide_with_bodies" getter="is_collide_with_bodies_enabled"> + If [code]true[/code], collision with [PhysicsBody2D]s will be reported. Default value: [code]true[/code]. </member> <member name="collision_mask" type="int" setter="set_collision_mask" getter="get_collision_mask"> The ray's collision mask. Only objects in at least one collision layer enabled in the mask will be detected. diff --git a/doc/classes/ResourceSaver.xml b/doc/classes/ResourceSaver.xml index ae0d8e909d..bf3ea95bce 100644 --- a/doc/classes/ResourceSaver.xml +++ b/doc/classes/ResourceSaver.xml @@ -1,10 +1,10 @@ <?xml version="1.0" encoding="UTF-8" ?> <class name="ResourceSaver" inherits="Object" category="Core" version="3.1"> <brief_description> - Resource Saving Interface. + Resource saving interface. </brief_description> <description> - Resource Saving Interface. This interface is used for saving resources to disk. + Resource saving interface, used for saving resources to disk. </description> <tutorials> </tutorials> @@ -17,7 +17,7 @@ <argument index="0" name="type" type="Resource"> </argument> <description> - Return the list of extensions available for saving a resource of a given type. + Returns the list of extensions available for saving a resource of a given type. </description> </method> <method name="save"> @@ -30,7 +30,7 @@ <argument index="2" name="flags" type="int" default="0"> </argument> <description> - Save a resource to disk, to a given path. + Saves a resource to disk. </description> </method> </methods> diff --git a/doc/classes/RigidBody.xml b/doc/classes/RigidBody.xml index 4ae1ef8e94..eea1e0321b 100644 --- a/doc/classes/RigidBody.xml +++ b/doc/classes/RigidBody.xml @@ -168,14 +168,14 @@ </members> <signals> <signal name="body_entered"> - <argument index="0" name="body" type="Object"> + <argument index="0" name="body" type="Node"> </argument> <description> Emitted when a body enters into contact with this one. Contact monitor and contacts reported must be enabled for this to work. </description> </signal> <signal name="body_exited"> - <argument index="0" name="body" type="Object"> + <argument index="0" name="body" type="Node"> </argument> <description> Emitted when a body shape exits contact with this one. Contact monitor and contacts reported must be enabled for this to work. @@ -184,7 +184,7 @@ <signal name="body_shape_entered"> <argument index="0" name="body_id" type="int"> </argument> - <argument index="1" name="body" type="Object"> + <argument index="1" name="body" type="Node"> </argument> <argument index="2" name="body_shape" type="int"> </argument> @@ -198,7 +198,7 @@ <signal name="body_shape_exited"> <argument index="0" name="body_id" type="int"> </argument> - <argument index="1" name="body" type="Object"> + <argument index="1" name="body" type="Node"> </argument> <argument index="2" name="body_shape" type="int"> </argument> diff --git a/doc/classes/RigidBody2D.xml b/doc/classes/RigidBody2D.xml index 2265c777c8..1f6b3934c2 100644 --- a/doc/classes/RigidBody2D.xml +++ b/doc/classes/RigidBody2D.xml @@ -173,14 +173,14 @@ </members> <signals> <signal name="body_entered"> - <argument index="0" name="body" type="Object"> + <argument index="0" name="body" type="Node"> </argument> <description> Emitted when a body enters into contact with this one. [member contact_monitor] must be [code]true[/code] and [member contacts_reported] greater than [code]0[/code]. </description> </signal> <signal name="body_exited"> - <argument index="0" name="body" type="Object"> + <argument index="0" name="body" type="Node"> </argument> <description> Emitted when a body exits contact with this one. [member contact_monitor] must be [code]true[/code] and [member contacts_reported] greater than [code]0[/code]. @@ -189,7 +189,7 @@ <signal name="body_shape_entered"> <argument index="0" name="body_id" type="int"> </argument> - <argument index="1" name="body" type="Object"> + <argument index="1" name="body" type="Node"> </argument> <argument index="2" name="body_shape" type="int"> </argument> @@ -202,7 +202,7 @@ <signal name="body_shape_exited"> <argument index="0" name="body_id" type="int"> </argument> - <argument index="1" name="body" type="Object"> + <argument index="1" name="body" type="Node"> </argument> <argument index="2" name="body_shape" type="int"> </argument> diff --git a/doc/classes/SceneTree.xml b/doc/classes/SceneTree.xml index c85bee9b84..11362ee680 100644 --- a/doc/classes/SceneTree.xml +++ b/doc/classes/SceneTree.xml @@ -329,21 +329,21 @@ </description> </signal> <signal name="node_added"> - <argument index="0" name="node" type="Object"> + <argument index="0" name="node" type="Node"> </argument> <description> Emitted whenever a node is added to the SceneTree. </description> </signal> <signal name="node_configuration_warning_changed"> - <argument index="0" name="node" type="Object"> + <argument index="0" name="node" type="Node"> </argument> <description> Emitted when a node's configuration changed. Only emitted in tool mode. </description> </signal> <signal name="node_removed"> - <argument index="0" name="node" type="Object"> + <argument index="0" name="node" type="Node"> </argument> <description> Emitted whenever a node is removed from the SceneTree. diff --git a/doc/classes/Script.xml b/doc/classes/Script.xml index 09c60afc2f..128d7475cc 100644 --- a/doc/classes/Script.xml +++ b/doc/classes/Script.xml @@ -4,8 +4,8 @@ A class stored as a resource. </brief_description> <description> - A class stored as a resource. The script exends the functionality of all objects that instance it. - The 'new' method of a script subclass creates a new instance. [method Object.set_script] extends an existing object, if that object's class matches one of the script's base classes. + A class stored as a resource. A script exends the functionality of all objects that instance it. + The [code]new[/code] method of a script subclass creates a new instance. [method Object.set_script] extends an existing object, if that object's class matches one of the script's base classes. </description> <tutorials> <link>http://docs.godotengine.org/en/3.0/getting_started/step_by_step/scripting.html</link> @@ -17,7 +17,7 @@ <return type="bool"> </return> <description> - Returns true if the script can be instanced. + Returns [code]true[/code] if the script can be instanced. </description> </method> <method name="get_base_script" qualifiers="const"> @@ -31,6 +31,7 @@ <return type="String"> </return> <description> + Returns the script's base type. </description> </method> <method name="has_script_signal" qualifiers="const"> @@ -39,14 +40,14 @@ <argument index="0" name="signal_name" type="String"> </argument> <description> - Returns true if the script, or a base class, defines a signal with the given name. + Returns [code]true[/code] if the script, or a base class, defines a signal with the given name. </description> </method> <method name="has_source_code" qualifiers="const"> <return type="bool"> </return> <description> - Returns true if the script contains non-empty source code. + Returns [code]true[/code] if the script contains non-empty source code. </description> </method> <method name="instance_has" qualifiers="const"> @@ -55,14 +56,14 @@ <argument index="0" name="base_object" type="Object"> </argument> <description> - Returns true if 'base_object' is an instance of this script. + Returns [code]true[/code] if [code]base_object[/code] is an instance of this script. </description> </method> <method name="is_tool" qualifiers="const"> <return type="bool"> </return> <description> - Returns true if the script is a tool script. A tool script can run in the editor. + Returns [code]true[/code] if the script is a tool script. A tool script can run in the editor. </description> </method> <method name="reload"> @@ -77,7 +78,7 @@ </methods> <members> <member name="source_code" type="String" setter="set_source_code" getter="get_source_code"> - The script source code, or an empty string if source code is not available. When set, does not reload the class implementation automatically. + The script source code or an empty string if source code is not available. When set, does not reload the class implementation automatically. </member> </members> <constants> diff --git a/doc/classes/ScriptCreateDialog.xml b/doc/classes/ScriptCreateDialog.xml index a3ad3a778e..3de068dbcb 100644 --- a/doc/classes/ScriptCreateDialog.xml +++ b/doc/classes/ScriptCreateDialog.xml @@ -31,7 +31,7 @@ </methods> <signals> <signal name="script_created"> - <argument index="0" name="script" type="Object"> + <argument index="0" name="script" type="Script"> </argument> <description> Emitted when the user clicks the OK button. diff --git a/doc/classes/ScriptEditor.xml b/doc/classes/ScriptEditor.xml index 4bfd07fdad..435ab8aafc 100644 --- a/doc/classes/ScriptEditor.xml +++ b/doc/classes/ScriptEditor.xml @@ -70,14 +70,14 @@ </methods> <signals> <signal name="editor_script_changed"> - <argument index="0" name="script" type="Object"> + <argument index="0" name="script" type="Script"> </argument> <description> Emitted when user changed active script. Argument is a freshly activated [Script]. </description> </signal> <signal name="script_close"> - <argument index="0" name="script" type="Object"> + <argument index="0" name="script" type="Script"> </argument> <description> Emitted when editor is about to close the active script. Argument is a [Script] that is going to be closed. diff --git a/doc/classes/Shape.xml b/doc/classes/Shape.xml index d31da20f07..bc1a429418 100644 --- a/doc/classes/Shape.xml +++ b/doc/classes/Shape.xml @@ -4,7 +4,7 @@ Base class for all 3D shape resources. </brief_description> <description> - Base class for all 3D shape resources. All 3D shapes that inherit from this can be set into a [PhysicsBody] or [Area]. + Base class for all 3D shape resources. Nodes that inherit from this can be used as shapes for a [PhysicsBody] or [Area] objects. </description> <tutorials> <link>http://docs.godotengine.org/en/3.0/tutorials/physics/physics_introduction.html</link> diff --git a/doc/classes/Spatial.xml b/doc/classes/Spatial.xml index ef1bcc30b3..4fa60b2e44 100644 --- a/doc/classes/Spatial.xml +++ b/doc/classes/Spatial.xml @@ -296,11 +296,11 @@ World space (global) [Transform] of this node. </member> <member name="rotation" type="Vector3" setter="set_rotation" getter="get_rotation"> - Rotation part of the local transformation, specified in terms of YXZ-Euler angles in the format (X-angle, Y-angle, Z-angle), in radians. - Note that in the mathematical sense, rotation is a matrix and not a vector. The three Euler angles, which are the three indepdent parameters of the Euler-angle parametrization of the rotation matrix, are stored in a [Vector3] data structure not because the rotation is a vector, but only because [Vector3] exists as a convenient data-structure to store 3 floating point numbers. Therefore, applying affine operations on the rotation "vector" is not meaningful. + Rotation part of the local transformation in radians, specified in terms of YXZ-Euler angles in the format (X-angle, Y-angle, Z-angle). + Note that in the mathematical sense, rotation is a matrix and not a vector. The three Euler angles, which are the three independent parameters of the Euler-angle parametrization of the rotation matrix, are stored in a [Vector3] data structure not because the rotation is a vector, but only because [Vector3] exists as a convenient data-structure to store 3 floating point numbers. Therefore, applying affine operations on the rotation "vector" is not meaningful. </member> <member name="rotation_degrees" type="Vector3" setter="set_rotation_degrees" getter="get_rotation_degrees"> - Rotation part of the local transformation, specified in terms of YXZ-Euler angles in the format (X-angle, Y-angle, Z-angle), in degrees. + Rotation part of the local transformation in degrees, specified in terms of YXZ-Euler angles in the format (X-angle, Y-angle, Z-angle). </member> <member name="scale" type="Vector3" setter="set_scale" getter="get_scale"> Scale part of the local transformation. @@ -312,7 +312,7 @@ Local translation of this node. </member> <member name="visible" type="bool" setter="set_visible" getter="is_visible"> - Visibility of this node. Toggles if this node is rendered. + If [code]true[/code] this node is drawn. Default value: [code]true[/code]. </member> </members> <signals> diff --git a/doc/classes/String.xml b/doc/classes/String.xml index a42f508b59..d404c32b38 100644 --- a/doc/classes/String.xml +++ b/doc/classes/String.xml @@ -339,7 +339,7 @@ <method name="format"> <return type="String"> </return> - <argument index="0" name="values" type="var"> + <argument index="0" name="values" type="Variant"> </argument> <argument index="1" name="placeholder" type="String" default="{_}"> </argument> diff --git a/doc/classes/TileSet.xml b/doc/classes/TileSet.xml index a30d12d6b7..b98161e483 100644 --- a/doc/classes/TileSet.xml +++ b/doc/classes/TileSet.xml @@ -44,6 +44,14 @@ <description> </description> </method> + <method name="autotile_get_size" qualifiers="const"> + <return type="Vector2"> + </return> + <argument index="0" name="id" type="int"> + </argument> + <description> + </description> + </method> <method name="autotile_set_bitmask_mode"> <return type="void"> </return> @@ -54,6 +62,16 @@ <description> </description> </method> + <method name="autotile_set_size"> + <return type="void"> + </return> + <argument index="0" name="id" type="int"> + </argument> + <argument index="1" name="size" type="Vector2"> + </argument> + <description> + </description> + </method> <method name="clear"> <return type="void"> </return> diff --git a/doc/classes/Transform.xml b/doc/classes/Transform.xml index 24c009d922..09edfe4235 100644 --- a/doc/classes/Transform.xml +++ b/doc/classes/Transform.xml @@ -141,18 +141,18 @@ </description> </method> <method name="xform"> - <return type="var"> + <return type="Variant"> </return> - <argument index="0" name="v" type="var"> + <argument index="0" name="v" type="Variant"> </argument> <description> Transforms the given [Vector3], [Plane], or [AABB] by this transform. </description> </method> <method name="xform_inv"> - <return type="var"> + <return type="Variant"> </return> - <argument index="0" name="v" type="var"> + <argument index="0" name="v" type="Variant"> </argument> <description> Inverse-transforms the given [Vector3], [Plane], or [AABB] by this transform. diff --git a/doc/classes/Transform2D.xml b/doc/classes/Transform2D.xml index b38d9a1a86..bf0a745aa8 100644 --- a/doc/classes/Transform2D.xml +++ b/doc/classes/Transform2D.xml @@ -143,18 +143,18 @@ </description> </method> <method name="xform"> - <return type="var"> + <return type="Variant"> </return> - <argument index="0" name="v" type="var"> + <argument index="0" name="v" type="Variant"> </argument> <description> Transforms the given [Vector2] or [Rect2] by this transform. </description> </method> <method name="xform_inv"> - <return type="var"> + <return type="Variant"> </return> - <argument index="0" name="v" type="var"> + <argument index="0" name="v" type="Variant"> </argument> <description> Inverse-transforms the given [Vector2] or [Rect2] by this transform. diff --git a/doc/classes/Tree.xml b/doc/classes/Tree.xml index 533df57564..5c24df5be2 100644 --- a/doc/classes/Tree.xml +++ b/doc/classes/Tree.xml @@ -244,7 +244,7 @@ </members> <signals> <signal name="button_pressed"> - <argument index="0" name="item" type="Object"> + <argument index="0" name="item" type="TreeItem"> </argument> <argument index="1" name="column" type="int"> </argument> @@ -286,7 +286,7 @@ </description> </signal> <signal name="item_collapsed"> - <argument index="0" name="item" type="Object"> + <argument index="0" name="item" type="TreeItem"> </argument> <description> Emitted when an item is collapsed by a click on the folding arrow. @@ -324,7 +324,7 @@ </description> </signal> <signal name="multi_selected"> - <argument index="0" name="item" type="Object"> + <argument index="0" name="item" type="TreeItem"> </argument> <argument index="1" name="column" type="int"> </argument> diff --git a/doc/classes/VisibilityNotifier.xml b/doc/classes/VisibilityNotifier.xml index 2f22dc99bf..95da708420 100644 --- a/doc/classes/VisibilityNotifier.xml +++ b/doc/classes/VisibilityNotifier.xml @@ -26,14 +26,14 @@ </members> <signals> <signal name="camera_entered"> - <argument index="0" name="camera" type="Object"> + <argument index="0" name="camera" type="Camera"> </argument> <description> Emitted when the VisibilityNotifier enters a [Camera]'s view. </description> </signal> <signal name="camera_exited"> - <argument index="0" name="camera" type="Object"> + <argument index="0" name="camera" type="Camera"> </argument> <description> Emitted when the VisibilityNotifier exits a [Camera]'s view. diff --git a/doc/classes/VisibilityNotifier2D.xml b/doc/classes/VisibilityNotifier2D.xml index b98f2794d2..aaaa9b63bb 100644 --- a/doc/classes/VisibilityNotifier2D.xml +++ b/doc/classes/VisibilityNotifier2D.xml @@ -36,14 +36,14 @@ </description> </signal> <signal name="viewport_entered"> - <argument index="0" name="viewport" type="Object"> + <argument index="0" name="viewport" type="Viewport"> </argument> <description> Emitted when the VisibilityNotifier2D enters a [Viewport]'s view. </description> </signal> <signal name="viewport_exited"> - <argument index="0" name="viewport" type="Object"> + <argument index="0" name="viewport" type="Viewport"> </argument> <description> Emitted when the VisibilityNotifier2D exits a [Viewport]'s view. diff --git a/doc/classes/VisualServer.xml b/doc/classes/VisualServer.xml index 395fb9e829..afada05bf7 100644 --- a/doc/classes/VisualServer.xml +++ b/doc/classes/VisualServer.xml @@ -1552,7 +1552,7 @@ <argument index="0" name="feature" type="String"> </argument> <description> - Returns true, if the OS supports a certain feature. Features might be s3tc, etc, etc2 and pvrtc, + Returns [code]true[/code] if the OS supports a certain feature. Features might be s3tc, etc, etc2 and pvrtc, </description> </method> <method name="immediate_begin"> @@ -3110,7 +3110,7 @@ <argument index="2" name="scale" type="bool"> </argument> <description> - Sets a boot image. The color defines the background color and if scale is [code]true[/code], the image will be scaled to fit the screen size. + Sets a boot image. The color defines the background color and if scale is [code]true[/code] the image will be scaled to fit the screen size. </description> </method> <method name="set_debug_generate_wireframes"> @@ -3484,7 +3484,7 @@ <argument index="0" name="shrink" type="bool"> </argument> <description> - If [code]true[/code], sets internal processes to shrink all image data to half the size. + If [code]true[/code] sets internal processes to shrink all image data to half the size. </description> </method> <method name="texture_set_size_override"> @@ -3507,7 +3507,7 @@ <argument index="0" name="enable" type="bool"> </argument> <description> - If [code]true[/code], the image will be stored in the texture's images array if overwritten. + If [code]true[/code] the image will be stored in the texture's images array if overwritten. </description> </method> <method name="viewport_attach_camera"> @@ -3600,7 +3600,7 @@ <argument index="1" name="active" type="bool"> </argument> <description> - If [code]true[/code], sets the viewport active, else sets it inactive. + If [code]true[/code] sets the viewport active, else sets it inactive. </description> </method> <method name="viewport_set_canvas_layer"> @@ -3659,7 +3659,7 @@ <argument index="1" name="disabled" type="bool"> </argument> <description> - If [code]true[/code] a viewport's 3D rendering should be disabled. + If [code]true[/code] a viewport's 3D rendering is disabled. </description> </method> <method name="viewport_set_disable_environment"> @@ -3670,7 +3670,7 @@ <argument index="1" name="disabled" type="bool"> </argument> <description> - If [code]true[/code] rendering of a viewport's environment should be disabled. + If [code]true[/code] rendering of a viewport's environment is disabled. </description> </method> <method name="viewport_set_global_canvas_transform"> @@ -3692,7 +3692,7 @@ <argument index="1" name="enabled" type="bool"> </argument> <description> - If [code]true[/code] the viewport should render to hdr. + If [code]true[/code] the viewport renders to hdr. </description> </method> <method name="viewport_set_hide_canvas"> @@ -3703,7 +3703,7 @@ <argument index="1" name="hidden" type="bool"> </argument> <description> - If [code]true[/code] the viewport's canvas should not be rendered. + If [code]true[/code] the viewport's canvas is not rendered. </description> </method> <method name="viewport_set_hide_scenario"> @@ -3795,7 +3795,7 @@ <argument index="1" name="enabled" type="bool"> </argument> <description> - If [code]true[/code] the viewport should render its background as transparent. + If [code]true[/code] the viewport renders its background as transparent. </description> </method> <method name="viewport_set_update_mode"> @@ -3806,7 +3806,7 @@ <argument index="1" name="update_mode" type="int" enum="VisualServer.ViewportUpdateMode"> </argument> <description> - Sets when the viewport should be updated. See VIEWPORT_UPDATE_MODE_* constants for options. + Sets when the viewport should be updated. See [enum ViewportUpdateMode] constants for options. </description> </method> <method name="viewport_set_usage"> @@ -3817,7 +3817,7 @@ <argument index="1" name="usage" type="int" enum="VisualServer.ViewportUsage"> </argument> <description> - Sets what should be rendered in the viewport. See VIEWPORT_USAGE_* constants for options. + Sets the viewport's 2D/3D mode. See [enum ViewportUsage] constants for options. </description> </method> <method name="viewport_set_use_arvr"> @@ -3828,7 +3828,7 @@ <argument index="1" name="use_arvr" type="bool"> </argument> <description> - If [code]true[/code] the viewport should use augmented or virtual reality technologies. See [ARVRInterface]. + If [code]true[/code] the viewport uses augmented or virtual reality technologies. See [ARVRInterface]. </description> </method> <method name="viewport_set_vflip"> @@ -3839,7 +3839,7 @@ <argument index="1" name="enabled" type="bool"> </argument> <description> - If [code]true[/code] the viewport's rendering should be flipped vertically. + If [code]true[/code] the viewport's rendering is flipped vertically. </description> </method> </methods> diff --git a/drivers/gles2/rasterizer_gles2.cpp b/drivers/gles2/rasterizer_gles2.cpp index 76ee80aa07..efeab48ea2 100644 --- a/drivers/gles2/rasterizer_gles2.cpp +++ b/drivers/gles2/rasterizer_gles2.cpp @@ -321,9 +321,25 @@ void RasterizerGLES2::set_boot_image(const Ref<Image> &p_image, const Color &p_c Rect2 imgrect(0, 0, p_image->get_width(), p_image->get_height()); Rect2 screenrect; + if (p_scale) { - screenrect = imgrect; - screenrect.position += ((Size2(window_w, window_h) - screenrect.size) / 2.0).floor(); + if (window_w > window_h) { + //scale horizontally + screenrect.size.y = window_h; + screenrect.size.x = imgrect.size.x * window_h / imgrect.size.y; + screenrect.position.x = (window_w - screenrect.size.x) / 2; + + } else { + //scale vertically + screenrect.size.x = window_w; + screenrect.size.y = imgrect.size.y * window_w / imgrect.size.x; + screenrect.position.y = (window_h - screenrect.size.y) / 2; + } + } else { + + screenrect = imgrect; + screenrect.position += ((Size2(window_w, window_h) - screenrect.size) / 2.0).floor(); + } RasterizerStorageGLES2::Texture *t = storage->texture_owner.get(texture); glActiveTexture(GL_TEXTURE0 + storage->config.max_texture_image_units - 1); diff --git a/editor/SCsub b/editor/SCsub index d9bdf42d6f..6a4b06a97a 100644 --- a/editor/SCsub +++ b/editor/SCsub @@ -81,18 +81,6 @@ if env['tools']: env.Depends('#editor/builtin_fonts.gen.h', flist) env.CommandNoCache('#editor/builtin_fonts.gen.h', flist, run_in_subprocess(editor_builders.make_fonts_header)) - # Authors - env.Depends('#editor/authors.gen.h', "../AUTHORS.md") - env.CommandNoCache('#editor/authors.gen.h', "../AUTHORS.md", run_in_subprocess(editor_builders.make_authors_header)) - - # Donors - env.Depends('#editor/donors.gen.h', "../DONORS.md") - env.CommandNoCache('#editor/donors.gen.h', "../DONORS.md", run_in_subprocess(editor_builders.make_donors_header)) - - # License - env.Depends('#editor/license.gen.h', ["../COPYRIGHT.txt", "../LICENSE.txt"]) - env.CommandNoCache('#editor/license.gen.h', ["../COPYRIGHT.txt", "../LICENSE.txt"], run_in_subprocess(editor_builders.make_license_header)) - env.add_source_files(env.editor_sources, "*.cpp") env.add_source_files(env.editor_sources, ["#thirdparty/misc/clipper.cpp"]) diff --git a/editor/create_dialog.cpp b/editor/create_dialog.cpp index 8433f4ff7b..fd607e5b63 100644 --- a/editor/create_dialog.cpp +++ b/editor/create_dialog.cpp @@ -497,7 +497,11 @@ Object *CreateDialog::instance_selected() { if (custom != String()) { if (ScriptServer::is_global_class(custom)) { - return EditorNode::get_editor_data().script_class_instance(custom); + Object *obj = EditorNode::get_editor_data().script_class_instance(custom); + Node *n = Object::cast_to<Node>(obj); + if (n) + n->set_name(custom); + return obj; } return EditorNode::get_editor_data().instance_custom_type(selected->get_text(0), custom); } else { diff --git a/editor/doc/doc_data.cpp b/editor/doc/doc_data.cpp index fe1cf3484e..c90b2b14b3 100644 --- a/editor/doc/doc_data.cpp +++ b/editor/doc/doc_data.cpp @@ -382,7 +382,11 @@ void DocData::generate(bool p_basic_types) { PropertyInfo arginfo = EV->get().arguments[i]; ArgumentDoc argument; argument.name = arginfo.name; - argument.type = Variant::get_type_name(arginfo.type); + if (arginfo.type == Variant::OBJECT && arginfo.class_name != StringName()) { + argument.type = arginfo.class_name.operator String(); + } else { + argument.type = Variant::get_type_name(arginfo.type); + } signal.arguments.push_back(argument); } @@ -501,7 +505,7 @@ void DocData::generate(bool p_basic_types) { ad.name = arginfo.name; if (arginfo.type == Variant::NIL) - ad.type = "var"; + ad.type = "Variant"; else ad.type = Variant::get_type_name(arginfo.type); @@ -514,7 +518,7 @@ void DocData::generate(bool p_basic_types) { if (mi.return_val.type == Variant::NIL) { if (mi.return_val.name != "") - method.return_type = "var"; + method.return_type = "Variant"; } else { method.return_type = Variant::get_type_name(mi.return_val.type); } diff --git a/editor/doc/doc_dump.cpp b/editor/doc/doc_dump.cpp index adbe23dcd5..06d35c4d3a 100644 --- a/editor/doc/doc_dump.cpp +++ b/editor/doc/doc_dump.cpp @@ -142,7 +142,7 @@ void DocDump::dump(const String &p_file) { if (arginfo.hint == PROPERTY_HINT_RESOURCE_TYPE) type_name = arginfo.hint_string; else if (arginfo.type == Variant::NIL) - type_name = "var"; + type_name = "Variant"; else type_name = Variant::get_type_name(arginfo.type); diff --git a/editor/editor_builders.py b/editor/editor_builders.py index 6c2f9e298e..fa037980c2 100644 --- a/editor/editor_builders.py +++ b/editor/editor_builders.py @@ -146,267 +146,5 @@ def make_translations_header(target, source, env): g.close() - -def make_authors_header(target, source, env): - - sections = ["Project Founders", "Lead Developer", "Project Manager", "Developers"] - sections_id = ["dev_founders", "dev_lead", "dev_manager", "dev_names"] - - src = source[0] - dst = target[0] - f = open_utf8(src, "r") - g = open_utf8(dst, "w") - - g.write("/* THIS FILE IS GENERATED DO NOT EDIT */\n") - g.write("#ifndef _EDITOR_AUTHORS_H\n") - g.write("#define _EDITOR_AUTHORS_H\n") - - current_section = "" - reading = False - - def close_section(): - g.write("\t0\n") - g.write("};\n") - - for line in f: - if reading: - if line.startswith(" "): - g.write("\t\"" + escape_string(line.strip()) + "\",\n") - continue - if line.startswith("## "): - if reading: - close_section() - reading = False - for i in range(len(sections)): - if line.strip().endswith(sections[i]): - current_section = escape_string(sections_id[i]) - reading = True - g.write("static const char *" + current_section + "[] = {\n") - break - - if reading: - close_section() - - g.write("#endif\n") - - g.close() - f.close() - -def make_donors_header(target, source, env): - - sections = ["Platinum sponsors", "Gold sponsors", "Mini sponsors", "Gold donors", "Silver donors", "Bronze donors"] - sections_id = ["donor_s_plat", "donor_s_gold", "donor_s_mini", "donor_gold", "donor_silver", "donor_bronze"] - - src = source[0] - dst = target[0] - f = open_utf8(src, "r") - g = open_utf8(dst, "w") - - g.write("/* THIS FILE IS GENERATED DO NOT EDIT */\n") - g.write("#ifndef _EDITOR_DONORS_H\n") - g.write("#define _EDITOR_DONORS_H\n") - - current_section = "" - reading = False - - def close_section(): - g.write("\t0\n") - g.write("};\n") - - for line in f: - if reading >= 0: - if line.startswith(" "): - g.write("\t\"" + escape_string(line.strip()) + "\",\n") - continue - if line.startswith("## "): - if reading: - close_section() - reading = False - for i in range(len(sections)): - if line.strip().endswith(sections[i]): - current_section = escape_string(sections_id[i]) - reading = True - g.write("static const char *" + current_section + "[] = {\n") - break - - if reading: - close_section() - - g.write("#endif\n") - - g.close() - f.close() - - -def make_license_header(target, source, env): - - src_copyright = source[0] - src_license = source[1] - dst = target[0] - f = open_utf8(src_license, "r") - fc = open_utf8(src_copyright, "r") - g = open_utf8(dst, "w") - - g.write("/* THIS FILE IS GENERATED DO NOT EDIT */\n") - g.write("#ifndef _EDITOR_LICENSE_H\n") - g.write("#define _EDITOR_LICENSE_H\n") - g.write("static const char *about_license =") - - for line in f: - escaped_string = escape_string(line.strip()) - g.write("\n\t\"" + escaped_string + "\\n\"") - - g.write(";\n") - - tp_current = 0 - tp_file = "" - tp_comment = "" - tp_copyright = "" - tp_license = "" - - tp_licensename = "" - tp_licensebody = "" - - tp = [] - tp_licensetext = [] - for line in fc: - if line.startswith("#"): - continue - - if line.startswith("Files:"): - tp_file = line[6:].strip() - tp_current = 1 - elif line.startswith("Comment:"): - tp_comment = line[8:].strip() - tp_current = 2 - elif line.startswith("Copyright:"): - tp_copyright = line[10:].strip() - tp_current = 3 - elif line.startswith("License:"): - if tp_current != 0: - tp_license = line[8:].strip() - tp_current = 4 - else: - tp_licensename = line[8:].strip() - tp_current = 5 - elif line.startswith(" "): - if tp_current == 1: - tp_file += "\n" + line.strip() - elif tp_current == 3: - tp_copyright += "\n" + line.strip() - elif tp_current == 5: - if line.strip() == ".": - tp_licensebody += "\n" - else: - tp_licensebody += line[1:] - else: - if tp_current != 0: - if tp_current == 5: - tp_licensetext.append([tp_licensename, tp_licensebody]) - - tp_licensename = "" - tp_licensebody = "" - else: - added = False - for i in tp: - if i[0] == tp_comment: - i[1].append([tp_file, tp_copyright, tp_license]) - added = True - break - if not added: - tp.append([tp_comment,[[tp_file, tp_copyright, tp_license]]]) - - tp_file = [] - tp_comment = "" - tp_copyright = [] - tp_license = "" - tp_current = 0 - - tp_licensetext.append([tp_licensename, tp_licensebody]) - - about_thirdparty = "" - about_tp_copyright_count = "" - about_tp_license = "" - about_tp_copyright = "" - about_tp_file = "" - - for i in tp: - about_thirdparty += "\t\"" + i[0] + "\",\n" - about_tp_copyright_count += str(len(i[1])) + ", " - for j in i[1]: - file_body = "" - copyright_body = "" - for k in j[0].split("\n"): - if file_body != "": - file_body += "\\n\"\n" - escaped_string = escape_string(k.strip()) - file_body += "\t\"" + escaped_string - for k in j[1].split("\n"): - if copyright_body != "": - copyright_body += "\\n\"\n" - escaped_string = escape_string(k.strip()) - copyright_body += "\t\"" + escaped_string - - about_tp_file += "\t" + file_body + "\",\n" - about_tp_copyright += "\t" + copyright_body + "\",\n" - about_tp_license += "\t\"" + j[2] + "\",\n" - - about_license_name = "" - about_license_body = "" - - for i in tp_licensetext: - body = "" - for j in i[1].split("\n"): - if body != "": - body += "\\n\"\n" - escaped_string = escape_string(j.strip()) - body += "\t\"" + escaped_string - - about_license_name += "\t\"" + i[0] + "\",\n" - about_license_body += "\t" + body + "\",\n" - - g.write("static const char *about_thirdparty[] = {\n") - g.write(about_thirdparty) - g.write("\t0\n") - g.write("};\n") - g.write("#define THIRDPARTY_COUNT " + str(len(tp)) + "\n") - - g.write("static const int about_tp_copyright_count[] = {\n\t") - g.write(about_tp_copyright_count) - g.write("0\n};\n") - - g.write("static const char *about_tp_file[] = {\n") - g.write(about_tp_file) - g.write("\t0\n") - g.write("};\n") - - g.write("static const char *about_tp_copyright[] = {\n") - g.write(about_tp_copyright) - g.write("\t0\n") - g.write("};\n") - - g.write("static const char *about_tp_license[] = {\n") - g.write(about_tp_license) - g.write("\t0\n") - g.write("};\n") - - g.write("static const char *about_license_name[] = {\n") - g.write(about_license_name) - g.write("\t0\n") - g.write("};\n") - g.write("#define LICENSE_COUNT " + str(len(tp_licensetext)) + "\n") - - g.write("static const char *about_license_body[] = {\n") - g.write(about_license_body) - g.write("\t0\n") - g.write("};\n") - - g.write("#endif\n") - - g.close() - fc.close() - f.close() - - if __name__ == '__main__': subprocess_main(globals()) diff --git a/editor/editor_help.cpp b/editor/editor_help.cpp index 5a0a49d577..d84b9bff91 100644 --- a/editor/editor_help.cpp +++ b/editor/editor_help.cpp @@ -225,7 +225,6 @@ bool EditorHelpSearch::IncrementalSearch::work(uint64_t slot) { void EditorHelpSearch::_update_search() { search_options->clear(); - search_options->set_hide_root(true); String term = search_box->get_text(); if (term.length() < 2) @@ -307,6 +306,7 @@ EditorHelpSearch::EditorHelpSearch() { search_box->connect("text_changed", this, "_text_changed"); search_box->connect("gui_input", this, "_sbox_input"); search_options = memnew(Tree); + search_options->set_hide_root(true); vbc->add_margin_child(TTR("Matches:"), search_options, true); get_ok()->set_text(TTR("Open")); get_ok()->set_disabled(true); @@ -397,6 +397,16 @@ void EditorHelpIndex::_notification(int p_what) { //_update_icons search_box->set_right_icon(get_icon("Search", "EditorIcons")); search_box->set_clear_button_enabled(true); + + bool enable_rl = EditorSettings::get_singleton()->get("docks/scene_tree/draw_relationship_lines"); + Color rl_color = EditorSettings::get_singleton()->get("docks/scene_tree/relationship_line_color"); + + if (enable_rl) { + class_list->add_constant_override("draw_relationship_lines", 1); + class_list->add_color_override("relationship_line_color", rl_color); + } else { + class_list->add_constant_override("draw_relationship_lines", 0); + } } } @@ -410,7 +420,6 @@ void EditorHelpIndex::_update_class_list() { class_list->clear(); tree_item_map.clear(); TreeItem *root = class_list->create_item(); - class_list->set_hide_root(true); String filter = search_box->get_text().strip_edges(); String to_select = ""; @@ -489,10 +498,21 @@ EditorHelpIndex::EditorHelpIndex() { class_list = memnew(Tree); vbc->add_margin_child(TTR("Class List:") + " ", class_list, true); + class_list->set_hide_root(true); class_list->set_v_size_flags(SIZE_EXPAND_FILL); class_list->connect("item_activated", this, "_tree_item_selected"); + bool enable_rl = EditorSettings::get_singleton()->get("docks/scene_tree/draw_relationship_lines"); + Color rl_color = EditorSettings::get_singleton()->get("docks/scene_tree/relationship_line_color"); + + if (enable_rl) { + class_list->add_constant_override("draw_relationship_lines", 1); + class_list->add_color_override("relationship_line_color", rl_color); + } else { + class_list->add_constant_override("draw_relationship_lines", 0); + } + get_ok()->set_text(TTR("Open")); set_title(TTR("Search Classes")); } diff --git a/editor/editor_properties.cpp b/editor/editor_properties.cpp index 3c3df6b8ef..069b9147ce 100644 --- a/editor/editor_properties.cpp +++ b/editor/editor_properties.cpp @@ -651,6 +651,7 @@ public: int h = bsize * 2 + 1; int vofs = (rect.size.height - h) / 2; + Color color = get_color("highlight_color", "Editor"); for (int i = 0; i < 2; i++) { Point2 ofs(4, vofs); @@ -667,7 +668,8 @@ public: uint32_t idx = i * 10 + j; bool on = value & (1 << idx); Rect2 rect = Rect2(o, Size2(bsize, bsize)); - draw_rect(rect, Color(0, 0, 0, on ? 0.8 : 0.3)); + color.a = on ? 0.6 : 0.2; + draw_rect(rect, color); flag_rects.push_back(rect); } } diff --git a/editor/import/resource_importer_texture.cpp b/editor/import/resource_importer_texture.cpp index 2a25c08f26..af2615f9cf 100644 --- a/editor/import/resource_importer_texture.cpp +++ b/editor/import/resource_importer_texture.cpp @@ -431,8 +431,8 @@ Error ResourceImporterTexture::import(const String &p_source_file, const String int width = image->get_width(); image->lock(); - for (int i = 0; i < height; i++) { - for (int j = 0; j < width; j++) { + for (int i = 0; i < width; i++) { + for (int j = 0; j < height; j++) { image->set_pixel(i, j, image->get_pixel(i, j).inverted()); } } diff --git a/editor/inspector_dock.cpp b/editor/inspector_dock.cpp index 0335053162..9145a66510 100644 --- a/editor/inspector_dock.cpp +++ b/editor/inspector_dock.cpp @@ -36,6 +36,12 @@ void InspectorDock::_menu_option(int p_option) { switch (p_option) { + case EXPAND_ALL: { + _menu_expandall(); + } break; + case COLLAPSE_ALL: { + _menu_collapseall(); + } break; case RESOURCE_MAKE_BUILT_IN: { _unref_resource(); } break; diff --git a/editor/plugins/cpu_particles_editor_plugin.cpp b/editor/plugins/cpu_particles_editor_plugin.cpp index dc7176a6cc..8d3ebc5052 100644 --- a/editor/plugins/cpu_particles_editor_plugin.cpp +++ b/editor/plugins/cpu_particles_editor_plugin.cpp @@ -29,6 +29,7 @@ /*************************************************************************/ #include "cpu_particles_editor_plugin.h" + #include "editor/plugins/spatial_editor_plugin.h" void CPUParticlesEditor::_node_removed(Node *p_node) { diff --git a/editor/plugins/material_editor_plugin.cpp b/editor/plugins/material_editor_plugin.cpp index f282d391ff..5e59a73061 100644 --- a/editor/plugins/material_editor_plugin.cpp +++ b/editor/plugins/material_editor_plugin.cpp @@ -28,397 +28,9 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -// FIXME: Disabled as (according to reduz) users were complaining that it gets in the way -// Waiting for PropertyEditor rewrite (planned for 3.1) to be refactored. - #include "material_editor_plugin.h" -#include "scene/3d/particles.h" - -#if 0 - -#include "scene/main/viewport.h" - -void MaterialEditor::_gui_input(InputEvent p_event) { - - -} - -void MaterialEditor::_notification(int p_what) { - - if (p_what==NOTIFICATION_PHYSICS_PROCESS) { - - } - - - if (p_what==NOTIFICATION_READY) { - - //get_scene()->connect("node_removed",this,"_node_removed"); - - if (first_enter) { - //it's in propertyeditor so.. could be moved around - - light_1_switch->set_normal_texture(get_icon("MaterialPreviewLight1","EditorIcons")); - light_1_switch->set_pressed_texture(get_icon("MaterialPreviewLight1Off","EditorIcons")); - light_2_switch->set_normal_texture(get_icon("MaterialPreviewLight2","EditorIcons")); - light_2_switch->set_pressed_texture(get_icon("MaterialPreviewLight2Off","EditorIcons")); - - sphere_switch->set_normal_texture(get_icon("MaterialPreviewSphereOff","EditorIcons")); - sphere_switch->set_pressed_texture(get_icon("MaterialPreviewSphere","EditorIcons")); - box_switch->set_normal_texture(get_icon("MaterialPreviewCubeOff","EditorIcons")); - box_switch->set_pressed_texture(get_icon("MaterialPreviewCube","EditorIcons")); - - first_enter=false; - } - - } - - if (p_what==NOTIFICATION_DRAW) { - - - Ref<Texture> checkerboard = get_icon("Checkerboard","EditorIcons"); - Size2 size = get_size(); - - draw_texture_rect(checkerboard,Rect2(Point2(),size),true); - - } -} - - - -void MaterialEditor::edit(Ref<Material> p_material) { - - material=p_material; - - if (!material.is_null()) { - sphere_mesh->surface_set_material(0,material); - box_mesh->surface_set_material(0,material); - } else { - - hide(); - } - -} - - -void MaterialEditor::_button_pressed(Node* p_button) { - - if (p_button==light_1_switch) { - light1->set_enabled(!light_1_switch->is_pressed()); - } - - if (p_button==light_2_switch) { - light2->set_enabled(!light_2_switch->is_pressed()); - } - - if (p_button==box_switch) { - box_instance->show(); - sphere_instance->hide(); - box_switch->set_pressed(true); - sphere_switch->set_pressed(false); - } - - if (p_button==sphere_switch) { - box_instance->hide(); - sphere_instance->show(); - box_switch->set_pressed(false); - sphere_switch->set_pressed(true); - } - -} - -void MaterialEditor::_bind_methods() { - - ClassDB::bind_method(D_METHOD("_gui_input"),&MaterialEditor::_gui_input); - ClassDB::bind_method(D_METHOD("_button_pressed"),&MaterialEditor::_button_pressed); - -} - -MaterialEditor::MaterialEditor() { - - viewport = memnew( Viewport ); - Ref<World> world; - world.instance(); - viewport->set_world(world); //use own world - add_child(viewport); - viewport->set_disable_input(true); - - camera = memnew( Camera ); - camera->set_transform(Transform(Matrix3(),Vector3(0,0,3))); - camera->set_perspective(45,0.1,10); - viewport->add_child(camera); - - light1 = memnew( DirectionalLight ); - light1->set_transform(Transform().looking_at(Vector3(-1,-1,-1),Vector3(0,1,0))); - viewport->add_child(light1); - - light2 = memnew( DirectionalLight ); - light2->set_transform(Transform().looking_at(Vector3(0,1,0),Vector3(0,0,1))); - light2->set_color(Light::COLOR_DIFFUSE,Color(0.7,0.7,0.7)); - light2->set_color(Light::COLOR_SPECULAR,Color(0.7,0.7,0.7)); - viewport->add_child(light2); - - sphere_instance = memnew( MeshInstance ); - viewport->add_child(sphere_instance); - - box_instance = memnew( MeshInstance ); - viewport->add_child(box_instance); - - Transform box_xform; - box_xform.basis.rotate(Vector3(1,0,0),Math::deg2rad(25)); - box_xform.basis = box_xform.basis * Matrix3().rotated(Vector3(0,1,0),Math::deg2rad(25)); - box_xform.basis.scale(Vector3(0.8,0.8,0.8)); - box_instance->set_transform(box_xform); - - { - - sphere_mesh.instance(); - - - int lats=32; - int lons=32; - float radius=1.0; - - PoolVector<Vector3> vertices; - PoolVector<Vector3> normals; - PoolVector<Vector2> uvs; - PoolVector<float> tangents; - Matrix3 tt = Matrix3(Vector3(0,1,0),Math_PI*0.5); - - for(int i = 1; i <= lats; i++) { - double lat0 = Math_PI * (-0.5 + (double) (i - 1) / lats); - double z0 = Math::sin(lat0); - double zr0 = Math::cos(lat0); - - double lat1 = Math_PI * (-0.5 + (double) i / lats); - double z1 = Math::sin(lat1); - double zr1 = Math::cos(lat1); - - for(int j = lons; j >= 1; j--) { - - double lng0 = 2 * Math_PI * (double) (j - 1) / lons; - double x0 = Math::cos(lng0); - double y0 = Math::sin(lng0); - - double lng1 = 2 * Math_PI * (double) (j) / lons; - double x1 = Math::cos(lng1); - double y1 = Math::sin(lng1); - - - Vector3 v[4]={ - Vector3(x1 * zr0, z0, y1 *zr0), - Vector3(x1 * zr1, z1, y1 *zr1), - Vector3(x0 * zr1, z1, y0 *zr1), - Vector3(x0 * zr0, z0, y0 *zr0) - }; - -#define ADD_POINT(m_idx) \ - normals.push_back(v[m_idx]); \ - vertices.push_back(v[m_idx] * radius); \ - { \ - Vector2 uv(Math::atan2(v[m_idx].x, v[m_idx].z), Math::atan2(-v[m_idx].y, v[m_idx].z)); \ - uv /= Math_PI; \ - uv *= 4.0; \ - uv = uv * 0.5 + Vector2(0.5, 0.5); \ - uvs.push_back(uv); \ - } \ - { \ - Vector3 t = tt.xform(v[m_idx]); \ - tangents.push_back(t.x); \ - tangents.push_back(t.y); \ - tangents.push_back(t.z); \ - tangents.push_back(1.0); \ - } - - - - ADD_POINT(0); - ADD_POINT(1); - ADD_POINT(2); - - ADD_POINT(2); - ADD_POINT(3); - ADD_POINT(0); - } - } - - Array arr; - arr.resize(VS::ARRAY_MAX); - arr[VS::ARRAY_VERTEX]=vertices; - arr[VS::ARRAY_NORMAL]=normals; - arr[VS::ARRAY_TANGENT]=tangents; - arr[VS::ARRAY_TEX_UV]=uvs; - - sphere_mesh->add_surface(Mesh::PRIMITIVE_TRIANGLES,arr); - - sphere_instance->set_mesh(sphere_mesh); - - } - { - - - box_mesh.instance(); - - PoolVector<Vector3> vertices; - PoolVector<Vector3> normals; - PoolVector<float> tangents; - PoolVector<Vector3> uvs; - - int vtx_idx=0; -#define ADD_VTX(m_idx) \ - ; \ - vertices.push_back(face_points[m_idx]); \ - normals.push_back(normal_points[m_idx]); \ - tangents.push_back(normal_points[m_idx][1]); \ - tangents.push_back(normal_points[m_idx][2]); \ - tangents.push_back(normal_points[m_idx][0]); \ - tangents.push_back(1.0); \ - uvs.push_back(Vector3(uv_points[m_idx * 2 + 0], uv_points[m_idx * 2 + 1], 0)); \ - vtx_idx++;\ - - for (int i=0;i<6;i++) { - - - Vector3 face_points[4]; - Vector3 normal_points[4]; - float uv_points[8]={0,0,0,1,1,1,1,0}; - - for (int j=0;j<4;j++) { - - float v[3]; - v[0]=1.0; - v[1]=1-2*((j>>1)&1); - v[2]=v[1]*(1-2*(j&1)); - - for (int k=0;k<3;k++) { - - if (i<3) - face_points[j][(i+k)%3]=v[k]*(i>=3?-1:1); - else - face_points[3-j][(i+k)%3]=v[k]*(i>=3?-1:1); - } - normal_points[j]=Vector3(); - normal_points[j][i%3]=(i>=3?-1:1); - } - - //tri 1 - ADD_VTX(0); - ADD_VTX(1); - ADD_VTX(2); - //tri 2 - ADD_VTX(2); - ADD_VTX(3); - ADD_VTX(0); - - } - - - - Array d; - d.resize(VS::ARRAY_MAX); - d[VisualServer::ARRAY_NORMAL]= normals ; - d[VisualServer::ARRAY_TANGENT]= tangents ; - d[VisualServer::ARRAY_TEX_UV]= uvs ; - d[VisualServer::ARRAY_VERTEX]= vertices ; - - PoolVector<int> indices; - indices.resize(vertices.size()); - for(int i=0;i<vertices.size();i++) - indices.set(i,i); - d[VisualServer::ARRAY_INDEX]=indices; - - box_mesh->add_surface(Mesh::PRIMITIVE_TRIANGLES,d); - box_instance->set_mesh(box_mesh); - box_instance->hide(); - - - - } - - set_custom_minimum_size(Size2(1,150)*EDSCALE); - - HBoxContainer *hb = memnew( HBoxContainer ); - add_child(hb); - hb->set_anchors_and_margins_preset(Control::PRESET_WIDE, Control::PRESET_MODE_MINSIZE, 2); - - VBoxContainer *vb_shape = memnew( VBoxContainer ); - hb->add_child(vb_shape); - - sphere_switch = memnew( TextureButton ); - sphere_switch->set_toggle_mode(true); - sphere_switch->set_pressed(true); - vb_shape->add_child(sphere_switch); - sphere_switch->connect("pressed",this,"_button_pressed",varray(sphere_switch)); - - box_switch = memnew( TextureButton ); - box_switch->set_toggle_mode(true); - box_switch->set_pressed(false); - vb_shape->add_child(box_switch); - box_switch->connect("pressed",this,"_button_pressed",varray(box_switch)); - - hb->add_spacer(); - - VBoxContainer *vb_light = memnew( VBoxContainer ); - hb->add_child(vb_light); - - light_1_switch = memnew( TextureButton ); - light_1_switch->set_toggle_mode(true); - vb_light->add_child(light_1_switch); - light_1_switch->connect("pressed",this,"_button_pressed",varray(light_1_switch)); - - light_2_switch = memnew( TextureButton ); - light_2_switch->set_toggle_mode(true); - vb_light->add_child(light_2_switch); - light_2_switch->connect("pressed",this,"_button_pressed",varray(light_2_switch)); - - first_enter=true; - -} - - -void MaterialEditorPlugin::edit(Object *p_object) { - - Material * s = Object::cast_to<Material>(p_object); - if (!s) - return; - - material_editor->edit(Ref<Material>(s)); -} - -bool MaterialEditorPlugin::handles(Object *p_object) const { - - return p_object->is_type("Material"); -} - -void MaterialEditorPlugin::make_visible(bool p_visible) { - - if (p_visible) { - material_editor->show(); - //material_editor->set_process(true); - } else { - - material_editor->hide(); - //material_editor->set_process(false); - } - -} - -MaterialEditorPlugin::MaterialEditorPlugin(EditorNode *p_node) { - - editor=p_node; - material_editor = memnew( MaterialEditor ); - add_control_to_container(CONTAINER_PROPERTY_EDITOR_BOTTOM,material_editor); - material_editor->hide(); - - - -} - - -MaterialEditorPlugin::~MaterialEditorPlugin() -{ -} -#endif +#include "scene/resources/particles_material.h" String SpatialMaterialConversionPlugin::converts_to() const { diff --git a/editor/plugins/material_editor_plugin.h b/editor/plugins/material_editor_plugin.h index 31a927d83f..c06d95e700 100644 --- a/editor/plugins/material_editor_plugin.h +++ b/editor/plugins/material_editor_plugin.h @@ -32,77 +32,6 @@ #define MATERIAL_EDITOR_PLUGIN_H #include "editor/property_editor.h" -// FIXME: Disabled as (according to reduz) users were complaining that it gets in the way -// Waiting for PropertyEditor rewrite (planned for 3.1) to be refactored. -#if 0 - -#include "editor/editor_node.h" -#include "editor/editor_plugin.h" -#include "scene/3d/camera.h" -#include "scene/3d/light.h" -#include "scene/3d/mesh_instance.h" -#include "scene/resources/material.h" - -class MaterialEditor : public Control { - - GDCLASS(MaterialEditor, Control); - - - Viewport *viewport; - MeshInstance *sphere_instance; - MeshInstance *box_instance; - DirectionalLight *light1; - DirectionalLight *light2; - Camera *camera; - - Ref<Mesh> sphere_mesh; - Ref<Mesh> box_mesh; - - TextureButton *sphere_switch; - TextureButton *box_switch; - - TextureButton *light_1_switch; - TextureButton *light_2_switch; - - - Ref<Material> material; - - - void _button_pressed(Node* p_button); - bool first_enter; - -protected: - void _notification(int p_what); - void _gui_input(InputEvent p_event); - static void _bind_methods(); -public: - - void edit(Ref<Material> p_material); - MaterialEditor(); -}; - - -class MaterialEditorPlugin : public EditorPlugin { - - GDCLASS( MaterialEditorPlugin, EditorPlugin ); - - MaterialEditor *material_editor; - EditorNode *editor; - -public: - - virtual String get_name() const { return "Material"; } - bool has_main_screen() const { return false; } - virtual void edit(Object *p_node); - virtual bool handles(Object *p_node) const; - virtual void make_visible(bool p_visible); - - MaterialEditorPlugin(EditorNode *p_node); - ~MaterialEditorPlugin(); - -}; - -#endif class SpatialMaterialConversionPlugin : public EditorResourceConversionPlugin { GDCLASS(SpatialMaterialConversionPlugin, EditorResourceConversionPlugin) diff --git a/editor/plugins/particles_2d_editor_plugin.cpp b/editor/plugins/particles_2d_editor_plugin.cpp index ae5d510502..3bde157edf 100644 --- a/editor/plugins/particles_2d_editor_plugin.cpp +++ b/editor/plugins/particles_2d_editor_plugin.cpp @@ -32,8 +32,8 @@ #include "canvas_item_editor_plugin.h" #include "io/image_loader.h" -#include "scene/3d/particles.h" #include "scene/gui/separator.h" +#include "scene/resources/particles_material.h" void Particles2DEditorPlugin::edit(Object *p_object) { diff --git a/editor/plugins/particles_2d_editor_plugin.h b/editor/plugins/particles_2d_editor_plugin.h index 2b6123141b..71ca8ef499 100644 --- a/editor/plugins/particles_2d_editor_plugin.h +++ b/editor/plugins/particles_2d_editor_plugin.h @@ -34,7 +34,6 @@ #include "editor/editor_node.h" #include "editor/editor_plugin.h" #include "scene/2d/collision_polygon_2d.h" - #include "scene/2d/particles_2d.h" #include "scene/gui/box_container.h" #include "scene/gui/file_dialog.h" diff --git a/editor/plugins/particles_editor_plugin.cpp b/editor/plugins/particles_editor_plugin.cpp index 3c381158a4..9a1a60805f 100644 --- a/editor/plugins/particles_editor_plugin.cpp +++ b/editor/plugins/particles_editor_plugin.cpp @@ -29,9 +29,12 @@ /*************************************************************************/ #include "particles_editor_plugin.h" + #include "editor/plugins/spatial_editor_plugin.h" #include "io/resource_loader.h" #include "scene/3d/cpu_particles.h" +#include "scene/resources/particles_material.h" + bool ParticlesEditorBase::_generate(PoolVector<Vector3> &points, PoolVector<Vector3> &normals) { bool use_normals = emission_fill->get_selected() == 1; diff --git a/editor/plugins/particles_editor_plugin.h b/editor/plugins/particles_editor_plugin.h index 622ce6e8a9..830d30d98f 100644 --- a/editor/plugins/particles_editor_plugin.h +++ b/editor/plugins/particles_editor_plugin.h @@ -43,6 +43,7 @@ class ParticlesEditorBase : public Control { GDCLASS(ParticlesEditorBase, Control) + protected: Spatial *base_node; Panel *panel; diff --git a/editor/plugins/path_editor_plugin.cpp b/editor/plugins/path_editor_plugin.cpp index fc5156d26e..df6c40ed02 100644 --- a/editor/plugins/path_editor_plugin.cpp +++ b/editor/plugins/path_editor_plugin.cpp @@ -30,7 +30,7 @@ #include "path_editor_plugin.h" -#include "os/keyboard.h" +#include "core/os/keyboard.h" #include "scene/resources/curve.h" #include "spatial_editor_plugin.h" @@ -57,7 +57,7 @@ String PathSpatialGizmo::get_handle_name(int p_idx) const { return n; } -Variant PathSpatialGizmo::get_handle_value(int p_idx) const { +Variant PathSpatialGizmo::get_handle_value(int p_idx) { Ref<Curve3D> c = path->get_curve(); if (c.is_null()) diff --git a/editor/plugins/path_editor_plugin.h b/editor/plugins/path_editor_plugin.h index 61f309e794..c77b2a41cc 100644 --- a/editor/plugins/path_editor_plugin.h +++ b/editor/plugins/path_editor_plugin.h @@ -45,7 +45,7 @@ class PathSpatialGizmo : public EditorSpatialGizmo { public: virtual String get_handle_name(int p_idx) const; - virtual Variant get_handle_value(int p_idx) const; + virtual Variant get_handle_value(int p_idx); virtual void set_handle(int p_idx, Camera *p_camera, const Point2 &p_point); virtual void commit_handle(int p_idx, const Variant &p_restore, bool p_cancel = false); diff --git a/editor/plugins/script_text_editor.cpp b/editor/plugins/script_text_editor.cpp index 66705f85bf..e0eb89d6b6 100644 --- a/editor/plugins/script_text_editor.cpp +++ b/editor/plugins/script_text_editor.cpp @@ -1475,9 +1475,9 @@ ScriptTextEditor::ScriptTextEditor() { convert_case->set_name("convert_case"); edit_menu->get_popup()->add_child(convert_case); edit_menu->get_popup()->add_submenu_item(TTR("Convert Case"), "convert_case"); - convert_case->add_shortcut(ED_SHORTCUT("script_text_editor/convert_to_uppercase", TTR("Uppercase")), EDIT_TO_UPPERCASE); - convert_case->add_shortcut(ED_SHORTCUT("script_text_editor/convert_to_lowercase", TTR("Lowercase")), EDIT_TO_LOWERCASE); - convert_case->add_shortcut(ED_SHORTCUT("script_text_editor/capitalize", TTR("Capitalize")), EDIT_CAPITALIZE); + convert_case->add_shortcut(ED_SHORTCUT("script_text_editor/convert_to_uppercase", TTR("Uppercase"), KEY_MASK_SHIFT | KEY_F4), EDIT_TO_UPPERCASE); + convert_case->add_shortcut(ED_SHORTCUT("script_text_editor/convert_to_lowercase", TTR("Lowercase"), KEY_MASK_SHIFT | KEY_F5), EDIT_TO_LOWERCASE); + convert_case->add_shortcut(ED_SHORTCUT("script_text_editor/capitalize", TTR("Capitalize"), KEY_MASK_SHIFT | KEY_F6), EDIT_CAPITALIZE); convert_case->connect("id_pressed", this, "_edit_option"); highlighters["Standard"] = NULL; @@ -1568,10 +1568,6 @@ void ScriptTextEditor::register_editor() { ED_SHORTCUT("script_text_editor/goto_next_breakpoint", TTR("Goto Next Breakpoint"), KEY_MASK_CMD | KEY_PERIOD); ED_SHORTCUT("script_text_editor/goto_previous_breakpoint", TTR("Goto Previous Breakpoint"), KEY_MASK_CMD | KEY_COMMA); - ED_SHORTCUT("script_text_editor/convert_to_uppercase", TTR("Convert To Uppercase"), KEY_MASK_SHIFT | KEY_F4); - ED_SHORTCUT("script_text_editor/convert_to_lowercase", TTR("Convert To Lowercase"), KEY_MASK_SHIFT | KEY_F3); - ED_SHORTCUT("script_text_editor/capitalize", TTR("Capitalize"), KEY_MASK_SHIFT | KEY_F2); - ED_SHORTCUT("script_text_editor/find", TTR("Find..."), KEY_MASK_CMD | KEY_F); #ifdef OSX_ENABLED ED_SHORTCUT("script_text_editor/find_next", TTR("Find Next"), KEY_MASK_CMD | KEY_G); diff --git a/editor/plugins/spatial_editor_plugin.cpp b/editor/plugins/spatial_editor_plugin.cpp index 5179f8be85..e86424ee51 100644 --- a/editor/plugins/spatial_editor_plugin.cpp +++ b/editor/plugins/spatial_editor_plugin.cpp @@ -30,23 +30,25 @@ #include "spatial_editor_plugin.h" -#include "camera_matrix.h" +#include "core/math/camera_matrix.h" #include "core/os/input.h" - +#include "core/os/keyboard.h" +#include "core/print_string.h" +#include "core/project_settings.h" +#include "core/sort.h" #include "editor/editor_node.h" #include "editor/editor_settings.h" #include "editor/plugins/animation_player_editor_plugin.h" #include "editor/plugins/script_editor_plugin.h" #include "editor/script_editor_debugger.h" #include "editor/spatial_editor_gizmos.h" -#include "os/keyboard.h" -#include "print_string.h" -#include "project_settings.h" #include "scene/3d/camera.h" +#include "scene/3d/collision_shape.h" +#include "scene/3d/mesh_instance.h" +#include "scene/3d/physics_body.h" #include "scene/3d/visual_instance.h" #include "scene/resources/packed_scene.h" #include "scene/resources/surface_tool.h" -#include "sort.h" #define DISTANCE_DEFAULT 4 @@ -5378,7 +5380,6 @@ SpatialEditor::SpatialEditor(EditorNode *p_editor) { ED_SHORTCUT("spatial_editor/tool_move", TTR("Tool Move"), KEY_W); ED_SHORTCUT("spatial_editor/tool_rotate", TTR("Tool Rotate"), KEY_E); ED_SHORTCUT("spatial_editor/tool_scale", TTR("Tool Scale"), KEY_R); - ED_SHORTCUT("spatial_editor/snap_to_floor", TTR("Snap To Floor"), KEY_PAGEDOWN); ED_SHORTCUT("spatial_editor/freelook_toggle", TTR("Toggle Freelook"), KEY_MASK_SHIFT + KEY_F); @@ -5389,7 +5390,7 @@ SpatialEditor::SpatialEditor(EditorNode *p_editor) { hbc_menu->add_child(transform_menu); p = transform_menu->get_popup(); - p->add_shortcut(ED_SHORTCUT("spatial_editor/snap_to_floor", TTR("Snap object to floor")), MENU_SNAP_TO_FLOOR); + p->add_shortcut(ED_SHORTCUT("spatial_editor/snap_to_floor", TTR("Snap object to floor"), KEY_PAGEDOWN), MENU_SNAP_TO_FLOOR); p->add_shortcut(ED_SHORTCUT("spatial_editor/configure_snap", TTR("Configure Snap...")), MENU_TRANSFORM_CONFIGURE_SNAP); p->add_separator(); p->add_shortcut(ED_SHORTCUT("spatial_editor/transform_dialog", TTR("Transform Dialog...")), MENU_TRANSFORM_DIALOG); diff --git a/editor/project_export.cpp b/editor/project_export.cpp index 019d5d382c..df79317549 100644 --- a/editor/project_export.cpp +++ b/editor/project_export.cpp @@ -723,6 +723,25 @@ void ProjectExportDialog::_open_export_template_manager() { hide(); } +void ProjectExportDialog::_validate_export_path(const String &p_path) { + // Disable export via OK button or Enter key if LineEdit has an empty filename + bool invalid_path = (p_path.get_file().get_basename() == ""); + + // Check if state change before needlessly messing with signals + if (invalid_path && export_project->get_ok()->is_disabled()) + return; + if (!invalid_path && !export_project->get_ok()->is_disabled()) + return; + + if (invalid_path) { + export_project->get_ok()->set_disabled(true); + export_project->get_line_edit()->disconnect("text_entered", export_project, "_file_entered"); + } else { + export_project->get_ok()->set_disabled(false); + export_project->get_line_edit()->connect("text_entered", export_project, "_file_entered"); + } +} + void ProjectExportDialog::_export_project() { Ref<EditorExportPreset> current = EditorExport::get_singleton()->get_export_preset(presets->get_current()); @@ -732,12 +751,19 @@ void ProjectExportDialog::_export_project() { export_project->set_access(FileDialog::ACCESS_FILESYSTEM); export_project->clear_filters(); - export_project->set_current_file(default_filename); String extension = platform->get_binary_extension(current); - if (extension != String()) { export_project->add_filter("*." + extension + " ; " + platform->get_name() + " Export"); + export_project->set_current_file(default_filename + "." + extension); + } else { + export_project->set_current_file(default_filename); + } + + // Ensure that signal is connected if previous attempt left it disconnected with _validate_export_path + if (!export_project->get_line_edit()->is_connected("text_entered", export_project, "_file_entered")) { + export_project->get_ok()->set_disabled(false); + export_project->get_line_edit()->connect("text_entered", export_project, "_file_entered"); } export_project->set_mode(FileDialog::MODE_SAVE_FILE); @@ -746,7 +772,7 @@ void ProjectExportDialog::_export_project() { void ProjectExportDialog::_export_project_to_path(const String &p_path) { // Save this name for use in future exports (but drop the file extension) - default_filename = p_path.get_basename().get_file(); + default_filename = p_path.get_file().get_basename(); EditorSettings::get_singleton()->set_project_metadata("export_options", "default_filename", default_filename); Ref<EditorExportPreset> current = EditorExport::get_singleton()->get_export_preset(presets->get_current()); @@ -785,11 +811,13 @@ void ProjectExportDialog::_bind_methods() { ClassDB::bind_method("_export_pck_zip", &ProjectExportDialog::_export_pck_zip); ClassDB::bind_method("_export_pck_zip_selected", &ProjectExportDialog::_export_pck_zip_selected); ClassDB::bind_method("_open_export_template_manager", &ProjectExportDialog::_open_export_template_manager); + ClassDB::bind_method("_validate_export_path", &ProjectExportDialog::_validate_export_path); ClassDB::bind_method("_export_project", &ProjectExportDialog::_export_project); ClassDB::bind_method("_export_project_to_path", &ProjectExportDialog::_export_project_to_path); ClassDB::bind_method("_custom_features_changed", &ProjectExportDialog::_custom_features_changed); ClassDB::bind_method("_tab_changed", &ProjectExportDialog::_tab_changed); } + ProjectExportDialog::ProjectExportDialog() { set_title(TTR("Export")); @@ -942,6 +970,9 @@ ProjectExportDialog::ProjectExportDialog() { get_cancel()->set_text(TTR("Close")); get_ok()->set_text(TTR("Export PCK/Zip")); export_button = add_button(TTR("Export Project"), !OS::get_singleton()->get_swap_ok_cancel(), "export"); + export_button->connect("pressed", this, "_export_project"); + // Disable initially before we select a valid preset + export_button->set_disabled(true); export_pck_zip = memnew(FileDialog); export_pck_zip->add_filter("*.zip ; ZIP File"); @@ -981,7 +1012,7 @@ ProjectExportDialog::ProjectExportDialog() { export_project->set_access(FileDialog::ACCESS_FILESYSTEM); add_child(export_project); export_project->connect("file_selected", this, "_export_project_to_path"); - export_button->connect("pressed", this, "_export_project"); + export_project->get_line_edit()->connect("text_changed", this, "_validate_export_path"); export_debug = memnew(CheckButton); export_debug->set_text(TTR("Export With Debug")); @@ -997,10 +1028,14 @@ ProjectExportDialog::ProjectExportDialog() { editor_icons = "EditorIcons"; - default_filename = EditorSettings::get_singleton()->get_project_metadata("export_options", "default_filename", String()); - + default_filename = EditorSettings::get_singleton()->get_project_metadata("export_options", "default_filename", ""); + // If no default set, use project name if (default_filename == "") { + // If no project name defined, use a sane default default_filename = ProjectSettings::get_singleton()->get("application/config/name"); + if (default_filename == "") { + default_filename = "UnnamedProject"; + } } } diff --git a/editor/project_export.h b/editor/project_export.h index 1f8723febd..552c6d7faf 100644 --- a/editor/project_export.h +++ b/editor/project_export.h @@ -136,6 +136,7 @@ private: void _export_pck_zip(); void _export_pck_zip_selected(const String &p_path); + void _validate_export_path(const String &p_path); void _export_project(); void _export_project_to_path(const String &p_path); diff --git a/editor/project_manager.cpp b/editor/project_manager.cpp index 3a6a73d3cc..4d25a1da5c 100644 --- a/editor/project_manager.cpp +++ b/editor/project_manager.cpp @@ -1751,7 +1751,11 @@ ProjectManager::ProjectManager() { } break; } +#ifndef OSX_ENABLED + // The macOS platform implementation uses its own hiDPI window resizing code + // TODO: Resize windows on hiDPI displays on Windows and Linux and remove the line below OS::get_singleton()->set_window_size(OS::get_singleton()->get_window_size() * MAX(1, EDSCALE)); +#endif } FileDialog::set_default_show_hidden_files(EditorSettings::get_singleton()->get("filesystem/file_dialog/show_hidden_files")); diff --git a/editor/spatial_editor_gizmos.cpp b/editor/spatial_editor_gizmos.cpp index 1fe32b0ae2..00067b84f7 100644 --- a/editor/spatial_editor_gizmos.cpp +++ b/editor/spatial_editor_gizmos.cpp @@ -32,8 +32,27 @@ #include "geometry.h" #include "quick_hull.h" -#include "scene/3d/camera.h" +#include "scene/3d/audio_stream_player_3d.h" +#include "scene/3d/baked_lightmap.h" +#include "scene/3d/collision_polygon.h" +#include "scene/3d/collision_shape.h" +#include "scene/3d/gi_probe.h" +#include "scene/3d/light.h" +#include "scene/3d/listener.h" +#include "scene/3d/mesh_instance.h" +#include "scene/3d/navigation_mesh.h" +#include "scene/3d/particles.h" +#include "scene/3d/physics_joint.h" +#include "scene/3d/portal.h" +#include "scene/3d/position_3d.h" +#include "scene/3d/ray_cast.h" +#include "scene/3d/reflection_probe.h" +#include "scene/3d/room_instance.h" #include "scene/3d/soft_body.h" +#include "scene/3d/spring_arm.h" +#include "scene/3d/sprite_3d.h" +#include "scene/3d/vehicle_body.h" +#include "scene/3d/visibility_notifier.h" #include "scene/resources/box_shape.h" #include "scene/resources/capsule_shape.h" #include "scene/resources/convex_polygon_shape.h" @@ -44,12 +63,6 @@ #include "scene/resources/sphere_shape.h" #include "scene/resources/surface_tool.h" -// Keep small children away from this file. -// It's so ugly it will eat them alive - -// The previous comment is kept only for historical reasons. -// No children will be harmed by the viewing of this file... hopefully. - #define HANDLE_HALF_SIZE 9.5 bool EditorSpatialGizmo::is_editable() const { diff --git a/editor/spatial_editor_gizmos.h b/editor/spatial_editor_gizmos.h index 6f29e9d999..371e3bc689 100644 --- a/editor/spatial_editor_gizmos.h +++ b/editor/spatial_editor_gizmos.h @@ -32,27 +32,7 @@ #define SPATIAL_EDITOR_GIZMOS_H #include "editor/plugins/spatial_editor_plugin.h" -#include "scene/3d/audio_stream_player_3d.h" -#include "scene/3d/baked_lightmap.h" #include "scene/3d/camera.h" -#include "scene/3d/collision_polygon.h" -#include "scene/3d/collision_shape.h" -#include "scene/3d/gi_probe.h" -#include "scene/3d/light.h" -#include "scene/3d/listener.h" -#include "scene/3d/mesh_instance.h" -#include "scene/3d/navigation_mesh.h" -#include "scene/3d/particles.h" -#include "scene/3d/physics_joint.h" -#include "scene/3d/portal.h" -#include "scene/3d/position_3d.h" -#include "scene/3d/ray_cast.h" -#include "scene/3d/reflection_probe.h" -#include "scene/3d/room_instance.h" -#include "scene/3d/spring_arm.h" -#include "scene/3d/sprite_3d.h" -#include "scene/3d/vehicle_body.h" -#include "scene/3d/visibility_notifier.h" class Camera; diff --git a/modules/bullet/space_bullet.cpp b/modules/bullet/space_bullet.cpp index b12925b073..e8e6fc4d07 100644 --- a/modules/bullet/space_bullet.cpp +++ b/modules/bullet/space_bullet.cpp @@ -642,7 +642,7 @@ void SpaceBullet::destroy_world() { void SpaceBullet::check_ghost_overlaps() { /// Algorithm support variables - btConvexShape *other_body_shape; + btCollisionShape *other_body_shape; btConvexShape *area_shape; btGjkPairDetector::ClosestPointInput gjk_input; AreaBullet *area; @@ -694,20 +694,42 @@ void SpaceBullet::check_ghost_overlaps() { // For each other object shape for (z = otherObject->get_compound_shape()->getNumChildShapes() - 1; 0 <= z; --z) { - if (!otherObject->get_compound_shape()->getChildShape(z)->isConvex()) - continue; - - other_body_shape = static_cast<btConvexShape *>(otherObject->get_compound_shape()->getChildShape(z)); + other_body_shape = static_cast<btCollisionShape *>(otherObject->get_compound_shape()->getChildShape(z)); gjk_input.m_transformB = otherObject->get_transform__bullet() * otherObject->get_compound_shape()->getChildTransform(z); - btPointCollector result; - btGjkPairDetector gjk_pair_detector(area_shape, other_body_shape, gjk_simplex_solver, gjk_epa_pen_solver); - gjk_pair_detector.getClosestPoints(gjk_input, result, 0); + if (other_body_shape->isConvex()) { + + btPointCollector result; + btGjkPairDetector gjk_pair_detector(area_shape, static_cast<btConvexShape *>(other_body_shape), gjk_simplex_solver, gjk_epa_pen_solver); + gjk_pair_detector.getClosestPoints(gjk_input, result, 0); + + if (0 >= result.m_distance) { + hasOverlap = true; + goto collision_found; + } + + } else { + + btCollisionObjectWrapper obA(NULL, area_shape, area->get_bt_ghost(), gjk_input.m_transformA, -1, y); + btCollisionObjectWrapper obB(NULL, other_body_shape, otherObject->get_bt_collision_object(), gjk_input.m_transformB, -1, z); - if (0 >= result.m_distance) { - hasOverlap = true; - goto collision_found; + btCollisionAlgorithm *algorithm = dispatcher->findAlgorithm(&obA, &obB, NULL, BT_CONTACT_POINT_ALGORITHMS); + + if (!algorithm) + continue; + + GodotDeepPenetrationContactResultCallback contactPointResult(&obA, &obB); + algorithm->processCollision(&obA, &obB, dynamicsWorld->getDispatchInfo(), &contactPointResult); + + algorithm->~btCollisionAlgorithm(); + dispatcher->freeCollisionAlgorithm(algorithm); + + if (contactPointResult.hasHit()) { + hasOverlap = true; + goto collision_found; + } } + } // ~For each other object shape } // ~For each area shape diff --git a/modules/gdnative/gdnative/basis.cpp b/modules/gdnative/gdnative/basis.cpp index 372bdf3fb1..70d2814577 100644 --- a/modules/gdnative/gdnative/basis.cpp +++ b/modules/gdnative/gdnative/basis.cpp @@ -113,6 +113,40 @@ godot_vector3 GDAPI godot_basis_get_scale(const godot_basis *p_self) { return dest; } +godot_quat GDAPI godot_basis_get_quat(const godot_basis *p_self) { + godot_quat dest; + const Basis *self = (const Basis *)p_self; + *((Quat *)&dest) = self->get_quat(); + return dest; +} + +void GDAPI godot_basis_set_quat(godot_basis *p_self, const godot_quat *p_quat) { + Basis *self = (Basis *)p_self; + const Quat *quat = (const Quat *)p_quat; + self->set_quat(*quat); +} + +void GDAPI godot_basis_set_axis_angle_scale(godot_basis *p_self, const godot_vector3 *p_axis, godot_real p_phi, const godot_vector3 *p_scale) { + Basis *self = (Basis *)p_self; + const Vector3 *axis = (const Vector3 *)p_axis; + const Vector3 *scale = (const Vector3 *)p_scale; + self->set_axis_angle_scale(*axis, p_phi, *scale); +} + +void GDAPI godot_basis_set_euler_scale(godot_basis *p_self, const godot_vector3 *p_euler, const godot_vector3 *p_scale) { + Basis *self = (Basis *)p_self; + const Vector3 *euler = (const Vector3 *)p_euler; + const Vector3 *scale = (const Vector3 *)p_scale; + self->set_euler_scale(*euler, *scale); +} + +void GDAPI godot_basis_set_quat_scale(godot_basis *p_self, const godot_quat *p_quat, const godot_vector3 *p_scale) { + Basis *self = (Basis *)p_self; + const Quat *quat = (const Quat *)p_quat; + const Vector3 *scale = (const Vector3 *)p_scale; + self->set_quat_scale(*quat, *scale); +} + godot_vector3 GDAPI godot_basis_get_euler(const godot_basis *p_self) { godot_vector3 dest; const Basis *self = (const Basis *)p_self; diff --git a/modules/gdnative/gdnative/dictionary.cpp b/modules/gdnative/gdnative/dictionary.cpp index 786e614158..34cc91129e 100644 --- a/modules/gdnative/gdnative/dictionary.cpp +++ b/modules/gdnative/gdnative/dictionary.cpp @@ -155,6 +155,12 @@ godot_string GDAPI godot_dictionary_to_json(const godot_dictionary *p_self) { return raw_dest; } +godot_bool GDAPI godot_dictionary_erase_with_return(godot_dictionary *p_self, const godot_variant *p_key) { + Dictionary *self = (Dictionary *)p_self; + const Variant *key = (const Variant *)p_key; + return self->erase(*key); +} + #ifdef __cplusplus } #endif diff --git a/modules/gdnative/gdnative/gdnative.cpp b/modules/gdnative/gdnative/gdnative.cpp index 041990e137..73fca655a8 100644 --- a/modules/gdnative/gdnative/gdnative.cpp +++ b/modules/gdnative/gdnative/gdnative.cpp @@ -166,6 +166,10 @@ void _gdnative_report_loading_error(const godot_object *p_library, const char *p _err_print_error("gdnative_init", library->get_current_library_path().utf8().ptr(), 0, message.utf8().ptr()); } +bool GDAPI godot_is_instance_valid(const godot_object *p_object) { + return ObjectDB::instance_validate((Object *)p_object); +} + #ifdef __cplusplus } #endif diff --git a/modules/gdnative/gdnative/quat.cpp b/modules/gdnative/gdnative/quat.cpp index 56ff7fe3a8..ddec77edcd 100644 --- a/modules/gdnative/gdnative/quat.cpp +++ b/modules/gdnative/gdnative/quat.cpp @@ -49,6 +49,18 @@ void GDAPI godot_quat_new_with_axis_angle(godot_quat *r_dest, const godot_vector *dest = Quat(*axis, p_angle); } +void GDAPI godot_quat_new_with_basis(godot_quat *r_dest, const godot_basis *p_basis) { + const Basis *basis = (const Basis *)p_basis; + Quat *dest = (Quat *)r_dest; + *dest = Quat(*basis); +} + +void GDAPI godot_quat_new_with_euler(godot_quat *r_dest, const godot_vector3 *p_euler) { + const Vector3 *euler = (const Vector3 *)p_euler; + Quat *dest = (Quat *)r_dest; + *dest = Quat(*euler); +} + godot_real GDAPI godot_quat_get_x(const godot_quat *p_self) { const Quat *self = (const Quat *)p_self; return self->x; diff --git a/modules/gdnative/gdnative/transform.cpp b/modules/gdnative/gdnative/transform.cpp index 715f2e3c08..ee6140c7d0 100644 --- a/modules/gdnative/gdnative/transform.cpp +++ b/modules/gdnative/gdnative/transform.cpp @@ -56,6 +56,12 @@ void GDAPI godot_transform_new(godot_transform *r_dest, const godot_basis *p_bas *dest = Transform(*basis, *origin); } +void GDAPI godot_transform_new_with_quat(godot_transform *r_dest, const godot_quat *p_quat) { + const Quat *quat = (const Quat *)p_quat; + Transform *dest = (Transform *)r_dest; + *dest = Transform(*quat); +} + godot_basis GDAPI godot_transform_get_basis(const godot_transform *p_self) { godot_basis dest; const Transform *self = (const Transform *)p_self; diff --git a/modules/gdnative/gdnative_api.json b/modules/gdnative/gdnative_api.json index e326d11a84..dce3d7e96b 100644 --- a/modules/gdnative/gdnative_api.json +++ b/modules/gdnative/gdnative_api.json @@ -5,7 +5,98 @@ "major": 1, "minor": 0 }, - "next": null, + "next": { + "type": "CORE", + "version": { + "major": 1, + "minor": 1 + }, + "next": null, + "api": [ + { + "name": "godot_basis_get_quat", + "return_type": "godot_quat", + "arguments": [ + ["const godot_basis *", "p_self"] + ] + }, + { + "name": "godot_basis_set_quat", + "return_type": "void", + "arguments": [ + ["godot_basis *", "p_self"], + ["const godot_quat *", "p_quat"] + ] + }, + { + "name": "godot_basis_set_axis_angle_scale", + "return_type": "void", + "arguments": [ + ["godot_basis *", "p_self"], + ["const godot_vector3 *", "p_axis"], + ["godot_real", "p_phi"], + ["const godot_vector3 *", "p_scale"] + ] + }, + { + "name": "godot_basis_set_euler_scale", + "return_type": "void", + "arguments": [ + ["godot_basis *", "p_self"], + ["const godot_vector3 *", "p_euler"], + ["const godot_vector3 *", "p_scale"] + ] + }, + { + "name": "godot_basis_set_quat_scale", + "return_type": "void", + "arguments": [ + ["godot_basis *", "p_self"], + ["const godot_quat *", "p_quat"], + ["const godot_vector3 *", "p_scale"] + ] + }, + { + "name": "godot_dictionary_erase_with_return", + "return_type": "bool", + "arguments": [ + ["godot_dictionary *", "p_self"], + ["const godot_variant *", "p_key"] + ] + }, + { + "name": "godot_is_instance_valid", + "return_type": "bool", + "arguments": [ + ["const godot_object *", "p_object"] + ] + }, + { + "name": "godot_quat_new_with_basis", + "return_type": "void", + "arguments": [ + ["godot_quat *", "r_dest"], + ["const godot_basis *", "p_basis"] + ] + }, + { + "name": "godot_quat_new_with_euler", + "return_type": "void", + "arguments": [ + ["godot_quat *", "r_dest"], + ["const godot_vector3 *", "p_euler"] + ] + }, + { + "name": "godot_transform_new_with_quat", + "return_type": "void", + "arguments": [ + ["godot_transform *", "r_dest"], + ["const godot_quat *", "p_quat"] + ] + } + ] + }, "api": [ { "name": "godot_color_new_rgba", @@ -4484,7 +4575,7 @@ ] }, { - "name": "godot_string_wide_str", + "name": "godot_string_wide_str", "return_type": "const wchar_t *", "arguments": [ ["const godot_string *", "p_self"] @@ -5253,21 +5344,21 @@ "name": "godot_string_ascii", "return_type": "godot_char_string", "arguments": [ - ["const godot_string *", "p_self"] + ["const godot_string *", "p_self"] ] }, { "name": "godot_string_ascii_extended", "return_type": "godot_char_string", "arguments": [ - ["const godot_string *", "p_self"] + ["const godot_string *", "p_self"] ] }, { "name": "godot_string_utf8", "return_type": "godot_char_string", "arguments": [ - ["const godot_string *", "p_self"] + ["const godot_string *", "p_self"] ] }, { @@ -5765,15 +5856,15 @@ "minor": 0 }, "next": { - "type": "NATIVESCRIPT", - "version": { - "major": 1, - "minor": 1 - }, - "next": null, - "api": [ + "type": "NATIVESCRIPT", + "version": { + "major": 1, + "minor": 1 + }, + "next": null, + "api": [ { - "name": "godot_nativescript_set_method_argument_information", + "name": "godot_nativescript_set_method_argument_information", "return_type": "void", "arguments": [ ["void *", "p_gdnative_handle"], @@ -5784,7 +5875,7 @@ ] }, { - "name": "godot_nativescript_set_class_documentation", + "name": "godot_nativescript_set_class_documentation", "return_type": "void", "arguments": [ ["void *", "p_gdnative_handle"], @@ -5793,7 +5884,7 @@ ] }, { - "name": "godot_nativescript_set_method_documentation", + "name": "godot_nativescript_set_method_documentation", "return_type": "void", "arguments": [ ["void *", "p_gdnative_handle"], @@ -5803,7 +5894,7 @@ ] }, { - "name": "godot_nativescript_set_property_documentation", + "name": "godot_nativescript_set_property_documentation", "return_type": "void", "arguments": [ ["void *", "p_gdnative_handle"], @@ -5813,7 +5904,7 @@ ] }, { - "name": "godot_nativescript_set_signal_documentation", + "name": "godot_nativescript_set_signal_documentation", "return_type": "void", "arguments": [ ["void *", "p_gdnative_handle"], @@ -5874,7 +5965,7 @@ "return_type": "void *", "arguments": [ ["int", "p_idx"], - ["godot_object *", "p_object"] + ["godot_object *", "p_object"] ] }, { @@ -5885,7 +5976,7 @@ ["uint64_t", "p_line"] ] } - ] + ] }, "api": [ { diff --git a/modules/gdnative/gdnative_builders.py b/modules/gdnative/gdnative_builders.py index 8a1cd049af..f9d1ed9dc5 100644 --- a/modules/gdnative/gdnative_builders.py +++ b/modules/gdnative/gdnative_builders.py @@ -82,10 +82,35 @@ def _build_gdnative_api_struct_header(api): return ret_val + + def generate_core_extension_struct(core): + ret_val = [] + if core['next']: + ret_val += generate_core_extension_struct(core['next']) + + ret_val += [ + 'typedef struct godot_gdnative_core_' + ('{0}_{1}'.format(core['version']['major'], core['version']['minor'])) + '_api_struct {', + '\tunsigned int type;', + '\tgodot_gdnative_api_version version;', + '\tconst godot_gdnative_api_struct *next;', + ] + + for funcdef in core['api']: + args = ', '.join(['%s%s' % (_spaced(t), n) for t, n in funcdef['arguments']]) + ret_val.append('\t%s(*%s)(%s);' % (_spaced(funcdef['return_type']), funcdef['name'], args)) + + ret_val += ['} godot_gdnative_core_' + '{0}_{1}'.format(core['version']['major'], core['version']['minor']) + '_api_struct;', ''] + + return ret_val + + for ext in api['extensions']: name = ext['name'] out += generate_extension_struct(name, ext, False) + if api['core']['next']: + out += generate_core_extension_struct(api['core']['next']) + out += [ 'typedef struct godot_gdnative_core_api_struct {', '\tunsigned int type;', @@ -146,6 +171,27 @@ def _build_gdnative_api_struct_source(api): ret_val += ['};\n'] return ret_val + + + def get_core_struct_definition(core): + ret_val = [] + + if core['next']: + ret_val += get_core_struct_definition(core['next']) + + ret_val += [ + 'extern const godot_gdnative_core_' + ('{0}_{1}_api_struct api_{0}_{1}'.format(core['version']['major'], core['version']['minor'])) + ' = {', + '\tGDNATIVE_' + core['type'] + ',', + '\t{' + str(core['version']['major']) + ', ' + str(core['version']['minor']) + '},', + '\t' + ('NULL' if not core['next'] else ('(const godot_gdnative_api_struct *)& api_{0}_{1}'.format(core['version']['major'], core['version']['minor']))) + ',' + ] + + for funcdef in core['api']: + ret_val.append('\t%s,' % funcdef['name']) + + ret_val += ['};\n'] + + return ret_val for ext in api['extensions']: name = ext['name'] @@ -158,6 +204,9 @@ def _build_gdnative_api_struct_source(api): out += ['\t(godot_gdnative_api_struct *)&api_extension_' + name + '_struct,'] out += ['};\n'] + + if api['core']['next']: + out += get_core_struct_definition(api['core']['next']) out += [ 'extern const godot_gdnative_core_api_struct api_struct = {', diff --git a/modules/gdnative/include/gdnative/basis.h b/modules/gdnative/include/gdnative/basis.h index 53e950b4a2..ebe2b1125b 100644 --- a/modules/gdnative/include/gdnative/basis.h +++ b/modules/gdnative/include/gdnative/basis.h @@ -62,6 +62,7 @@ extern "C" { void GDAPI godot_basis_new_with_rows(godot_basis *r_dest, const godot_vector3 *p_x_axis, const godot_vector3 *p_y_axis, const godot_vector3 *p_z_axis); void GDAPI godot_basis_new_with_axis_and_angle(godot_basis *r_dest, const godot_vector3 *p_axis, const godot_real p_phi); void GDAPI godot_basis_new_with_euler(godot_basis *r_dest, const godot_vector3 *p_euler); +void GDAPI godot_basis_new_with_euler_quat(godot_basis *r_dest, const godot_quat *p_euler); godot_string GDAPI godot_basis_as_string(const godot_basis *p_self); @@ -81,6 +82,16 @@ godot_vector3 GDAPI godot_basis_get_scale(const godot_basis *p_self); godot_vector3 GDAPI godot_basis_get_euler(const godot_basis *p_self); +godot_quat GDAPI godot_basis_get_quat(const godot_basis *p_self); + +void GDAPI godot_basis_set_quat(godot_basis *p_self, const godot_quat *p_quat); + +void GDAPI godot_basis_set_axis_angle_scale(godot_basis *p_self, const godot_vector3 *p_axis, godot_real p_phi, const godot_vector3 *p_scale); + +void GDAPI godot_basis_set_euler_scale(godot_basis *p_self, const godot_vector3 *p_euler, const godot_vector3 *p_scale); + +void GDAPI godot_basis_set_quat_scale(godot_basis *p_self, const godot_quat *p_quat, const godot_vector3 *p_scale); + godot_real GDAPI godot_basis_tdotx(const godot_basis *p_self, const godot_vector3 *p_with); godot_real GDAPI godot_basis_tdoty(const godot_basis *p_self, const godot_vector3 *p_with); @@ -95,8 +106,6 @@ godot_int GDAPI godot_basis_get_orthogonal_index(const godot_basis *p_self); void GDAPI godot_basis_new(godot_basis *r_dest); -void GDAPI godot_basis_new_with_euler_quat(godot_basis *r_dest, const godot_quat *p_euler); - // p_elements is a pointer to an array of 3 (!!) vector3 void GDAPI godot_basis_get_elements(const godot_basis *p_self, godot_vector3 *p_elements); diff --git a/modules/gdnative/include/gdnative/dictionary.h b/modules/gdnative/include/gdnative/dictionary.h index a86d60dc72..faace818ee 100644 --- a/modules/gdnative/include/gdnative/dictionary.h +++ b/modules/gdnative/include/gdnative/dictionary.h @@ -94,6 +94,8 @@ godot_bool GDAPI godot_dictionary_operator_equal(const godot_dictionary *p_self, godot_string GDAPI godot_dictionary_to_json(const godot_dictionary *p_self); +godot_bool GDAPI godot_dictionary_erase_with_return(godot_dictionary *p_self, const godot_variant *p_key); + #ifdef __cplusplus } #endif diff --git a/modules/gdnative/include/gdnative/gdnative.h b/modules/gdnative/include/gdnative/gdnative.h index 4cf6e99b06..616c305f25 100644 --- a/modules/gdnative/include/gdnative/gdnative.h +++ b/modules/gdnative/include/gdnative/gdnative.h @@ -282,6 +282,10 @@ void GDAPI godot_print_error(const char *p_description, const char *p_function, void GDAPI godot_print_warning(const char *p_description, const char *p_function, const char *p_file, int p_line); void GDAPI godot_print(const godot_string *p_message); +// GDNATIVE CORE 1.0.1 + +bool GDAPI godot_is_instance_valid(const godot_object *p_object); + #ifdef __cplusplus } #endif diff --git a/modules/gdnative/include/gdnative/quat.h b/modules/gdnative/include/gdnative/quat.h index 4e86960aaf..b1290f745c 100644 --- a/modules/gdnative/include/gdnative/quat.h +++ b/modules/gdnative/include/gdnative/quat.h @@ -60,6 +60,8 @@ extern "C" { void GDAPI godot_quat_new(godot_quat *r_dest, const godot_real p_x, const godot_real p_y, const godot_real p_z, const godot_real p_w); void GDAPI godot_quat_new_with_axis_angle(godot_quat *r_dest, const godot_vector3 *p_axis, const godot_real p_angle); +void GDAPI godot_quat_new_with_basis(godot_quat *r_dest, const godot_basis *p_basis); +void GDAPI godot_quat_new_with_euler(godot_quat *r_dest, const godot_vector3 *p_euler); godot_real GDAPI godot_quat_get_x(const godot_quat *p_self); void GDAPI godot_quat_set_x(godot_quat *p_self, const godot_real val); diff --git a/modules/gdnative/include/gdnative/transform.h b/modules/gdnative/include/gdnative/transform.h index a646da146a..880f21c88a 100644 --- a/modules/gdnative/include/gdnative/transform.h +++ b/modules/gdnative/include/gdnative/transform.h @@ -62,6 +62,7 @@ extern "C" { void GDAPI godot_transform_new_with_axis_origin(godot_transform *r_dest, const godot_vector3 *p_x_axis, const godot_vector3 *p_y_axis, const godot_vector3 *p_z_axis, const godot_vector3 *p_origin); void GDAPI godot_transform_new(godot_transform *r_dest, const godot_basis *p_basis, const godot_vector3 *p_origin); +void GDAPI godot_transform_new_with_quat(godot_transform *r_dest, const godot_quat *p_quat); godot_basis GDAPI godot_transform_get_basis(const godot_transform *p_self); void GDAPI godot_transform_set_basis(godot_transform *p_self, const godot_basis *p_v); diff --git a/modules/gdnative/include/nativescript/godot_nativescript.h b/modules/gdnative/include/nativescript/godot_nativescript.h index 29bd9eec5a..d6a729be47 100644 --- a/modules/gdnative/include/nativescript/godot_nativescript.h +++ b/modules/gdnative/include/nativescript/godot_nativescript.h @@ -229,6 +229,8 @@ const void GDAPI *godot_nativescript_get_type_tag(const godot_object *p_object); typedef struct { GDCALLINGCONV void *(*alloc_instance_binding_data)(void *, const void *, godot_object *); GDCALLINGCONV void (*free_instance_binding_data)(void *, void *); + GDCALLINGCONV void (*refcount_incremented_instance_binding)(void *, godot_object *); + GDCALLINGCONV bool (*refcount_decremented_instance_binding)(void *, godot_object *); void *data; GDCALLINGCONV void (*free_func)(void *); } godot_instance_binding_functions; diff --git a/modules/gdnative/nativescript/nativescript.cpp b/modules/gdnative/nativescript/nativescript.cpp index 608c7aa4a5..3f88fabebd 100644 --- a/modules/gdnative/nativescript/nativescript.cpp +++ b/modules/gdnative/nativescript/nativescript.cpp @@ -1370,6 +1370,54 @@ void NativeScriptLanguage::free_instance_binding_data(void *p_data) { delete &binding_data; } +void NativeScriptLanguage::refcount_incremented_instance_binding(Object *p_object) { + + void *data = p_object->get_script_instance_binding(lang_idx); + + if (!data) + return; + + Vector<void *> &binding_data = *(Vector<void *> *)data; + + for (int i = 0; i < binding_data.size(); i++) { + if (!binding_data[i]) + continue; + + if (!binding_functions[i].first) + continue; + + if (binding_functions[i].second.refcount_incremented_instance_binding) { + binding_functions[i].second.refcount_incremented_instance_binding(binding_data[i], p_object); + } + } +} + +bool NativeScriptLanguage::refcount_decremented_instance_binding(Object *p_object) { + + void *data = p_object->get_script_instance_binding(lang_idx); + + if (!data) + return true; + + Vector<void *> &binding_data = *(Vector<void *> *)data; + + bool can_die = true; + + for (int i = 0; i < binding_data.size(); i++) { + if (!binding_data[i]) + continue; + + if (!binding_functions[i].first) + continue; + + if (binding_functions[i].second.refcount_decremented_instance_binding) { + can_die = can_die && binding_functions[i].second.refcount_decremented_instance_binding(binding_data[i], p_object); + } + } + + return can_die; +} + void NativeScriptLanguage::set_global_type_tag(int p_idx, StringName p_class_name, const void *p_type_tag) { if (!global_type_tags.has(p_idx)) { global_type_tags.insert(p_idx, HashMap<StringName, const void *>()); @@ -1537,12 +1585,16 @@ bool NativeScriptLanguage::handles_global_class_type(const String &p_type) const String NativeScriptLanguage::get_global_class_name(const String &p_path, String *r_base_type, String *r_icon_path) const { Ref<NativeScript> script = ResourceLoader::load(p_path, "NativeScript"); if (script.is_valid()) { - *r_base_type = script->get_instance_base_type(); - *r_icon_path = script->get_script_class_icon_path(); + if (r_base_type) + *r_base_type = script->get_instance_base_type(); + if (r_icon_path) + *r_icon_path = script->get_script_class_icon_path(); return script->get_script_class_name(); } - *r_base_type = String(); - *r_icon_path = String(); + if (r_base_type) + *r_base_type = String(); + if (r_icon_path) + *r_icon_path = String(); return String(); } diff --git a/modules/gdnative/nativescript/nativescript.h b/modules/gdnative/nativescript/nativescript.h index 6f18e2db27..ebfe36fd94 100644 --- a/modules/gdnative/nativescript/nativescript.h +++ b/modules/gdnative/nativescript/nativescript.h @@ -353,6 +353,8 @@ public: virtual void *alloc_instance_binding_data(Object *p_object); virtual void free_instance_binding_data(void *p_data); + virtual void refcount_incremented_instance_binding(Object *p_object); + virtual bool refcount_decremented_instance_binding(Object *p_object); void set_global_type_tag(int p_idx, StringName p_class_name, const void *p_type_tag); const void *get_global_type_tag(int p_idx, StringName p_class_name) const; diff --git a/modules/websocket/emws_client.cpp b/modules/websocket/emws_client.cpp index 00c36ebb47..836b564de8 100644 --- a/modules/websocket/emws_client.cpp +++ b/modules/websocket/emws_client.cpp @@ -62,25 +62,23 @@ EMSCRIPTEN_KEEPALIVE void _esws_on_close(void *obj, int code, char *reason, int Error EMWSClient::connect_to_host(String p_host, String p_path, uint16_t p_port, bool p_ssl, PoolVector<String> p_protocols) { + String proto_string = p_protocols.join(","); String str = "ws://"; - String proto_string = ""; if (p_ssl) str = "wss://"; str += p_host + ":" + itos(p_port) + p_path; - for (int i = 0; i < p_protocols.size(); i++) { - proto_string += p_protocols[i]; - proto_string += ","; - } - if (proto_string == "") - proto_string = "binary,"; - - proto_string = proto_string.substr(0, proto_string.length() - 1); _is_connecting = true; /* clang-format off */ int peer_sock = EM_ASM_INT({ - var socket = new WebSocket(UTF8ToString($1), UTF8ToString($2).split(",")); + var proto_str = UTF8ToString($2); + var socket = null; + if (proto_str) { + socket = new WebSocket(UTF8ToString($1), proto_str.split(",")); + } else { + socket = new WebSocket(UTF8ToString($1)); + } var c_ptr = Module.IDHandler.get($0); socket.binaryType = "arraybuffer"; diff --git a/modules/websocket/lws_client.cpp b/modules/websocket/lws_client.cpp index ac31daa108..09f6422058 100644 --- a/modules/websocket/lws_client.cpp +++ b/modules/websocket/lws_client.cpp @@ -48,12 +48,10 @@ Error LWSClient::connect_to_host(String p_host, String p_path, uint16_t p_port, ERR_FAIL_COND_V(!addr.is_valid(), ERR_INVALID_PARAMETER); - // prepare protocols - if (p_protocols.size() == 0) // default to binary protocol - p_protocols.append("binary"); + // Prepare protocols _lws_make_protocols(this, &LWSClient::_lws_gd_callback, p_protocols, &_lws_ref); - // init lws client + // Init lws client struct lws_context_creation_info info; struct lws_client_connect_info i; @@ -87,7 +85,10 @@ Error LWSClient::connect_to_host(String p_host, String p_path, uint16_t p_port, strncpy(pbuf, p_path.utf8().get_data(), 2048); i.context = context; - i.protocol = _lws_ref->lws_names; + if (p_protocols.size() > 0) + i.protocol = _lws_ref->lws_names; + else + i.protocol = NULL; i.address = abuf; i.host = hbuf; i.path = pbuf; @@ -134,13 +135,13 @@ int LWSClient::_handle_cb(struct lws *wsi, enum lws_callback_reasons reason, voi case LWS_CALLBACK_CLIENT_CONNECTION_ERROR: _on_error(); destroy_context(); - return -1; // we should close the connection (would probably happen anyway) + return -1; // We should close the connection (would probably happen anyway) case LWS_CALLBACK_CLIENT_CLOSED: peer->close(); destroy_context(); _on_disconnect(); - return 0; // we can end here + return 0; // We can end here case LWS_CALLBACK_CLIENT_RECEIVE: peer->read_wsi(in, len); diff --git a/modules/websocket/lws_helper.h b/modules/websocket/lws_helper.h index 85a1e3769f..70256ccf16 100644 --- a/modules/websocket/lws_helper.h +++ b/modules/websocket/lws_helper.h @@ -105,53 +105,54 @@ static bool _lws_poll(struct lws_context *context, _LWSRef *ref) { } /* - * prepare the protocol_structs to be fed to context - * also prepare the protocol string used by the client + * Prepare the protocol_structs to be fed to context. + * Also prepare the protocol string used by the client. */ static void _lws_make_protocols(void *p_obj, lws_callback_function *p_callback, PoolVector<String> p_names, _LWSRef **r_lws_ref) { - /* the input strings might go away after this call, - * we need to copy them. Will clear them when - * destroying the context */ + // The input strings might go away after this call, we need to copy them. + // We will clear them when destroying the context. int i; int len = p_names.size(); size_t data_size = sizeof(struct LWSPeer::PeerData); PoolVector<String>::Read pnr = p_names.read(); - /* - * This is a reference connecting the object with lws - * keep track of status, mallocs, etc. - * Must survive as long the context - * Must be freed manually when context creation fails. - */ + // This is a reference connecting the object with lws keep track of status, mallocs, etc. + // Must survive as long the context. + // Must be freed manually when context creation fails. _LWSRef *ref = _lws_create_ref(p_obj); - /* LWS protocol structs */ + // LWS protocol structs. ref->lws_structs = (struct lws_protocols *)memalloc(sizeof(struct lws_protocols) * (len + 2)); memset(ref->lws_structs, 0, sizeof(struct lws_protocols) * (len + 2)); CharString strings = p_names.join(",").ascii(); int str_len = strings.length(); - /* Joined string of protocols, double the size: comma separated first, NULL separated last */ - ref->lws_names = (char *)memalloc((str_len + 1) * 2); /* plus the terminator */ + // Joined string of protocols, double the size: comma separated first, NULL separated last + ref->lws_names = (char *)memalloc((str_len + 1) * 2); // Plus the terminator char *names_ptr = ref->lws_names; struct lws_protocols *structs_ptr = ref->lws_structs; - copymem(names_ptr, strings.get_data(), str_len); - names_ptr[str_len] = '\0'; /* NULL terminator */ - /* NULL terminated strings to be used in protocol structs */ - copymem(&names_ptr[str_len + 1], strings.get_data(), str_len); - names_ptr[(str_len * 2) + 1] = '\0'; /* NULL terminator */ + // Comma separated protocols string to be used in client Sec-WebSocket-Protocol header + if (str_len > 0) + copymem(names_ptr, strings.get_data(), str_len); + names_ptr[str_len] = '\0'; // NULL terminator + + // NULL terminated protocol strings to be used in protocol structs + if (str_len > 0) + copymem(&names_ptr[str_len + 1], strings.get_data(), str_len); + names_ptr[(str_len * 2) + 1] = '\0'; // NULL terminator int pos = str_len + 1; - /* the first protocol is always http-only */ - structs_ptr[0].name = "http-only"; + // The first protocol is the default for any http request (before upgrade). + // It is also used as the websocket protocol when no subprotocol is specified. + structs_ptr[0].name = "default"; structs_ptr[0].callback = p_callback; structs_ptr[0].per_session_data_size = data_size; structs_ptr[0].rx_buffer_size = LWS_BUF_SIZE; structs_ptr[0].tx_packet_size = LWS_PACKET_SIZE; - /* add user defined protocols */ + // Add user defined protocols for (i = 0; i < len; i++) { structs_ptr[i + 1].name = (const char *)&names_ptr[pos]; structs_ptr[i + 1].callback = p_callback; @@ -161,7 +162,7 @@ static void _lws_make_protocols(void *p_obj, lws_callback_function *p_callback, pos += pnr[i].ascii().length() + 1; names_ptr[pos - 1] = '\0'; } - /* add protocols terminator */ + // Add protocols terminator structs_ptr[len + 1].name = NULL; structs_ptr[len + 1].callback = NULL; structs_ptr[len + 1].per_session_data_size = 0; diff --git a/modules/websocket/lws_server.cpp b/modules/websocket/lws_server.cpp index bb724bce9c..4a614f6933 100644 --- a/modules/websocket/lws_server.cpp +++ b/modules/websocket/lws_server.cpp @@ -41,9 +41,6 @@ Error LWSServer::listen(int p_port, PoolVector<String> p_protocols, bool gd_mp_a struct lws_context_creation_info info; memset(&info, 0, sizeof info); - if (p_protocols.size() == 0) // default to binary protocol - p_protocols.append(String("binary")); - // Prepare lws protocol structs _lws_make_protocols(this, &LWSServer::_lws_gd_callback, p_protocols, &_lws_ref); diff --git a/platform/osx/os_osx.mm b/platform/osx/os_osx.mm index 79d7ec410a..44b4223a65 100644 --- a/platform/osx/os_osx.mm +++ b/platform/osx/os_osx.mm @@ -1604,7 +1604,9 @@ void OS_OSX::set_custom_mouse_cursor(const RES &p_cursor, CursorShape p_shape, c } ERR_FAIL_COND(!texture.is_valid()); + ERR_FAIL_COND(p_hotspot.x < 0 || p_hotspot.y < 0); ERR_FAIL_COND(texture_size.width > 256 || texture_size.height > 256); + ERR_FAIL_COND(p_hotspot.x > texture_size.width || p_hotspot.y > texture_size.height); image = texture->get_data(); diff --git a/platform/windows/SCsub b/platform/windows/SCsub index 53ed3bf887..586533e817 100644 --- a/platform/windows/SCsub +++ b/platform/windows/SCsub @@ -7,6 +7,7 @@ from platform_methods import run_in_subprocess import platform_windows_builders common_win = [ + "godot_win.cpp", "context_gl_win.cpp", "crash_handler_win.cpp", "os_windows.cpp", @@ -17,17 +18,17 @@ common_win = [ "windows_terminal_logger.cpp" ] -restarget = "godot_res" + env["OBJSUFFIX"] +res_file = 'godot_res.rc' -obj = env.RES(restarget, 'godot_res.rc') +res_target = "godot_res" + env["OBJSUFFIX"] -common_win.append(obj) +res_obj = env.RES(res_target, res_file) -prog = env.add_program('#bin/godot', ['godot_win.cpp'] + common_win, PROGSUFFIX=env["PROGSUFFIX"]) +prog = env.add_program('#bin/godot', common_win + res_obj, PROGSUFFIX=env["PROGSUFFIX"]) # Microsoft Visual Studio Project Generation if env['vsproj']: - env.vs_srcs = env.vs_srcs + ["platform/windows/godot_win.cpp"] + env.vs_srcs = env.vs_srcs + ["platform/windows/" + res_file] for x in common_win: env.vs_srcs = env.vs_srcs + ["platform/windows/" + str(x)] diff --git a/platform/windows/os_windows.cpp b/platform/windows/os_windows.cpp index 7009df8e57..88793386ab 100644 --- a/platform/windows/os_windows.cpp +++ b/platform/windows/os_windows.cpp @@ -249,7 +249,11 @@ bool OS_Windows::can_draw() const { #define MI_WP_SIGNATURE 0xFF515700 #define SIGNATURE_MASK 0xFFFFFF00 +// Keeping the name suggested by Microsoft, but this macro really answers: +// Is this mouse event emulated from touch or pen input? #define IsPenEvent(dw) (((dw)&SIGNATURE_MASK) == MI_WP_SIGNATURE) +// This one tells whether the event comes from touchscreen (and not from pen) +#define IsTouchEvent(dw) (IsPenEvent(dw) && ((dw)&0x80)) void OS_Windows::_touch_event(bool p_pressed, float p_x, float p_y, int idx) { @@ -469,7 +473,7 @@ LRESULT OS_Windows::WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) if (input->is_emulating_mouse_from_touch()) { // Universal translation enabled; ignore OS translation LPARAM extra = GetMessageExtraInfo(); - if (IsPenEvent(extra)) { + if (IsTouchEvent(extra)) { break; } } @@ -560,7 +564,7 @@ LRESULT OS_Windows::WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) if (input->is_emulating_mouse_from_touch()) { // Universal translation enabled; ignore OS translations for left button LPARAM extra = GetMessageExtraInfo(); - if (IsPenEvent(extra)) { + if (IsTouchEvent(extra)) { break; } } @@ -2248,7 +2252,9 @@ void OS_Windows::set_custom_mouse_cursor(const RES &p_cursor, CursorShape p_shap } ERR_FAIL_COND(!texture.is_valid()); + ERR_FAIL_COND(p_hotspot.x < 0 || p_hotspot.y < 0); ERR_FAIL_COND(texture_size.width > 256 || texture_size.height > 256); + ERR_FAIL_COND(p_hotspot.x > texture_size.width || p_hotspot.y > texture_size.height); image = texture->get_data(); diff --git a/platform/x11/os_x11.cpp b/platform/x11/os_x11.cpp index a62bd714d2..a57a8c6bb9 100644 --- a/platform/x11/os_x11.cpp +++ b/platform/x11/os_x11.cpp @@ -2534,7 +2534,9 @@ void OS_X11::set_custom_mouse_cursor(const RES &p_cursor, CursorShape p_shape, c } ERR_FAIL_COND(!texture.is_valid()); + ERR_FAIL_COND(p_hotspot.x < 0 || p_hotspot.y < 0); ERR_FAIL_COND(texture_size.width > 256 || texture_size.height > 256); + ERR_FAIL_COND(p_hotspot.x > texture_size.width || p_hotspot.y > texture_size.height); image = texture->get_data(); diff --git a/scene/2d/collision_object_2d.cpp b/scene/2d/collision_object_2d.cpp index 1e2184bd41..7ade74e8a6 100644 --- a/scene/2d/collision_object_2d.cpp +++ b/scene/2d/collision_object_2d.cpp @@ -384,7 +384,7 @@ void CollisionObject2D::_bind_methods() { BIND_VMETHOD(MethodInfo("_input_event", PropertyInfo(Variant::OBJECT, "viewport"), PropertyInfo(Variant::OBJECT, "event", PROPERTY_HINT_RESOURCE_TYPE, "InputEvent"), PropertyInfo(Variant::INT, "shape_idx"))); - ADD_SIGNAL(MethodInfo("input_event", PropertyInfo(Variant::OBJECT, "viewport"), PropertyInfo(Variant::OBJECT, "event", PROPERTY_HINT_RESOURCE_TYPE, "InputEvent"), PropertyInfo(Variant::INT, "shape_idx"))); + ADD_SIGNAL(MethodInfo("input_event", PropertyInfo(Variant::OBJECT, "viewport", PROPERTY_HINT_RESOURCE_TYPE, "Node"), PropertyInfo(Variant::OBJECT, "event", PROPERTY_HINT_RESOURCE_TYPE, "InputEvent"), PropertyInfo(Variant::INT, "shape_idx"))); ADD_SIGNAL(MethodInfo("mouse_entered")); ADD_SIGNAL(MethodInfo("mouse_exited")); diff --git a/scene/2d/cpu_particles_2d.cpp b/scene/2d/cpu_particles_2d.cpp index 136d41e2f9..a8e0f0d07f 100644 --- a/scene/2d/cpu_particles_2d.cpp +++ b/scene/2d/cpu_particles_2d.cpp @@ -30,9 +30,7 @@ #include "cpu_particles_2d.h" -#include "scene/3d/particles.h" -#include "scene/main/viewport.h" -#include "scene/resources/surface_tool.h" +//#include "scene/resources/particles_material.h" #include "servers/visual_server.h" void CPUParticles2D::set_emitting(bool p_emitting) { diff --git a/scene/2d/cpu_particles_2d.h b/scene/2d/cpu_particles_2d.h index fa8e6b54ef..dbe9f59748 100644 --- a/scene/2d/cpu_particles_2d.h +++ b/scene/2d/cpu_particles_2d.h @@ -30,10 +30,10 @@ #ifndef CPU_PARTICLES_2D_H #define CPU_PARTICLES_2D_H + #include "rid.h" #include "scene/2d/node_2d.h" -#include "scene/main/timer.h" -#include "scene/resources/material.h" +#include "scene/resources/texture.h" /** @author Juan Linietsky <reduzio@gmail.com> diff --git a/scene/2d/particles_2d.cpp b/scene/2d/particles_2d.cpp index a4c3057416..7e824cdf75 100644 --- a/scene/2d/particles_2d.cpp +++ b/scene/2d/particles_2d.cpp @@ -30,10 +30,13 @@ #include "particles_2d.h" -#include "engine.h" -#include "scene/3d/particles.h" +#include "scene/resources/particles_material.h" #include "scene/scene_string_names.h" +#ifdef TOOLS_ENABLED +#include "core/engine.h" +#endif + void Particles2D::set_emitting(bool p_emitting) { VS::get_singleton()->particles_set_emitting(particles, p_emitting); @@ -114,7 +117,7 @@ void Particles2D::set_process_material(const Ref<Material> &p_material) { process_material = p_material; Ref<ParticlesMaterial> pm = p_material; if (pm.is_valid() && !pm->get_flag(ParticlesMaterial::FLAG_DISABLE_Z) && pm->get_gravity() == Vector3(0, -9.8, 0)) { - //likely a new material, modify it! + // Likely a new (3D) material, modify it to match 2D space pm->set_flag(ParticlesMaterial::FLAG_DISABLE_Z, true); pm->set_gravity(Vector3(0, 98, 0)); } diff --git a/scene/2d/particles_2d.h b/scene/2d/particles_2d.h index 31a66afb2a..816149ba79 100644 --- a/scene/2d/particles_2d.h +++ b/scene/2d/particles_2d.h @@ -28,11 +28,11 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#ifndef PARTICLES_FRAME_H -#define PARTICLES_FRAME_H +#ifndef PARTICLES_2D_H +#define PARTICLES_2D_H +#include "rid.h" #include "scene/2d/node_2d.h" -#include "scene/resources/color_ramp.h" #include "scene/resources/texture.h" class Particles2D : public Node2D { @@ -132,4 +132,4 @@ public: VARIANT_ENUM_CAST(Particles2D::DrawOrder) -#endif // PARTICLES_FRAME_H +#endif // PARTICLES_2D_H diff --git a/scene/2d/physics_body_2d.cpp b/scene/2d/physics_body_2d.cpp index 1ac7799ec5..dc93414669 100644 --- a/scene/2d/physics_body_2d.cpp +++ b/scene/2d/physics_body_2d.cpp @@ -180,6 +180,10 @@ real_t StaticBody2D::get_constant_angular_velocity() const { #ifndef DISABLE_DEPRECATED void StaticBody2D::set_friction(real_t p_friction) { + if (p_friction == 1.0) { // default value, don't create an override for that + return; + } + ERR_EXPLAIN("The method set_friction has been deprecated and will be removed in the future, use physics material instead.") WARN_DEPRECATED @@ -206,6 +210,10 @@ real_t StaticBody2D::get_friction() const { void StaticBody2D::set_bounce(real_t p_bounce) { + if (p_bounce == 0.0) { // default value, don't create an override for that + return; + } + ERR_EXPLAIN("The method set_bounce has been deprecated and will be removed in the future, use physics material instead.") WARN_DEPRECATED @@ -275,7 +283,7 @@ void StaticBody2D::_bind_methods() { ADD_PROPERTYNO(PropertyInfo(Variant::REAL, "friction", PROPERTY_HINT_RANGE, "0,1,0.01", 0), "set_friction", "get_friction"); ADD_PROPERTYNZ(PropertyInfo(Variant::REAL, "bounce", PROPERTY_HINT_RANGE, "0,1,0.01", 0), "set_bounce", "get_bounce"); #endif // DISABLE_DEPRECATED - ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "physics_material_override", PROPERTY_HINT_RESOURCE_TYPE, "PhysicsMaterial"), "set_physics_material_override", "get_physics_material_override"); + ADD_PROPERTYNZ(PropertyInfo(Variant::OBJECT, "physics_material_override", PROPERTY_HINT_RESOURCE_TYPE, "PhysicsMaterial"), "set_physics_material_override", "get_physics_material_override"); } StaticBody2D::StaticBody2D() : @@ -396,13 +404,13 @@ void RigidBody2D::_body_inout(int p_status, ObjectID p_instance, int p_body_shap node->disconnect(SceneStringNames::get_singleton()->tree_entered, this, SceneStringNames::get_singleton()->_body_enter_tree); node->disconnect(SceneStringNames::get_singleton()->tree_exiting, this, SceneStringNames::get_singleton()->_body_exit_tree); if (in_scene) - emit_signal(SceneStringNames::get_singleton()->body_exited, obj); + emit_signal(SceneStringNames::get_singleton()->body_exited, node); } contact_monitor->body_map.erase(E); } if (node && in_scene) { - emit_signal(SceneStringNames::get_singleton()->body_shape_exited, objid, obj, p_body_shape, p_local_shape); + emit_signal(SceneStringNames::get_singleton()->body_shape_exited, objid, node, p_body_shape, p_local_shape); } } } @@ -599,8 +607,13 @@ real_t RigidBody2D::get_weight() const { #ifndef DISABLE_DEPRECATED void RigidBody2D::set_friction(real_t p_friction) { + if (p_friction == 1.0) { // default value, don't create an override for that + return; + } + ERR_EXPLAIN("The method set_friction has been deprecated and will be removed in the future, use physics material instead.") WARN_DEPRECATED + ERR_FAIL_COND(p_friction < 0 || p_friction > 1); if (physics_material_override.is_null()) { @@ -623,6 +636,10 @@ real_t RigidBody2D::get_friction() const { void RigidBody2D::set_bounce(real_t p_bounce) { + if (p_bounce == 0.0) { // default value, don't create an override for that + return; + } + ERR_EXPLAIN("The method set_bounce has been deprecated and will be removed in the future, use physics material instead.") WARN_DEPRECATED @@ -1028,7 +1045,7 @@ void RigidBody2D::_bind_methods() { ADD_PROPERTYNO(PropertyInfo(Variant::REAL, "friction", PROPERTY_HINT_RANGE, "0,1,0.01", 0), "set_friction", "get_friction"); ADD_PROPERTYNZ(PropertyInfo(Variant::REAL, "bounce", PROPERTY_HINT_RANGE, "0,1,0.01", 0), "set_bounce", "get_bounce"); #endif // DISABLE_DEPRECATED - ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "physics_material_override", PROPERTY_HINT_RESOURCE_TYPE, "PhysicsMaterial"), "set_physics_material_override", "get_physics_material_override"); + ADD_PROPERTYNZ(PropertyInfo(Variant::OBJECT, "physics_material_override", PROPERTY_HINT_RESOURCE_TYPE, "PhysicsMaterial"), "set_physics_material_override", "get_physics_material_override"); ADD_PROPERTY(PropertyInfo(Variant::REAL, "gravity_scale", PROPERTY_HINT_RANGE, "-128,128,0.01"), "set_gravity_scale", "get_gravity_scale"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "custom_integrator"), "set_use_custom_integrator", "is_using_custom_integrator"); ADD_PROPERTY(PropertyInfo(Variant::INT, "continuous_cd", PROPERTY_HINT_ENUM, "Disabled,Cast Ray,Cast Shape"), "set_continuous_collision_detection_mode", "get_continuous_collision_detection_mode"); @@ -1046,10 +1063,10 @@ void RigidBody2D::_bind_methods() { ADD_PROPERTYNZ(PropertyInfo(Variant::VECTOR2, "applied_force"), "set_applied_force", "get_applied_force"); ADD_PROPERTYNZ(PropertyInfo(Variant::REAL, "applied_torque"), "set_applied_torque", "get_applied_torque"); - ADD_SIGNAL(MethodInfo("body_shape_entered", PropertyInfo(Variant::INT, "body_id"), PropertyInfo(Variant::OBJECT, "body"), PropertyInfo(Variant::INT, "body_shape"), PropertyInfo(Variant::INT, "local_shape"))); - ADD_SIGNAL(MethodInfo("body_shape_exited", PropertyInfo(Variant::INT, "body_id"), PropertyInfo(Variant::OBJECT, "body"), PropertyInfo(Variant::INT, "body_shape"), PropertyInfo(Variant::INT, "local_shape"))); - ADD_SIGNAL(MethodInfo("body_entered", PropertyInfo(Variant::OBJECT, "body"))); - ADD_SIGNAL(MethodInfo("body_exited", PropertyInfo(Variant::OBJECT, "body"))); + ADD_SIGNAL(MethodInfo("body_shape_entered", PropertyInfo(Variant::INT, "body_id"), PropertyInfo(Variant::OBJECT, "body", PROPERTY_HINT_RESOURCE_TYPE, "Node"), PropertyInfo(Variant::INT, "body_shape"), PropertyInfo(Variant::INT, "local_shape"))); + ADD_SIGNAL(MethodInfo("body_shape_exited", PropertyInfo(Variant::INT, "body_id"), PropertyInfo(Variant::OBJECT, "body", PROPERTY_HINT_RESOURCE_TYPE, "Node"), PropertyInfo(Variant::INT, "body_shape"), PropertyInfo(Variant::INT, "local_shape"))); + ADD_SIGNAL(MethodInfo("body_entered", PropertyInfo(Variant::OBJECT, "body", PROPERTY_HINT_RESOURCE_TYPE, "Node"))); + ADD_SIGNAL(MethodInfo("body_exited", PropertyInfo(Variant::OBJECT, "body", PROPERTY_HINT_RESOURCE_TYPE, "Node"))); ADD_SIGNAL(MethodInfo("sleeping_state_changed")); BIND_ENUM_CONSTANT(MODE_RIGID); diff --git a/scene/2d/ray_cast_2d.cpp b/scene/2d/ray_cast_2d.cpp index 9582c08110..d9b3cb07fc 100644 --- a/scene/2d/ray_cast_2d.cpp +++ b/scene/2d/ray_cast_2d.cpp @@ -218,6 +218,8 @@ void RayCast2D::_update_raycast_state() { against_shape = rr.shape; } else { collided = false; + against = 0; + against_shape = 0; } } diff --git a/scene/3d/area.cpp b/scene/3d/area.cpp index 6ea980ec97..40a1029201 100644 --- a/scene/3d/area.cpp +++ b/scene/3d/area.cpp @@ -243,7 +243,7 @@ void Area::_clear_monitoring() { emit_signal(SceneStringNames::get_singleton()->body_shape_exited, E->key(), node, E->get().shapes[i].body_shape, E->get().shapes[i].area_shape); } - emit_signal(SceneStringNames::get_singleton()->body_exited, obj); + emit_signal(SceneStringNames::get_singleton()->body_exited, node); node->disconnect(SceneStringNames::get_singleton()->tree_entered, this, SceneStringNames::get_singleton()->_body_enter_tree); node->disconnect(SceneStringNames::get_singleton()->tree_exiting, this, SceneStringNames::get_singleton()->_body_exit_tree); @@ -699,10 +699,10 @@ void Area::_bind_methods() { ClassDB::bind_method(D_METHOD("set_reverb_uniformity", "amount"), &Area::set_reverb_uniformity); ClassDB::bind_method(D_METHOD("get_reverb_uniformity"), &Area::get_reverb_uniformity); - ADD_SIGNAL(MethodInfo("body_shape_entered", PropertyInfo(Variant::INT, "body_id"), PropertyInfo(Variant::OBJECT, "body"), PropertyInfo(Variant::INT, "body_shape"), PropertyInfo(Variant::INT, "area_shape"))); - ADD_SIGNAL(MethodInfo("body_shape_exited", PropertyInfo(Variant::INT, "body_id"), PropertyInfo(Variant::OBJECT, "body"), PropertyInfo(Variant::INT, "body_shape"), PropertyInfo(Variant::INT, "area_shape"))); - ADD_SIGNAL(MethodInfo("body_entered", PropertyInfo(Variant::OBJECT, "body"))); - ADD_SIGNAL(MethodInfo("body_exited", PropertyInfo(Variant::OBJECT, "body"))); + ADD_SIGNAL(MethodInfo("body_shape_entered", PropertyInfo(Variant::INT, "body_id"), PropertyInfo(Variant::OBJECT, "body", PROPERTY_HINT_RESOURCE_TYPE, "Node"), PropertyInfo(Variant::INT, "body_shape"), PropertyInfo(Variant::INT, "area_shape"))); + ADD_SIGNAL(MethodInfo("body_shape_exited", PropertyInfo(Variant::INT, "body_id"), PropertyInfo(Variant::OBJECT, "body", PROPERTY_HINT_RESOURCE_TYPE, "Node"), PropertyInfo(Variant::INT, "body_shape"), PropertyInfo(Variant::INT, "area_shape"))); + ADD_SIGNAL(MethodInfo("body_entered", PropertyInfo(Variant::OBJECT, "body", PROPERTY_HINT_RESOURCE_TYPE, "Node"))); + ADD_SIGNAL(MethodInfo("body_exited", PropertyInfo(Variant::OBJECT, "body", PROPERTY_HINT_RESOURCE_TYPE, "Node"))); ADD_SIGNAL(MethodInfo("area_shape_entered", PropertyInfo(Variant::INT, "area_id"), PropertyInfo(Variant::OBJECT, "area", PROPERTY_HINT_RESOURCE_TYPE, "Area"), PropertyInfo(Variant::INT, "area_shape"), PropertyInfo(Variant::INT, "self_shape"))); ADD_SIGNAL(MethodInfo("area_shape_exited", PropertyInfo(Variant::INT, "area_id"), PropertyInfo(Variant::OBJECT, "area", PROPERTY_HINT_RESOURCE_TYPE, "Area"), PropertyInfo(Variant::INT, "area_shape"), PropertyInfo(Variant::INT, "self_shape"))); diff --git a/scene/3d/collision_object.cpp b/scene/3d/collision_object.cpp index e19e45b263..99b8ce0567 100644 --- a/scene/3d/collision_object.cpp +++ b/scene/3d/collision_object.cpp @@ -148,7 +148,7 @@ void CollisionObject::_bind_methods() { BIND_VMETHOD(MethodInfo("_input_event", PropertyInfo(Variant::OBJECT, "camera"), PropertyInfo(Variant::OBJECT, "event", PROPERTY_HINT_RESOURCE_TYPE, "InputEvent"), PropertyInfo(Variant::VECTOR3, "click_position"), PropertyInfo(Variant::VECTOR3, "click_normal"), PropertyInfo(Variant::INT, "shape_idx"))); - ADD_SIGNAL(MethodInfo("input_event", PropertyInfo(Variant::OBJECT, "camera"), PropertyInfo(Variant::OBJECT, "event", PROPERTY_HINT_RESOURCE_TYPE, "InputEvent"), PropertyInfo(Variant::VECTOR3, "click_position"), PropertyInfo(Variant::VECTOR3, "click_normal"), PropertyInfo(Variant::INT, "shape_idx"))); + ADD_SIGNAL(MethodInfo("input_event", PropertyInfo(Variant::OBJECT, "camera", PROPERTY_HINT_RESOURCE_TYPE, "Node"), PropertyInfo(Variant::OBJECT, "event", PROPERTY_HINT_RESOURCE_TYPE, "InputEvent"), PropertyInfo(Variant::VECTOR3, "click_position"), PropertyInfo(Variant::VECTOR3, "click_normal"), PropertyInfo(Variant::INT, "shape_idx"))); ADD_SIGNAL(MethodInfo("mouse_entered")); ADD_SIGNAL(MethodInfo("mouse_exited")); diff --git a/scene/3d/cpu_particles.cpp b/scene/3d/cpu_particles.cpp index 3f76303ad3..712f0ba78b 100644 --- a/scene/3d/cpu_particles.cpp +++ b/scene/3d/cpu_particles.cpp @@ -30,10 +30,9 @@ #include "cpu_particles.h" -#include "particles.h" #include "scene/3d/camera.h" -#include "scene/main/viewport.h" -#include "scene/resources/surface_tool.h" +#include "scene/3d/particles.h" +#include "scene/resources/particles_material.h" #include "servers/visual_server.h" AABB CPUParticles::get_aabb() const { diff --git a/scene/3d/cpu_particles.h b/scene/3d/cpu_particles.h index 85bce789f7..47d0ef3f5e 100644 --- a/scene/3d/cpu_particles.h +++ b/scene/3d/cpu_particles.h @@ -30,10 +30,9 @@ #ifndef CPU_PARTICLES_H #define CPU_PARTICLES_H + #include "rid.h" #include "scene/3d/visual_instance.h" -#include "scene/main/timer.h" -#include "scene/resources/material.h" /** @author Juan Linietsky <reduzio@gmail.com> diff --git a/scene/3d/particles.cpp b/scene/3d/particles.cpp index 6ba569ac75..10b26778ef 100644 --- a/scene/3d/particles.cpp +++ b/scene/3d/particles.cpp @@ -29,7 +29,7 @@ /*************************************************************************/ #include "particles.h" -#include "scene/resources/surface_tool.h" + #include "servers/visual_server.h" AABB Particles::get_aabb() const { @@ -378,1219 +378,3 @@ Particles::~Particles() { VS::get_singleton()->free(particles); } - -////////////////////////////////////// - -Mutex *ParticlesMaterial::material_mutex = NULL; -SelfList<ParticlesMaterial>::List ParticlesMaterial::dirty_materials; -Map<ParticlesMaterial::MaterialKey, ParticlesMaterial::ShaderData> ParticlesMaterial::shader_map; -ParticlesMaterial::ShaderNames *ParticlesMaterial::shader_names = NULL; - -void ParticlesMaterial::init_shaders() { - -#ifndef NO_THREADS - material_mutex = Mutex::create(); -#endif - - shader_names = memnew(ShaderNames); - - shader_names->spread = "spread"; - shader_names->flatness = "flatness"; - shader_names->initial_linear_velocity = "initial_linear_velocity"; - shader_names->initial_angle = "initial_angle"; - shader_names->angular_velocity = "angular_velocity"; - shader_names->orbit_velocity = "orbit_velocity"; - shader_names->linear_accel = "linear_accel"; - shader_names->radial_accel = "radial_accel"; - shader_names->tangent_accel = "tangent_accel"; - shader_names->damping = "damping"; - shader_names->scale = "scale"; - shader_names->hue_variation = "hue_variation"; - shader_names->anim_speed = "anim_speed"; - shader_names->anim_offset = "anim_offset"; - - shader_names->initial_linear_velocity_random = "initial_linear_velocity_random"; - shader_names->initial_angle_random = "initial_angle_random"; - shader_names->angular_velocity_random = "angular_velocity_random"; - shader_names->orbit_velocity_random = "orbit_velocity_random"; - shader_names->linear_accel_random = "linear_accel_random"; - shader_names->radial_accel_random = "radial_accel_random"; - shader_names->tangent_accel_random = "tangent_accel_random"; - shader_names->damping_random = "damping_random"; - shader_names->scale_random = "scale_random"; - shader_names->hue_variation_random = "hue_variation_random"; - shader_names->anim_speed_random = "anim_speed_random"; - shader_names->anim_offset_random = "anim_offset_random"; - - shader_names->angle_texture = "angle_texture"; - shader_names->angular_velocity_texture = "angular_velocity_texture"; - shader_names->orbit_velocity_texture = "orbit_velocity_texture"; - shader_names->linear_accel_texture = "linear_accel_texture"; - shader_names->radial_accel_texture = "radial_accel_texture"; - shader_names->tangent_accel_texture = "tangent_accel_texture"; - shader_names->damping_texture = "damping_texture"; - shader_names->scale_texture = "scale_texture"; - shader_names->hue_variation_texture = "hue_variation_texture"; - shader_names->anim_speed_texture = "anim_speed_texture"; - shader_names->anim_offset_texture = "anim_offset_texture"; - - shader_names->color = "color_value"; - shader_names->color_ramp = "color_ramp"; - - shader_names->emission_sphere_radius = "emission_sphere_radius"; - shader_names->emission_box_extents = "emission_box_extents"; - shader_names->emission_texture_point_count = "emission_texture_point_count"; - shader_names->emission_texture_points = "emission_texture_points"; - shader_names->emission_texture_normal = "emission_texture_normal"; - shader_names->emission_texture_color = "emission_texture_color"; - - shader_names->trail_divisor = "trail_divisor"; - shader_names->trail_size_modifier = "trail_size_modifier"; - shader_names->trail_color_modifier = "trail_color_modifier"; - - shader_names->gravity = "gravity"; -} - -void ParticlesMaterial::finish_shaders() { - -#ifndef NO_THREADS - memdelete(material_mutex); -#endif - - memdelete(shader_names); -} - -void ParticlesMaterial::_update_shader() { - - dirty_materials.remove(&element); - - MaterialKey mk = _compute_key(); - if (mk.key == current_key.key) - return; //no update required in the end - - if (shader_map.has(current_key)) { - shader_map[current_key].users--; - if (shader_map[current_key].users == 0) { - //deallocate shader, as it's no longer in use - VS::get_singleton()->free(shader_map[current_key].shader); - shader_map.erase(current_key); - } - } - - current_key = mk; - - if (shader_map.has(mk)) { - - VS::get_singleton()->material_set_shader(_get_material(), shader_map[mk].shader); - shader_map[mk].users++; - return; - } - - //must create a shader! - - String code = "shader_type particles;\n"; - - code += "uniform float spread;\n"; - code += "uniform float flatness;\n"; - code += "uniform float initial_linear_velocity;\n"; - code += "uniform float initial_angle;\n"; - code += "uniform float angular_velocity;\n"; - code += "uniform float orbit_velocity;\n"; - code += "uniform float linear_accel;\n"; - code += "uniform float radial_accel;\n"; - code += "uniform float tangent_accel;\n"; - code += "uniform float damping;\n"; - code += "uniform float scale;\n"; - code += "uniform float hue_variation;\n"; - code += "uniform float anim_speed;\n"; - code += "uniform float anim_offset;\n"; - - code += "uniform float initial_linear_velocity_random;\n"; - code += "uniform float initial_angle_random;\n"; - code += "uniform float angular_velocity_random;\n"; - code += "uniform float orbit_velocity_random;\n"; - code += "uniform float linear_accel_random;\n"; - code += "uniform float radial_accel_random;\n"; - code += "uniform float tangent_accel_random;\n"; - code += "uniform float damping_random;\n"; - code += "uniform float scale_random;\n"; - code += "uniform float hue_variation_random;\n"; - code += "uniform float anim_speed_random;\n"; - code += "uniform float anim_offset_random;\n"; - - switch (emission_shape) { - case EMISSION_SHAPE_POINT: { - //do none - } break; - case EMISSION_SHAPE_SPHERE: { - code += "uniform float emission_sphere_radius;\n"; - } break; - case EMISSION_SHAPE_BOX: { - code += "uniform vec3 emission_box_extents;\n"; - } break; - case EMISSION_SHAPE_DIRECTED_POINTS: { - code += "uniform sampler2D emission_texture_normal : hint_black;\n"; - } //fallthrough - case EMISSION_SHAPE_POINTS: { - code += "uniform sampler2D emission_texture_points : hint_black;\n"; - code += "uniform int emission_texture_point_count;\n"; - if (emission_color_texture.is_valid()) { - code += "uniform sampler2D emission_texture_color : hint_white;\n"; - } - } break; - } - - code += "uniform vec4 color_value : hint_color;\n"; - - code += "uniform int trail_divisor;\n"; - - code += "uniform vec3 gravity;\n"; - - if (color_ramp.is_valid()) - code += "uniform sampler2D color_ramp;\n"; - - if (tex_parameters[PARAM_INITIAL_LINEAR_VELOCITY].is_valid()) - code += "uniform sampler2D linear_velocity_texture;\n"; - if (tex_parameters[PARAM_ORBIT_VELOCITY].is_valid()) - code += "uniform sampler2D orbit_velocity_texture;\n"; - if (tex_parameters[PARAM_ANGULAR_VELOCITY].is_valid()) - code += "uniform sampler2D angular_velocity_texture;\n"; - if (tex_parameters[PARAM_LINEAR_ACCEL].is_valid()) - code += "uniform sampler2D linear_accel_texture;\n"; - if (tex_parameters[PARAM_RADIAL_ACCEL].is_valid()) - code += "uniform sampler2D radial_accel_texture;\n"; - if (tex_parameters[PARAM_TANGENTIAL_ACCEL].is_valid()) - code += "uniform sampler2D tangent_accel_texture;\n"; - if (tex_parameters[PARAM_DAMPING].is_valid()) - code += "uniform sampler2D damping_texture;\n"; - if (tex_parameters[PARAM_ANGLE].is_valid()) - code += "uniform sampler2D angle_texture;\n"; - if (tex_parameters[PARAM_SCALE].is_valid()) - code += "uniform sampler2D scale_texture;\n"; - if (tex_parameters[PARAM_HUE_VARIATION].is_valid()) - code += "uniform sampler2D hue_variation_texture;\n"; - if (tex_parameters[PARAM_ANIM_SPEED].is_valid()) - code += "uniform sampler2D anim_speed_texture;\n"; - if (tex_parameters[PARAM_ANIM_OFFSET].is_valid()) - code += "uniform sampler2D anim_offset_texture;\n"; - - if (trail_size_modifier.is_valid()) { - code += "uniform sampler2D trail_size_modifier;\n"; - } - - if (trail_color_modifier.is_valid()) { - code += "uniform sampler2D trail_color_modifier;\n"; - } - - //need a random function - code += "\n\n"; - code += "float rand_from_seed(inout uint seed) {\n"; - code += " int k;\n"; - code += " int s = int(seed);\n"; - code += " if (s == 0)\n"; - code += " s = 305420679;\n"; - code += " k = s / 127773;\n"; - code += " s = 16807 * (s - k * 127773) - 2836 * k;\n"; - code += " if (s < 0)\n"; - code += " s += 2147483647;\n"; - code += " seed = uint(s);\n"; - code += " return float(seed % uint(65536))/65535.0;\n"; - code += "}\n"; - code += "\n"; - - code += "float rand_from_seed_m1_p1(inout uint seed) {\n"; - code += " return rand_from_seed(seed)*2.0-1.0;\n"; - code += "}\n"; - code += "\n"; - - //improve seed quality - code += "uint hash(uint x) {\n"; - code += " x = ((x >> uint(16)) ^ x) * uint(73244475);\n"; - code += " x = ((x >> uint(16)) ^ x) * uint(73244475);\n"; - code += " x = (x >> uint(16)) ^ x;\n"; - code += " return x;\n"; - code += "}\n"; - code += "\n"; - - code += "void vertex() {\n"; - code += " uint base_number = NUMBER/uint(trail_divisor);\n"; - code += " uint alt_seed = hash(base_number+uint(1)+RANDOM_SEED);\n"; - code += " float angle_rand = rand_from_seed(alt_seed);\n"; - code += " float scale_rand = rand_from_seed(alt_seed);\n"; - code += " float hue_rot_rand = rand_from_seed(alt_seed);\n"; - code += " float anim_offset_rand = rand_from_seed(alt_seed);\n"; - code += " float pi = 3.14159;\n"; - code += " float degree_to_rad = pi / 180.0;\n"; - code += "\n"; - - if (emission_shape >= EMISSION_SHAPE_POINTS) { - code += " int point = min(emission_texture_point_count-1,int(rand_from_seed(alt_seed) * float(emission_texture_point_count)));\n"; - code += " ivec2 emission_tex_size = textureSize( emission_texture_points, 0 );\n"; - code += " ivec2 emission_tex_ofs = ivec2( point % emission_tex_size.x, point / emission_tex_size.x );\n"; - } - code += " if (RESTART) {\n"; - - if (tex_parameters[PARAM_INITIAL_LINEAR_VELOCITY].is_valid()) - code += " float tex_linear_velocity = textureLod(linear_velocity_texture,vec2(0.0,0.0),0.0).r;\n"; - else - code += " float tex_linear_velocity = 0.0;\n"; - - if (tex_parameters[PARAM_ANGLE].is_valid()) - code += " float tex_angle = textureLod(angle_texture,vec2(0.0,0.0),0.0).r;\n"; - else - code += " float tex_angle = 0.0;\n"; - - if (tex_parameters[PARAM_ANIM_OFFSET].is_valid()) - code += " float tex_anim_offset = textureLod(anim_offset_texture,vec2(0.0,0.0),0.0).r;\n"; - else - code += " float tex_anim_offset = 0.0;\n"; - - code += " float spread_rad = spread*degree_to_rad;\n"; - - if (flags[FLAG_DISABLE_Z]) { - - code += " float angle1_rad = rand_from_seed_m1_p1(alt_seed)*spread_rad;\n"; - code += " vec3 rot = vec3( cos(angle1_rad), sin(angle1_rad),0.0 );\n"; - code += " VELOCITY = rot*initial_linear_velocity*mix(1.0, rand_from_seed(alt_seed), initial_linear_velocity_random);\n"; - - } else { - //initiate velocity spread in 3D - code += " float angle1_rad = rand_from_seed_m1_p1(alt_seed)*spread_rad;\n"; - code += " float angle2_rad = rand_from_seed_m1_p1(alt_seed)*spread_rad*(1.0-flatness);\n"; - code += " vec3 direction_xz = vec3( sin(angle1_rad), 0, cos(angle1_rad));\n"; - code += " vec3 direction_yz = vec3( 0, sin(angle2_rad), cos(angle2_rad));\n"; - code += " direction_yz.z = direction_yz.z / sqrt(direction_yz.z); //better uniform distribution\n"; - code += " vec3 direction = vec3(direction_xz.x * direction_yz.z, direction_yz.y, direction_xz.z * direction_yz.z);\n"; - code += " direction = normalize(direction);\n"; - code += " VELOCITY = direction*initial_linear_velocity*mix(1.0, rand_from_seed(alt_seed), initial_linear_velocity_random);\n"; - } - - code += " float base_angle = (initial_angle+tex_angle)*mix(1.0,angle_rand,initial_angle_random);\n"; - code += " CUSTOM.x = base_angle*degree_to_rad;\n"; //angle - code += " CUSTOM.y = 0.0;\n"; //phase - code += " CUSTOM.z = (anim_offset+tex_anim_offset)*mix(1.0,anim_offset_rand,anim_offset_random);\n"; //animation offset (0-1) - switch (emission_shape) { - case EMISSION_SHAPE_POINT: { - //do none - } break; - case EMISSION_SHAPE_SPHERE: { - code += " TRANSFORM[3].xyz = normalize(vec3(rand_from_seed(alt_seed) * 2.0 - 1.0, rand_from_seed(alt_seed) * 2.0-1.0, rand_from_seed(alt_seed) * 2.0-1.0 ))*emission_sphere_radius;\n"; - } break; - case EMISSION_SHAPE_BOX: { - code += " TRANSFORM[3].xyz = vec3(rand_from_seed(alt_seed) * 2.0 - 1.0, rand_from_seed(alt_seed) * 2.0-1.0, rand_from_seed(alt_seed) * 2.0-1.0)*emission_box_extents;\n"; - } break; - case EMISSION_SHAPE_POINTS: - case EMISSION_SHAPE_DIRECTED_POINTS: { - code += " TRANSFORM[3].xyz = texelFetch(emission_texture_points, emission_tex_ofs,0).xyz;\n"; - - if (emission_shape == EMISSION_SHAPE_DIRECTED_POINTS) { - if (flags[FLAG_DISABLE_Z]) { - - code += " mat2 rotm;"; - code += " rotm[0] = texelFetch(emission_texture_normal, emission_tex_ofs,0).xy;\n"; - code += " rotm[1] = rotm[0].yx * vec2(1.0,-1.0);\n"; - code += " VELOCITY.xy = rotm * VELOCITY.xy;\n"; - } else { - code += " vec3 normal = texelFetch(emission_texture_normal, emission_tex_ofs,0).xyz;\n"; - code += " vec3 v0 = abs(normal.z) < 0.999 ? vec3(0.0, 0.0, 1.0) : vec3(0, 1.0, 0.0);\n"; - code += " vec3 tangent = normalize(cross(v0, normal));\n"; - code += " vec3 bitangent = normalize(cross(tangent, normal));\n"; - code += " VELOCITY = mat3(tangent,bitangent,normal) * VELOCITY;\n"; - } - } - } break; - } - code += " VELOCITY = (EMISSION_TRANSFORM * vec4(VELOCITY,0.0)).xyz;\n"; - code += " TRANSFORM = EMISSION_TRANSFORM * TRANSFORM;\n"; - if (flags[FLAG_DISABLE_Z]) { - code += " VELOCITY.z = 0.0;\n"; - code += " TRANSFORM[3].z = 0.0;\n"; - } - - code += " } else {\n"; - - code += " CUSTOM.y += DELTA/LIFETIME;\n"; - if (tex_parameters[PARAM_INITIAL_LINEAR_VELOCITY].is_valid()) - code += " float tex_linear_velocity = textureLod(linear_velocity_texture,vec2(CUSTOM.y,0.0),0.0).r;\n"; - else - code += " float tex_linear_velocity = 0.0;\n"; - - if (flags[FLAG_DISABLE_Z]) { - - if (tex_parameters[PARAM_ORBIT_VELOCITY].is_valid()) - code += " float tex_orbit_velocity = textureLod(orbit_velocity_texture,vec2(CUSTOM.y,0.0),0.0).r;\n"; - else - code += " float tex_orbit_velocity = 0.0;\n"; - } - - if (tex_parameters[PARAM_ANGULAR_VELOCITY].is_valid()) - code += " float tex_angular_velocity = textureLod(angular_velocity_texture,vec2(CUSTOM.y,0.0),0.0).r;\n"; - else - code += " float tex_angular_velocity = 0.0;\n"; - - if (tex_parameters[PARAM_LINEAR_ACCEL].is_valid()) - code += " float tex_linear_accel = textureLod(linear_accel_texture,vec2(CUSTOM.y,0.0),0.0).r;\n"; - else - code += " float tex_linear_accel = 0.0;\n"; - - if (tex_parameters[PARAM_RADIAL_ACCEL].is_valid()) - code += " float tex_radial_accel = textureLod(radial_accel_texture,vec2(CUSTOM.y,0.0),0.0).r;\n"; - else - code += " float tex_radial_accel = 0.0;\n"; - - if (tex_parameters[PARAM_TANGENTIAL_ACCEL].is_valid()) - code += " float tex_tangent_accel = textureLod(tangent_accel_texture,vec2(CUSTOM.y,0.0),0.0).r;\n"; - else - code += " float tex_tangent_accel = 0.0;\n"; - - if (tex_parameters[PARAM_DAMPING].is_valid()) - code += " float tex_damping = textureLod(damping_texture,vec2(CUSTOM.y,0.0),0.0).r;\n"; - else - code += " float tex_damping = 0.0;\n"; - - if (tex_parameters[PARAM_ANGLE].is_valid()) - code += " float tex_angle = textureLod(angle_texture,vec2(CUSTOM.y,0.0),0.0).r;\n"; - else - code += " float tex_angle = 0.0;\n"; - - if (tex_parameters[PARAM_ANIM_SPEED].is_valid()) - code += " float tex_anim_speed = textureLod(anim_speed_texture,vec2(CUSTOM.y,0.0),0.0).r;\n"; - else - code += " float tex_anim_speed = 0.0;\n"; - - if (tex_parameters[PARAM_ANIM_OFFSET].is_valid()) - code += " float tex_anim_offset = textureLod(anim_offset_texture,vec2(CUSTOM.y,0.0),0.0).r;\n"; - else - code += " float tex_anim_offset = 0.0;\n"; - - code += " vec3 force = gravity; \n"; - code += " vec3 pos = TRANSFORM[3].xyz; \n"; - if (flags[FLAG_DISABLE_Z]) { - code += " pos.z = 0.0; \n"; - } - code += " //apply linear acceleration\n"; - code += " force += length(VELOCITY) > 0.0 ? normalize(VELOCITY) * (linear_accel+tex_linear_accel)*mix(1.0,rand_from_seed(alt_seed),linear_accel_random) : vec3(0.0);\n"; - code += " //apply radial acceleration\n"; - code += " vec3 org = EMISSION_TRANSFORM[3].xyz;\n"; - code += " vec3 diff = pos-org;\n"; - code += " force += length(diff) > 0.0 ? normalize(diff) * (radial_accel+tex_radial_accel)*mix(1.0,rand_from_seed(alt_seed),radial_accel_random) : vec3(0.0);\n"; - code += " //apply tangential acceleration;\n"; - if (flags[FLAG_DISABLE_Z]) { - code += " force += length(diff.yx) > 0.0 ? vec3(normalize(diff.yx * vec2(-1.0,1.0)),0.0) * ((tangent_accel+tex_tangent_accel)*mix(1.0,rand_from_seed(alt_seed),tangent_accel_random)) : vec3(0.0);\n"; - - } else { - code += " vec3 crossDiff = cross(normalize(diff),normalize(gravity));\n"; - code += " force += length(crossDiff) > 0.0 ? normalize(crossDiff) * ((tangent_accel+tex_tangent_accel)*mix(1.0,rand_from_seed(alt_seed),tangent_accel_random)) : vec3(0.0);\n"; - } - code += " //apply attractor forces\n"; - code += " VELOCITY += force * DELTA;\n"; - code += " //orbit velocity\n"; - if (flags[FLAG_DISABLE_Z]) { - - code += " float orbit_amount = (orbit_velocity+tex_orbit_velocity)*mix(1.0,rand_from_seed(alt_seed),orbit_velocity_random);\n"; - code += " if (orbit_amount!=0.0) {\n"; - code += " float ang = orbit_amount * DELTA * pi * 2.0;\n"; - code += " mat2 rot = mat2(vec2(cos(ang),-sin(ang)),vec2(sin(ang),cos(ang)));\n"; - code += " TRANSFORM[3].xy-=diff.xy;\n"; - code += " TRANSFORM[3].xy+=rot * diff.xy;\n"; - code += " }\n"; - } - - if (tex_parameters[PARAM_INITIAL_LINEAR_VELOCITY].is_valid()) { - code += " VELOCITY = normalize(VELOCITY)*tex_linear_velocity;\n"; - } - code += " if (damping + tex_damping > 0.0) {\n"; - code += " \n"; - code += " float v = length(VELOCITY);\n"; - code += " float damp = (damping+tex_damping)*mix(1.0,rand_from_seed(alt_seed),damping_random);\n"; - code += " v -= damp * DELTA;\n"; - code += " if (v < 0.0) {\n"; - code += " VELOCITY = vec3(0.0);\n"; - code += " } else {\n"; - code += " VELOCITY = normalize(VELOCITY) * v;\n"; - code += " }\n"; - code += " }\n"; - code += " float base_angle = (initial_angle+tex_angle)*mix(1.0,angle_rand,initial_angle_random);\n"; - code += " base_angle += CUSTOM.y*LIFETIME*(angular_velocity+tex_angular_velocity)*mix(1.0,rand_from_seed(alt_seed)*2.0-1.0,angular_velocity_random);\n"; - code += " CUSTOM.x = base_angle*degree_to_rad;\n"; //angle - code += " CUSTOM.z = (anim_offset+tex_anim_offset)*mix(1.0,anim_offset_rand,anim_offset_random)+CUSTOM.y*(anim_speed+tex_anim_speed)*mix(1.0,rand_from_seed(alt_seed),anim_speed_random);\n"; //angle - if (flags[FLAG_ANIM_LOOP]) { - code += " CUSTOM.z = mod(CUSTOM.z,1.0);\n"; //loop - - } else { - code += " CUSTOM.z = clamp(CUSTOM.z,0.0,1.0);\n"; //0 to 1 only - } - code += " }\n"; - //apply color - //apply hue rotation - if (tex_parameters[PARAM_SCALE].is_valid()) - code += " float tex_scale = textureLod(scale_texture,vec2(CUSTOM.y,0.0),0.0).r;\n"; - else - code += " float tex_scale = 1.0;\n"; - - if (tex_parameters[PARAM_HUE_VARIATION].is_valid()) - code += " float tex_hue_variation = textureLod(hue_variation_texture,vec2(CUSTOM.y,0.0),0.0).r;\n"; - else - code += " float tex_hue_variation = 0.0;\n"; - - code += " float hue_rot_angle = (hue_variation+tex_hue_variation)*pi*2.0*mix(1.0,hue_rot_rand*2.0-1.0,hue_variation_random);\n"; - code += " float hue_rot_c = cos(hue_rot_angle);\n"; - code += " float hue_rot_s = sin(hue_rot_angle);\n"; - code += " mat4 hue_rot_mat = mat4( vec4(0.299, 0.587, 0.114, 0.0),\n"; - code += " vec4(0.299, 0.587, 0.114, 0.0),\n"; - code += " vec4(0.299, 0.587, 0.114, 0.0),\n"; - code += " vec4(0.000, 0.000, 0.000, 1.0)) +\n"; - code += " mat4( vec4(0.701, -0.587, -0.114, 0.0),\n"; - code += " vec4(-0.299, 0.413, -0.114, 0.0),\n"; - code += " vec4(-0.300, -0.588, 0.886, 0.0),\n"; - code += " vec4(0.000, 0.000, 0.000, 0.0)) * hue_rot_c +\n"; - code += " mat4( vec4(0.168, 0.330, -0.497, 0.0),\n"; - code += " vec4(-0.328, 0.035, 0.292, 0.0),\n"; - code += " vec4(1.250, -1.050, -0.203, 0.0),\n"; - code += " vec4(0.000, 0.000, 0.000, 0.0)) * hue_rot_s;\n"; - if (color_ramp.is_valid()) { - code += " COLOR = hue_rot_mat * textureLod(color_ramp,vec2(CUSTOM.y,0.0),0.0);\n"; - } else { - code += " COLOR = hue_rot_mat * color_value;\n"; - } - if (emission_color_texture.is_valid() && emission_shape >= EMISSION_SHAPE_POINTS) { - code += " COLOR*= texelFetch(emission_texture_color,emission_tex_ofs,0);\n"; - } - if (trail_color_modifier.is_valid()) { - code += " if (trail_divisor > 1) { COLOR *= textureLod(trail_color_modifier,vec2(float(int(NUMBER)%trail_divisor)/float(trail_divisor-1),0.0),0.0); }\n"; - } - code += "\n"; - - if (flags[FLAG_DISABLE_Z]) { - - if (flags[FLAG_ALIGN_Y_TO_VELOCITY]) { - code += " if (length(VELOCITY) > 0.0) { TRANSFORM[1].xyz = normalize(VELOCITY); } else { TRANSFORM[1].xyz = normalize(TRANSFORM[1].xyz); }\n"; - code += " TRANSFORM[0].xyz = normalize(cross(TRANSFORM[1].xyz,TRANSFORM[2].xyz));\n"; - code += " TRANSFORM[2] = vec4(0.0,0.0,1.0,0.0);\n"; - } else { - code += " TRANSFORM[0] = vec4(cos(CUSTOM.x),-sin(CUSTOM.x),0.0,0.0);\n"; - code += " TRANSFORM[1] = vec4(sin(CUSTOM.x),cos(CUSTOM.x),0.0,0.0);\n"; - code += " TRANSFORM[2] = vec4(0.0,0.0,1.0,0.0);\n"; - } - - } else { - //orient particle Y towards velocity - if (flags[FLAG_ALIGN_Y_TO_VELOCITY]) { - code += " if (length(VELOCITY) > 0.0) { TRANSFORM[1].xyz = normalize(VELOCITY); } else { TRANSFORM[1].xyz = normalize(TRANSFORM[1].xyz); }\n"; - code += " if (TRANSFORM[1].xyz == normalize(TRANSFORM[0].xyz)) {\n"; - code += " TRANSFORM[0].xyz = normalize(cross(normalize(TRANSFORM[1].xyz),normalize(TRANSFORM[2].xyz)));\n"; - code += " TRANSFORM[2].xyz = normalize(cross(normalize(TRANSFORM[0].xyz),normalize(TRANSFORM[1].xyz)));\n"; - code += " } else {\n"; - code += " TRANSFORM[2].xyz = normalize(cross(normalize(TRANSFORM[0].xyz),normalize(TRANSFORM[1].xyz)));\n"; - code += " TRANSFORM[0].xyz = normalize(cross(normalize(TRANSFORM[1].xyz),normalize(TRANSFORM[2].xyz)));\n"; - code += " }\n"; - } else { - code += " TRANSFORM[0].xyz = normalize(TRANSFORM[0].xyz);\n"; - code += " TRANSFORM[1].xyz = normalize(TRANSFORM[1].xyz);\n"; - code += " TRANSFORM[2].xyz = normalize(TRANSFORM[2].xyz);\n"; - } - //turn particle by rotation in Y - if (flags[FLAG_ROTATE_Y]) { - code += " TRANSFORM = TRANSFORM * mat4( vec4(cos(CUSTOM.x),0.0,-sin(CUSTOM.x),0.0), vec4(0.0,1.0,0.0,0.0),vec4(sin(CUSTOM.x),0.0,cos(CUSTOM.x),0.0),vec4(0.0,0.0,0.0,1.0));\n"; - } - } - //scale by scale - code += " float base_scale = mix(scale*tex_scale,1.0,scale_random*scale_rand);\n"; - code += " if (base_scale==0.0) base_scale=0.000001;\n"; - if (trail_size_modifier.is_valid()) { - code += " if (trail_divisor > 1) { base_scale *= textureLod(trail_size_modifier,vec2(float(int(NUMBER)%trail_divisor)/float(trail_divisor-1),0.0),0.0).r; } \n"; - } - - code += " TRANSFORM[0].xyz *= base_scale;\n"; - code += " TRANSFORM[1].xyz *= base_scale;\n"; - code += " TRANSFORM[2].xyz *= base_scale;\n"; - if (flags[FLAG_DISABLE_Z]) { - code += " VELOCITY.z = 0.0;\n"; - code += " TRANSFORM[3].z = 0.0;\n"; - } - code += "}\n"; - code += "\n"; - - ShaderData shader_data; - shader_data.shader = VS::get_singleton()->shader_create(); - shader_data.users = 1; - - VS::get_singleton()->shader_set_code(shader_data.shader, code); - - shader_map[mk] = shader_data; - - VS::get_singleton()->material_set_shader(_get_material(), shader_data.shader); -} - -void ParticlesMaterial::flush_changes() { - - if (material_mutex) - material_mutex->lock(); - - while (dirty_materials.first()) { - - dirty_materials.first()->self()->_update_shader(); - } - - if (material_mutex) - material_mutex->unlock(); -} - -void ParticlesMaterial::_queue_shader_change() { - - if (material_mutex) - material_mutex->lock(); - - if (!element.in_list()) { - dirty_materials.add(&element); - } - - if (material_mutex) - material_mutex->unlock(); -} - -bool ParticlesMaterial::_is_shader_dirty() const { - - bool dirty = false; - - if (material_mutex) - material_mutex->lock(); - - dirty = element.in_list(); - - if (material_mutex) - material_mutex->unlock(); - - return dirty; -} - -void ParticlesMaterial::set_spread(float p_spread) { - - spread = p_spread; - VisualServer::get_singleton()->material_set_param(_get_material(), shader_names->spread, p_spread); -} - -float ParticlesMaterial::get_spread() const { - - return spread; -} - -void ParticlesMaterial::set_flatness(float p_flatness) { - - flatness = p_flatness; - VisualServer::get_singleton()->material_set_param(_get_material(), shader_names->flatness, p_flatness); -} -float ParticlesMaterial::get_flatness() const { - - return flatness; -} - -void ParticlesMaterial::set_param(Parameter p_param, float p_value) { - - ERR_FAIL_INDEX(p_param, PARAM_MAX); - - parameters[p_param] = p_value; - - switch (p_param) { - case PARAM_INITIAL_LINEAR_VELOCITY: { - VisualServer::get_singleton()->material_set_param(_get_material(), shader_names->initial_linear_velocity, p_value); - } break; - case PARAM_ANGULAR_VELOCITY: { - VisualServer::get_singleton()->material_set_param(_get_material(), shader_names->angular_velocity, p_value); - } break; - case PARAM_ORBIT_VELOCITY: { - VisualServer::get_singleton()->material_set_param(_get_material(), shader_names->orbit_velocity, p_value); - } break; - case PARAM_LINEAR_ACCEL: { - VisualServer::get_singleton()->material_set_param(_get_material(), shader_names->linear_accel, p_value); - } break; - case PARAM_RADIAL_ACCEL: { - VisualServer::get_singleton()->material_set_param(_get_material(), shader_names->radial_accel, p_value); - } break; - case PARAM_TANGENTIAL_ACCEL: { - VisualServer::get_singleton()->material_set_param(_get_material(), shader_names->tangent_accel, p_value); - } break; - case PARAM_DAMPING: { - VisualServer::get_singleton()->material_set_param(_get_material(), shader_names->damping, p_value); - } break; - case PARAM_ANGLE: { - VisualServer::get_singleton()->material_set_param(_get_material(), shader_names->initial_angle, p_value); - } break; - case PARAM_SCALE: { - VisualServer::get_singleton()->material_set_param(_get_material(), shader_names->scale, p_value); - } break; - case PARAM_HUE_VARIATION: { - VisualServer::get_singleton()->material_set_param(_get_material(), shader_names->hue_variation, p_value); - } break; - case PARAM_ANIM_SPEED: { - VisualServer::get_singleton()->material_set_param(_get_material(), shader_names->anim_speed, p_value); - } break; - case PARAM_ANIM_OFFSET: { - VisualServer::get_singleton()->material_set_param(_get_material(), shader_names->anim_offset, p_value); - } break; - } -} -float ParticlesMaterial::get_param(Parameter p_param) const { - - ERR_FAIL_INDEX_V(p_param, PARAM_MAX, 0); - - return parameters[p_param]; -} - -void ParticlesMaterial::set_param_randomness(Parameter p_param, float p_value) { - - ERR_FAIL_INDEX(p_param, PARAM_MAX); - - randomness[p_param] = p_value; - - switch (p_param) { - case PARAM_INITIAL_LINEAR_VELOCITY: { - VisualServer::get_singleton()->material_set_param(_get_material(), shader_names->initial_linear_velocity_random, p_value); - } break; - case PARAM_ANGULAR_VELOCITY: { - VisualServer::get_singleton()->material_set_param(_get_material(), shader_names->angular_velocity_random, p_value); - } break; - case PARAM_ORBIT_VELOCITY: { - VisualServer::get_singleton()->material_set_param(_get_material(), shader_names->orbit_velocity_random, p_value); - } break; - case PARAM_LINEAR_ACCEL: { - VisualServer::get_singleton()->material_set_param(_get_material(), shader_names->linear_accel_random, p_value); - } break; - case PARAM_RADIAL_ACCEL: { - VisualServer::get_singleton()->material_set_param(_get_material(), shader_names->radial_accel_random, p_value); - } break; - case PARAM_TANGENTIAL_ACCEL: { - VisualServer::get_singleton()->material_set_param(_get_material(), shader_names->tangent_accel_random, p_value); - } break; - case PARAM_DAMPING: { - VisualServer::get_singleton()->material_set_param(_get_material(), shader_names->damping_random, p_value); - } break; - case PARAM_ANGLE: { - VisualServer::get_singleton()->material_set_param(_get_material(), shader_names->initial_angle_random, p_value); - } break; - case PARAM_SCALE: { - VisualServer::get_singleton()->material_set_param(_get_material(), shader_names->scale_random, p_value); - } break; - case PARAM_HUE_VARIATION: { - VisualServer::get_singleton()->material_set_param(_get_material(), shader_names->hue_variation_random, p_value); - } break; - case PARAM_ANIM_SPEED: { - VisualServer::get_singleton()->material_set_param(_get_material(), shader_names->anim_speed_random, p_value); - } break; - case PARAM_ANIM_OFFSET: { - VisualServer::get_singleton()->material_set_param(_get_material(), shader_names->anim_offset_random, p_value); - } break; - } -} -float ParticlesMaterial::get_param_randomness(Parameter p_param) const { - - ERR_FAIL_INDEX_V(p_param, PARAM_MAX, 0); - - return randomness[p_param]; -} - -static void _adjust_curve_range(const Ref<Texture> &p_texture, float p_min, float p_max) { - - Ref<CurveTexture> curve_tex = p_texture; - if (!curve_tex.is_valid()) - return; - - curve_tex->ensure_default_setup(p_min, p_max); -} - -void ParticlesMaterial::set_param_texture(Parameter p_param, const Ref<Texture> &p_texture) { - - ERR_FAIL_INDEX(p_param, PARAM_MAX); - - tex_parameters[p_param] = p_texture; - - switch (p_param) { - case PARAM_INITIAL_LINEAR_VELOCITY: { - //do none for this one - } break; - case PARAM_ANGULAR_VELOCITY: { - VisualServer::get_singleton()->material_set_param(_get_material(), shader_names->angular_velocity_texture, p_texture); - _adjust_curve_range(p_texture, -360, 360); - } break; - case PARAM_ORBIT_VELOCITY: { - VisualServer::get_singleton()->material_set_param(_get_material(), shader_names->orbit_velocity_texture, p_texture); - _adjust_curve_range(p_texture, -500, 500); - } break; - case PARAM_LINEAR_ACCEL: { - VisualServer::get_singleton()->material_set_param(_get_material(), shader_names->linear_accel_texture, p_texture); - _adjust_curve_range(p_texture, -200, 200); - } break; - case PARAM_RADIAL_ACCEL: { - VisualServer::get_singleton()->material_set_param(_get_material(), shader_names->radial_accel_texture, p_texture); - _adjust_curve_range(p_texture, -200, 200); - } break; - case PARAM_TANGENTIAL_ACCEL: { - VisualServer::get_singleton()->material_set_param(_get_material(), shader_names->tangent_accel_texture, p_texture); - _adjust_curve_range(p_texture, -200, 200); - } break; - case PARAM_DAMPING: { - VisualServer::get_singleton()->material_set_param(_get_material(), shader_names->damping_texture, p_texture); - _adjust_curve_range(p_texture, 0, 100); - } break; - case PARAM_ANGLE: { - VisualServer::get_singleton()->material_set_param(_get_material(), shader_names->angle_texture, p_texture); - _adjust_curve_range(p_texture, -360, 360); - } break; - case PARAM_SCALE: { - VisualServer::get_singleton()->material_set_param(_get_material(), shader_names->scale_texture, p_texture); - - Ref<CurveTexture> curve_tex = p_texture; - if (curve_tex.is_valid()) { - curve_tex->ensure_default_setup(); - } - - } break; - case PARAM_HUE_VARIATION: { - VisualServer::get_singleton()->material_set_param(_get_material(), shader_names->hue_variation_texture, p_texture); - _adjust_curve_range(p_texture, -1, 1); - } break; - case PARAM_ANIM_SPEED: { - VisualServer::get_singleton()->material_set_param(_get_material(), shader_names->anim_speed_texture, p_texture); - _adjust_curve_range(p_texture, 0, 200); - } break; - case PARAM_ANIM_OFFSET: { - VisualServer::get_singleton()->material_set_param(_get_material(), shader_names->anim_offset_texture, p_texture); - } break; - } - - _queue_shader_change(); -} -Ref<Texture> ParticlesMaterial::get_param_texture(Parameter p_param) const { - - ERR_FAIL_INDEX_V(p_param, PARAM_MAX, Ref<Texture>()); - - return tex_parameters[p_param]; -} - -void ParticlesMaterial::set_color(const Color &p_color) { - - VisualServer::get_singleton()->material_set_param(_get_material(), shader_names->color, p_color); - color = p_color; -} - -Color ParticlesMaterial::get_color() const { - - return color; -} - -void ParticlesMaterial::set_color_ramp(const Ref<Texture> &p_texture) { - - color_ramp = p_texture; - VisualServer::get_singleton()->material_set_param(_get_material(), shader_names->color_ramp, p_texture); - _queue_shader_change(); - _change_notify(); -} - -Ref<Texture> ParticlesMaterial::get_color_ramp() const { - - return color_ramp; -} - -void ParticlesMaterial::set_flag(Flags p_flag, bool p_enable) { - ERR_FAIL_INDEX(p_flag, FLAG_MAX); - flags[p_flag] = p_enable; - _queue_shader_change(); - if (p_flag == FLAG_DISABLE_Z) { - _change_notify(); - } -} - -bool ParticlesMaterial::get_flag(Flags p_flag) const { - ERR_FAIL_INDEX_V(p_flag, FLAG_MAX, false); - return flags[p_flag]; -} - -void ParticlesMaterial::set_emission_shape(EmissionShape p_shape) { - - emission_shape = p_shape; - _change_notify(); - _queue_shader_change(); -} - -void ParticlesMaterial::set_emission_sphere_radius(float p_radius) { - - emission_sphere_radius = p_radius; - VisualServer::get_singleton()->material_set_param(_get_material(), shader_names->emission_sphere_radius, p_radius); -} - -void ParticlesMaterial::set_emission_box_extents(Vector3 p_extents) { - - emission_box_extents = p_extents; - VisualServer::get_singleton()->material_set_param(_get_material(), shader_names->emission_box_extents, p_extents); -} - -void ParticlesMaterial::set_emission_point_texture(const Ref<Texture> &p_points) { - - emission_point_texture = p_points; - VisualServer::get_singleton()->material_set_param(_get_material(), shader_names->emission_texture_points, p_points); -} - -void ParticlesMaterial::set_emission_normal_texture(const Ref<Texture> &p_normals) { - - emission_normal_texture = p_normals; - VisualServer::get_singleton()->material_set_param(_get_material(), shader_names->emission_texture_normal, p_normals); -} - -void ParticlesMaterial::set_emission_color_texture(const Ref<Texture> &p_colors) { - - emission_color_texture = p_colors; - VisualServer::get_singleton()->material_set_param(_get_material(), shader_names->emission_texture_color, p_colors); - _queue_shader_change(); -} - -void ParticlesMaterial::set_emission_point_count(int p_count) { - - emission_point_count = p_count; - VisualServer::get_singleton()->material_set_param(_get_material(), shader_names->emission_texture_point_count, p_count); -} - -ParticlesMaterial::EmissionShape ParticlesMaterial::get_emission_shape() const { - - return emission_shape; -} - -float ParticlesMaterial::get_emission_sphere_radius() const { - - return emission_sphere_radius; -} -Vector3 ParticlesMaterial::get_emission_box_extents() const { - - return emission_box_extents; -} -Ref<Texture> ParticlesMaterial::get_emission_point_texture() const { - - return emission_point_texture; -} -Ref<Texture> ParticlesMaterial::get_emission_normal_texture() const { - - return emission_normal_texture; -} - -Ref<Texture> ParticlesMaterial::get_emission_color_texture() const { - - return emission_color_texture; -} - -int ParticlesMaterial::get_emission_point_count() const { - - return emission_point_count; -} - -void ParticlesMaterial::set_trail_divisor(int p_divisor) { - - trail_divisor = p_divisor; - VisualServer::get_singleton()->material_set_param(_get_material(), shader_names->trail_divisor, p_divisor); -} - -int ParticlesMaterial::get_trail_divisor() const { - - return trail_divisor; -} - -void ParticlesMaterial::set_trail_size_modifier(const Ref<CurveTexture> &p_trail_size_modifier) { - - trail_size_modifier = p_trail_size_modifier; - - Ref<CurveTexture> curve = trail_size_modifier; - if (curve.is_valid()) { - curve->ensure_default_setup(); - } - - VisualServer::get_singleton()->material_set_param(_get_material(), shader_names->trail_size_modifier, curve); - _queue_shader_change(); -} - -Ref<CurveTexture> ParticlesMaterial::get_trail_size_modifier() const { - - return trail_size_modifier; -} - -void ParticlesMaterial::set_trail_color_modifier(const Ref<GradientTexture> &p_trail_color_modifier) { - - trail_color_modifier = p_trail_color_modifier; - VisualServer::get_singleton()->material_set_param(_get_material(), shader_names->trail_color_modifier, p_trail_color_modifier); - _queue_shader_change(); -} - -Ref<GradientTexture> ParticlesMaterial::get_trail_color_modifier() const { - - return trail_color_modifier; -} - -void ParticlesMaterial::set_gravity(const Vector3 &p_gravity) { - - gravity = p_gravity; - Vector3 gset = gravity; - if (gset == Vector3()) { - gset = Vector3(0, -0.000001, 0); //as gravity is used as upvector in some calculations - } - VisualServer::get_singleton()->material_set_param(_get_material(), shader_names->gravity, gset); -} - -Vector3 ParticlesMaterial::get_gravity() const { - - return gravity; -} - -RID ParticlesMaterial::get_shader_rid() const { - - ERR_FAIL_COND_V(!shader_map.has(current_key), RID()); - return shader_map[current_key].shader; -} - -void ParticlesMaterial::_validate_property(PropertyInfo &property) const { - - if (property.name == "color" && color_ramp.is_valid()) { - property.usage = 0; - } - - if (property.name == "emission_sphere_radius" && emission_shape != EMISSION_SHAPE_SPHERE) { - property.usage = 0; - } - - if (property.name == "emission_box_extents" && emission_shape != EMISSION_SHAPE_BOX) { - property.usage = 0; - } - - if ((property.name == "emission_point_texture" || property.name == "emission_color_texture") && (emission_shape < EMISSION_SHAPE_POINTS)) { - property.usage = 0; - } - - if (property.name == "emission_normal_texture" && emission_shape != EMISSION_SHAPE_DIRECTED_POINTS) { - property.usage = 0; - } - - if (property.name == "emission_point_count" && (emission_shape != EMISSION_SHAPE_POINTS && emission_shape != EMISSION_SHAPE_DIRECTED_POINTS)) { - property.usage = 0; - } - - if (property.name.begins_with("orbit_") && !flags[FLAG_DISABLE_Z]) { - property.usage = 0; - } -} - -Shader::Mode ParticlesMaterial::get_shader_mode() const { - - return Shader::MODE_PARTICLES; -} - -void ParticlesMaterial::_bind_methods() { - - ClassDB::bind_method(D_METHOD("set_spread", "degrees"), &ParticlesMaterial::set_spread); - ClassDB::bind_method(D_METHOD("get_spread"), &ParticlesMaterial::get_spread); - - ClassDB::bind_method(D_METHOD("set_flatness", "amount"), &ParticlesMaterial::set_flatness); - ClassDB::bind_method(D_METHOD("get_flatness"), &ParticlesMaterial::get_flatness); - - ClassDB::bind_method(D_METHOD("set_param", "param", "value"), &ParticlesMaterial::set_param); - ClassDB::bind_method(D_METHOD("get_param", "param"), &ParticlesMaterial::get_param); - - ClassDB::bind_method(D_METHOD("set_param_randomness", "param", "randomness"), &ParticlesMaterial::set_param_randomness); - ClassDB::bind_method(D_METHOD("get_param_randomness", "param"), &ParticlesMaterial::get_param_randomness); - - ClassDB::bind_method(D_METHOD("set_param_texture", "param", "texture"), &ParticlesMaterial::set_param_texture); - ClassDB::bind_method(D_METHOD("get_param_texture", "param"), &ParticlesMaterial::get_param_texture); - - ClassDB::bind_method(D_METHOD("set_color", "color"), &ParticlesMaterial::set_color); - ClassDB::bind_method(D_METHOD("get_color"), &ParticlesMaterial::get_color); - - ClassDB::bind_method(D_METHOD("set_color_ramp", "ramp"), &ParticlesMaterial::set_color_ramp); - ClassDB::bind_method(D_METHOD("get_color_ramp"), &ParticlesMaterial::get_color_ramp); - - ClassDB::bind_method(D_METHOD("set_flag", "flag", "enable"), &ParticlesMaterial::set_flag); - ClassDB::bind_method(D_METHOD("get_flag", "flag"), &ParticlesMaterial::get_flag); - - ClassDB::bind_method(D_METHOD("set_emission_shape", "shape"), &ParticlesMaterial::set_emission_shape); - ClassDB::bind_method(D_METHOD("get_emission_shape"), &ParticlesMaterial::get_emission_shape); - - ClassDB::bind_method(D_METHOD("set_emission_sphere_radius", "radius"), &ParticlesMaterial::set_emission_sphere_radius); - ClassDB::bind_method(D_METHOD("get_emission_sphere_radius"), &ParticlesMaterial::get_emission_sphere_radius); - - ClassDB::bind_method(D_METHOD("set_emission_box_extents", "extents"), &ParticlesMaterial::set_emission_box_extents); - ClassDB::bind_method(D_METHOD("get_emission_box_extents"), &ParticlesMaterial::get_emission_box_extents); - - ClassDB::bind_method(D_METHOD("set_emission_point_texture", "texture"), &ParticlesMaterial::set_emission_point_texture); - ClassDB::bind_method(D_METHOD("get_emission_point_texture"), &ParticlesMaterial::get_emission_point_texture); - - ClassDB::bind_method(D_METHOD("set_emission_normal_texture", "texture"), &ParticlesMaterial::set_emission_normal_texture); - ClassDB::bind_method(D_METHOD("get_emission_normal_texture"), &ParticlesMaterial::get_emission_normal_texture); - - ClassDB::bind_method(D_METHOD("set_emission_color_texture", "texture"), &ParticlesMaterial::set_emission_color_texture); - ClassDB::bind_method(D_METHOD("get_emission_color_texture"), &ParticlesMaterial::get_emission_color_texture); - - ClassDB::bind_method(D_METHOD("set_emission_point_count", "point_count"), &ParticlesMaterial::set_emission_point_count); - ClassDB::bind_method(D_METHOD("get_emission_point_count"), &ParticlesMaterial::get_emission_point_count); - - ClassDB::bind_method(D_METHOD("set_trail_divisor", "divisor"), &ParticlesMaterial::set_trail_divisor); - ClassDB::bind_method(D_METHOD("get_trail_divisor"), &ParticlesMaterial::get_trail_divisor); - - ClassDB::bind_method(D_METHOD("set_trail_size_modifier", "texture"), &ParticlesMaterial::set_trail_size_modifier); - ClassDB::bind_method(D_METHOD("get_trail_size_modifier"), &ParticlesMaterial::get_trail_size_modifier); - - ClassDB::bind_method(D_METHOD("set_trail_color_modifier", "texture"), &ParticlesMaterial::set_trail_color_modifier); - ClassDB::bind_method(D_METHOD("get_trail_color_modifier"), &ParticlesMaterial::get_trail_color_modifier); - - ClassDB::bind_method(D_METHOD("get_gravity"), &ParticlesMaterial::get_gravity); - ClassDB::bind_method(D_METHOD("set_gravity", "accel_vec"), &ParticlesMaterial::set_gravity); - - ADD_GROUP("Trail", "trail_"); - ADD_PROPERTY(PropertyInfo(Variant::INT, "trail_divisor", PROPERTY_HINT_RANGE, "1,1000000,1"), "set_trail_divisor", "get_trail_divisor"); - ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "trail_size_modifier", PROPERTY_HINT_RESOURCE_TYPE, "CurveTexture"), "set_trail_size_modifier", "get_trail_size_modifier"); - ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "trail_color_modifier", PROPERTY_HINT_RESOURCE_TYPE, "GradientTexture"), "set_trail_color_modifier", "get_trail_color_modifier"); - ADD_GROUP("Emission Shape", "emission_"); - ADD_PROPERTY(PropertyInfo(Variant::INT, "emission_shape", PROPERTY_HINT_ENUM, "Point,Sphere,Box,Points,Directed Points"), "set_emission_shape", "get_emission_shape"); - ADD_PROPERTY(PropertyInfo(Variant::REAL, "emission_sphere_radius", PROPERTY_HINT_RANGE, "0.01,128,0.01,or_greater"), "set_emission_sphere_radius", "get_emission_sphere_radius"); - ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "emission_box_extents"), "set_emission_box_extents", "get_emission_box_extents"); - ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "emission_point_texture", PROPERTY_HINT_RESOURCE_TYPE, "Texture"), "set_emission_point_texture", "get_emission_point_texture"); - ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "emission_normal_texture", PROPERTY_HINT_RESOURCE_TYPE, "Texture"), "set_emission_normal_texture", "get_emission_normal_texture"); - ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "emission_color_texture", PROPERTY_HINT_RESOURCE_TYPE, "Texture"), "set_emission_color_texture", "get_emission_color_texture"); - ADD_PROPERTY(PropertyInfo(Variant::INT, "emission_point_count", PROPERTY_HINT_RANGE, "0,1000000,1"), "set_emission_point_count", "get_emission_point_count"); - ADD_GROUP("Flags", "flag_"); - ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "flag_align_y"), "set_flag", "get_flag", FLAG_ALIGN_Y_TO_VELOCITY); - ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "flag_rotate_y"), "set_flag", "get_flag", FLAG_ROTATE_Y); - ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "flag_disable_z"), "set_flag", "get_flag", FLAG_DISABLE_Z); - ADD_GROUP("Spread", ""); - ADD_PROPERTY(PropertyInfo(Variant::REAL, "spread", PROPERTY_HINT_RANGE, "0,180,0.01"), "set_spread", "get_spread"); - ADD_PROPERTY(PropertyInfo(Variant::REAL, "flatness", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_flatness", "get_flatness"); - ADD_GROUP("Gravity", ""); - ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "gravity"), "set_gravity", "get_gravity"); - ADD_GROUP("Initial Velocity", "initial_"); - ADD_PROPERTYI(PropertyInfo(Variant::REAL, "initial_velocity", PROPERTY_HINT_RANGE, "0,1000,0.01,or_greater"), "set_param", "get_param", PARAM_INITIAL_LINEAR_VELOCITY); - ADD_PROPERTYI(PropertyInfo(Variant::REAL, "initial_velocity_random", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_param_randomness", "get_param_randomness", PARAM_INITIAL_LINEAR_VELOCITY); - ADD_GROUP("Angular Velocity", "angular_"); - ADD_PROPERTYI(PropertyInfo(Variant::REAL, "angular_velocity", PROPERTY_HINT_RANGE, "-360,360,0.01"), "set_param", "get_param", PARAM_ANGULAR_VELOCITY); - ADD_PROPERTYI(PropertyInfo(Variant::REAL, "angular_velocity_random", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_param_randomness", "get_param_randomness", PARAM_ANGULAR_VELOCITY); - ADD_PROPERTYI(PropertyInfo(Variant::OBJECT, "angular_velocity_curve", PROPERTY_HINT_RESOURCE_TYPE, "CurveTexture"), "set_param_texture", "get_param_texture", PARAM_ANGULAR_VELOCITY); - ADD_GROUP("Orbit Velocity", "orbit_"); - ADD_PROPERTYI(PropertyInfo(Variant::REAL, "orbit_velocity", PROPERTY_HINT_RANGE, "-1000,1000,0.01,or_lesser,or_greater"), "set_param", "get_param", PARAM_ORBIT_VELOCITY); - ADD_PROPERTYI(PropertyInfo(Variant::REAL, "orbit_velocity_random", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_param_randomness", "get_param_randomness", PARAM_ORBIT_VELOCITY); - ADD_PROPERTYI(PropertyInfo(Variant::OBJECT, "orbit_velocity_curve", PROPERTY_HINT_RESOURCE_TYPE, "CurveTexture"), "set_param_texture", "get_param_texture", PARAM_ORBIT_VELOCITY); - ADD_GROUP("Linear Accel", "linear_"); - ADD_PROPERTYI(PropertyInfo(Variant::REAL, "linear_accel", PROPERTY_HINT_RANGE, "-100,100,0.01,or_lesser,or_greater"), "set_param", "get_param", PARAM_LINEAR_ACCEL); - ADD_PROPERTYI(PropertyInfo(Variant::REAL, "linear_accel_random", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_param_randomness", "get_param_randomness", PARAM_LINEAR_ACCEL); - ADD_PROPERTYI(PropertyInfo(Variant::OBJECT, "linear_accel_curve", PROPERTY_HINT_RESOURCE_TYPE, "CurveTexture"), "set_param_texture", "get_param_texture", PARAM_LINEAR_ACCEL); - ADD_GROUP("Radial Accel", "radial_"); - ADD_PROPERTYI(PropertyInfo(Variant::REAL, "radial_accel", PROPERTY_HINT_RANGE, "-100,100,0.01,or_lesser,or_greater"), "set_param", "get_param", PARAM_RADIAL_ACCEL); - ADD_PROPERTYI(PropertyInfo(Variant::REAL, "radial_accel_random", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_param_randomness", "get_param_randomness", PARAM_RADIAL_ACCEL); - ADD_PROPERTYI(PropertyInfo(Variant::OBJECT, "radial_accel_curve", PROPERTY_HINT_RESOURCE_TYPE, "CurveTexture"), "set_param_texture", "get_param_texture", PARAM_RADIAL_ACCEL); - ADD_GROUP("Tangential Accel", "tangential_"); - ADD_PROPERTYI(PropertyInfo(Variant::REAL, "tangential_accel", PROPERTY_HINT_RANGE, "-100,100,0.01,or_lesser,or_greater"), "set_param", "get_param", PARAM_TANGENTIAL_ACCEL); - ADD_PROPERTYI(PropertyInfo(Variant::REAL, "tangential_accel_random", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_param_randomness", "get_param_randomness", PARAM_TANGENTIAL_ACCEL); - ADD_PROPERTYI(PropertyInfo(Variant::OBJECT, "tangential_accel_curve", PROPERTY_HINT_RESOURCE_TYPE, "CurveTexture"), "set_param_texture", "get_param_texture", PARAM_TANGENTIAL_ACCEL); - ADD_GROUP("Damping", ""); - ADD_PROPERTYI(PropertyInfo(Variant::REAL, "damping", PROPERTY_HINT_RANGE, "0,100,0.01,or_greater"), "set_param", "get_param", PARAM_DAMPING); - ADD_PROPERTYI(PropertyInfo(Variant::REAL, "damping_random", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_param_randomness", "get_param_randomness", PARAM_DAMPING); - ADD_PROPERTYI(PropertyInfo(Variant::OBJECT, "damping_curve", PROPERTY_HINT_RESOURCE_TYPE, "CurveTexture"), "set_param_texture", "get_param_texture", PARAM_DAMPING); - ADD_GROUP("Angle", ""); - ADD_PROPERTYI(PropertyInfo(Variant::REAL, "angle", PROPERTY_HINT_RANGE, "-720,720,0.1,or_lesser,or_greater"), "set_param", "get_param", PARAM_ANGLE); - ADD_PROPERTYI(PropertyInfo(Variant::REAL, "angle_random", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_param_randomness", "get_param_randomness", PARAM_ANGLE); - ADD_PROPERTYI(PropertyInfo(Variant::OBJECT, "angle_curve", PROPERTY_HINT_RESOURCE_TYPE, "CurveTexture"), "set_param_texture", "get_param_texture", PARAM_ANGLE); - ADD_GROUP("Scale", ""); - ADD_PROPERTYI(PropertyInfo(Variant::REAL, "scale", PROPERTY_HINT_RANGE, "0,1000,0.01,or_greater"), "set_param", "get_param", PARAM_SCALE); - ADD_PROPERTYI(PropertyInfo(Variant::REAL, "scale_random", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_param_randomness", "get_param_randomness", PARAM_SCALE); - ADD_PROPERTYI(PropertyInfo(Variant::OBJECT, "scale_curve", PROPERTY_HINT_RESOURCE_TYPE, "CurveTexture"), "set_param_texture", "get_param_texture", PARAM_SCALE); - ADD_GROUP("Color", ""); - ADD_PROPERTY(PropertyInfo(Variant::COLOR, "color"), "set_color", "get_color"); - ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "color_ramp", PROPERTY_HINT_RESOURCE_TYPE, "GradientTexture"), "set_color_ramp", "get_color_ramp"); - - ADD_GROUP("Hue Variation", "hue_"); - ADD_PROPERTYI(PropertyInfo(Variant::REAL, "hue_variation", PROPERTY_HINT_RANGE, "-1,1,0.1"), "set_param", "get_param", PARAM_HUE_VARIATION); - ADD_PROPERTYI(PropertyInfo(Variant::REAL, "hue_variation_random", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_param_randomness", "get_param_randomness", PARAM_HUE_VARIATION); - ADD_PROPERTYI(PropertyInfo(Variant::OBJECT, "hue_variation_curve", PROPERTY_HINT_RESOURCE_TYPE, "CurveTexture"), "set_param_texture", "get_param_texture", PARAM_HUE_VARIATION); - ADD_GROUP("Animation", "anim_"); - ADD_PROPERTYI(PropertyInfo(Variant::REAL, "anim_speed", PROPERTY_HINT_RANGE, "0,128,0.01,or_greater"), "set_param", "get_param", PARAM_ANIM_SPEED); - ADD_PROPERTYI(PropertyInfo(Variant::REAL, "anim_speed_random", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_param_randomness", "get_param_randomness", PARAM_ANIM_SPEED); - ADD_PROPERTYI(PropertyInfo(Variant::OBJECT, "anim_speed_curve", PROPERTY_HINT_RESOURCE_TYPE, "CurveTexture"), "set_param_texture", "get_param_texture", PARAM_ANIM_SPEED); - ADD_PROPERTYI(PropertyInfo(Variant::REAL, "anim_offset", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_param", "get_param", PARAM_ANIM_OFFSET); - ADD_PROPERTYI(PropertyInfo(Variant::REAL, "anim_offset_random", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_param_randomness", "get_param_randomness", PARAM_ANIM_OFFSET); - ADD_PROPERTYI(PropertyInfo(Variant::OBJECT, "anim_offset_curve", PROPERTY_HINT_RESOURCE_TYPE, "CurveTexture"), "set_param_texture", "get_param_texture", PARAM_ANIM_OFFSET); - ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "anim_loop"), "set_flag", "get_flag", FLAG_ANIM_LOOP); - - BIND_ENUM_CONSTANT(PARAM_INITIAL_LINEAR_VELOCITY); - BIND_ENUM_CONSTANT(PARAM_ANGULAR_VELOCITY); - BIND_ENUM_CONSTANT(PARAM_ORBIT_VELOCITY); - BIND_ENUM_CONSTANT(PARAM_LINEAR_ACCEL); - BIND_ENUM_CONSTANT(PARAM_RADIAL_ACCEL); - BIND_ENUM_CONSTANT(PARAM_TANGENTIAL_ACCEL); - BIND_ENUM_CONSTANT(PARAM_DAMPING); - BIND_ENUM_CONSTANT(PARAM_ANGLE); - BIND_ENUM_CONSTANT(PARAM_SCALE); - BIND_ENUM_CONSTANT(PARAM_HUE_VARIATION); - BIND_ENUM_CONSTANT(PARAM_ANIM_SPEED); - BIND_ENUM_CONSTANT(PARAM_ANIM_OFFSET); - BIND_ENUM_CONSTANT(PARAM_MAX); - - BIND_ENUM_CONSTANT(FLAG_ALIGN_Y_TO_VELOCITY); - BIND_ENUM_CONSTANT(FLAG_ROTATE_Y); - BIND_ENUM_CONSTANT(FLAG_MAX); - - BIND_ENUM_CONSTANT(EMISSION_SHAPE_POINT); - BIND_ENUM_CONSTANT(EMISSION_SHAPE_SPHERE); - BIND_ENUM_CONSTANT(EMISSION_SHAPE_BOX); - BIND_ENUM_CONSTANT(EMISSION_SHAPE_POINTS); - BIND_ENUM_CONSTANT(EMISSION_SHAPE_DIRECTED_POINTS); -} - -ParticlesMaterial::ParticlesMaterial() : - element(this) { - - set_spread(45); - set_flatness(0); - set_param(PARAM_INITIAL_LINEAR_VELOCITY, 1); - set_param(PARAM_ORBIT_VELOCITY, 0); - set_param(PARAM_LINEAR_ACCEL, 0); - set_param(PARAM_RADIAL_ACCEL, 0); - set_param(PARAM_TANGENTIAL_ACCEL, 0); - set_param(PARAM_DAMPING, 0); - set_param(PARAM_ANGLE, 0); - set_param(PARAM_SCALE, 1); - set_param(PARAM_HUE_VARIATION, 0); - set_param(PARAM_ANIM_SPEED, 0); - set_param(PARAM_ANIM_OFFSET, 0); - set_emission_shape(EMISSION_SHAPE_POINT); - set_emission_sphere_radius(1); - set_emission_box_extents(Vector3(1, 1, 1)); - set_trail_divisor(1); - set_gravity(Vector3(0, -9.8, 0)); - emission_point_count = 1; - - for (int i = 0; i < PARAM_MAX; i++) { - set_param_randomness(Parameter(i), 0); - } - - for (int i = 0; i < FLAG_MAX; i++) { - flags[i] = false; - } - - set_color(Color(1, 1, 1, 1)); - - current_key.key = 0; - current_key.invalid_key = 1; - - _queue_shader_change(); -} - -ParticlesMaterial::~ParticlesMaterial() { - - if (material_mutex) - material_mutex->lock(); - - if (shader_map.has(current_key)) { - shader_map[current_key].users--; - if (shader_map[current_key].users == 0) { - //deallocate shader, as it's no longer in use - VS::get_singleton()->free(shader_map[current_key].shader); - shader_map.erase(current_key); - } - - VS::get_singleton()->material_set_shader(_get_material(), RID()); - } - - if (material_mutex) - material_mutex->unlock(); -} diff --git a/scene/3d/particles.h b/scene/3d/particles.h index 17e21c6cee..742246f78c 100644 --- a/scene/3d/particles.h +++ b/scene/3d/particles.h @@ -28,12 +28,11 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#ifndef VISUALINSTANCEPARTICLES_H -#define VISUALINSTANCEPARTICLES_H +#ifndef PARTICLES_H +#define PARTICLES_H #include "rid.h" #include "scene/3d/visual_instance.h" -#include "scene/main/timer.h" #include "scene/resources/material.h" /** @@ -135,269 +134,4 @@ public: VARIANT_ENUM_CAST(Particles::DrawOrder) -class ParticlesMaterial : public Material { - - GDCLASS(ParticlesMaterial, Material) - -public: - enum Parameter { - - PARAM_INITIAL_LINEAR_VELOCITY, - PARAM_ANGULAR_VELOCITY, - PARAM_ORBIT_VELOCITY, - PARAM_LINEAR_ACCEL, - PARAM_RADIAL_ACCEL, - PARAM_TANGENTIAL_ACCEL, - PARAM_DAMPING, - PARAM_ANGLE, - PARAM_SCALE, - PARAM_HUE_VARIATION, - PARAM_ANIM_SPEED, - PARAM_ANIM_OFFSET, - PARAM_MAX - }; - - enum Flags { - FLAG_ALIGN_Y_TO_VELOCITY, - FLAG_ROTATE_Y, - FLAG_DISABLE_Z, - FLAG_ANIM_LOOP, - FLAG_MAX - }; - - enum EmissionShape { - EMISSION_SHAPE_POINT, - EMISSION_SHAPE_SPHERE, - EMISSION_SHAPE_BOX, - EMISSION_SHAPE_POINTS, - EMISSION_SHAPE_DIRECTED_POINTS, - }; - -private: - union MaterialKey { - - struct { - uint32_t texture_mask : 16; - uint32_t texture_color : 1; - uint32_t flags : 4; - uint32_t emission_shape : 2; - uint32_t trail_size_texture : 1; - uint32_t trail_color_texture : 1; - uint32_t invalid_key : 1; - uint32_t has_emission_color : 1; - }; - - uint32_t key; - - bool operator<(const MaterialKey &p_key) const { - return key < p_key.key; - } - }; - - struct ShaderData { - RID shader; - int users; - }; - - static Map<MaterialKey, ShaderData> shader_map; - - MaterialKey current_key; - - _FORCE_INLINE_ MaterialKey _compute_key() const { - - MaterialKey mk; - mk.key = 0; - for (int i = 0; i < PARAM_MAX; i++) { - if (tex_parameters[i].is_valid()) { - mk.texture_mask |= (1 << i); - } - } - for (int i = 0; i < FLAG_MAX; i++) { - if (flags[i]) { - mk.flags |= (1 << i); - } - } - - mk.texture_color = color_ramp.is_valid() ? 1 : 0; - mk.emission_shape = emission_shape; - mk.trail_color_texture = trail_color_modifier.is_valid() ? 1 : 0; - mk.trail_size_texture = trail_size_modifier.is_valid() ? 1 : 0; - mk.has_emission_color = emission_shape >= EMISSION_SHAPE_POINTS && emission_color_texture.is_valid(); - - return mk; - } - - static Mutex *material_mutex; - static SelfList<ParticlesMaterial>::List dirty_materials; - - struct ShaderNames { - StringName spread; - StringName flatness; - StringName initial_linear_velocity; - StringName initial_angle; - StringName angular_velocity; - StringName orbit_velocity; - StringName linear_accel; - StringName radial_accel; - StringName tangent_accel; - StringName damping; - StringName scale; - StringName hue_variation; - StringName anim_speed; - StringName anim_offset; - - StringName initial_linear_velocity_random; - StringName initial_angle_random; - StringName angular_velocity_random; - StringName orbit_velocity_random; - StringName linear_accel_random; - StringName radial_accel_random; - StringName tangent_accel_random; - StringName damping_random; - StringName scale_random; - StringName hue_variation_random; - StringName anim_speed_random; - StringName anim_offset_random; - - StringName angle_texture; - StringName angular_velocity_texture; - StringName orbit_velocity_texture; - StringName linear_accel_texture; - StringName radial_accel_texture; - StringName tangent_accel_texture; - StringName damping_texture; - StringName scale_texture; - StringName hue_variation_texture; - StringName anim_speed_texture; - StringName anim_offset_texture; - - StringName color; - StringName color_ramp; - - StringName emission_sphere_radius; - StringName emission_box_extents; - StringName emission_texture_point_count; - StringName emission_texture_points; - StringName emission_texture_normal; - StringName emission_texture_color; - - StringName trail_divisor; - StringName trail_size_modifier; - StringName trail_color_modifier; - - StringName gravity; - }; - - static ShaderNames *shader_names; - - SelfList<ParticlesMaterial> element; - - void _update_shader(); - _FORCE_INLINE_ void _queue_shader_change(); - _FORCE_INLINE_ bool _is_shader_dirty() const; - - float spread; - float flatness; - - float parameters[PARAM_MAX]; - float randomness[PARAM_MAX]; - - Ref<Texture> tex_parameters[PARAM_MAX]; - Color color; - Ref<Texture> color_ramp; - - bool flags[FLAG_MAX]; - - EmissionShape emission_shape; - float emission_sphere_radius; - Vector3 emission_box_extents; - Ref<Texture> emission_point_texture; - Ref<Texture> emission_normal_texture; - Ref<Texture> emission_color_texture; - int emission_point_count; - - bool anim_loop; - - int trail_divisor; - - Ref<CurveTexture> trail_size_modifier; - Ref<GradientTexture> trail_color_modifier; - - Vector3 gravity; - - //do not save emission points here - -protected: - static void _bind_methods(); - virtual void _validate_property(PropertyInfo &property) const; - -public: - void set_spread(float p_spread); - float get_spread() const; - - void set_flatness(float p_flatness); - float get_flatness() const; - - void set_param(Parameter p_param, float p_value); - float get_param(Parameter p_param) const; - - void set_param_randomness(Parameter p_param, float p_value); - float get_param_randomness(Parameter p_param) const; - - void set_param_texture(Parameter p_param, const Ref<Texture> &p_texture); - Ref<Texture> get_param_texture(Parameter p_param) const; - - void set_color(const Color &p_color); - Color get_color() const; - - void set_color_ramp(const Ref<Texture> &p_texture); - Ref<Texture> get_color_ramp() const; - - void set_flag(Flags p_flag, bool p_enable); - bool get_flag(Flags p_flag) const; - - void set_emission_shape(EmissionShape p_shape); - void set_emission_sphere_radius(float p_radius); - void set_emission_box_extents(Vector3 p_extents); - void set_emission_point_texture(const Ref<Texture> &p_points); - void set_emission_normal_texture(const Ref<Texture> &p_normals); - void set_emission_color_texture(const Ref<Texture> &p_colors); - void set_emission_point_count(int p_count); - - EmissionShape get_emission_shape() const; - float get_emission_sphere_radius() const; - Vector3 get_emission_box_extents() const; - Ref<Texture> get_emission_point_texture() const; - Ref<Texture> get_emission_normal_texture() const; - Ref<Texture> get_emission_color_texture() const; - int get_emission_point_count() const; - - void set_trail_divisor(int p_divisor); - int get_trail_divisor() const; - - void set_trail_size_modifier(const Ref<CurveTexture> &p_trail_size_modifier); - Ref<CurveTexture> get_trail_size_modifier() const; - - void set_trail_color_modifier(const Ref<GradientTexture> &p_trail_color_modifier); - Ref<GradientTexture> get_trail_color_modifier() const; - - void set_gravity(const Vector3 &p_gravity); - Vector3 get_gravity() const; - - static void init_shaders(); - static void finish_shaders(); - static void flush_changes(); - - RID get_shader_rid() const; - - virtual Shader::Mode get_shader_mode() const; - - ParticlesMaterial(); - ~ParticlesMaterial(); -}; - -VARIANT_ENUM_CAST(ParticlesMaterial::Parameter) -VARIANT_ENUM_CAST(ParticlesMaterial::Flags) -VARIANT_ENUM_CAST(ParticlesMaterial::EmissionShape) - -#endif +#endif // PARTICLES_H diff --git a/scene/3d/physics_body.cpp b/scene/3d/physics_body.cpp index 441f2f2549..f7af6a57dd 100644 --- a/scene/3d/physics_body.cpp +++ b/scene/3d/physics_body.cpp @@ -171,6 +171,10 @@ PhysicsBody::PhysicsBody(PhysicsServer::BodyMode p_mode) : #ifndef DISABLE_DEPRECATED void StaticBody::set_friction(real_t p_friction) { + if (p_friction == 1.0) { // default value, don't create an override for that + return; + } + ERR_EXPLAIN("The method set_friction has been deprecated and will be removed in the future, use physics material instead.") WARN_DEPRECATED @@ -197,6 +201,10 @@ real_t StaticBody::get_friction() const { void StaticBody::set_bounce(real_t p_bounce) { + if (p_bounce == 0.0) { // default value, don't create an override for that + return; + } + ERR_EXPLAIN("The method set_bounce has been deprecated and will be removed in the future, use physics material instead.") WARN_DEPRECATED @@ -288,7 +296,7 @@ void StaticBody::_bind_methods() { ADD_PROPERTYNO(PropertyInfo(Variant::REAL, "friction", PROPERTY_HINT_RANGE, "0,1,0.01", 0), "set_friction", "get_friction"); ADD_PROPERTYNZ(PropertyInfo(Variant::REAL, "bounce", PROPERTY_HINT_RANGE, "0,1,0.01", 0), "set_bounce", "get_bounce"); #endif // DISABLE_DEPRECATED - ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "physics_material_override", PROPERTY_HINT_RESOURCE_TYPE, "PhysicsMaterial"), "set_physics_material_override", "get_physics_material_override"); + ADD_PROPERTYNZ(PropertyInfo(Variant::OBJECT, "physics_material_override", PROPERTY_HINT_RESOURCE_TYPE, "PhysicsMaterial"), "set_physics_material_override", "get_physics_material_override"); ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "constant_linear_velocity"), "set_constant_linear_velocity", "get_constant_linear_velocity"); ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "constant_angular_velocity"), "set_constant_angular_velocity", "get_constant_angular_velocity"); } @@ -407,7 +415,7 @@ void RigidBody::_body_inout(int p_status, ObjectID p_instance, int p_body_shape, node->disconnect(SceneStringNames::get_singleton()->tree_entered, this, SceneStringNames::get_singleton()->_body_enter_tree); node->disconnect(SceneStringNames::get_singleton()->tree_exiting, this, SceneStringNames::get_singleton()->_body_exit_tree); if (in_tree) - emit_signal(SceneStringNames::get_singleton()->body_exited, obj); + emit_signal(SceneStringNames::get_singleton()->body_exited, node); } contact_monitor->body_map.erase(E); @@ -606,8 +614,13 @@ real_t RigidBody::get_weight() const { #ifndef DISABLE_DEPRECATED void RigidBody::set_friction(real_t p_friction) { + if (p_friction == 1.0) { // default value, don't create an override for that + return; + } + ERR_EXPLAIN("The method set_friction has been deprecated and will be removed in the future, use physics material instead.") WARN_DEPRECATED + ERR_FAIL_COND(p_friction < 0 || p_friction > 1); if (physics_material_override.is_null()) { @@ -620,6 +633,7 @@ real_t RigidBody::get_friction() const { ERR_EXPLAIN("The method get_friction has been deprecated and will be removed in the future, use physics material instead.") WARN_DEPRECATED + if (physics_material_override.is_null()) { return 1; } @@ -628,8 +642,14 @@ real_t RigidBody::get_friction() const { } void RigidBody::set_bounce(real_t p_bounce) { + + if (p_bounce == 0.0) { // default value, don't create an override for that + return; + } + ERR_EXPLAIN("The method set_bounce has been deprecated and will be removed in the future, use physics material instead.") WARN_DEPRECATED + ERR_FAIL_COND(p_bounce < 0 || p_bounce > 1); if (physics_material_override.is_null()) { @@ -989,7 +1009,7 @@ void RigidBody::_bind_methods() { ADD_PROPERTYNO(PropertyInfo(Variant::REAL, "friction", PROPERTY_HINT_RANGE, "0,1,0.01", 0), "set_friction", "get_friction"); ADD_PROPERTYNZ(PropertyInfo(Variant::REAL, "bounce", PROPERTY_HINT_RANGE, "0,1,0.01", 0), "set_bounce", "get_bounce"); #endif // DISABLE_DEPRECATED - ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "physics_material_override", PROPERTY_HINT_RESOURCE_TYPE, "PhysicsMaterial"), "set_physics_material_override", "get_physics_material_override"); + ADD_PROPERTYNZ(PropertyInfo(Variant::OBJECT, "physics_material_override", PROPERTY_HINT_RESOURCE_TYPE, "PhysicsMaterial"), "set_physics_material_override", "get_physics_material_override"); ADD_PROPERTY(PropertyInfo(Variant::REAL, "gravity_scale", PROPERTY_HINT_RANGE, "-128,128,0.01"), "set_gravity_scale", "get_gravity_scale"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "custom_integrator"), "set_use_custom_integrator", "is_using_custom_integrator"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "continuous_cd"), "set_use_continuous_collision_detection", "is_using_continuous_collision_detection"); @@ -1011,10 +1031,10 @@ void RigidBody::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "angular_velocity"), "set_angular_velocity", "get_angular_velocity"); ADD_PROPERTY(PropertyInfo(Variant::REAL, "angular_damp", PROPERTY_HINT_RANGE, "-1,128,0.01"), "set_angular_damp", "get_angular_damp"); - ADD_SIGNAL(MethodInfo("body_shape_entered", PropertyInfo(Variant::INT, "body_id"), PropertyInfo(Variant::OBJECT, "body"), PropertyInfo(Variant::INT, "body_shape"), PropertyInfo(Variant::INT, "local_shape"))); - ADD_SIGNAL(MethodInfo("body_shape_exited", PropertyInfo(Variant::INT, "body_id"), PropertyInfo(Variant::OBJECT, "body"), PropertyInfo(Variant::INT, "body_shape"), PropertyInfo(Variant::INT, "local_shape"))); - ADD_SIGNAL(MethodInfo("body_entered", PropertyInfo(Variant::OBJECT, "body"))); - ADD_SIGNAL(MethodInfo("body_exited", PropertyInfo(Variant::OBJECT, "body"))); + ADD_SIGNAL(MethodInfo("body_shape_entered", PropertyInfo(Variant::INT, "body_id"), PropertyInfo(Variant::OBJECT, "body", PROPERTY_HINT_RESOURCE_TYPE, "Node"), PropertyInfo(Variant::INT, "body_shape"), PropertyInfo(Variant::INT, "local_shape"))); + ADD_SIGNAL(MethodInfo("body_shape_exited", PropertyInfo(Variant::INT, "body_id"), PropertyInfo(Variant::OBJECT, "body", PROPERTY_HINT_RESOURCE_TYPE, "Node"), PropertyInfo(Variant::INT, "body_shape"), PropertyInfo(Variant::INT, "local_shape"))); + ADD_SIGNAL(MethodInfo("body_entered", PropertyInfo(Variant::OBJECT, "body", PROPERTY_HINT_RESOURCE_TYPE, "Node"))); + ADD_SIGNAL(MethodInfo("body_exited", PropertyInfo(Variant::OBJECT, "body", PROPERTY_HINT_RESOURCE_TYPE, "Node"))); ADD_SIGNAL(MethodInfo("sleeping_state_changed")); BIND_ENUM_CONSTANT(MODE_RIGID); diff --git a/scene/gui/control.cpp b/scene/gui/control.cpp index e094a063be..fad91c29cf 100644 --- a/scene/gui/control.cpp +++ b/scene/gui/control.cpp @@ -2956,7 +2956,7 @@ void Control::_bind_methods() { BIND_ENUM_CONSTANT(ANCHOR_END); ADD_SIGNAL(MethodInfo("resized")); - ADD_SIGNAL(MethodInfo("gui_input", PropertyInfo(Variant::OBJECT, "ev", PROPERTY_HINT_RESOURCE_TYPE, "InputEvent"))); + ADD_SIGNAL(MethodInfo("gui_input", PropertyInfo(Variant::OBJECT, "event", PROPERTY_HINT_RESOURCE_TYPE, "InputEvent"))); ADD_SIGNAL(MethodInfo("mouse_entered")); ADD_SIGNAL(MethodInfo("mouse_exited")); ADD_SIGNAL(MethodInfo("focus_entered")); diff --git a/scene/gui/graph_edit.cpp b/scene/gui/graph_edit.cpp index a7163adbe6..8797ab6fd3 100644 --- a/scene/gui/graph_edit.cpp +++ b/scene/gui/graph_edit.cpp @@ -1279,7 +1279,7 @@ void GraphEdit::_bind_methods() { ADD_SIGNAL(MethodInfo("disconnection_request", PropertyInfo(Variant::STRING, "from"), PropertyInfo(Variant::INT, "from_slot"), PropertyInfo(Variant::STRING, "to"), PropertyInfo(Variant::INT, "to_slot"))); ADD_SIGNAL(MethodInfo("popup_request", PropertyInfo(Variant::VECTOR2, "p_position"))); ADD_SIGNAL(MethodInfo("duplicate_nodes_request")); - ADD_SIGNAL(MethodInfo("node_selected", PropertyInfo(Variant::OBJECT, "node"))); + ADD_SIGNAL(MethodInfo("node_selected", PropertyInfo(Variant::OBJECT, "node", PROPERTY_HINT_RESOURCE_TYPE, "Node"))); ADD_SIGNAL(MethodInfo("connection_to_empty", PropertyInfo(Variant::STRING, "from"), PropertyInfo(Variant::INT, "from_slot"), PropertyInfo(Variant::VECTOR2, "release_position"))); ADD_SIGNAL(MethodInfo("delete_nodes_request")); ADD_SIGNAL(MethodInfo("_begin_node_move")); diff --git a/scene/gui/tree.cpp b/scene/gui/tree.cpp index 6f09488b64..eaf7ad7670 100644 --- a/scene/gui/tree.cpp +++ b/scene/gui/tree.cpp @@ -1419,7 +1419,7 @@ int Tree::draw_item(const Point2i &p_pos, const Point2 &p_draw_ofs, const Size2 while (c) { - if (cache.draw_relationship_lines == 1) { + if (cache.draw_relationship_lines == 1 && (c->get_parent() != root || c->get_parent() == root && !hide_root)) { int root_ofs = children_pos.x + ((p_item->disable_folding || hide_folding) ? cache.hseparation : cache.item_margin); int parent_ofs = p_pos.x + ((p_item->disable_folding || hide_folding) ? cache.hseparation : cache.item_margin); Point2i root_pos = Point2i(root_ofs, children_pos.y + label_h / 2) - cache.offset + p_draw_ofs; @@ -3831,16 +3831,16 @@ void Tree::_bind_methods() { ADD_SIGNAL(MethodInfo("item_selected")); ADD_SIGNAL(MethodInfo("cell_selected")); - ADD_SIGNAL(MethodInfo("multi_selected", PropertyInfo(Variant::OBJECT, "item"), PropertyInfo(Variant::INT, "column"), PropertyInfo(Variant::BOOL, "selected"))); + ADD_SIGNAL(MethodInfo("multi_selected", PropertyInfo(Variant::OBJECT, "item", PROPERTY_HINT_RESOURCE_TYPE, "TreeItem"), PropertyInfo(Variant::INT, "column"), PropertyInfo(Variant::BOOL, "selected"))); ADD_SIGNAL(MethodInfo("item_rmb_selected", PropertyInfo(Variant::VECTOR2, "position"))); ADD_SIGNAL(MethodInfo("empty_tree_rmb_selected", PropertyInfo(Variant::VECTOR2, "position"))); ADD_SIGNAL(MethodInfo("item_edited")); ADD_SIGNAL(MethodInfo("item_rmb_edited")); ADD_SIGNAL(MethodInfo("item_custom_button_pressed")); ADD_SIGNAL(MethodInfo("item_double_clicked")); - ADD_SIGNAL(MethodInfo("item_collapsed", PropertyInfo(Variant::OBJECT, "item"))); + ADD_SIGNAL(MethodInfo("item_collapsed", PropertyInfo(Variant::OBJECT, "item", PROPERTY_HINT_RESOURCE_TYPE, "TreeItem"))); //ADD_SIGNAL( MethodInfo("item_doubleclicked" ) ); - ADD_SIGNAL(MethodInfo("button_pressed", PropertyInfo(Variant::OBJECT, "item"), PropertyInfo(Variant::INT, "column"), PropertyInfo(Variant::INT, "id"))); + ADD_SIGNAL(MethodInfo("button_pressed", PropertyInfo(Variant::OBJECT, "item", PROPERTY_HINT_RESOURCE_TYPE, "TreeItem"), PropertyInfo(Variant::INT, "column"), PropertyInfo(Variant::INT, "id"))); ADD_SIGNAL(MethodInfo("custom_popup_edited", PropertyInfo(Variant::BOOL, "arrow_clicked"))); ADD_SIGNAL(MethodInfo("item_activated")); ADD_SIGNAL(MethodInfo("column_title_pressed", PropertyInfo(Variant::INT, "column"))); diff --git a/scene/main/scene_tree.cpp b/scene/main/scene_tree.cpp index 1d23650a1e..11268cc5c6 100644 --- a/scene/main/scene_tree.cpp +++ b/scene/main/scene_tree.cpp @@ -1862,10 +1862,10 @@ void SceneTree::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::BOOL, "multiplayer_poll"), "set_multiplayer_poll_enabled", "is_multiplayer_poll_enabled"); ADD_SIGNAL(MethodInfo("tree_changed")); - ADD_SIGNAL(MethodInfo("node_added", PropertyInfo(Variant::OBJECT, "node"))); - ADD_SIGNAL(MethodInfo("node_removed", PropertyInfo(Variant::OBJECT, "node"))); + ADD_SIGNAL(MethodInfo("node_added", PropertyInfo(Variant::OBJECT, "node", PROPERTY_HINT_RESOURCE_TYPE, "Node"))); + ADD_SIGNAL(MethodInfo("node_removed", PropertyInfo(Variant::OBJECT, "node", PROPERTY_HINT_RESOURCE_TYPE, "Node"))); ADD_SIGNAL(MethodInfo("screen_resized")); - ADD_SIGNAL(MethodInfo("node_configuration_warning_changed", PropertyInfo(Variant::OBJECT, "node"))); + ADD_SIGNAL(MethodInfo("node_configuration_warning_changed", PropertyInfo(Variant::OBJECT, "node", PROPERTY_HINT_RESOURCE_TYPE, "Node"))); ADD_SIGNAL(MethodInfo("idle_frame")); ADD_SIGNAL(MethodInfo("physics_frame")); diff --git a/scene/register_scene_types.cpp b/scene/register_scene_types.cpp index a4422af21d..97230d422b 100644 --- a/scene/register_scene_types.cpp +++ b/scene/register_scene_types.cpp @@ -144,6 +144,7 @@ #include "scene/resources/mesh_data_tool.h" #include "scene/resources/mesh_library.h" #include "scene/resources/packed_scene.h" +#include "scene/resources/particles_material.h" #include "scene/resources/plane_shape.h" #include "scene/resources/polygon_path_finder.h" #include "scene/resources/primitive_meshes.h" @@ -165,8 +166,6 @@ #include "scene/resources/world_2d.h" #include "scene/scene_string_names.h" -#include "scene/3d/cpu_particles.h" -#include "scene/3d/particles.h" #include "scene/3d/scenario_fx.h" #include "scene/3d/spatial.h" @@ -179,6 +178,7 @@ #include "scene/3d/camera.h" #include "scene/3d/collision_polygon.h" #include "scene/3d/collision_shape.h" +#include "scene/3d/cpu_particles.h" #include "scene/3d/gi_probe.h" #include "scene/3d/immediate_geometry.h" #include "scene/3d/interpolated_camera.h" @@ -188,6 +188,7 @@ #include "scene/3d/multimesh_instance.h" #include "scene/3d/navigation.h" #include "scene/3d/navigation_mesh.h" +#include "scene/3d/particles.h" #include "scene/3d/path.h" #include "scene/3d/physics_body.h" #include "scene/3d/physics_joint.h" diff --git a/scene/resources/particles_material.cpp b/scene/resources/particles_material.cpp new file mode 100644 index 0000000000..218a4cefe7 --- /dev/null +++ b/scene/resources/particles_material.cpp @@ -0,0 +1,1259 @@ +/*************************************************************************/ +/* particles_material.cpp */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2018 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 "particles_material.h" + +Mutex *ParticlesMaterial::material_mutex = NULL; +SelfList<ParticlesMaterial>::List ParticlesMaterial::dirty_materials; +Map<ParticlesMaterial::MaterialKey, ParticlesMaterial::ShaderData> ParticlesMaterial::shader_map; +ParticlesMaterial::ShaderNames *ParticlesMaterial::shader_names = NULL; + +void ParticlesMaterial::init_shaders() { + +#ifndef NO_THREADS + material_mutex = Mutex::create(); +#endif + + shader_names = memnew(ShaderNames); + + shader_names->spread = "spread"; + shader_names->flatness = "flatness"; + shader_names->initial_linear_velocity = "initial_linear_velocity"; + shader_names->initial_angle = "initial_angle"; + shader_names->angular_velocity = "angular_velocity"; + shader_names->orbit_velocity = "orbit_velocity"; + shader_names->linear_accel = "linear_accel"; + shader_names->radial_accel = "radial_accel"; + shader_names->tangent_accel = "tangent_accel"; + shader_names->damping = "damping"; + shader_names->scale = "scale"; + shader_names->hue_variation = "hue_variation"; + shader_names->anim_speed = "anim_speed"; + shader_names->anim_offset = "anim_offset"; + + shader_names->initial_linear_velocity_random = "initial_linear_velocity_random"; + shader_names->initial_angle_random = "initial_angle_random"; + shader_names->angular_velocity_random = "angular_velocity_random"; + shader_names->orbit_velocity_random = "orbit_velocity_random"; + shader_names->linear_accel_random = "linear_accel_random"; + shader_names->radial_accel_random = "radial_accel_random"; + shader_names->tangent_accel_random = "tangent_accel_random"; + shader_names->damping_random = "damping_random"; + shader_names->scale_random = "scale_random"; + shader_names->hue_variation_random = "hue_variation_random"; + shader_names->anim_speed_random = "anim_speed_random"; + shader_names->anim_offset_random = "anim_offset_random"; + + shader_names->angle_texture = "angle_texture"; + shader_names->angular_velocity_texture = "angular_velocity_texture"; + shader_names->orbit_velocity_texture = "orbit_velocity_texture"; + shader_names->linear_accel_texture = "linear_accel_texture"; + shader_names->radial_accel_texture = "radial_accel_texture"; + shader_names->tangent_accel_texture = "tangent_accel_texture"; + shader_names->damping_texture = "damping_texture"; + shader_names->scale_texture = "scale_texture"; + shader_names->hue_variation_texture = "hue_variation_texture"; + shader_names->anim_speed_texture = "anim_speed_texture"; + shader_names->anim_offset_texture = "anim_offset_texture"; + + shader_names->color = "color_value"; + shader_names->color_ramp = "color_ramp"; + + shader_names->emission_sphere_radius = "emission_sphere_radius"; + shader_names->emission_box_extents = "emission_box_extents"; + shader_names->emission_texture_point_count = "emission_texture_point_count"; + shader_names->emission_texture_points = "emission_texture_points"; + shader_names->emission_texture_normal = "emission_texture_normal"; + shader_names->emission_texture_color = "emission_texture_color"; + + shader_names->trail_divisor = "trail_divisor"; + shader_names->trail_size_modifier = "trail_size_modifier"; + shader_names->trail_color_modifier = "trail_color_modifier"; + + shader_names->gravity = "gravity"; +} + +void ParticlesMaterial::finish_shaders() { + +#ifndef NO_THREADS + memdelete(material_mutex); +#endif + + memdelete(shader_names); +} + +void ParticlesMaterial::_update_shader() { + + dirty_materials.remove(&element); + + MaterialKey mk = _compute_key(); + if (mk.key == current_key.key) + return; //no update required in the end + + if (shader_map.has(current_key)) { + shader_map[current_key].users--; + if (shader_map[current_key].users == 0) { + //deallocate shader, as it's no longer in use + VS::get_singleton()->free(shader_map[current_key].shader); + shader_map.erase(current_key); + } + } + + current_key = mk; + + if (shader_map.has(mk)) { + + VS::get_singleton()->material_set_shader(_get_material(), shader_map[mk].shader); + shader_map[mk].users++; + return; + } + + //must create a shader! + + String code = "shader_type particles;\n"; + + code += "uniform float spread;\n"; + code += "uniform float flatness;\n"; + code += "uniform float initial_linear_velocity;\n"; + code += "uniform float initial_angle;\n"; + code += "uniform float angular_velocity;\n"; + code += "uniform float orbit_velocity;\n"; + code += "uniform float linear_accel;\n"; + code += "uniform float radial_accel;\n"; + code += "uniform float tangent_accel;\n"; + code += "uniform float damping;\n"; + code += "uniform float scale;\n"; + code += "uniform float hue_variation;\n"; + code += "uniform float anim_speed;\n"; + code += "uniform float anim_offset;\n"; + + code += "uniform float initial_linear_velocity_random;\n"; + code += "uniform float initial_angle_random;\n"; + code += "uniform float angular_velocity_random;\n"; + code += "uniform float orbit_velocity_random;\n"; + code += "uniform float linear_accel_random;\n"; + code += "uniform float radial_accel_random;\n"; + code += "uniform float tangent_accel_random;\n"; + code += "uniform float damping_random;\n"; + code += "uniform float scale_random;\n"; + code += "uniform float hue_variation_random;\n"; + code += "uniform float anim_speed_random;\n"; + code += "uniform float anim_offset_random;\n"; + + switch (emission_shape) { + case EMISSION_SHAPE_POINT: { + //do none + } break; + case EMISSION_SHAPE_SPHERE: { + code += "uniform float emission_sphere_radius;\n"; + } break; + case EMISSION_SHAPE_BOX: { + code += "uniform vec3 emission_box_extents;\n"; + } break; + case EMISSION_SHAPE_DIRECTED_POINTS: { + code += "uniform sampler2D emission_texture_normal : hint_black;\n"; + } //fallthrough + case EMISSION_SHAPE_POINTS: { + code += "uniform sampler2D emission_texture_points : hint_black;\n"; + code += "uniform int emission_texture_point_count;\n"; + if (emission_color_texture.is_valid()) { + code += "uniform sampler2D emission_texture_color : hint_white;\n"; + } + } break; + } + + code += "uniform vec4 color_value : hint_color;\n"; + + code += "uniform int trail_divisor;\n"; + + code += "uniform vec3 gravity;\n"; + + if (color_ramp.is_valid()) + code += "uniform sampler2D color_ramp;\n"; + + if (tex_parameters[PARAM_INITIAL_LINEAR_VELOCITY].is_valid()) + code += "uniform sampler2D linear_velocity_texture;\n"; + if (tex_parameters[PARAM_ORBIT_VELOCITY].is_valid()) + code += "uniform sampler2D orbit_velocity_texture;\n"; + if (tex_parameters[PARAM_ANGULAR_VELOCITY].is_valid()) + code += "uniform sampler2D angular_velocity_texture;\n"; + if (tex_parameters[PARAM_LINEAR_ACCEL].is_valid()) + code += "uniform sampler2D linear_accel_texture;\n"; + if (tex_parameters[PARAM_RADIAL_ACCEL].is_valid()) + code += "uniform sampler2D radial_accel_texture;\n"; + if (tex_parameters[PARAM_TANGENTIAL_ACCEL].is_valid()) + code += "uniform sampler2D tangent_accel_texture;\n"; + if (tex_parameters[PARAM_DAMPING].is_valid()) + code += "uniform sampler2D damping_texture;\n"; + if (tex_parameters[PARAM_ANGLE].is_valid()) + code += "uniform sampler2D angle_texture;\n"; + if (tex_parameters[PARAM_SCALE].is_valid()) + code += "uniform sampler2D scale_texture;\n"; + if (tex_parameters[PARAM_HUE_VARIATION].is_valid()) + code += "uniform sampler2D hue_variation_texture;\n"; + if (tex_parameters[PARAM_ANIM_SPEED].is_valid()) + code += "uniform sampler2D anim_speed_texture;\n"; + if (tex_parameters[PARAM_ANIM_OFFSET].is_valid()) + code += "uniform sampler2D anim_offset_texture;\n"; + + if (trail_size_modifier.is_valid()) { + code += "uniform sampler2D trail_size_modifier;\n"; + } + + if (trail_color_modifier.is_valid()) { + code += "uniform sampler2D trail_color_modifier;\n"; + } + + //need a random function + code += "\n\n"; + code += "float rand_from_seed(inout uint seed) {\n"; + code += " int k;\n"; + code += " int s = int(seed);\n"; + code += " if (s == 0)\n"; + code += " s = 305420679;\n"; + code += " k = s / 127773;\n"; + code += " s = 16807 * (s - k * 127773) - 2836 * k;\n"; + code += " if (s < 0)\n"; + code += " s += 2147483647;\n"; + code += " seed = uint(s);\n"; + code += " return float(seed % uint(65536)) / 65535.0;\n"; + code += "}\n"; + code += "\n"; + + code += "float rand_from_seed_m1_p1(inout uint seed) {\n"; + code += " return rand_from_seed(seed) * 2.0 - 1.0;\n"; + code += "}\n"; + code += "\n"; + + //improve seed quality + code += "uint hash(uint x) {\n"; + code += " x = ((x >> uint(16)) ^ x) * uint(73244475);\n"; + code += " x = ((x >> uint(16)) ^ x) * uint(73244475);\n"; + code += " x = (x >> uint(16)) ^ x;\n"; + code += " return x;\n"; + code += "}\n"; + code += "\n"; + + code += "void vertex() {\n"; + code += " uint base_number = NUMBER / uint(trail_divisor);\n"; + code += " uint alt_seed = hash(base_number + uint(1) + RANDOM_SEED);\n"; + code += " float angle_rand = rand_from_seed(alt_seed);\n"; + code += " float scale_rand = rand_from_seed(alt_seed);\n"; + code += " float hue_rot_rand = rand_from_seed(alt_seed);\n"; + code += " float anim_offset_rand = rand_from_seed(alt_seed);\n"; + code += " float pi = 3.14159;\n"; + code += " float degree_to_rad = pi / 180.0;\n"; + code += "\n"; + + if (emission_shape >= EMISSION_SHAPE_POINTS) { + code += " int point = min(emission_texture_point_count - 1, int(rand_from_seed(alt_seed) * float(emission_texture_point_count)));\n"; + code += " ivec2 emission_tex_size = textureSize(emission_texture_points, 0);\n"; + code += " ivec2 emission_tex_ofs = ivec2(point % emission_tex_size.x, point / emission_tex_size.x);\n"; + } + code += " if (RESTART) {\n"; + + if (tex_parameters[PARAM_INITIAL_LINEAR_VELOCITY].is_valid()) + code += " float tex_linear_velocity = textureLod(linear_velocity_texture, vec2(0.0, 0.0), 0.0).r;\n"; + else + code += " float tex_linear_velocity = 0.0;\n"; + + if (tex_parameters[PARAM_ANGLE].is_valid()) + code += " float tex_angle = textureLod(angle_texture, vec2(0.0, 0.0), 0.0).r;\n"; + else + code += " float tex_angle = 0.0;\n"; + + if (tex_parameters[PARAM_ANIM_OFFSET].is_valid()) + code += " float tex_anim_offset = textureLod(anim_offset_texture, vec2(0.0, 0.0), 0.0).r;\n"; + else + code += " float tex_anim_offset = 0.0;\n"; + + code += " float spread_rad = spread * degree_to_rad;\n"; + + if (flags[FLAG_DISABLE_Z]) { + + code += " float angle1_rad = rand_from_seed_m1_p1(alt_seed) * spread_rad;\n"; + code += " vec3 rot = vec3(cos(angle1_rad), sin(angle1_rad), 0.0);\n"; + code += " VELOCITY = rot * initial_linear_velocity * mix(1.0, rand_from_seed(alt_seed), initial_linear_velocity_random);\n"; + + } else { + //initiate velocity spread in 3D + code += " float angle1_rad = rand_from_seed_m1_p1(alt_seed) * spread_rad;\n"; + code += " float angle2_rad = rand_from_seed_m1_p1(alt_seed) * spread_rad * (1.0 - flatness);\n"; + code += " vec3 direction_xz = vec3(sin(angle1_rad), 0, cos(angle1_rad));\n"; + code += " vec3 direction_yz = vec3(0, sin(angle2_rad), cos(angle2_rad));\n"; + code += " direction_yz.z = direction_yz.z / sqrt(direction_yz.z); // better uniform distribution\n"; + code += " vec3 direction = vec3(direction_xz.x * direction_yz.z, direction_yz.y, direction_xz.z * direction_yz.z);\n"; + code += " direction = normalize(direction);\n"; + code += " VELOCITY = direction * initial_linear_velocity * mix(1.0, rand_from_seed(alt_seed), initial_linear_velocity_random);\n"; + } + + code += " float base_angle = (initial_angle + tex_angle) * mix(1.0, angle_rand, initial_angle_random);\n"; + code += " CUSTOM.x = base_angle * degree_to_rad;\n"; // angle + code += " CUSTOM.y = 0.0;\n"; // phase + code += " CUSTOM.z = (anim_offset + tex_anim_offset) * mix(1.0, anim_offset_rand, anim_offset_random);\n"; // animation offset (0-1) + + switch (emission_shape) { + case EMISSION_SHAPE_POINT: { + //do none + } break; + case EMISSION_SHAPE_SPHERE: { + code += " TRANSFORM[3].xyz = normalize(vec3(rand_from_seed(alt_seed) * 2.0 - 1.0, rand_from_seed(alt_seed) * 2.0 - 1.0, rand_from_seed(alt_seed) * 2.0 - 1.0)) * emission_sphere_radius;\n"; + } break; + case EMISSION_SHAPE_BOX: { + code += " TRANSFORM[3].xyz = vec3(rand_from_seed(alt_seed) * 2.0 - 1.0, rand_from_seed(alt_seed) * 2.0 - 1.0, rand_from_seed(alt_seed) * 2.0 - 1.0) * emission_box_extents;\n"; + } break; + case EMISSION_SHAPE_POINTS: + case EMISSION_SHAPE_DIRECTED_POINTS: { + code += " TRANSFORM[3].xyz = texelFetch(emission_texture_points, emission_tex_ofs, 0).xyz;\n"; + + if (emission_shape == EMISSION_SHAPE_DIRECTED_POINTS) { + if (flags[FLAG_DISABLE_Z]) { + + code += " mat2 rotm;"; + code += " rotm[0] = texelFetch(emission_texture_normal, emission_tex_ofs, 0).xy;\n"; + code += " rotm[1] = rotm[0].yx * vec2(1.0, -1.0);\n"; + code += " VELOCITY.xy = rotm * VELOCITY.xy;\n"; + } else { + code += " vec3 normal = texelFetch(emission_texture_normal, emission_tex_ofs, 0).xyz;\n"; + code += " vec3 v0 = abs(normal.z) < 0.999 ? vec3(0.0, 0.0, 1.0) : vec3(0, 1.0, 0.0);\n"; + code += " vec3 tangent = normalize(cross(v0, normal));\n"; + code += " vec3 bitangent = normalize(cross(tangent, normal));\n"; + code += " VELOCITY = mat3(tangent, bitangent, normal) * VELOCITY;\n"; + } + } + } break; + } + code += " VELOCITY = (EMISSION_TRANSFORM * vec4(VELOCITY, 0.0)).xyz;\n"; + code += " TRANSFORM = EMISSION_TRANSFORM * TRANSFORM;\n"; + if (flags[FLAG_DISABLE_Z]) { + code += " VELOCITY.z = 0.0;\n"; + code += " TRANSFORM[3].z = 0.0;\n"; + } + + code += " } else {\n"; + + code += " CUSTOM.y += DELTA / LIFETIME;\n"; + if (tex_parameters[PARAM_INITIAL_LINEAR_VELOCITY].is_valid()) + code += " float tex_linear_velocity = textureLod(linear_velocity_texture, vec2(CUSTOM.y, 0.0), 0.0).r;\n"; + else + code += " float tex_linear_velocity = 0.0;\n"; + + if (flags[FLAG_DISABLE_Z]) { + + if (tex_parameters[PARAM_ORBIT_VELOCITY].is_valid()) + code += " float tex_orbit_velocity = textureLod(orbit_velocity_texture, vec2(CUSTOM.y, 0.0), 0.0).r;\n"; + else + code += " float tex_orbit_velocity = 0.0;\n"; + } + + if (tex_parameters[PARAM_ANGULAR_VELOCITY].is_valid()) + code += " float tex_angular_velocity = textureLod(angular_velocity_texture, vec2(CUSTOM.y, 0.0), 0.0).r;\n"; + else + code += " float tex_angular_velocity = 0.0;\n"; + + if (tex_parameters[PARAM_LINEAR_ACCEL].is_valid()) + code += " float tex_linear_accel = textureLod(linear_accel_texture, vec2(CUSTOM.y, 0.0), 0.0).r;\n"; + else + code += " float tex_linear_accel = 0.0;\n"; + + if (tex_parameters[PARAM_RADIAL_ACCEL].is_valid()) + code += " float tex_radial_accel = textureLod(radial_accel_texture, vec2(CUSTOM.y, 0.0), 0.0).r;\n"; + else + code += " float tex_radial_accel = 0.0;\n"; + + if (tex_parameters[PARAM_TANGENTIAL_ACCEL].is_valid()) + code += " float tex_tangent_accel = textureLod(tangent_accel_texture, vec2(CUSTOM.y, 0.0), 0.0).r;\n"; + else + code += " float tex_tangent_accel = 0.0;\n"; + + if (tex_parameters[PARAM_DAMPING].is_valid()) + code += " float tex_damping = textureLod(damping_texture, vec2(CUSTOM.y, 0.0), 0.0).r;\n"; + else + code += " float tex_damping = 0.0;\n"; + + if (tex_parameters[PARAM_ANGLE].is_valid()) + code += " float tex_angle = textureLod(angle_texture, vec2(CUSTOM.y, 0.0), 0.0).r;\n"; + else + code += " float tex_angle = 0.0;\n"; + + if (tex_parameters[PARAM_ANIM_SPEED].is_valid()) + code += " float tex_anim_speed = textureLod(anim_speed_texture, vec2(CUSTOM.y, 0.0), 0.0).r;\n"; + else + code += " float tex_anim_speed = 0.0;\n"; + + if (tex_parameters[PARAM_ANIM_OFFSET].is_valid()) + code += " float tex_anim_offset = textureLod(anim_offset_texture, vec2(CUSTOM.y, 0.0), 0.0).r;\n"; + else + code += " float tex_anim_offset = 0.0;\n"; + + code += " vec3 force = gravity;\n"; + code += " vec3 pos = TRANSFORM[3].xyz;\n"; + if (flags[FLAG_DISABLE_Z]) { + code += " pos.z = 0.0;\n"; + } + code += " // apply linear acceleration\n"; + code += " force += length(VELOCITY) > 0.0 ? normalize(VELOCITY) * (linear_accel + tex_linear_accel) * mix(1.0, rand_from_seed(alt_seed), linear_accel_random) : vec3(0.0);\n"; + code += " // apply radial acceleration\n"; + code += " vec3 org = EMISSION_TRANSFORM[3].xyz;\n"; + code += " vec3 diff = pos - org;\n"; + code += " force += length(diff) > 0.0 ? normalize(diff) * (radial_accel + tex_radial_accel) * mix(1.0, rand_from_seed(alt_seed), radial_accel_random) : vec3(0.0);\n"; + code += " // apply tangential acceleration;\n"; + if (flags[FLAG_DISABLE_Z]) { + code += " force += length(diff.yx) > 0.0 ? vec3(normalize(diff.yx * vec2(-1.0, 1.0)), 0.0) * ((tangent_accel + tex_tangent_accel) * mix(1.0, rand_from_seed(alt_seed), tangent_accel_random)) : vec3(0.0);\n"; + + } else { + code += " vec3 crossDiff = cross(normalize(diff), normalize(gravity));\n"; + code += " force += length(crossDiff) > 0.0 ? normalize(crossDiff) * ((tangent_accel + tex_tangent_accel) * mix(1.0, rand_from_seed(alt_seed), tangent_accel_random)) : vec3(0.0);\n"; + } + code += " // apply attractor forces\n"; + code += " VELOCITY += force * DELTA;\n"; + code += " // orbit velocity\n"; + if (flags[FLAG_DISABLE_Z]) { + + code += " float orbit_amount = (orbit_velocity + tex_orbit_velocity) * mix(1.0, rand_from_seed(alt_seed), orbit_velocity_random);\n"; + code += " if (orbit_amount != 0.0) {\n"; + code += " float ang = orbit_amount * DELTA * pi * 2.0;\n"; + code += " mat2 rot = mat2(vec2(cos(ang), -sin(ang)), vec2(sin(ang), cos(ang)));\n"; + code += " TRANSFORM[3].xy -= diff.xy;\n"; + code += " TRANSFORM[3].xy += rot * diff.xy;\n"; + code += " }\n"; + } + + if (tex_parameters[PARAM_INITIAL_LINEAR_VELOCITY].is_valid()) { + code += " VELOCITY = normalize(VELOCITY) * tex_linear_velocity;\n"; + } + code += " if (damping + tex_damping > 0.0) {\n"; + code += " float v = length(VELOCITY);\n"; + code += " float damp = (damping + tex_damping) * mix(1.0, rand_from_seed(alt_seed), damping_random);\n"; + code += " v -= damp * DELTA;\n"; + code += " if (v < 0.0) {\n"; + code += " VELOCITY = vec3(0.0);\n"; + code += " } else {\n"; + code += " VELOCITY = normalize(VELOCITY) * v;\n"; + code += " }\n"; + code += " }\n"; + code += " float base_angle = (initial_angle + tex_angle) * mix(1.0, angle_rand, initial_angle_random);\n"; + code += " base_angle += CUSTOM.y * LIFETIME * (angular_velocity + tex_angular_velocity) * mix(1.0, rand_from_seed(alt_seed) * 2.0 - 1.0, angular_velocity_random);\n"; + code += " CUSTOM.x = base_angle * degree_to_rad;\n"; // angle + code += " CUSTOM.z = (anim_offset + tex_anim_offset) * mix(1.0, anim_offset_rand, anim_offset_random) + CUSTOM.y * (anim_speed + tex_anim_speed) * mix(1.0, rand_from_seed(alt_seed), anim_speed_random);\n"; // angle + if (flags[FLAG_ANIM_LOOP]) { + code += " CUSTOM.z = mod(CUSTOM.z, 1.0);\n"; // loop + + } else { + code += " CUSTOM.z = clamp(CUSTOM.z, 0.0, 1.0);\n"; // 0 to 1 only + } + code += " }\n"; + // apply color + // apply hue rotation + if (tex_parameters[PARAM_SCALE].is_valid()) + code += " float tex_scale = textureLod(scale_texture, vec2(CUSTOM.y, 0.0), 0.0).r;\n"; + else + code += " float tex_scale = 1.0;\n"; + + if (tex_parameters[PARAM_HUE_VARIATION].is_valid()) + code += " float tex_hue_variation = textureLod(hue_variation_texture, vec2(CUSTOM.y, 0.0), 0.0).r;\n"; + else + code += " float tex_hue_variation = 0.0;\n"; + + code += " float hue_rot_angle = (hue_variation + tex_hue_variation) * pi * 2.0 * mix(1.0, hue_rot_rand * 2.0 - 1.0, hue_variation_random);\n"; + code += " float hue_rot_c = cos(hue_rot_angle);\n"; + code += " float hue_rot_s = sin(hue_rot_angle);\n"; + code += " mat4 hue_rot_mat = mat4(vec4(0.299, 0.587, 0.114, 0.0),\n"; + code += " vec4(0.299, 0.587, 0.114, 0.0),\n"; + code += " vec4(0.299, 0.587, 0.114, 0.0),\n"; + code += " vec4(0.000, 0.000, 0.000, 1.0)) +\n"; + code += " mat4(vec4(0.701, -0.587, -0.114, 0.0),\n"; + code += " vec4(-0.299, 0.413, -0.114, 0.0),\n"; + code += " vec4(-0.300, -0.588, 0.886, 0.0),\n"; + code += " vec4(0.000, 0.000, 0.000, 0.0)) * hue_rot_c +\n"; + code += " mat4(vec4(0.168, 0.330, -0.497, 0.0),\n"; + code += " vec4(-0.328, 0.035, 0.292, 0.0),\n"; + code += " vec4(1.250, -1.050, -0.203, 0.0),\n"; + code += " vec4(0.000, 0.000, 0.000, 0.0)) * hue_rot_s;\n"; + if (color_ramp.is_valid()) { + code += " COLOR = hue_rot_mat * textureLod(color_ramp, vec2(CUSTOM.y, 0.0), 0.0);\n"; + } else { + code += " COLOR = hue_rot_mat * color_value;\n"; + } + if (emission_color_texture.is_valid() && emission_shape >= EMISSION_SHAPE_POINTS) { + code += " COLOR *= texelFetch(emission_texture_color, emission_tex_ofs, 0);\n"; + } + if (trail_color_modifier.is_valid()) { + code += " if (trail_divisor > 1) {\n"; + code += " COLOR *= textureLod(trail_color_modifier, vec2(float(int(NUMBER) % trail_divisor) / float(trail_divisor - 1), 0.0), 0.0);\n"; + code += " }\n"; + } + code += "\n"; + + if (flags[FLAG_DISABLE_Z]) { + + if (flags[FLAG_ALIGN_Y_TO_VELOCITY]) { + code += " if (length(VELOCITY) > 0.0) {\n"; + code += " TRANSFORM[1].xyz = normalize(VELOCITY);\n"; + code += " } else {\n"; + code += " TRANSFORM[1].xyz = normalize(TRANSFORM[1].xyz);\n"; + code += " }\n"; + code += " TRANSFORM[0].xyz = normalize(cross(TRANSFORM[1].xyz, TRANSFORM[2].xyz));\n"; + code += " TRANSFORM[2] = vec4(0.0, 0.0, 1.0, 0.0);\n"; + } else { + code += " TRANSFORM[0] = vec4(cos(CUSTOM.x), -sin(CUSTOM.x), 0.0, 0.0);\n"; + code += " TRANSFORM[1] = vec4(sin(CUSTOM.x), cos(CUSTOM.x), 0.0, 0.0);\n"; + code += " TRANSFORM[2] = vec4(0.0, 0.0, 1.0, 0.0);\n"; + } + + } else { + // orient particle Y towards velocity + if (flags[FLAG_ALIGN_Y_TO_VELOCITY]) { + code += " if (length(VELOCITY) > 0.0) {\n"; + code += " TRANSFORM[1].xyz = normalize(VELOCITY);\n"; + code += " } else {\n"; + code += " TRANSFORM[1].xyz = normalize(TRANSFORM[1].xyz);\n"; + code += " }\n"; + code += " if (TRANSFORM[1].xyz == normalize(TRANSFORM[0].xyz)) {\n"; + code += " TRANSFORM[0].xyz = normalize(cross(normalize(TRANSFORM[1].xyz), normalize(TRANSFORM[2].xyz)));\n"; + code += " TRANSFORM[2].xyz = normalize(cross(normalize(TRANSFORM[0].xyz), normalize(TRANSFORM[1].xyz)));\n"; + code += " } else {\n"; + code += " TRANSFORM[2].xyz = normalize(cross(normalize(TRANSFORM[0].xyz), normalize(TRANSFORM[1].xyz)));\n"; + code += " TRANSFORM[0].xyz = normalize(cross(normalize(TRANSFORM[1].xyz), normalize(TRANSFORM[2].xyz)));\n"; + code += " }\n"; + } else { + code += " TRANSFORM[0].xyz = normalize(TRANSFORM[0].xyz);\n"; + code += " TRANSFORM[1].xyz = normalize(TRANSFORM[1].xyz);\n"; + code += " TRANSFORM[2].xyz = normalize(TRANSFORM[2].xyz);\n"; + } + // turn particle by rotation in Y + if (flags[FLAG_ROTATE_Y]) { + code += " TRANSFORM = TRANSFORM * mat4(vec4(cos(CUSTOM.x), 0.0, -sin(CUSTOM.x), 0.0), vec4(0.0, 1.0, 0.0, 0.0), vec4(sin(CUSTOM.x), 0.0, cos(CUSTOM.x), 0.0), vec4(0.0, 0.0, 0.0, 1.0));\n"; + } + } + //scale by scale + code += " float base_scale = mix(scale * tex_scale, 1.0, scale_random * scale_rand);\n"; + code += " if (base_scale == 0.0) {\n"; + code += " base_scale = 0.000001;\n"; + code += " }\n"; + if (trail_size_modifier.is_valid()) { + code += " if (trail_divisor > 1) {\n"; + code += " base_scale *= textureLod(trail_size_modifier, vec2(float(int(NUMBER) % trail_divisor) / float(trail_divisor - 1), 0.0), 0.0).r;\n"; + code += " }\n"; + } + + code += " TRANSFORM[0].xyz *= base_scale;\n"; + code += " TRANSFORM[1].xyz *= base_scale;\n"; + code += " TRANSFORM[2].xyz *= base_scale;\n"; + if (flags[FLAG_DISABLE_Z]) { + code += " VELOCITY.z = 0.0;\n"; + code += " TRANSFORM[3].z = 0.0;\n"; + } + code += "}\n"; + code += "\n"; + + ShaderData shader_data; + shader_data.shader = VS::get_singleton()->shader_create(); + shader_data.users = 1; + + VS::get_singleton()->shader_set_code(shader_data.shader, code); + + shader_map[mk] = shader_data; + + VS::get_singleton()->material_set_shader(_get_material(), shader_data.shader); +} + +void ParticlesMaterial::flush_changes() { + + if (material_mutex) + material_mutex->lock(); + + while (dirty_materials.first()) { + + dirty_materials.first()->self()->_update_shader(); + } + + if (material_mutex) + material_mutex->unlock(); +} + +void ParticlesMaterial::_queue_shader_change() { + + if (material_mutex) + material_mutex->lock(); + + if (!element.in_list()) { + dirty_materials.add(&element); + } + + if (material_mutex) + material_mutex->unlock(); +} + +bool ParticlesMaterial::_is_shader_dirty() const { + + bool dirty = false; + + if (material_mutex) + material_mutex->lock(); + + dirty = element.in_list(); + + if (material_mutex) + material_mutex->unlock(); + + return dirty; +} + +void ParticlesMaterial::set_spread(float p_spread) { + + spread = p_spread; + VisualServer::get_singleton()->material_set_param(_get_material(), shader_names->spread, p_spread); +} + +float ParticlesMaterial::get_spread() const { + + return spread; +} + +void ParticlesMaterial::set_flatness(float p_flatness) { + + flatness = p_flatness; + VisualServer::get_singleton()->material_set_param(_get_material(), shader_names->flatness, p_flatness); +} +float ParticlesMaterial::get_flatness() const { + + return flatness; +} + +void ParticlesMaterial::set_param(Parameter p_param, float p_value) { + + ERR_FAIL_INDEX(p_param, PARAM_MAX); + + parameters[p_param] = p_value; + + switch (p_param) { + case PARAM_INITIAL_LINEAR_VELOCITY: { + VisualServer::get_singleton()->material_set_param(_get_material(), shader_names->initial_linear_velocity, p_value); + } break; + case PARAM_ANGULAR_VELOCITY: { + VisualServer::get_singleton()->material_set_param(_get_material(), shader_names->angular_velocity, p_value); + } break; + case PARAM_ORBIT_VELOCITY: { + VisualServer::get_singleton()->material_set_param(_get_material(), shader_names->orbit_velocity, p_value); + } break; + case PARAM_LINEAR_ACCEL: { + VisualServer::get_singleton()->material_set_param(_get_material(), shader_names->linear_accel, p_value); + } break; + case PARAM_RADIAL_ACCEL: { + VisualServer::get_singleton()->material_set_param(_get_material(), shader_names->radial_accel, p_value); + } break; + case PARAM_TANGENTIAL_ACCEL: { + VisualServer::get_singleton()->material_set_param(_get_material(), shader_names->tangent_accel, p_value); + } break; + case PARAM_DAMPING: { + VisualServer::get_singleton()->material_set_param(_get_material(), shader_names->damping, p_value); + } break; + case PARAM_ANGLE: { + VisualServer::get_singleton()->material_set_param(_get_material(), shader_names->initial_angle, p_value); + } break; + case PARAM_SCALE: { + VisualServer::get_singleton()->material_set_param(_get_material(), shader_names->scale, p_value); + } break; + case PARAM_HUE_VARIATION: { + VisualServer::get_singleton()->material_set_param(_get_material(), shader_names->hue_variation, p_value); + } break; + case PARAM_ANIM_SPEED: { + VisualServer::get_singleton()->material_set_param(_get_material(), shader_names->anim_speed, p_value); + } break; + case PARAM_ANIM_OFFSET: { + VisualServer::get_singleton()->material_set_param(_get_material(), shader_names->anim_offset, p_value); + } break; + } +} +float ParticlesMaterial::get_param(Parameter p_param) const { + + ERR_FAIL_INDEX_V(p_param, PARAM_MAX, 0); + + return parameters[p_param]; +} + +void ParticlesMaterial::set_param_randomness(Parameter p_param, float p_value) { + + ERR_FAIL_INDEX(p_param, PARAM_MAX); + + randomness[p_param] = p_value; + + switch (p_param) { + case PARAM_INITIAL_LINEAR_VELOCITY: { + VisualServer::get_singleton()->material_set_param(_get_material(), shader_names->initial_linear_velocity_random, p_value); + } break; + case PARAM_ANGULAR_VELOCITY: { + VisualServer::get_singleton()->material_set_param(_get_material(), shader_names->angular_velocity_random, p_value); + } break; + case PARAM_ORBIT_VELOCITY: { + VisualServer::get_singleton()->material_set_param(_get_material(), shader_names->orbit_velocity_random, p_value); + } break; + case PARAM_LINEAR_ACCEL: { + VisualServer::get_singleton()->material_set_param(_get_material(), shader_names->linear_accel_random, p_value); + } break; + case PARAM_RADIAL_ACCEL: { + VisualServer::get_singleton()->material_set_param(_get_material(), shader_names->radial_accel_random, p_value); + } break; + case PARAM_TANGENTIAL_ACCEL: { + VisualServer::get_singleton()->material_set_param(_get_material(), shader_names->tangent_accel_random, p_value); + } break; + case PARAM_DAMPING: { + VisualServer::get_singleton()->material_set_param(_get_material(), shader_names->damping_random, p_value); + } break; + case PARAM_ANGLE: { + VisualServer::get_singleton()->material_set_param(_get_material(), shader_names->initial_angle_random, p_value); + } break; + case PARAM_SCALE: { + VisualServer::get_singleton()->material_set_param(_get_material(), shader_names->scale_random, p_value); + } break; + case PARAM_HUE_VARIATION: { + VisualServer::get_singleton()->material_set_param(_get_material(), shader_names->hue_variation_random, p_value); + } break; + case PARAM_ANIM_SPEED: { + VisualServer::get_singleton()->material_set_param(_get_material(), shader_names->anim_speed_random, p_value); + } break; + case PARAM_ANIM_OFFSET: { + VisualServer::get_singleton()->material_set_param(_get_material(), shader_names->anim_offset_random, p_value); + } break; + } +} +float ParticlesMaterial::get_param_randomness(Parameter p_param) const { + + ERR_FAIL_INDEX_V(p_param, PARAM_MAX, 0); + + return randomness[p_param]; +} + +static void _adjust_curve_range(const Ref<Texture> &p_texture, float p_min, float p_max) { + + Ref<CurveTexture> curve_tex = p_texture; + if (!curve_tex.is_valid()) + return; + + curve_tex->ensure_default_setup(p_min, p_max); +} + +void ParticlesMaterial::set_param_texture(Parameter p_param, const Ref<Texture> &p_texture) { + + ERR_FAIL_INDEX(p_param, PARAM_MAX); + + tex_parameters[p_param] = p_texture; + + switch (p_param) { + case PARAM_INITIAL_LINEAR_VELOCITY: { + //do none for this one + } break; + case PARAM_ANGULAR_VELOCITY: { + VisualServer::get_singleton()->material_set_param(_get_material(), shader_names->angular_velocity_texture, p_texture); + _adjust_curve_range(p_texture, -360, 360); + } break; + case PARAM_ORBIT_VELOCITY: { + VisualServer::get_singleton()->material_set_param(_get_material(), shader_names->orbit_velocity_texture, p_texture); + _adjust_curve_range(p_texture, -500, 500); + } break; + case PARAM_LINEAR_ACCEL: { + VisualServer::get_singleton()->material_set_param(_get_material(), shader_names->linear_accel_texture, p_texture); + _adjust_curve_range(p_texture, -200, 200); + } break; + case PARAM_RADIAL_ACCEL: { + VisualServer::get_singleton()->material_set_param(_get_material(), shader_names->radial_accel_texture, p_texture); + _adjust_curve_range(p_texture, -200, 200); + } break; + case PARAM_TANGENTIAL_ACCEL: { + VisualServer::get_singleton()->material_set_param(_get_material(), shader_names->tangent_accel_texture, p_texture); + _adjust_curve_range(p_texture, -200, 200); + } break; + case PARAM_DAMPING: { + VisualServer::get_singleton()->material_set_param(_get_material(), shader_names->damping_texture, p_texture); + _adjust_curve_range(p_texture, 0, 100); + } break; + case PARAM_ANGLE: { + VisualServer::get_singleton()->material_set_param(_get_material(), shader_names->angle_texture, p_texture); + _adjust_curve_range(p_texture, -360, 360); + } break; + case PARAM_SCALE: { + VisualServer::get_singleton()->material_set_param(_get_material(), shader_names->scale_texture, p_texture); + + Ref<CurveTexture> curve_tex = p_texture; + if (curve_tex.is_valid()) { + curve_tex->ensure_default_setup(); + } + + } break; + case PARAM_HUE_VARIATION: { + VisualServer::get_singleton()->material_set_param(_get_material(), shader_names->hue_variation_texture, p_texture); + _adjust_curve_range(p_texture, -1, 1); + } break; + case PARAM_ANIM_SPEED: { + VisualServer::get_singleton()->material_set_param(_get_material(), shader_names->anim_speed_texture, p_texture); + _adjust_curve_range(p_texture, 0, 200); + } break; + case PARAM_ANIM_OFFSET: { + VisualServer::get_singleton()->material_set_param(_get_material(), shader_names->anim_offset_texture, p_texture); + } break; + } + + _queue_shader_change(); +} +Ref<Texture> ParticlesMaterial::get_param_texture(Parameter p_param) const { + + ERR_FAIL_INDEX_V(p_param, PARAM_MAX, Ref<Texture>()); + + return tex_parameters[p_param]; +} + +void ParticlesMaterial::set_color(const Color &p_color) { + + VisualServer::get_singleton()->material_set_param(_get_material(), shader_names->color, p_color); + color = p_color; +} + +Color ParticlesMaterial::get_color() const { + + return color; +} + +void ParticlesMaterial::set_color_ramp(const Ref<Texture> &p_texture) { + + color_ramp = p_texture; + VisualServer::get_singleton()->material_set_param(_get_material(), shader_names->color_ramp, p_texture); + _queue_shader_change(); + _change_notify(); +} + +Ref<Texture> ParticlesMaterial::get_color_ramp() const { + + return color_ramp; +} + +void ParticlesMaterial::set_flag(Flags p_flag, bool p_enable) { + ERR_FAIL_INDEX(p_flag, FLAG_MAX); + flags[p_flag] = p_enable; + _queue_shader_change(); + if (p_flag == FLAG_DISABLE_Z) { + _change_notify(); + } +} + +bool ParticlesMaterial::get_flag(Flags p_flag) const { + ERR_FAIL_INDEX_V(p_flag, FLAG_MAX, false); + return flags[p_flag]; +} + +void ParticlesMaterial::set_emission_shape(EmissionShape p_shape) { + + emission_shape = p_shape; + _change_notify(); + _queue_shader_change(); +} + +void ParticlesMaterial::set_emission_sphere_radius(float p_radius) { + + emission_sphere_radius = p_radius; + VisualServer::get_singleton()->material_set_param(_get_material(), shader_names->emission_sphere_radius, p_radius); +} + +void ParticlesMaterial::set_emission_box_extents(Vector3 p_extents) { + + emission_box_extents = p_extents; + VisualServer::get_singleton()->material_set_param(_get_material(), shader_names->emission_box_extents, p_extents); +} + +void ParticlesMaterial::set_emission_point_texture(const Ref<Texture> &p_points) { + + emission_point_texture = p_points; + VisualServer::get_singleton()->material_set_param(_get_material(), shader_names->emission_texture_points, p_points); +} + +void ParticlesMaterial::set_emission_normal_texture(const Ref<Texture> &p_normals) { + + emission_normal_texture = p_normals; + VisualServer::get_singleton()->material_set_param(_get_material(), shader_names->emission_texture_normal, p_normals); +} + +void ParticlesMaterial::set_emission_color_texture(const Ref<Texture> &p_colors) { + + emission_color_texture = p_colors; + VisualServer::get_singleton()->material_set_param(_get_material(), shader_names->emission_texture_color, p_colors); + _queue_shader_change(); +} + +void ParticlesMaterial::set_emission_point_count(int p_count) { + + emission_point_count = p_count; + VisualServer::get_singleton()->material_set_param(_get_material(), shader_names->emission_texture_point_count, p_count); +} + +ParticlesMaterial::EmissionShape ParticlesMaterial::get_emission_shape() const { + + return emission_shape; +} + +float ParticlesMaterial::get_emission_sphere_radius() const { + + return emission_sphere_radius; +} +Vector3 ParticlesMaterial::get_emission_box_extents() const { + + return emission_box_extents; +} +Ref<Texture> ParticlesMaterial::get_emission_point_texture() const { + + return emission_point_texture; +} +Ref<Texture> ParticlesMaterial::get_emission_normal_texture() const { + + return emission_normal_texture; +} + +Ref<Texture> ParticlesMaterial::get_emission_color_texture() const { + + return emission_color_texture; +} + +int ParticlesMaterial::get_emission_point_count() const { + + return emission_point_count; +} + +void ParticlesMaterial::set_trail_divisor(int p_divisor) { + + trail_divisor = p_divisor; + VisualServer::get_singleton()->material_set_param(_get_material(), shader_names->trail_divisor, p_divisor); +} + +int ParticlesMaterial::get_trail_divisor() const { + + return trail_divisor; +} + +void ParticlesMaterial::set_trail_size_modifier(const Ref<CurveTexture> &p_trail_size_modifier) { + + trail_size_modifier = p_trail_size_modifier; + + Ref<CurveTexture> curve = trail_size_modifier; + if (curve.is_valid()) { + curve->ensure_default_setup(); + } + + VisualServer::get_singleton()->material_set_param(_get_material(), shader_names->trail_size_modifier, curve); + _queue_shader_change(); +} + +Ref<CurveTexture> ParticlesMaterial::get_trail_size_modifier() const { + + return trail_size_modifier; +} + +void ParticlesMaterial::set_trail_color_modifier(const Ref<GradientTexture> &p_trail_color_modifier) { + + trail_color_modifier = p_trail_color_modifier; + VisualServer::get_singleton()->material_set_param(_get_material(), shader_names->trail_color_modifier, p_trail_color_modifier); + _queue_shader_change(); +} + +Ref<GradientTexture> ParticlesMaterial::get_trail_color_modifier() const { + + return trail_color_modifier; +} + +void ParticlesMaterial::set_gravity(const Vector3 &p_gravity) { + + gravity = p_gravity; + Vector3 gset = gravity; + if (gset == Vector3()) { + gset = Vector3(0, -0.000001, 0); //as gravity is used as upvector in some calculations + } + VisualServer::get_singleton()->material_set_param(_get_material(), shader_names->gravity, gset); +} + +Vector3 ParticlesMaterial::get_gravity() const { + + return gravity; +} + +RID ParticlesMaterial::get_shader_rid() const { + + ERR_FAIL_COND_V(!shader_map.has(current_key), RID()); + return shader_map[current_key].shader; +} + +void ParticlesMaterial::_validate_property(PropertyInfo &property) const { + + if (property.name == "color" && color_ramp.is_valid()) { + property.usage = 0; + } + + if (property.name == "emission_sphere_radius" && emission_shape != EMISSION_SHAPE_SPHERE) { + property.usage = 0; + } + + if (property.name == "emission_box_extents" && emission_shape != EMISSION_SHAPE_BOX) { + property.usage = 0; + } + + if ((property.name == "emission_point_texture" || property.name == "emission_color_texture") && (emission_shape < EMISSION_SHAPE_POINTS)) { + property.usage = 0; + } + + if (property.name == "emission_normal_texture" && emission_shape != EMISSION_SHAPE_DIRECTED_POINTS) { + property.usage = 0; + } + + if (property.name == "emission_point_count" && (emission_shape != EMISSION_SHAPE_POINTS && emission_shape != EMISSION_SHAPE_DIRECTED_POINTS)) { + property.usage = 0; + } + + if (property.name.begins_with("orbit_") && !flags[FLAG_DISABLE_Z]) { + property.usage = 0; + } +} + +Shader::Mode ParticlesMaterial::get_shader_mode() const { + + return Shader::MODE_PARTICLES; +} + +void ParticlesMaterial::_bind_methods() { + + ClassDB::bind_method(D_METHOD("set_spread", "degrees"), &ParticlesMaterial::set_spread); + ClassDB::bind_method(D_METHOD("get_spread"), &ParticlesMaterial::get_spread); + + ClassDB::bind_method(D_METHOD("set_flatness", "amount"), &ParticlesMaterial::set_flatness); + ClassDB::bind_method(D_METHOD("get_flatness"), &ParticlesMaterial::get_flatness); + + ClassDB::bind_method(D_METHOD("set_param", "param", "value"), &ParticlesMaterial::set_param); + ClassDB::bind_method(D_METHOD("get_param", "param"), &ParticlesMaterial::get_param); + + ClassDB::bind_method(D_METHOD("set_param_randomness", "param", "randomness"), &ParticlesMaterial::set_param_randomness); + ClassDB::bind_method(D_METHOD("get_param_randomness", "param"), &ParticlesMaterial::get_param_randomness); + + ClassDB::bind_method(D_METHOD("set_param_texture", "param", "texture"), &ParticlesMaterial::set_param_texture); + ClassDB::bind_method(D_METHOD("get_param_texture", "param"), &ParticlesMaterial::get_param_texture); + + ClassDB::bind_method(D_METHOD("set_color", "color"), &ParticlesMaterial::set_color); + ClassDB::bind_method(D_METHOD("get_color"), &ParticlesMaterial::get_color); + + ClassDB::bind_method(D_METHOD("set_color_ramp", "ramp"), &ParticlesMaterial::set_color_ramp); + ClassDB::bind_method(D_METHOD("get_color_ramp"), &ParticlesMaterial::get_color_ramp); + + ClassDB::bind_method(D_METHOD("set_flag", "flag", "enable"), &ParticlesMaterial::set_flag); + ClassDB::bind_method(D_METHOD("get_flag", "flag"), &ParticlesMaterial::get_flag); + + ClassDB::bind_method(D_METHOD("set_emission_shape", "shape"), &ParticlesMaterial::set_emission_shape); + ClassDB::bind_method(D_METHOD("get_emission_shape"), &ParticlesMaterial::get_emission_shape); + + ClassDB::bind_method(D_METHOD("set_emission_sphere_radius", "radius"), &ParticlesMaterial::set_emission_sphere_radius); + ClassDB::bind_method(D_METHOD("get_emission_sphere_radius"), &ParticlesMaterial::get_emission_sphere_radius); + + ClassDB::bind_method(D_METHOD("set_emission_box_extents", "extents"), &ParticlesMaterial::set_emission_box_extents); + ClassDB::bind_method(D_METHOD("get_emission_box_extents"), &ParticlesMaterial::get_emission_box_extents); + + ClassDB::bind_method(D_METHOD("set_emission_point_texture", "texture"), &ParticlesMaterial::set_emission_point_texture); + ClassDB::bind_method(D_METHOD("get_emission_point_texture"), &ParticlesMaterial::get_emission_point_texture); + + ClassDB::bind_method(D_METHOD("set_emission_normal_texture", "texture"), &ParticlesMaterial::set_emission_normal_texture); + ClassDB::bind_method(D_METHOD("get_emission_normal_texture"), &ParticlesMaterial::get_emission_normal_texture); + + ClassDB::bind_method(D_METHOD("set_emission_color_texture", "texture"), &ParticlesMaterial::set_emission_color_texture); + ClassDB::bind_method(D_METHOD("get_emission_color_texture"), &ParticlesMaterial::get_emission_color_texture); + + ClassDB::bind_method(D_METHOD("set_emission_point_count", "point_count"), &ParticlesMaterial::set_emission_point_count); + ClassDB::bind_method(D_METHOD("get_emission_point_count"), &ParticlesMaterial::get_emission_point_count); + + ClassDB::bind_method(D_METHOD("set_trail_divisor", "divisor"), &ParticlesMaterial::set_trail_divisor); + ClassDB::bind_method(D_METHOD("get_trail_divisor"), &ParticlesMaterial::get_trail_divisor); + + ClassDB::bind_method(D_METHOD("set_trail_size_modifier", "texture"), &ParticlesMaterial::set_trail_size_modifier); + ClassDB::bind_method(D_METHOD("get_trail_size_modifier"), &ParticlesMaterial::get_trail_size_modifier); + + ClassDB::bind_method(D_METHOD("set_trail_color_modifier", "texture"), &ParticlesMaterial::set_trail_color_modifier); + ClassDB::bind_method(D_METHOD("get_trail_color_modifier"), &ParticlesMaterial::get_trail_color_modifier); + + ClassDB::bind_method(D_METHOD("get_gravity"), &ParticlesMaterial::get_gravity); + ClassDB::bind_method(D_METHOD("set_gravity", "accel_vec"), &ParticlesMaterial::set_gravity); + + ADD_GROUP("Trail", "trail_"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "trail_divisor", PROPERTY_HINT_RANGE, "1,1000000,1"), "set_trail_divisor", "get_trail_divisor"); + ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "trail_size_modifier", PROPERTY_HINT_RESOURCE_TYPE, "CurveTexture"), "set_trail_size_modifier", "get_trail_size_modifier"); + ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "trail_color_modifier", PROPERTY_HINT_RESOURCE_TYPE, "GradientTexture"), "set_trail_color_modifier", "get_trail_color_modifier"); + ADD_GROUP("Emission Shape", "emission_"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "emission_shape", PROPERTY_HINT_ENUM, "Point,Sphere,Box,Points,Directed Points"), "set_emission_shape", "get_emission_shape"); + ADD_PROPERTY(PropertyInfo(Variant::REAL, "emission_sphere_radius", PROPERTY_HINT_RANGE, "0.01,128,0.01,or_greater"), "set_emission_sphere_radius", "get_emission_sphere_radius"); + ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "emission_box_extents"), "set_emission_box_extents", "get_emission_box_extents"); + ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "emission_point_texture", PROPERTY_HINT_RESOURCE_TYPE, "Texture"), "set_emission_point_texture", "get_emission_point_texture"); + ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "emission_normal_texture", PROPERTY_HINT_RESOURCE_TYPE, "Texture"), "set_emission_normal_texture", "get_emission_normal_texture"); + ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "emission_color_texture", PROPERTY_HINT_RESOURCE_TYPE, "Texture"), "set_emission_color_texture", "get_emission_color_texture"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "emission_point_count", PROPERTY_HINT_RANGE, "0,1000000,1"), "set_emission_point_count", "get_emission_point_count"); + ADD_GROUP("Flags", "flag_"); + ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "flag_align_y"), "set_flag", "get_flag", FLAG_ALIGN_Y_TO_VELOCITY); + ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "flag_rotate_y"), "set_flag", "get_flag", FLAG_ROTATE_Y); + ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "flag_disable_z"), "set_flag", "get_flag", FLAG_DISABLE_Z); + ADD_GROUP("Spread", ""); + ADD_PROPERTY(PropertyInfo(Variant::REAL, "spread", PROPERTY_HINT_RANGE, "0,180,0.01"), "set_spread", "get_spread"); + ADD_PROPERTY(PropertyInfo(Variant::REAL, "flatness", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_flatness", "get_flatness"); + ADD_GROUP("Gravity", ""); + ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "gravity"), "set_gravity", "get_gravity"); + ADD_GROUP("Initial Velocity", "initial_"); + ADD_PROPERTYI(PropertyInfo(Variant::REAL, "initial_velocity", PROPERTY_HINT_RANGE, "0,1000,0.01,or_greater"), "set_param", "get_param", PARAM_INITIAL_LINEAR_VELOCITY); + ADD_PROPERTYI(PropertyInfo(Variant::REAL, "initial_velocity_random", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_param_randomness", "get_param_randomness", PARAM_INITIAL_LINEAR_VELOCITY); + ADD_GROUP("Angular Velocity", "angular_"); + ADD_PROPERTYI(PropertyInfo(Variant::REAL, "angular_velocity", PROPERTY_HINT_RANGE, "-360,360,0.01"), "set_param", "get_param", PARAM_ANGULAR_VELOCITY); + ADD_PROPERTYI(PropertyInfo(Variant::REAL, "angular_velocity_random", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_param_randomness", "get_param_randomness", PARAM_ANGULAR_VELOCITY); + ADD_PROPERTYI(PropertyInfo(Variant::OBJECT, "angular_velocity_curve", PROPERTY_HINT_RESOURCE_TYPE, "CurveTexture"), "set_param_texture", "get_param_texture", PARAM_ANGULAR_VELOCITY); + ADD_GROUP("Orbit Velocity", "orbit_"); + ADD_PROPERTYI(PropertyInfo(Variant::REAL, "orbit_velocity", PROPERTY_HINT_RANGE, "-1000,1000,0.01,or_lesser,or_greater"), "set_param", "get_param", PARAM_ORBIT_VELOCITY); + ADD_PROPERTYI(PropertyInfo(Variant::REAL, "orbit_velocity_random", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_param_randomness", "get_param_randomness", PARAM_ORBIT_VELOCITY); + ADD_PROPERTYI(PropertyInfo(Variant::OBJECT, "orbit_velocity_curve", PROPERTY_HINT_RESOURCE_TYPE, "CurveTexture"), "set_param_texture", "get_param_texture", PARAM_ORBIT_VELOCITY); + ADD_GROUP("Linear Accel", "linear_"); + ADD_PROPERTYI(PropertyInfo(Variant::REAL, "linear_accel", PROPERTY_HINT_RANGE, "-100,100,0.01,or_lesser,or_greater"), "set_param", "get_param", PARAM_LINEAR_ACCEL); + ADD_PROPERTYI(PropertyInfo(Variant::REAL, "linear_accel_random", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_param_randomness", "get_param_randomness", PARAM_LINEAR_ACCEL); + ADD_PROPERTYI(PropertyInfo(Variant::OBJECT, "linear_accel_curve", PROPERTY_HINT_RESOURCE_TYPE, "CurveTexture"), "set_param_texture", "get_param_texture", PARAM_LINEAR_ACCEL); + ADD_GROUP("Radial Accel", "radial_"); + ADD_PROPERTYI(PropertyInfo(Variant::REAL, "radial_accel", PROPERTY_HINT_RANGE, "-100,100,0.01,or_lesser,or_greater"), "set_param", "get_param", PARAM_RADIAL_ACCEL); + ADD_PROPERTYI(PropertyInfo(Variant::REAL, "radial_accel_random", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_param_randomness", "get_param_randomness", PARAM_RADIAL_ACCEL); + ADD_PROPERTYI(PropertyInfo(Variant::OBJECT, "radial_accel_curve", PROPERTY_HINT_RESOURCE_TYPE, "CurveTexture"), "set_param_texture", "get_param_texture", PARAM_RADIAL_ACCEL); + ADD_GROUP("Tangential Accel", "tangential_"); + ADD_PROPERTYI(PropertyInfo(Variant::REAL, "tangential_accel", PROPERTY_HINT_RANGE, "-100,100,0.01,or_lesser,or_greater"), "set_param", "get_param", PARAM_TANGENTIAL_ACCEL); + ADD_PROPERTYI(PropertyInfo(Variant::REAL, "tangential_accel_random", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_param_randomness", "get_param_randomness", PARAM_TANGENTIAL_ACCEL); + ADD_PROPERTYI(PropertyInfo(Variant::OBJECT, "tangential_accel_curve", PROPERTY_HINT_RESOURCE_TYPE, "CurveTexture"), "set_param_texture", "get_param_texture", PARAM_TANGENTIAL_ACCEL); + ADD_GROUP("Damping", ""); + ADD_PROPERTYI(PropertyInfo(Variant::REAL, "damping", PROPERTY_HINT_RANGE, "0,100,0.01,or_greater"), "set_param", "get_param", PARAM_DAMPING); + ADD_PROPERTYI(PropertyInfo(Variant::REAL, "damping_random", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_param_randomness", "get_param_randomness", PARAM_DAMPING); + ADD_PROPERTYI(PropertyInfo(Variant::OBJECT, "damping_curve", PROPERTY_HINT_RESOURCE_TYPE, "CurveTexture"), "set_param_texture", "get_param_texture", PARAM_DAMPING); + ADD_GROUP("Angle", ""); + ADD_PROPERTYI(PropertyInfo(Variant::REAL, "angle", PROPERTY_HINT_RANGE, "-720,720,0.1,or_lesser,or_greater"), "set_param", "get_param", PARAM_ANGLE); + ADD_PROPERTYI(PropertyInfo(Variant::REAL, "angle_random", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_param_randomness", "get_param_randomness", PARAM_ANGLE); + ADD_PROPERTYI(PropertyInfo(Variant::OBJECT, "angle_curve", PROPERTY_HINT_RESOURCE_TYPE, "CurveTexture"), "set_param_texture", "get_param_texture", PARAM_ANGLE); + ADD_GROUP("Scale", ""); + ADD_PROPERTYI(PropertyInfo(Variant::REAL, "scale", PROPERTY_HINT_RANGE, "0,1000,0.01,or_greater"), "set_param", "get_param", PARAM_SCALE); + ADD_PROPERTYI(PropertyInfo(Variant::REAL, "scale_random", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_param_randomness", "get_param_randomness", PARAM_SCALE); + ADD_PROPERTYI(PropertyInfo(Variant::OBJECT, "scale_curve", PROPERTY_HINT_RESOURCE_TYPE, "CurveTexture"), "set_param_texture", "get_param_texture", PARAM_SCALE); + ADD_GROUP("Color", ""); + ADD_PROPERTY(PropertyInfo(Variant::COLOR, "color"), "set_color", "get_color"); + ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "color_ramp", PROPERTY_HINT_RESOURCE_TYPE, "GradientTexture"), "set_color_ramp", "get_color_ramp"); + + ADD_GROUP("Hue Variation", "hue_"); + ADD_PROPERTYI(PropertyInfo(Variant::REAL, "hue_variation", PROPERTY_HINT_RANGE, "-1,1,0.1"), "set_param", "get_param", PARAM_HUE_VARIATION); + ADD_PROPERTYI(PropertyInfo(Variant::REAL, "hue_variation_random", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_param_randomness", "get_param_randomness", PARAM_HUE_VARIATION); + ADD_PROPERTYI(PropertyInfo(Variant::OBJECT, "hue_variation_curve", PROPERTY_HINT_RESOURCE_TYPE, "CurveTexture"), "set_param_texture", "get_param_texture", PARAM_HUE_VARIATION); + ADD_GROUP("Animation", "anim_"); + ADD_PROPERTYI(PropertyInfo(Variant::REAL, "anim_speed", PROPERTY_HINT_RANGE, "0,128,0.01,or_greater"), "set_param", "get_param", PARAM_ANIM_SPEED); + ADD_PROPERTYI(PropertyInfo(Variant::REAL, "anim_speed_random", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_param_randomness", "get_param_randomness", PARAM_ANIM_SPEED); + ADD_PROPERTYI(PropertyInfo(Variant::OBJECT, "anim_speed_curve", PROPERTY_HINT_RESOURCE_TYPE, "CurveTexture"), "set_param_texture", "get_param_texture", PARAM_ANIM_SPEED); + ADD_PROPERTYI(PropertyInfo(Variant::REAL, "anim_offset", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_param", "get_param", PARAM_ANIM_OFFSET); + ADD_PROPERTYI(PropertyInfo(Variant::REAL, "anim_offset_random", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_param_randomness", "get_param_randomness", PARAM_ANIM_OFFSET); + ADD_PROPERTYI(PropertyInfo(Variant::OBJECT, "anim_offset_curve", PROPERTY_HINT_RESOURCE_TYPE, "CurveTexture"), "set_param_texture", "get_param_texture", PARAM_ANIM_OFFSET); + ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "anim_loop"), "set_flag", "get_flag", FLAG_ANIM_LOOP); + + BIND_ENUM_CONSTANT(PARAM_INITIAL_LINEAR_VELOCITY); + BIND_ENUM_CONSTANT(PARAM_ANGULAR_VELOCITY); + BIND_ENUM_CONSTANT(PARAM_ORBIT_VELOCITY); + BIND_ENUM_CONSTANT(PARAM_LINEAR_ACCEL); + BIND_ENUM_CONSTANT(PARAM_RADIAL_ACCEL); + BIND_ENUM_CONSTANT(PARAM_TANGENTIAL_ACCEL); + BIND_ENUM_CONSTANT(PARAM_DAMPING); + BIND_ENUM_CONSTANT(PARAM_ANGLE); + BIND_ENUM_CONSTANT(PARAM_SCALE); + BIND_ENUM_CONSTANT(PARAM_HUE_VARIATION); + BIND_ENUM_CONSTANT(PARAM_ANIM_SPEED); + BIND_ENUM_CONSTANT(PARAM_ANIM_OFFSET); + BIND_ENUM_CONSTANT(PARAM_MAX); + + BIND_ENUM_CONSTANT(FLAG_ALIGN_Y_TO_VELOCITY); + BIND_ENUM_CONSTANT(FLAG_ROTATE_Y); + BIND_ENUM_CONSTANT(FLAG_MAX); + + BIND_ENUM_CONSTANT(EMISSION_SHAPE_POINT); + BIND_ENUM_CONSTANT(EMISSION_SHAPE_SPHERE); + BIND_ENUM_CONSTANT(EMISSION_SHAPE_BOX); + BIND_ENUM_CONSTANT(EMISSION_SHAPE_POINTS); + BIND_ENUM_CONSTANT(EMISSION_SHAPE_DIRECTED_POINTS); +} + +ParticlesMaterial::ParticlesMaterial() : + element(this) { + + set_spread(45); + set_flatness(0); + set_param(PARAM_INITIAL_LINEAR_VELOCITY, 1); + set_param(PARAM_ORBIT_VELOCITY, 0); + set_param(PARAM_LINEAR_ACCEL, 0); + set_param(PARAM_RADIAL_ACCEL, 0); + set_param(PARAM_TANGENTIAL_ACCEL, 0); + set_param(PARAM_DAMPING, 0); + set_param(PARAM_ANGLE, 0); + set_param(PARAM_SCALE, 1); + set_param(PARAM_HUE_VARIATION, 0); + set_param(PARAM_ANIM_SPEED, 0); + set_param(PARAM_ANIM_OFFSET, 0); + set_emission_shape(EMISSION_SHAPE_POINT); + set_emission_sphere_radius(1); + set_emission_box_extents(Vector3(1, 1, 1)); + set_trail_divisor(1); + set_gravity(Vector3(0, -9.8, 0)); + emission_point_count = 1; + + for (int i = 0; i < PARAM_MAX; i++) { + set_param_randomness(Parameter(i), 0); + } + + for (int i = 0; i < FLAG_MAX; i++) { + flags[i] = false; + } + + set_color(Color(1, 1, 1, 1)); + + current_key.key = 0; + current_key.invalid_key = 1; + + _queue_shader_change(); +} + +ParticlesMaterial::~ParticlesMaterial() { + + if (material_mutex) + material_mutex->lock(); + + if (shader_map.has(current_key)) { + shader_map[current_key].users--; + if (shader_map[current_key].users == 0) { + //deallocate shader, as it's no longer in use + VS::get_singleton()->free(shader_map[current_key].shader); + shader_map.erase(current_key); + } + + VS::get_singleton()->material_set_shader(_get_material(), RID()); + } + + if (material_mutex) + material_mutex->unlock(); +} diff --git a/scene/resources/particles_material.h b/scene/resources/particles_material.h new file mode 100644 index 0000000000..8090926fa3 --- /dev/null +++ b/scene/resources/particles_material.h @@ -0,0 +1,302 @@ +/*************************************************************************/ +/* particles_material.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2018 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 "rid.h" +#include "scene/resources/material.h" + +#ifndef PARTICLES_MATERIAL_H +#define PARTICLES_MATERIAL_H + +class ParticlesMaterial : public Material { + + GDCLASS(ParticlesMaterial, Material) + +public: + enum Parameter { + + PARAM_INITIAL_LINEAR_VELOCITY, + PARAM_ANGULAR_VELOCITY, + PARAM_ORBIT_VELOCITY, + PARAM_LINEAR_ACCEL, + PARAM_RADIAL_ACCEL, + PARAM_TANGENTIAL_ACCEL, + PARAM_DAMPING, + PARAM_ANGLE, + PARAM_SCALE, + PARAM_HUE_VARIATION, + PARAM_ANIM_SPEED, + PARAM_ANIM_OFFSET, + PARAM_MAX + }; + + enum Flags { + FLAG_ALIGN_Y_TO_VELOCITY, + FLAG_ROTATE_Y, + FLAG_DISABLE_Z, + FLAG_ANIM_LOOP, + FLAG_MAX + }; + + enum EmissionShape { + EMISSION_SHAPE_POINT, + EMISSION_SHAPE_SPHERE, + EMISSION_SHAPE_BOX, + EMISSION_SHAPE_POINTS, + EMISSION_SHAPE_DIRECTED_POINTS, + }; + +private: + union MaterialKey { + + struct { + uint32_t texture_mask : 16; + uint32_t texture_color : 1; + uint32_t flags : 4; + uint32_t emission_shape : 2; + uint32_t trail_size_texture : 1; + uint32_t trail_color_texture : 1; + uint32_t invalid_key : 1; + uint32_t has_emission_color : 1; + }; + + uint32_t key; + + bool operator<(const MaterialKey &p_key) const { + return key < p_key.key; + } + }; + + struct ShaderData { + RID shader; + int users; + }; + + static Map<MaterialKey, ShaderData> shader_map; + + MaterialKey current_key; + + _FORCE_INLINE_ MaterialKey _compute_key() const { + + MaterialKey mk; + mk.key = 0; + for (int i = 0; i < PARAM_MAX; i++) { + if (tex_parameters[i].is_valid()) { + mk.texture_mask |= (1 << i); + } + } + for (int i = 0; i < FLAG_MAX; i++) { + if (flags[i]) { + mk.flags |= (1 << i); + } + } + + mk.texture_color = color_ramp.is_valid() ? 1 : 0; + mk.emission_shape = emission_shape; + mk.trail_color_texture = trail_color_modifier.is_valid() ? 1 : 0; + mk.trail_size_texture = trail_size_modifier.is_valid() ? 1 : 0; + mk.has_emission_color = emission_shape >= EMISSION_SHAPE_POINTS && emission_color_texture.is_valid(); + + return mk; + } + + static Mutex *material_mutex; + static SelfList<ParticlesMaterial>::List dirty_materials; + + struct ShaderNames { + StringName spread; + StringName flatness; + StringName initial_linear_velocity; + StringName initial_angle; + StringName angular_velocity; + StringName orbit_velocity; + StringName linear_accel; + StringName radial_accel; + StringName tangent_accel; + StringName damping; + StringName scale; + StringName hue_variation; + StringName anim_speed; + StringName anim_offset; + + StringName initial_linear_velocity_random; + StringName initial_angle_random; + StringName angular_velocity_random; + StringName orbit_velocity_random; + StringName linear_accel_random; + StringName radial_accel_random; + StringName tangent_accel_random; + StringName damping_random; + StringName scale_random; + StringName hue_variation_random; + StringName anim_speed_random; + StringName anim_offset_random; + + StringName angle_texture; + StringName angular_velocity_texture; + StringName orbit_velocity_texture; + StringName linear_accel_texture; + StringName radial_accel_texture; + StringName tangent_accel_texture; + StringName damping_texture; + StringName scale_texture; + StringName hue_variation_texture; + StringName anim_speed_texture; + StringName anim_offset_texture; + + StringName color; + StringName color_ramp; + + StringName emission_sphere_radius; + StringName emission_box_extents; + StringName emission_texture_point_count; + StringName emission_texture_points; + StringName emission_texture_normal; + StringName emission_texture_color; + + StringName trail_divisor; + StringName trail_size_modifier; + StringName trail_color_modifier; + + StringName gravity; + }; + + static ShaderNames *shader_names; + + SelfList<ParticlesMaterial> element; + + void _update_shader(); + _FORCE_INLINE_ void _queue_shader_change(); + _FORCE_INLINE_ bool _is_shader_dirty() const; + + float spread; + float flatness; + + float parameters[PARAM_MAX]; + float randomness[PARAM_MAX]; + + Ref<Texture> tex_parameters[PARAM_MAX]; + Color color; + Ref<Texture> color_ramp; + + bool flags[FLAG_MAX]; + + EmissionShape emission_shape; + float emission_sphere_radius; + Vector3 emission_box_extents; + Ref<Texture> emission_point_texture; + Ref<Texture> emission_normal_texture; + Ref<Texture> emission_color_texture; + int emission_point_count; + + bool anim_loop; + + int trail_divisor; + + Ref<CurveTexture> trail_size_modifier; + Ref<GradientTexture> trail_color_modifier; + + Vector3 gravity; + + //do not save emission points here + +protected: + static void _bind_methods(); + virtual void _validate_property(PropertyInfo &property) const; + +public: + void set_spread(float p_spread); + float get_spread() const; + + void set_flatness(float p_flatness); + float get_flatness() const; + + void set_param(Parameter p_param, float p_value); + float get_param(Parameter p_param) const; + + void set_param_randomness(Parameter p_param, float p_value); + float get_param_randomness(Parameter p_param) const; + + void set_param_texture(Parameter p_param, const Ref<Texture> &p_texture); + Ref<Texture> get_param_texture(Parameter p_param) const; + + void set_color(const Color &p_color); + Color get_color() const; + + void set_color_ramp(const Ref<Texture> &p_texture); + Ref<Texture> get_color_ramp() const; + + void set_flag(Flags p_flag, bool p_enable); + bool get_flag(Flags p_flag) const; + + void set_emission_shape(EmissionShape p_shape); + void set_emission_sphere_radius(float p_radius); + void set_emission_box_extents(Vector3 p_extents); + void set_emission_point_texture(const Ref<Texture> &p_points); + void set_emission_normal_texture(const Ref<Texture> &p_normals); + void set_emission_color_texture(const Ref<Texture> &p_colors); + void set_emission_point_count(int p_count); + + EmissionShape get_emission_shape() const; + float get_emission_sphere_radius() const; + Vector3 get_emission_box_extents() const; + Ref<Texture> get_emission_point_texture() const; + Ref<Texture> get_emission_normal_texture() const; + Ref<Texture> get_emission_color_texture() const; + int get_emission_point_count() const; + + void set_trail_divisor(int p_divisor); + int get_trail_divisor() const; + + void set_trail_size_modifier(const Ref<CurveTexture> &p_trail_size_modifier); + Ref<CurveTexture> get_trail_size_modifier() const; + + void set_trail_color_modifier(const Ref<GradientTexture> &p_trail_color_modifier); + Ref<GradientTexture> get_trail_color_modifier() const; + + void set_gravity(const Vector3 &p_gravity); + Vector3 get_gravity() const; + + static void init_shaders(); + static void finish_shaders(); + static void flush_changes(); + + RID get_shader_rid() const; + + virtual Shader::Mode get_shader_mode() const; + + ParticlesMaterial(); + ~ParticlesMaterial(); +}; + +VARIANT_ENUM_CAST(ParticlesMaterial::Parameter) +VARIANT_ENUM_CAST(ParticlesMaterial::Flags) +VARIANT_ENUM_CAST(ParticlesMaterial::EmissionShape) + +#endif // PARTICLES_MATERIAL_H diff --git a/scene/resources/tile_set.cpp b/scene/resources/tile_set.cpp index 8112d6be00..23074b4bae 100644 --- a/scene/resources/tile_set.cpp +++ b/scene/resources/tile_set.cpp @@ -940,6 +940,8 @@ void TileSet::_bind_methods() { ClassDB::bind_method(D_METHOD("create_tile", "id"), &TileSet::create_tile); ClassDB::bind_method(D_METHOD("autotile_set_bitmask_mode", "id", "mode"), &TileSet::autotile_set_bitmask_mode); ClassDB::bind_method(D_METHOD("autotile_get_bitmask_mode", "id"), &TileSet::autotile_get_bitmask_mode); + ClassDB::bind_method(D_METHOD("autotile_set_size", "id", "size"), &TileSet::autotile_set_size); + ClassDB::bind_method(D_METHOD("autotile_get_size", "id"), &TileSet::autotile_get_size); ClassDB::bind_method(D_METHOD("tile_set_name", "id", "name"), &TileSet::tile_set_name); ClassDB::bind_method(D_METHOD("tile_get_name", "id"), &TileSet::tile_get_name); ClassDB::bind_method(D_METHOD("tile_set_texture", "id", "texture"), &TileSet::tile_set_texture); diff --git a/servers/visual/shader_language.cpp b/servers/visual/shader_language.cpp index ffb130048f..9500f35732 100644 --- a/servers/visual/shader_language.cpp +++ b/servers/visual/shader_language.cpp @@ -2368,9 +2368,9 @@ int ShaderLanguage::get_cardinality(DataType p_type) { 2, 3, 4, - 2, - 3, 4, + 9, + 16, 1, 1, 1, @@ -3307,7 +3307,9 @@ ShaderLanguage::Node *ShaderLanguage::_reduce_expression(BlockNode *p_block, Sha ERR_FAIL_COND_V(op->arguments[0]->type != Node::TYPE_VARIABLE, p_node); - DataType base = get_scalar_type(op->get_datatype()); + DataType type = op->get_datatype(); + DataType base = get_scalar_type(type); + int cardinality = get_cardinality(type); Vector<ConstantNode::Value> values; @@ -3318,19 +3320,9 @@ ShaderLanguage::Node *ShaderLanguage::_reduce_expression(BlockNode *p_block, Sha ConstantNode *cn = static_cast<ConstantNode *>(op->arguments[i]); if (get_scalar_type(cn->datatype) == base) { - - int cardinality = get_cardinality(op->arguments[i]->get_datatype()); - if (cn->values.size() == cardinality) { - - for (int j = 0; j < cn->values.size(); j++) { - values.push_back(cn->values[j]); - } - } else if (cn->values.size() == 1) { - - for (int j = 0; j < cardinality; j++) { - values.push_back(cn->values[0]); - } - } // else: should be filtered by the parser as it's an invalid constructor + for (int j = 0; j < cn->values.size(); j++) { + values.push_back(cn->values[j]); + } } else if (get_scalar_type(cn->datatype) == cn->datatype) { ConstantNode::Value v; @@ -3347,6 +3339,29 @@ ShaderLanguage::Node *ShaderLanguage::_reduce_expression(BlockNode *p_block, Sha } } + if (values.size() == 1) { + if (type >= TYPE_MAT2 && type <= TYPE_MAT4) { + ConstantNode::Value value = values[0]; + ConstantNode::Value zero; + zero.real = 0.0f; + int size = 2 + (type - TYPE_MAT2); + + values.clear(); + for (int i = 0; i < size; i++) { + for (int j = 0; j < size; j++) { + values.push_back(i == j ? value : zero); + } + } + } else { + for (int i = 1; i < cardinality; i++) { + values.push_back(values[0]); + } + } + } else if (values.size() != cardinality) { + ERR_PRINT("Failed to reduce expression, values and cardinality mismatch."); + return p_node; + } + ConstantNode *cn = alloc_node<ConstantNode>(); cn->datatype = op->get_datatype(); cn->values = values; |