diff options
96 files changed, 2339 insertions, 429 deletions
diff --git a/.gitignore b/.gitignore index 0de1e682a0..cbb0b5b133 100644 --- a/.gitignore +++ b/.gitignore @@ -91,6 +91,9 @@ bld/ # Hints for improving IntelliSense, created together with VS project cpp.hint +# Visualizers for the VS debugger +*.natvis + #NUNIT *.VisualState.xml TestResult.xml diff --git a/core/class_db.cpp b/core/class_db.cpp index 57e88044b5..edd49fe95f 100644 --- a/core/class_db.cpp +++ b/core/class_db.cpp @@ -1036,7 +1036,6 @@ bool ClassDB::get_property(Object *p_object, const StringName &p_property, Varia r_value = *c; return true; } - //if (check->constant_map.fin) check = check->inherits_ptr; } @@ -1163,24 +1162,6 @@ bool ClassDB::has_method(StringName p_class, StringName p_method, bool p_no_inhe return false; } -bool ClassDB::get_setter_and_type_for_property(const StringName &p_class, const StringName &p_prop, StringName &r_class, StringName &r_setter) { - - ClassInfo *type = classes.getptr(p_class); - ClassInfo *check = type; - while (check) { - - if (check->property_setget.has(p_prop)) { - r_class = check->name; - r_setter = check->property_setget[p_prop].setter; - return true; - } - - check = check->inherits_ptr; - } - - return false; -} - #ifdef DEBUG_METHODS_ENABLED MethodBind *ClassDB::bind_methodfi(uint32_t p_flags, MethodBind *p_bind, const MethodDefinition &method_name, const Variant **p_defs, int p_defcount) { StringName mdname = method_name.name; diff --git a/core/class_db.h b/core/class_db.h index b8b681301d..55fe01ec6d 100644 --- a/core/class_db.h +++ b/core/class_db.h @@ -349,8 +349,6 @@ public: static StringName get_category(const StringName &p_node); - static bool get_setter_and_type_for_property(const StringName &p_class, const StringName &p_prop, StringName &r_class, StringName &r_setter); - static void set_class_enabled(StringName p_class, bool p_enable); static bool is_class_enabled(StringName p_class); diff --git a/core/math/math_2d.cpp b/core/math/math_2d.cpp index c77fe96ff2..11003c1cd5 100644 --- a/core/math/math_2d.cpp +++ b/core/math/math_2d.cpp @@ -222,35 +222,6 @@ Vector2 Vector2::cubic_interpolate(const Vector2 &p_b, const Vector2 &p_pre_a, c (2.0 * p0 - 5.0 * p1 + 4 * p2 - p3) * t2 + (-p0 + 3.0 * p1 - 3.0 * p2 + p3) * t3); return out; - - /* - real_t mu = p_t; - real_t mu2 = mu*mu; - - Vector2 a0 = p_post_b - p_b - p_pre_a + *this; - Vector2 a1 = p_pre_a - *this - a0; - Vector2 a2 = p_b - p_pre_a; - Vector2 a3 = *this; - - return ( a0*mu*mu2 + a1*mu2 + a2*mu + a3 ); -*/ - /* - real_t t = p_t; - real_t t2 = t*t; - real_t t3 = t2*t; - - real_t a = 2.0*t3- 3.0*t2 + 1; - real_t b = -2.0*t3+ 3.0*t2; - real_t c = t3- 2.0*t2 + t; - real_t d = t3- t2; - - Vector2 p_a=*this; - - return Vector2( - (a * p_a.x) + (b *p_b.x) + (c * p_pre_a.x) + (d * p_post_b.x), - (a * p_a.y) + (b *p_b.y) + (c * p_pre_a.y) + (d * p_post_b.y) - ); -*/ } // slide returns the component of the vector along the given plane, specified by its normal vector. diff --git a/core/math/math_2d.h b/core/math/math_2d.h index d788318f5e..60351445c0 100644 --- a/core/math/math_2d.h +++ b/core/math/math_2d.h @@ -382,6 +382,11 @@ struct Rect2 { size = end - begin; } + inline Rect2 abs() const { + + return Rect2(Point2(position.x + MIN(size.x, 0), position.y + MIN(size.y, 0)), size.abs()); + } + operator String() const { return String(position) + ", " + String(size); } Rect2() {} diff --git a/core/os/os.h b/core/os/os.h index 4f968020cc..979ad7e92a 100644 --- a/core/os/os.h +++ b/core/os/os.h @@ -92,14 +92,16 @@ public: bool resizable; bool borderless_window; bool maximized; + bool use_vsync; float get_aspect() const { return (float)width / (float)height; } - VideoMode(int p_width = 1024, int p_height = 600, bool p_fullscreen = false, bool p_resizable = true, bool p_borderless_window = false, bool p_maximized = false) { + VideoMode(int p_width = 1024, int p_height = 600, bool p_fullscreen = false, bool p_resizable = true, bool p_borderless_window = false, bool p_maximized = false, bool p_use_vsync = false) { width = p_width; height = p_height; fullscreen = p_fullscreen; resizable = p_resizable; borderless_window = p_borderless_window; maximized = p_maximized; + use_vsync = p_use_vsync; } }; diff --git a/core/variant_call.cpp b/core/variant_call.cpp index 991573e8d7..f66cce85c9 100644 --- a/core/variant_call.cpp +++ b/core/variant_call.cpp @@ -360,6 +360,7 @@ struct _VariantCall { VCALL_LOCALMEM2R(Rect2, grow_margin); VCALL_LOCALMEM4R(Rect2, grow_individual); VCALL_LOCALMEM1R(Rect2, expand); + VCALL_LOCALMEM0R(Rect2, abs); VCALL_LOCALMEM0R(Vector3, min_axis); VCALL_LOCALMEM0R(Vector3, max_axis); @@ -1526,6 +1527,7 @@ void register_variant_methods() { ADDFUNC2R(RECT2, RECT2, Rect2, grow_margin, INT, "margin", REAL, "by", varray()); ADDFUNC4R(RECT2, RECT2, Rect2, grow_individual, REAL, "left", REAL, "top", REAL, "right", REAL, " bottom", varray()); ADDFUNC1R(RECT2, RECT2, Rect2, expand, VECTOR2, "to", varray()); + ADDFUNC0R(RECT2, RECT2, Rect2, abs, varray()); ADDFUNC0R(VECTOR3, INT, Vector3, min_axis, varray()); ADDFUNC0R(VECTOR3, INT, Vector3, max_axis, varray()); diff --git a/doc/classes/AnimationPlayer.xml b/doc/classes/AnimationPlayer.xml index 3b1ce37619..6ae0debc3a 100644 --- a/doc/classes/AnimationPlayer.xml +++ b/doc/classes/AnimationPlayer.xml @@ -250,8 +250,8 @@ <member name="autoplay" type="String" setter="set_autoplay" getter="get_autoplay"> The name of the animation to play when the scene loads. Default value: [code]""[/code]. </member> - <member name="playback_default_blend_time" type="float" setter="set_default_blend_time" getter="get_default_blend_time"> - The default time in which to blend animations. Ranges from 0 to 4096 with 0.01 precision. Default value: [code]0[/code]. + <member name="current_animation" type="String" setter="set_current_animation" getter="get_current_animation"> + The name of the current animation. Default value: [code]""[/code]. </member> <member name="playback_process_mode" type="int" setter="set_animation_process_mode" getter="get_animation_process_mode" enum="AnimationPlayer.AnimationProcessMode"> The process notification in which to update animations. Default value: [enum ANIMATION_PROCESS_IDLE]. diff --git a/doc/classes/AnimationTreePlayer.xml b/doc/classes/AnimationTreePlayer.xml index 4fb33eb5a3..37005c3bd3 100644 --- a/doc/classes/AnimationTreePlayer.xml +++ b/doc/classes/AnimationTreePlayer.xml @@ -4,7 +4,7 @@ Animation Player that uses a node graph for the blending. </brief_description> <description> - Animation Player that uses a node graph for the blending. This kind of player is very useful when animating character or other skeleton based rigs, because it can combine several animations to form a desired pose. + A node graph tool for blending multiple animations bound to an [AnimationPlayer]. Especially useful for animating characters or other skeleton-based rigs. It can combine several animations to form a desired pose. </description> <tutorials> </tutorials> @@ -19,7 +19,7 @@ <argument index="1" name="id" type="String"> </argument> <description> - Add a node of a given type in the graph with given id. + Adds a [code]type[/code] node to the graph with name [code]id[/code]. </description> </method> <method name="advance"> @@ -28,6 +28,7 @@ <argument index="0" name="delta" type="float"> </argument> <description> + Shifts position in the animation timeline. Delta is the time in seconds to shift. </description> </method> <method name="animation_node_get_animation" qualifiers="const"> @@ -36,7 +37,7 @@ <argument index="0" name="id" type="String"> </argument> <description> - Returns an animation given its name. + Returns the [AnimationPlayer]'s animation bound to the [code]AnimationTreePlayer[/code]'s animation node with name [code]id[/code]. </description> </method> <method name="animation_node_get_master_animation" qualifiers="const"> @@ -45,6 +46,7 @@ <argument index="0" name="id" type="String"> </argument> <description> + Returns the name of the [member master_player]'s animation bound to this animation node. </description> </method> <method name="animation_node_set_animation"> @@ -55,7 +57,7 @@ <argument index="1" name="animation" type="Animation"> </argument> <description> - Set the animation for an animation node. + Binds a new animation from the [member master_player] to the [code]AnimationTreePlayer[/code]'s animation node with name [code]id[/code]. </description> </method> <method name="animation_node_set_filter_path"> @@ -68,6 +70,7 @@ <argument index="2" name="enable" type="bool"> </argument> <description> + If [code]enable[/code] is [code]true[/code], the animation node with ID [code]id[/code] turns off the track modifying the property at [code]path[/code]. The modified node's children continue to animate. </description> </method> <method name="animation_node_set_master_animation"> @@ -78,6 +81,7 @@ <argument index="1" name="source" type="String"> </argument> <description> + Binds the animation named [code]source[/code] from [member master_player] to the animation node [code]id[/code]. Recalculates caches. </description> </method> <method name="are_nodes_connected" qualifiers="const"> @@ -123,6 +127,7 @@ <argument index="2" name="enable" type="bool"> </argument> <description> + If [code]enable[/code] is [code]true[/code], the blend2 node with ID [code]id[/code] turns off the track modifying the property at [code]path[/code]. The modified node's children continue to animate. </description> </method> <method name="blend3_node_get_amount" qualifiers="const"> @@ -199,6 +204,7 @@ <return type="NodePath"> </return> <description> + Returns the path to the [AnimationPlayer] from which this [code]AnimationTreePlayer[/code] binds animations to animation nodes. </description> </method> <method name="get_node_list"> @@ -423,6 +429,7 @@ <argument index="2" name="enable" type="bool"> </argument> <description> + If [code]enable[/code] is [code]true[/code], the oneshot node with ID [code]id[/code] turns off the track modifying the property at [code]path[/code]. The modified node's children continue to animate. </description> </method> <method name="oneshot_node_start"> @@ -440,13 +447,14 @@ <argument index="0" name="id" type="String"> </argument> <description> - Stops a OneShot node given its name. + Stops the OneShot node with name [code]id[/code]. </description> </method> <method name="recompute_caches"> <return type="void"> </return> <description> + Manually recalculates the cache of track information generated from animation nodes. Needed when external sources modify the animation nodes' state. </description> </method> <method name="remove_node"> @@ -455,6 +463,7 @@ <argument index="0" name="id" type="String"> </argument> <description> + Removes the animation node with name [code]id[/code]. </description> </method> <method name="reset"> @@ -496,7 +505,7 @@ <argument index="0" name="id" type="String"> </argument> <description> - Returns time scale value of a TimeScale node given its name. + Returns time scale value of the TimeScale node with name [code]id[/code]. </description> </method> <method name="timescale_node_set_scale"> @@ -507,7 +516,7 @@ <argument index="1" name="scale" type="float"> </argument> <description> - Sets time scale value of a TimeScale node given its name and value. + Sets the time scale of the TimeScale node with name [code]id[/code] to [code]scale[/code]. </description> </method> <method name="timeseek_node_seek"> @@ -518,7 +527,7 @@ <argument index="1" name="seconds" type="float"> </argument> <description> - Sets time seek value of a TimeSeek node given its name and value. + Sets the time seek value of the TimeSeek node with name [code]id[/code] to [code]seconds[/code] </description> </method> <method name="transition_node_delete_input"> @@ -529,6 +538,7 @@ <argument index="1" name="input_idx" type="int"> </argument> <description> + Deletes the input at [code]input_idx[/code] for the transition node with name [code]id[/code]. </description> </method> <method name="transition_node_get_current" qualifiers="const"> @@ -537,6 +547,7 @@ <argument index="0" name="id" type="String"> </argument> <description> + Returns the index of the currently evaluated input for the transition node with name [code]id[/code]. </description> </method> <method name="transition_node_get_input_count" qualifiers="const"> @@ -545,6 +556,7 @@ <argument index="0" name="id" type="String"> </argument> <description> + Returns the number of inputs for the transition node with name [code]id[/code]. </description> </method> <method name="transition_node_get_xfade_time" qualifiers="const"> @@ -553,6 +565,7 @@ <argument index="0" name="id" type="String"> </argument> <description> + Returns the cross fade time for the transition node with name [code]id[/code]. </description> </method> <method name="transition_node_has_input_auto_advance" qualifiers="const"> @@ -563,6 +576,7 @@ <argument index="1" name="input_idx" type="int"> </argument> <description> + Returns [code]true[/code] if the input at [code]input_idx[/code] on transition node with name [code]id[/code] is set to automatically advance to the next input upon completion. </description> </method> <method name="transition_node_set_current"> @@ -573,6 +587,7 @@ <argument index="1" name="input_idx" type="int"> </argument> <description> + The transition node with name [code]id[/code] sets its current input at [code]input_idx[/code]. </description> </method> <method name="transition_node_set_input_auto_advance"> @@ -585,6 +600,7 @@ <argument index="2" name="enable" type="bool"> </argument> <description> + The transition node with name [code]id[/code] advances to its next input automatically when the input at [code]input_idx[/code] completes. </description> </method> <method name="transition_node_set_input_count"> @@ -595,6 +611,7 @@ <argument index="1" name="count" type="int"> </argument> <description> + Resizes the number of inputs available for the transition node with name [code]id[/code]. </description> </method> <method name="transition_node_set_xfade_time"> @@ -605,11 +622,22 @@ <argument index="1" name="time_sec" type="float"> </argument> <description> + The transition node with name [code]id[/code] sets its cross fade time to [code]time_sec[/code]. </description> </method> </methods> <members> <member name="playback_process_mode" type="int" setter="set_animation_process_mode" getter="get_animation_process_mode" enum="AnimationTreePlayer.AnimationProcessMode"> + The thread in which to update animations. Default value: [enum ANIMATION_PROCESS_IDLE]. + </member> + <member name="master_player" type="NodePath" setter="set_master_player" getter="get_master_player"> + The path to the [AnimationPlayer] from which this [code]AnimationTreePlayer[/code] binds animations to animation nodes. + </member> + <member name="base_path" type="NodePath" setter="set_base_path" getter="get_base_path"> + The node from which to relatively access other nodes. Default value: [code]".."[/code]. + </member> + <member name="active" type="bool" setter="set_active" getter="is_active"> + If [code]true[/code] the [code]AnimationTreePlayer[/code] is able to play animations. Default value: [code]false[/code]. </member> </members> <constants> @@ -644,8 +672,10 @@ Transition node. </constant> <constant name="ANIMATION_PROCESS_PHYSICS" value="0" enum="AnimationProcessMode"> + Process animation during the physics process. This is especially useful when animating physics bodies. </constant> <constant name="ANIMATION_PROCESS_IDLE" value="1" enum="AnimationProcessMode"> + Process animation during the idle process. </constant> </constants> </class> diff --git a/doc/classes/Array.xml b/doc/classes/Array.xml index a7f9a6e09c..9445a1732e 100644 --- a/doc/classes/Array.xml +++ b/doc/classes/Array.xml @@ -284,6 +284,16 @@ </argument> <description> Sort the array using a custom method and return reference to the array. The arguments are an object that holds the method and the name of such method. The custom method receives two arguments (a pair of elements from the array) and must return true if the first argument is less than the second, and return false otherwise. Note: you cannot randomize the return value as the heapsort algorithm expects a deterministic result. Doing so will result in unexpected behavior. + [codeblock] + class MyCustomSorter: + static func sort(a, b): + if a[0] < b[0]: + return true + return false + + var my_items = [[5, "Potato"], [9, "Rice"], [4, "Tomato"]] + my_items.sort_custom(MyCustomSorter, "sort") + [/codeblock] </description> </method> </methods> diff --git a/doc/classes/EditorFileSystem.xml b/doc/classes/EditorFileSystem.xml index f577a4676f..54b3accb19 100644 --- a/doc/classes/EditorFileSystem.xml +++ b/doc/classes/EditorFileSystem.xml @@ -33,6 +33,7 @@ <argument index="0" name="path" type="String"> </argument> <description> + Returns a view into the filesystem at [code]path[/code]. </description> </method> <method name="get_scanning_progress" qualifiers="const"> @@ -83,6 +84,7 @@ <argument index="0" name="resources" type="PoolStringArray"> </argument> <description> + Remitted if a resource is reimported. </description> </signal> <signal name="sources_changed"> diff --git a/doc/classes/FileDialog.xml b/doc/classes/FileDialog.xml index 8057e95d44..3387b4a2ed 100644 --- a/doc/classes/FileDialog.xml +++ b/doc/classes/FileDialog.xml @@ -103,6 +103,9 @@ </member> <member name="mode" type="int" setter="set_mode" getter="get_mode" enum="FileDialog.Mode"> </member> + <member name="mode_overrides_title" type="bool" setter="set_mode_overrides_title" getter="is_mode_overriding_title"> + If [code]true[/code], changing the [code]mode[/code] property will set the window title accordingly (e. g. setting mode to [code]MODE_OPEN_FILE[/code] will change the window title to "Open a File"). + </member> <member name="show_hidden_files" type="bool" setter="set_show_hidden_files" getter="is_showing_hidden_files"> </member> </members> diff --git a/doc/classes/MeshInstance.xml b/doc/classes/MeshInstance.xml index f754341fef..ac26c2946f 100644 --- a/doc/classes/MeshInstance.xml +++ b/doc/classes/MeshInstance.xml @@ -4,7 +4,7 @@ Node that instances meshes into a scenario. </brief_description> <description> - MeshInstance is a [Node] that takes a [Mesh] resource and adds it to the current scenario by creating an instance of it. This is the class most often used to get 3D geometry rendered and can be used to instance a single [Mesh] in many places. This allows to reuse geometry and save on resources. When a [Mesh] has to be instanced more than thousands of times at close proximity, consider using a [MultiMesh] in a [MultiMeshInstance] instead. + MeshInstance is a node that takes a [Mesh] resource and adds it to the current scenario by creating an instance of it. This is the class most often used to get 3D geometry rendered and can be used to instance a single [Mesh] in many places. This allows to reuse geometry and save on resources. When a [Mesh] has to be instanced more than thousands of times at close proximity, consider using a [MultiMesh] in a [MultiMeshInstance] instead. </description> <tutorials> </tutorials> @@ -15,20 +15,21 @@ <return type="void"> </return> <description> - This helper creates a [StaticBody] child [Node] with a [ConvexPolygonShape] [CollisionShape] calculated from the mesh geometry. It's mainly used for testing. + This helper creates a [StaticBody] child node with a [ConvexPolygonShape] collision shape calculated from the mesh geometry. It's mainly used for testing. </description> </method> <method name="create_debug_tangents"> <return type="void"> </return> <description> + This helper creates a [MeshInstance] child node with gizmos at every vertex calculated from the mesh geometry. It's mainly used for testing. </description> </method> <method name="create_trimesh_collision"> <return type="void"> </return> <description> - This helper creates a [StaticBody] child [Node] with a [ConcavePolygonShape] [CollisionShape] calculated from the mesh geometry. It's mainly used for testing. + This helper creates a [StaticBody] child node with a [ConcavePolygonShape] collision shape calculated from the mesh geometry. It's mainly used for testing. </description> </method> <method name="get_surface_material" qualifiers="const"> diff --git a/doc/classes/Texture.xml b/doc/classes/Texture.xml index 855a8f12de..52972177bf 100644 --- a/doc/classes/Texture.xml +++ b/doc/classes/Texture.xml @@ -117,22 +117,26 @@ </methods> <constants> <constant name="FLAG_MIPMAPS" value="1" enum="Flags"> - Generate mipmaps, to enable smooth zooming out of the texture. + Generate mipmaps, which are smaller versions of the same texture to use when zoomed out, keeping the aspect ratio. </constant> <constant name="FLAG_REPEAT" value="2" enum="Flags"> - Repeat (instead of clamp to edge). + Repeats texture (instead of clamp to edge). </constant> <constant name="FLAG_FILTER" value="4" enum="Flags"> - Turn on magnifying filter, to enable smooth zooming in of the texture. + Magnifying filter, to enable smooth zooming in of the texture. </constant> <constant name="FLAGS_DEFAULT" value="7" enum="Flags"> Default flags. Generate mipmaps, repeat, and filter are enabled. </constant> <constant name="FLAG_ANISOTROPIC_FILTER" value="8" enum="Flags"> + Anisotropic mipmap filtering. Generates smaller versions of the same texture with different aspect ratios. + More effective on planes often shown going to the horrizon as those textures (Walls or Ground for example) get squashed in the viewport to different aspect ratios and regular mipmaps keep the aspect ratio so they don't optimize storage that well in those cases. </constant> <constant name="FLAG_CONVERT_TO_LINEAR" value="16" enum="Flags"> + Converts texture to SRGB color space. </constant> <constant name="FLAG_MIRRORED_REPEAT" value="32" enum="Flags"> + Repeats texture with alternate sections mirrored. </constant> <constant name="FLAG_VIDEO_SURFACE" value="4096" enum="Flags"> Texture is a video surface. diff --git a/doc/classes/VisualServer.xml b/doc/classes/VisualServer.xml index 479c0606f2..6627ba15d5 100644 --- a/doc/classes/VisualServer.xml +++ b/doc/classes/VisualServer.xml @@ -24,6 +24,7 @@ <argument index="3" name="bottom" type="RID"> </argument> <description> + Sets images to be rendered in the window margin. </description> </method> <method name="black_bars_set_margins"> @@ -38,12 +39,14 @@ <argument index="3" name="bottom" type="int"> </argument> <description> + Sets margin size, where black bars (or images, if [method black_bars_set_images] was used) are rendered. </description> </method> <method name="canvas_create"> <return type="RID"> </return> <description> + Creates a canvas and returns the assigned [RID]. </description> </method> <method name="canvas_item_add_circle"> @@ -58,6 +61,7 @@ <argument index="3" name="color" type="Color"> </argument> <description> + Adds a circle command to the [CanvasItem]'s draw commands. </description> </method> <method name="canvas_item_add_clip_ignore"> @@ -68,6 +72,7 @@ <argument index="1" name="ignore" type="bool"> </argument> <description> + If ignore is [code]true[/code], the VisualServer does not perform clipping. </description> </method> <method name="canvas_item_add_line"> @@ -86,6 +91,7 @@ <argument index="5" name="antialiased" type="bool" default="false"> </argument> <description> + Adds a line command to the [CanvasItem]'s draw commands. </description> </method> <method name="canvas_item_add_mesh"> @@ -98,6 +104,7 @@ <argument index="2" name="skeleton" type="RID"> </argument> <description> + Adds a [Mesh] to the [CanvasItem]'s draw commands. Only affects its aabb at the moment. </description> </method> <method name="canvas_item_add_multimesh"> @@ -110,6 +117,7 @@ <argument index="2" name="skeleton" type="RID"> </argument> <description> + Adds a [MultiMesh] to the [CanvasItem]'s draw commands. Only affects its aabb at the moment. </description> </method> <method name="canvas_item_add_nine_patch"> @@ -138,6 +146,8 @@ <argument index="10" name="normal_map" type="RID"> </argument> <description> + Adds a nine patch image to the [CanvasItem]'s draw commands. + See [NinePatchRect] for more explanation. </description> </method> <method name="canvas_item_add_particles"> @@ -156,6 +166,7 @@ <argument index="5" name="v_frames" type="int"> </argument> <description> + Adds a particles system to the [CanvasItem]'s draw commands. </description> </method> <method name="canvas_item_add_polygon"> @@ -176,6 +187,7 @@ <argument index="6" name="antialiased" type="bool" default="false"> </argument> <description> + Adds a polygon to the [CanvasItem]'s draw commands. </description> </method> <method name="canvas_item_add_polyline"> @@ -192,6 +204,7 @@ <argument index="4" name="antialiased" type="bool" default="false"> </argument> <description> + Adds a polyline, which is a line from mutliple points with a width, to the [CanvasItem]'s draw commands. </description> </method> <method name="canvas_item_add_primitive"> @@ -212,6 +225,7 @@ <argument index="6" name="normal_map" type="RID"> </argument> <description> + Adds a primitive to the [CanvasItem]'s draw commands. </description> </method> <method name="canvas_item_add_rect"> @@ -224,6 +238,7 @@ <argument index="2" name="color" type="Color"> </argument> <description> + Adds a rectangle to the [CanvasItem]'s draw commands. </description> </method> <method name="canvas_item_add_set_transform"> @@ -234,6 +249,8 @@ <argument index="1" name="transform" type="Transform2D"> </argument> <description> + Adds a [Transform2D] command to the [CanvasItem]'s draw commands. + This sets the extra_matrix uniform when executed. This affects the later command's of the canvas item. </description> </method> <method name="canvas_item_add_texture_rect"> @@ -254,6 +271,7 @@ <argument index="6" name="normal_map" type="RID"> </argument> <description> + Adds a textured rect to the [CanvasItem]'s draw commands. </description> </method> <method name="canvas_item_add_texture_rect_region"> @@ -276,6 +294,7 @@ <argument index="7" name="clip_uv" type="bool" default="true"> </argument> <description> + Adds a texture rect with region setting to the [CanvasItem]'s draw commands. </description> </method> <method name="canvas_item_add_triangle_array"> @@ -298,6 +317,7 @@ <argument index="7" name="normal_map" type="RID"> </argument> <description> + Adds a triangle array to the [CanvasItem]'s draw commands. </description> </method> <method name="canvas_item_clear"> @@ -306,12 +326,14 @@ <argument index="0" name="item" type="RID"> </argument> <description> + Clears the [CanvasItem] and removes all commands in it. </description> </method> <method name="canvas_item_create"> <return type="RID"> </return> <description> + Creates a new [CanvasItem] and returns its [RID]. </description> </method> <method name="canvas_item_set_clip"> @@ -322,6 +344,7 @@ <argument index="1" name="clip" type="bool"> </argument> <description> + Sets clipping for the [CanvasItem]. </description> </method> <method name="canvas_item_set_copy_to_backbuffer"> @@ -334,6 +357,7 @@ <argument index="2" name="rect" type="Rect2"> </argument> <description> + Sets the [CanvasItem] to copy a rect to the backbuffer. </description> </method> <method name="canvas_item_set_custom_rect"> @@ -346,6 +370,7 @@ <argument index="2" name="rect" type="Rect2" default="Rect2( 0, 0, 0, 0 )"> </argument> <description> + Defines a custom drawing rectangle for the [CanvasItem]. </description> </method> <method name="canvas_item_set_distance_field_mode"> @@ -366,6 +391,7 @@ <argument index="1" name="enabled" type="bool"> </argument> <description> + Sets [CanvasItem] to be drawn behind its parent. </description> </method> <method name="canvas_item_set_draw_index"> @@ -376,6 +402,7 @@ <argument index="1" name="index" type="int"> </argument> <description> + Sets the index for the [CanvasItem]. </description> </method> <method name="canvas_item_set_light_mask"> @@ -386,6 +413,7 @@ <argument index="1" name="mask" type="int"> </argument> <description> + The light mask. See [LightOccluder2D] for more information on light masks. </description> </method> <method name="canvas_item_set_material"> @@ -396,6 +424,7 @@ <argument index="1" name="material" type="RID"> </argument> <description> + Sets a new material to the [CanvasItem]. </description> </method> <method name="canvas_item_set_modulate"> @@ -406,6 +435,7 @@ <argument index="1" name="color" type="Color"> </argument> <description> + Sets the color that modulates the [CanvasItem] and its children. </description> </method> <method name="canvas_item_set_parent"> @@ -416,6 +446,7 @@ <argument index="1" name="parent" type="RID"> </argument> <description> + Sets the parent for the [CanvasItem]. </description> </method> <method name="canvas_item_set_self_modulate"> @@ -426,6 +457,7 @@ <argument index="1" name="color" type="Color"> </argument> <description> + Sets the color that modulates the [CanvasItem] without children. </description> </method> <method name="canvas_item_set_sort_children_by_y"> @@ -436,6 +468,7 @@ <argument index="1" name="enabled" type="bool"> </argument> <description> + Sets if [CanvasItem]'s children should be sorted by y-position. </description> </method> <method name="canvas_item_set_transform"> @@ -446,6 +479,7 @@ <argument index="1" name="transform" type="Transform2D"> </argument> <description> + Sets the [CanvasItem]'s [Transform2D]. </description> </method> <method name="canvas_item_set_use_parent_material"> @@ -456,6 +490,7 @@ <argument index="1" name="enabled" type="bool"> </argument> <description> + Sets if the [CanvasItem] uses its parent's material. </description> </method> <method name="canvas_item_set_visible"> @@ -466,6 +501,7 @@ <argument index="1" name="visible" type="bool"> </argument> <description> + Sets if the canvas item (including its children) is visible. </description> </method> <method name="canvas_item_set_z"> @@ -476,6 +512,7 @@ <argument index="1" name="z" type="int"> </argument> <description> + Sets the [CanvasItem]'s z order position. </description> </method> <method name="canvas_item_set_z_as_relative_to_parent"> @@ -486,6 +523,7 @@ <argument index="1" name="enabled" type="bool"> </argument> <description> + If this is enabled, the z-position of the parent will be added to the childrens z-position. </description> </method> <method name="canvas_light_attach_to_canvas"> @@ -496,12 +534,14 @@ <argument index="1" name="canvas" type="RID"> </argument> <description> + Attaches the canvas light to the canvas. Removes it from its previous canvas. </description> </method> <method name="canvas_light_create"> <return type="RID"> </return> <description> + Creates a canvas light. </description> </method> <method name="canvas_light_occluder_attach_to_canvas"> @@ -512,12 +552,14 @@ <argument index="1" name="canvas" type="RID"> </argument> <description> + Attaches a light occluder to the canvas. Removes it from its previous canvas. </description> </method> <method name="canvas_light_occluder_create"> <return type="RID"> </return> <description> + Creates a light occluder. </description> </method> <method name="canvas_light_occluder_set_enabled"> @@ -528,6 +570,7 @@ <argument index="1" name="enabled" type="bool"> </argument> <description> + Enables or disables light occluder. </description> </method> <method name="canvas_light_occluder_set_light_mask"> @@ -538,6 +581,7 @@ <argument index="1" name="mask" type="int"> </argument> <description> + The light mask. See [LightOccluder2D] for more information on light masks </description> </method> <method name="canvas_light_occluder_set_polygon"> @@ -548,6 +592,7 @@ <argument index="1" name="polygon" type="RID"> </argument> <description> + Sets a light occluder's polygon. </description> </method> <method name="canvas_light_occluder_set_transform"> @@ -558,6 +603,7 @@ <argument index="1" name="transform" type="Transform2D"> </argument> <description> + Sets a light occluder's [Transform2D]. </description> </method> <method name="canvas_light_set_color"> @@ -568,6 +614,7 @@ <argument index="1" name="color" type="Color"> </argument> <description> + Sets the color for a light. </description> </method> <method name="canvas_light_set_enabled"> @@ -578,6 +625,7 @@ <argument index="1" name="enabled" type="bool"> </argument> <description> + Enables or disables a canvas light. </description> </method> <method name="canvas_light_set_energy"> @@ -588,6 +636,7 @@ <argument index="1" name="energy" type="float"> </argument> <description> + Sets a canvas light's energy. </description> </method> <method name="canvas_light_set_height"> @@ -598,6 +647,7 @@ <argument index="1" name="height" type="float"> </argument> <description> + Sets a canvas light's height. </description> </method> <method name="canvas_light_set_item_cull_mask"> @@ -608,6 +658,7 @@ <argument index="1" name="mask" type="int"> </argument> <description> + The light mask. See [LightOccluder2D] for more information on light masks </description> </method> <method name="canvas_light_set_item_shadow_cull_mask"> @@ -618,6 +669,7 @@ <argument index="1" name="mask" type="int"> </argument> <description> + The shadow mask. binary about wich layers this canvas light affects wich canvas item's shadows. See [LightOccluder2D] for more information on light masks. </description> </method> <method name="canvas_light_set_layer_range"> @@ -630,6 +682,7 @@ <argument index="2" name="max_layer" type="int"> </argument> <description> + The layer range that gets rendered with this light. </description> </method> <method name="canvas_light_set_mode"> @@ -640,6 +693,7 @@ <argument index="1" name="mode" type="int" enum="VisualServer.CanvasLightMode"> </argument> <description> + The mode of the light, see CANVAS_LIGHT_MODE_* constants. </description> </method> <method name="canvas_light_set_scale"> @@ -660,6 +714,7 @@ <argument index="1" name="size" type="int"> </argument> <description> + Sets the width of the shadow buffer, size gets scaled to the next power of two for this. </description> </method> <method name="canvas_light_set_shadow_color"> @@ -670,6 +725,7 @@ <argument index="1" name="color" type="Color"> </argument> <description> + Sets the color of the canvas light's shadow. </description> </method> <method name="canvas_light_set_shadow_enabled"> @@ -680,6 +736,7 @@ <argument index="1" name="enabled" type="bool"> </argument> <description> + Enables or disables the canvas light's shadow. </description> </method> <method name="canvas_light_set_shadow_filter"> @@ -690,6 +747,7 @@ <argument index="1" name="filter" type="int" enum="VisualServer.CanvasLightShadowFilter"> </argument> <description> + Sets the canvas light's shadow's filter, see CANVAS_LIGHT_SHADOW_FILTER_* constants. </description> </method> <method name="canvas_light_set_shadow_gradient_length"> @@ -700,6 +758,7 @@ <argument index="1" name="length" type="float"> </argument> <description> + Sets the length of the shadow's gradient. </description> </method> <method name="canvas_light_set_shadow_smooth"> @@ -710,6 +769,7 @@ <argument index="1" name="smooth" type="float"> </argument> <description> + Smoothens the shadow. The lower, the more smooth. </description> </method> <method name="canvas_light_set_texture"> @@ -740,6 +800,7 @@ <argument index="1" name="transform" type="Transform2D"> </argument> <description> + Sets the canvas light's [Transform2D]. </description> </method> <method name="canvas_light_set_z_range"> @@ -758,6 +819,7 @@ <return type="RID"> </return> <description> + Creates a new light occluder polygon. </description> </method> <method name="canvas_occluder_polygon_set_cull_mode"> @@ -768,6 +830,7 @@ <argument index="1" name="mode" type="int" enum="VisualServer.CanvasOccluderPolygonCullMode"> </argument> <description> + Sets an occluder polygons cull mode. See CANVAS_OCCLUDER_POLYGON_CULL_MODE_* constants. </description> </method> <method name="canvas_occluder_polygon_set_shape"> @@ -780,6 +843,7 @@ <argument index="2" name="closed" type="bool"> </argument> <description> + Sets the shape of the occluder polygon. </description> </method> <method name="canvas_occluder_polygon_set_shape_as_lines"> @@ -790,6 +854,7 @@ <argument index="1" name="shape" type="PoolVector2Array"> </argument> <description> + Sets the shape of the occluder polygon as lines. </description> </method> <method name="canvas_set_item_mirroring"> @@ -802,6 +867,7 @@ <argument index="2" name="mirroring" type="Vector2"> </argument> <description> + A copy of the canvas item will be drawn with a local offset of the mirroring [Vector2]. </description> </method> <method name="canvas_set_modulate"> @@ -812,6 +878,7 @@ <argument index="1" name="color" type="Color"> </argument> <description> + Modulates all colors in the given canvas. </description> </method> <method name="draw"> @@ -820,12 +887,14 @@ <argument index="0" name="swap_buffers" type="bool" default="true"> </argument> <description> + Draws a frame. </description> </method> <method name="finish"> <return type="void"> </return> <description> + Removes buffers and clears testcubes. </description> </method> <method name="force_draw"> @@ -834,12 +903,14 @@ <argument index="0" name="swap_buffers" type="bool" default="true"> </argument> <description> + Draws a frame. Same as [method draw]. </description> </method> <method name="force_sync"> <return type="void"> </return> <description> + Syncronizes threads. </description> </method> <method name="free"> @@ -848,6 +919,7 @@ <argument index="0" name="rid" type="RID"> </argument> <description> + Tries to free an object in the VisualServer. </description> </method> <method name="get_render_info"> @@ -856,30 +928,35 @@ <argument index="0" name="info" type="int" enum="VisualServer.RenderInfo"> </argument> <description> + Returns a certain information, see RENDER_INFO_* for options. </description> </method> <method name="get_test_cube"> <return type="RID"> </return> <description> + Returns the id of the test cube. Creates one if none exists. </description> </method> <method name="get_test_texture"> <return type="RID"> </return> <description> + Returns the id of the test texture. Creates one if none exists. </description> </method> <method name="get_white_texture"> <return type="RID"> </return> <description> + Returns the id of a white texture. Creates one if none exists. </description> </method> <method name="has_changed" qualifiers="const"> <return type="bool"> </return> <description> + Returns [code]true[/code] if changes have been made to the VisualServer's data. [method draw] is usually called if this happens. </description> </method> <method name="has_feature" qualifiers="const"> @@ -896,12 +973,14 @@ <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, </description> </method> <method name="init"> <return type="void"> </return> <description> + Initializes the visual server. </description> </method> <method name="make_sphere_mesh"> @@ -914,12 +993,14 @@ <argument index="2" name="radius" type="float"> </argument> <description> + Returns a mesh of a sphere with the given amount of horizontal and vertical subdivisions. </description> </method> <method name="material_create"> <return type="RID"> </return> <description> + Returns an empty material. </description> </method> <method name="material_get_param" qualifiers="const"> @@ -930,6 +1011,7 @@ <argument index="1" name="parameter" type="String"> </argument> <description> + Returns the value of a certain material's parameter. </description> </method> <method name="material_get_shader" qualifiers="const"> @@ -938,6 +1020,7 @@ <argument index="0" name="shader_material" type="RID"> </argument> <description> + Returns the shader of a certain material's shader. Returns an empty RID if the material doesn't have a shader. </description> </method> <method name="material_set_line_width"> @@ -948,6 +1031,7 @@ <argument index="1" name="width" type="float"> </argument> <description> + Sets a materials line width. </description> </method> <method name="material_set_next_pass"> @@ -958,6 +1042,7 @@ <argument index="1" name="next_material" type="RID"> </argument> <description> + Sets an objects next material. </description> </method> <method name="material_set_param"> @@ -970,6 +1055,7 @@ <argument index="2" name="value" type="Variant"> </argument> <description> + Sets a materials parameter. </description> </method> <method name="material_set_render_priority"> @@ -980,6 +1066,7 @@ <argument index="1" name="priority" type="int"> </argument> <description> + Sets a material's render priority. </description> </method> <method name="material_set_shader"> @@ -990,6 +1077,7 @@ <argument index="1" name="shader" type="RID"> </argument> <description> + Sets a shader material's shader. </description> </method> <method name="mesh_add_surface_from_arrays"> @@ -1006,6 +1094,7 @@ <argument index="4" name="compress_format" type="int" default="97792"> </argument> <description> + Adds a surface generated from the Arrays to a mesh. See PRIMITIVE_TYPE_* constants for types. </description> </method> <method name="mesh_clear"> @@ -1014,12 +1103,14 @@ <argument index="0" name="mesh" type="RID"> </argument> <description> + Removes all surfaces from a mesh. </description> </method> <method name="mesh_create"> <return type="RID"> </return> <description> + Creates a new mesh. </description> </method> <method name="mesh_get_blend_shape_count" qualifiers="const"> @@ -1028,6 +1119,7 @@ <argument index="0" name="mesh" type="RID"> </argument> <description> + Returns a mesh's blend shape count. </description> </method> <method name="mesh_get_blend_shape_mode" qualifiers="const"> @@ -1036,6 +1128,7 @@ <argument index="0" name="mesh" type="RID"> </argument> <description> + Returns a mesh's blend shape mode. </description> </method> <method name="mesh_get_custom_aabb" qualifiers="const"> @@ -1044,6 +1137,7 @@ <argument index="0" name="mesh" type="RID"> </argument> <description> + Returns a mesh's custom aabb. </description> </method> <method name="mesh_get_surface_count" qualifiers="const"> @@ -1052,6 +1146,7 @@ <argument index="0" name="mesh" type="RID"> </argument> <description> + Returns a mesh's number of surfaces. </description> </method> <method name="mesh_remove_surface"> @@ -1062,6 +1157,7 @@ <argument index="1" name="index" type="int"> </argument> <description> + Removes a mesh's surface. </description> </method> <method name="mesh_set_blend_shape_count"> @@ -1072,6 +1168,7 @@ <argument index="1" name="amount" type="int"> </argument> <description> + Sets a mesh's blend shape count. </description> </method> <method name="mesh_set_blend_shape_mode"> @@ -1082,6 +1179,7 @@ <argument index="1" name="mode" type="int" enum="VisualServer.BlendShapeMode"> </argument> <description> + Sets a mesh's blend shape mode. </description> </method> <method name="mesh_set_custom_aabb"> @@ -1092,6 +1190,7 @@ <argument index="1" name="aabb" type="AABB"> </argument> <description> + Sets a mesh's custom aabb. </description> </method> <method name="mesh_surface_get_aabb" qualifiers="const"> @@ -1102,6 +1201,7 @@ <argument index="1" name="surface" type="int"> </argument> <description> + Returns a mesh's surface's aabb. </description> </method> <method name="mesh_surface_get_array" qualifiers="const"> @@ -1112,6 +1212,7 @@ <argument index="1" name="surface" type="int"> </argument> <description> + Returns a mesh's surface's vertex buffer. </description> </method> <method name="mesh_surface_get_array_index_len" qualifiers="const"> @@ -1122,6 +1223,7 @@ <argument index="1" name="surface" type="int"> </argument> <description> + Returns a mesh's surface's amount of indices. </description> </method> <method name="mesh_surface_get_array_len" qualifiers="const"> @@ -1132,6 +1234,7 @@ <argument index="1" name="surface" type="int"> </argument> <description> + Returns a mesh's surface's amount of vertices. </description> </method> <method name="mesh_surface_get_arrays" qualifiers="const"> @@ -1142,6 +1245,7 @@ <argument index="1" name="surface" type="int"> </argument> <description> + Returns a mesh's surface's buffer arrays. </description> </method> <method name="mesh_surface_get_blend_shape_arrays" qualifiers="const"> @@ -1152,6 +1256,7 @@ <argument index="1" name="surface" type="int"> </argument> <description> + Returns a mesh's surface's arrays for blend shapes </description> </method> <method name="mesh_surface_get_format" qualifiers="const"> @@ -1162,6 +1267,7 @@ <argument index="1" name="surface" type="int"> </argument> <description> + Returns the format of a mesh's surface. </description> </method> <method name="mesh_surface_get_index_array" qualifiers="const"> @@ -1172,6 +1278,7 @@ <argument index="1" name="surface" type="int"> </argument> <description> + Returns a mesh's surface's index buffer. </description> </method> <method name="mesh_surface_get_material" qualifiers="const"> @@ -1182,6 +1289,7 @@ <argument index="1" name="surface" type="int"> </argument> <description> + Returns a mesh's surface's material. </description> </method> <method name="mesh_surface_get_primitive_type" qualifiers="const"> @@ -1192,6 +1300,7 @@ <argument index="1" name="surface" type="int"> </argument> <description> + Returns the primitive type of a mesh's surface. </description> </method> <method name="mesh_surface_get_skeleton_aabb" qualifiers="const"> @@ -1202,6 +1311,7 @@ <argument index="1" name="surface" type="int"> </argument> <description> + Returns the aabb of a mesh's surface's skeleton. </description> </method> <method name="mesh_surface_set_material"> @@ -1214,6 +1324,7 @@ <argument index="2" name="material" type="RID"> </argument> <description> + Sets a mesh's surface's material. </description> </method> <method name="request_frame_drawn_callback"> @@ -1240,6 +1351,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. </description> </method> <method name="set_debug_generate_wireframes"> @@ -1262,6 +1374,7 @@ <return type="RID"> </return> <description> + Creates an empty shader. </description> </method> <method name="shader_get_code" qualifiers="const"> @@ -1270,6 +1383,7 @@ <argument index="0" name="shader" type="RID"> </argument> <description> + Returns a shader's code. </description> </method> <method name="shader_get_default_texture_param" qualifiers="const"> @@ -1280,6 +1394,7 @@ <argument index="1" name="name" type="String"> </argument> <description> + Returns a default texture from a shader searched by name. </description> </method> <method name="shader_get_param_list" qualifiers="const"> @@ -1288,6 +1403,7 @@ <argument index="0" name="shader" type="RID"> </argument> <description> + Returns the parameters of a shader. </description> </method> <method name="shader_set_code"> @@ -1298,6 +1414,7 @@ <argument index="1" name="code" type="String"> </argument> <description> + Sets a shader's code. </description> </method> <method name="shader_set_default_texture_param"> @@ -1310,12 +1427,14 @@ <argument index="2" name="texture" type="RID"> </argument> <description> + Sets a shader's default texture. Overwrites the texture given by name. </description> </method> <method name="sky_create"> <return type="RID"> </return> <description> + Creates an empty sky. </description> </method> <method name="sky_set_texture"> @@ -1328,6 +1447,7 @@ <argument index="2" name="radiance_size" type="int"> </argument> <description> + Sets a sky's texture. </description> </method> <method name="sync"> @@ -1350,12 +1470,14 @@ <argument index="4" name="flags" type="int" default="7"> </argument> <description> + Allocates space for a texture's image or video. </description> </method> <method name="texture_create"> <return type="RID"> </return> <description> + Creates an empty texture. </description> </method> <method name="texture_create_from_image"> @@ -1366,12 +1488,14 @@ <argument index="1" name="flags" type="int" default="7"> </argument> <description> + Creates a texture, allocates the space for an image, and fills in the image. </description> </method> <method name="texture_debug_usage"> <return type="Array"> </return> <description> + Returns a list of all the textures and their information. </description> </method> <method name="texture_get_data" qualifiers="const"> @@ -1382,6 +1506,7 @@ <argument index="1" name="cube_side" type="int" enum="VisualServer.CubeMapSide" default="0"> </argument> <description> + Returns a copy of a texture's image unless it's a CubeMap, in wich case it returns the [RID] of the image at one of the cubes sides. </description> </method> <method name="texture_get_flags" qualifiers="const"> @@ -1390,6 +1515,7 @@ <argument index="0" name="texture" type="RID"> </argument> <description> + Returns the flags of a texture. </description> </method> <method name="texture_get_format" qualifiers="const"> @@ -1398,6 +1524,7 @@ <argument index="0" name="texture" type="RID"> </argument> <description> + Returns the format of the texture's image. </description> </method> <method name="texture_get_height" qualifiers="const"> @@ -1406,6 +1533,7 @@ <argument index="0" name="texture" type="RID"> </argument> <description> + Returns the texture's height. </description> </method> <method name="texture_get_path" qualifiers="const"> @@ -1414,6 +1542,7 @@ <argument index="0" name="texture" type="RID"> </argument> <description> + Returns the texture's path. </description> </method> <method name="texture_get_texid" qualifiers="const"> @@ -1422,6 +1551,7 @@ <argument index="0" name="texture" type="RID"> </argument> <description> + Returns the opengl id of the texture's image. </description> </method> <method name="texture_get_width" qualifiers="const"> @@ -1430,6 +1560,7 @@ <argument index="0" name="texture" type="RID"> </argument> <description> + Returns the texture's width. </description> </method> <method name="texture_set_data"> @@ -1442,6 +1573,7 @@ <argument index="2" name="cube_side" type="int" enum="VisualServer.CubeMapSide" default="0"> </argument> <description> + Sets the texture's image data. If it's a CubeMap, it sets the image data at a cube side. </description> </method> <method name="texture_set_flags"> @@ -1452,6 +1584,7 @@ <argument index="1" name="flags" type="int"> </argument> <description> + Sets the texture's flags. See [enum TextureFlags] for options </description> </method> <method name="texture_set_path"> @@ -1462,6 +1595,7 @@ <argument index="1" name="path" type="String"> </argument> <description> + Sets the texture's path. </description> </method> <method name="texture_set_shrink_all_x2_on_set_data"> @@ -1470,6 +1604,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. </description> </method> <method name="texture_set_size_override"> @@ -1482,6 +1617,7 @@ <argument index="2" name="height" type="int"> </argument> <description> + Overwrites the texture's width and height. </description> </method> <method name="textures_keep_original"> @@ -1490,6 +1626,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. </description> </method> <method name="viewport_attach_camera"> @@ -1500,6 +1637,7 @@ <argument index="1" name="camera" type="RID"> </argument> <description> + Sets a viewport's camera. </description> </method> <method name="viewport_attach_canvas"> @@ -1510,6 +1648,7 @@ <argument index="1" name="canvas" type="RID"> </argument> <description> + Sets a viewport's canvas. </description> </method> <method name="viewport_attach_to_screen"> @@ -1522,12 +1661,14 @@ <argument index="2" name="screen" type="int" default="0"> </argument> <description> + Attaches a viewport to a screen. </description> </method> <method name="viewport_create"> <return type="RID"> </return> <description> + Creates an empty viewport. </description> </method> <method name="viewport_detach"> @@ -1536,6 +1677,7 @@ <argument index="0" name="viewport" type="RID"> </argument> <description> + Detaches the viewport from the screen. </description> </method> <method name="viewport_get_render_info"> @@ -1546,6 +1688,7 @@ <argument index="1" name="info" type="int" enum="VisualServer.ViewportRenderInfo"> </argument> <description> + Returns a viewport's render info. for options see VIEWPORT_RENDER_INFO* constants. </description> </method> <method name="viewport_get_texture" qualifiers="const"> @@ -1554,6 +1697,7 @@ <argument index="0" name="viewport" type="RID"> </argument> <description> + Returns the viewport's last rendered frame. </description> </method> <method name="viewport_remove_canvas"> @@ -1564,6 +1708,7 @@ <argument index="1" name="canvas" type="RID"> </argument> <description> + Detaches a viewport from a canvas and vice versa. </description> </method> <method name="viewport_set_active"> @@ -1574,6 +1719,7 @@ <argument index="1" name="active" type="bool"> </argument> <description> + If [code]true[/code], sets the viewport active, else sets it inactive. </description> </method> <method name="viewport_set_canvas_layer"> @@ -1586,6 +1732,7 @@ <argument index="2" name="layer" type="int"> </argument> <description> + Sets the renderlayer for a viewport's canvas. </description> </method> <method name="viewport_set_canvas_transform"> @@ -1598,6 +1745,7 @@ <argument index="2" name="offset" type="Transform2D"> </argument> <description> + Sets the transformation of a viewport's canvas. </description> </method> <method name="viewport_set_clear_mode"> @@ -1608,6 +1756,7 @@ <argument index="1" name="clear_mode" type="int" enum="VisualServer.ViewportClearMode"> </argument> <description> + Sets the clear mode of a viewport. See VIEWPORT_CLEAR_MODE_* constants for options. </description> </method> <method name="viewport_set_debug_draw"> @@ -1618,6 +1767,7 @@ <argument index="1" name="draw" type="int" enum="VisualServer.ViewportDebugDraw"> </argument> <description> + Sets the debug draw mode of a viewport. See VIEWPORT_DEBUG_DRAW_* constants for options. </description> </method> <method name="viewport_set_disable_3d"> @@ -1628,6 +1778,7 @@ <argument index="1" name="disabled" type="bool"> </argument> <description> + If [code]true[/code] a viewport's 3D rendering should be disabled. </description> </method> <method name="viewport_set_disable_environment"> @@ -1638,6 +1789,7 @@ <argument index="1" name="disabled" type="bool"> </argument> <description> + If [code]true[/code] rendering of a viewport's environment should be disabled. </description> </method> <method name="viewport_set_global_canvas_transform"> @@ -1648,6 +1800,7 @@ <argument index="1" name="transform" type="Transform2D"> </argument> <description> + Sets the viewport's global transformation matrix. </description> </method> <method name="viewport_set_hdr"> @@ -1658,6 +1811,7 @@ <argument index="1" name="enabled" type="bool"> </argument> <description> + If [code]true[/code] the viewport should render to hdr. </description> </method> <method name="viewport_set_hide_canvas"> @@ -1668,6 +1822,7 @@ <argument index="1" name="hidden" type="bool"> </argument> <description> + If [code]true[/code] the viewport's canvas should not be rendered. </description> </method> <method name="viewport_set_hide_scenario"> @@ -1688,6 +1843,7 @@ <argument index="1" name="msaa" type="int" enum="VisualServer.ViewportMSAA"> </argument> <description> + Sets the anti-aliasing mode. see [enum ViewportMSAA] for options. </description> </method> <method name="viewport_set_parent_viewport"> @@ -1698,6 +1854,7 @@ <argument index="1" name="parent_viewport" type="RID"> </argument> <description> + Sets the viewport's parent to another viewport. </description> </method> <method name="viewport_set_scenario"> @@ -1708,6 +1865,8 @@ <argument index="1" name="scenario" type="RID"> </argument> <description> + Sets a viewport's scenario. + The scenario contains information about the [enum ScenarioDebugMode], environment information, reflection atlas etc. </description> </method> <method name="viewport_set_shadow_atlas_quadrant_subdivision"> @@ -1720,6 +1879,7 @@ <argument index="2" name="subdivision" type="int"> </argument> <description> + Sets the shadow atlas quadrant's subdivision. </description> </method> <method name="viewport_set_shadow_atlas_size"> @@ -1730,6 +1890,7 @@ <argument index="1" name="size" type="int"> </argument> <description> + Sets the size of the shadow atlas's images. </description> </method> <method name="viewport_set_size"> @@ -1742,6 +1903,7 @@ <argument index="2" name="height" type="int"> </argument> <description> + Sets the viewport's width and height. </description> </method> <method name="viewport_set_transparent_background"> @@ -1752,6 +1914,7 @@ <argument index="1" name="enabled" type="bool"> </argument> <description> + If [code]true[/code] the viewport should render its background as transparent. </description> </method> <method name="viewport_set_update_mode"> @@ -1762,6 +1925,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. </description> </method> <method name="viewport_set_usage"> @@ -1772,6 +1936,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. </description> </method> <method name="viewport_set_use_arvr"> @@ -1782,6 +1947,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]. </description> </method> <method name="viewport_set_vflip"> @@ -1792,6 +1958,7 @@ <argument index="1" name="enabled" type="bool"> </argument> <description> + If [code]true[/code] the viewport's rendering should be flipped vertically. </description> </method> </methods> @@ -1803,160 +1970,232 @@ </signals> <constants> <constant name="NO_INDEX_ARRAY" value="-1"> + Marks an error that shows that the index array is empty. </constant> <constant name="ARRAY_WEIGHTS_SIZE" value="4"> </constant> <constant name="CANVAS_ITEM_Z_MIN" value="-4096"> + The minimum Z-layer for canvas items. </constant> <constant name="CANVAS_ITEM_Z_MAX" value="4096"> + The maximum Z-layer for canvas items. </constant> <constant name="MAX_GLOW_LEVELS" value="7"> </constant> <constant name="MAX_CURSORS" value="8"> </constant> <constant name="MATERIAL_RENDER_PRIORITY_MIN" value="-128"> + The minimum renderpriority of all materials. </constant> <constant name="MATERIAL_RENDER_PRIORITY_MAX" value="127"> + The maximum renderpriority of all materials. </constant> <constant name="CUBEMAP_LEFT" value="0" enum="CubeMapSide"> + Marks the left side of a cubemap. </constant> <constant name="CUBEMAP_RIGHT" value="1" enum="CubeMapSide"> + Marks the right side of a cubemap. </constant> <constant name="CUBEMAP_BOTTOM" value="2" enum="CubeMapSide"> + Marks the bottom side of a cubemap. </constant> <constant name="CUBEMAP_TOP" value="3" enum="CubeMapSide"> + Marks the top side of a cubemap. </constant> <constant name="CUBEMAP_FRONT" value="4" enum="CubeMapSide"> + Marks the front side of a cubemap. </constant> <constant name="CUBEMAP_BACK" value="5" enum="CubeMapSide"> + Marks the back side of a cubemap. </constant> <constant name="TEXTURE_FLAG_MIPMAPS" value="1" enum="TextureFlags"> + Generate mipmaps, which are smaller versions of the same texture to use when zoomed out, keeping the aspect ratio. </constant> <constant name="TEXTURE_FLAG_REPEAT" value="2" enum="TextureFlags"> + Repeat (instead of clamp to edge). </constant> <constant name="TEXTURE_FLAG_FILTER" value="4" enum="TextureFlags"> + Turn on magnifying filter, to enable smooth zooming in of the texture. </constant> <constant name="TEXTURE_FLAG_ANISOTROPIC_FILTER" value="8" enum="TextureFlags"> + Anisotropic mipmap filtering. Generates smaller versions of the same texture with different aspect ratios. + More effective on planes often shown going to the horrizon as those textures (Walls or Ground for example) get squashed in the viewport to different aspect ratios and regular mipmaps keep the aspect ratio so they don't optimize storage that well in those cases. </constant> <constant name="TEXTURE_FLAG_CONVERT_TO_LINEAR" value="16" enum="TextureFlags"> + Converts texture to SRGB color space. </constant> <constant name="TEXTURE_FLAG_MIRRORED_REPEAT" value="32" enum="TextureFlags"> + Repeat texture with alternate sections mirrored. </constant> <constant name="TEXTURE_FLAG_CUBEMAP" value="2048" enum="TextureFlags"> + Texture is a cubemap. </constant> <constant name="TEXTURE_FLAG_USED_FOR_STREAMING" value="4096" enum="TextureFlags"> + Texture is a video surface. </constant> <constant name="TEXTURE_FLAGS_DEFAULT" value="7" enum="TextureFlags"> + Default flags. Generate mipmaps, repeat, and filter are enabled. </constant> <constant name="SHADER_SPATIAL" value="0" enum="ShaderMode"> + Shader is a 3D shader. </constant> <constant name="SHADER_CANVAS_ITEM" value="1" enum="ShaderMode"> + Shader is a 2D shader. </constant> <constant name="SHADER_PARTICLES" value="2" enum="ShaderMode"> + Shader is a particle shader. </constant> <constant name="SHADER_MAX" value="3" enum="ShaderMode"> + Marks maximum of the shader types array. used internally. </constant> <constant name="ARRAY_VERTEX" value="0" enum="ArrayType"> + Array is a vertex array. </constant> <constant name="ARRAY_NORMAL" value="1" enum="ArrayType"> + Array is a normal array. </constant> <constant name="ARRAY_TANGENT" value="2" enum="ArrayType"> + Array is a tangent array. </constant> <constant name="ARRAY_COLOR" value="3" enum="ArrayType"> + Array is a color array. </constant> <constant name="ARRAY_TEX_UV" value="4" enum="ArrayType"> + Array is a uv coordinates array. </constant> <constant name="ARRAY_TEX_UV2" value="5" enum="ArrayType"> + Array is a uv coordinates array for the second uv coordinates. </constant> <constant name="ARRAY_BONES" value="6" enum="ArrayType"> + Array contains bone information. </constant> <constant name="ARRAY_WEIGHTS" value="7" enum="ArrayType"> + Array is weight information. </constant> <constant name="ARRAY_INDEX" value="8" enum="ArrayType"> + Array is index array. </constant> <constant name="ARRAY_MAX" value="9" enum="ArrayType"> + Marks the maximum of the array types. Used internally. </constant> <constant name="ARRAY_FORMAT_VERTEX" value="1" enum="ArrayFormat"> + Flag used to mark a vertex array. </constant> <constant name="ARRAY_FORMAT_NORMAL" value="2" enum="ArrayFormat"> + Flag used to mark a normal array. </constant> <constant name="ARRAY_FORMAT_TANGENT" value="4" enum="ArrayFormat"> + Flag used to mark a tangent array. </constant> <constant name="ARRAY_FORMAT_COLOR" value="8" enum="ArrayFormat"> + Flag used to mark a color array. </constant> <constant name="ARRAY_FORMAT_TEX_UV" value="16" enum="ArrayFormat"> + Flag used to mark a uv coordinates array. </constant> <constant name="ARRAY_FORMAT_TEX_UV2" value="32" enum="ArrayFormat"> + Flag used to mark a uv coordinates array for the second uv coordinates. </constant> <constant name="ARRAY_FORMAT_BONES" value="64" enum="ArrayFormat"> + Flag used to mark a bone information array. </constant> <constant name="ARRAY_FORMAT_WEIGHTS" value="128" enum="ArrayFormat"> + Flag used to mark a weights array. </constant> <constant name="ARRAY_FORMAT_INDEX" value="256" enum="ArrayFormat"> + Flag used to mark a index array. </constant> <constant name="ARRAY_COMPRESS_VERTEX" value="512" enum="ArrayFormat"> + Flag used to mark a compressed (half float) vertex array. </constant> <constant name="ARRAY_COMPRESS_NORMAL" value="1024" enum="ArrayFormat"> + Flag used to mark a compressed (half float) normal array. </constant> <constant name="ARRAY_COMPRESS_TANGENT" value="2048" enum="ArrayFormat"> + Flag used to mark a compressed (half float) tangent array. </constant> <constant name="ARRAY_COMPRESS_COLOR" value="4096" enum="ArrayFormat"> + Flag used to mark a compressed (half float) color array. </constant> <constant name="ARRAY_COMPRESS_TEX_UV" value="8192" enum="ArrayFormat"> + Flag used to mark a compressed (half float) uv coordinates array. </constant> <constant name="ARRAY_COMPRESS_TEX_UV2" value="16384" enum="ArrayFormat"> + Flag used to mark a compressed (half float) uv coordinates array for the second uv coordinates. </constant> <constant name="ARRAY_COMPRESS_BONES" value="32768" enum="ArrayFormat"> </constant> <constant name="ARRAY_COMPRESS_WEIGHTS" value="65536" enum="ArrayFormat"> + Flag used to mark a compressed (half float) weight array. </constant> <constant name="ARRAY_COMPRESS_INDEX" value="131072" enum="ArrayFormat"> </constant> <constant name="ARRAY_FLAG_USE_2D_VERTICES" value="262144" enum="ArrayFormat"> + Flag used to mark that the array contains 2D vertices. </constant> <constant name="ARRAY_FLAG_USE_16_BIT_BONES" value="524288" enum="ArrayFormat"> + Flag used to mark that the array uses 16 bit bones instead of 8 bit. </constant> <constant name="ARRAY_COMPRESS_DEFAULT" value="97792" enum="ArrayFormat"> + Used to set flags ARRAY_COMPRESS_VERTEX, ARRAY_COMPRESS_NORMAL, ARRAY_COMPRESS_TANGENT, ARRAY_COMPRESS_COLOR, ARRAY_COMPRESS_TEX_UV, ARRAY_COMPRESS_TEX_UV2 and ARRAY_COMPRESS_WEIGHTS quickly. </constant> <constant name="PRIMITIVE_POINTS" value="0" enum="PrimitiveType"> + Primitive to draw consists of points. </constant> <constant name="PRIMITIVE_LINES" value="1" enum="PrimitiveType"> + Primitive to draw consists of lines. </constant> <constant name="PRIMITIVE_LINE_STRIP" value="2" enum="PrimitiveType"> + Primitive to draw consists of a line strip from start to end. </constant> <constant name="PRIMITIVE_LINE_LOOP" value="3" enum="PrimitiveType"> + Primitive to draw consists of a line loop (a line strip with a line between the last and the first vertex). </constant> <constant name="PRIMITIVE_TRIANGLES" value="4" enum="PrimitiveType"> + Primitive to draw consists of triangles. </constant> <constant name="PRIMITIVE_TRIANGLE_STRIP" value="5" enum="PrimitiveType"> + Primitive to draw consists of a triangle strip (the last 3 verticies are always combined to make a triangle). </constant> <constant name="PRIMITIVE_TRIANGLE_FAN" value="6" enum="PrimitiveType"> + Primitive to draw consists of a triangle strip (the last 2 verticies are always combined with the first to make a triangle). </constant> <constant name="PRIMITIVE_MAX" value="7" enum="PrimitiveType"> + Marks the primitive types endpoint. used internally. </constant> <constant name="BLEND_SHAPE_MODE_NORMALIZED" value="0" enum="BlendShapeMode"> </constant> <constant name="BLEND_SHAPE_MODE_RELATIVE" value="1" enum="BlendShapeMode"> </constant> <constant name="LIGHT_DIRECTIONAL" value="0" enum="LightType"> + Is a directional (sun) light. </constant> <constant name="LIGHT_OMNI" value="1" enum="LightType"> + is an omni light. </constant> <constant name="LIGHT_SPOT" value="2" enum="LightType"> + is an spot light. </constant> <constant name="LIGHT_PARAM_ENERGY" value="0" enum="LightParam"> + The light's energy. </constant> <constant name="LIGHT_PARAM_SPECULAR" value="2" enum="LightParam"> + The light's influence on specularity. </constant> <constant name="LIGHT_PARAM_RANGE" value="3" enum="LightParam"> + The light's range. </constant> <constant name="LIGHT_PARAM_ATTENUATION" value="4" enum="LightParam"> + The light's attenuation. </constant> <constant name="LIGHT_PARAM_SPOT_ANGLE" value="5" enum="LightParam"> + The spotlight's angle. </constant> <constant name="LIGHT_PARAM_SPOT_ATTENUATION" value="6" enum="LightParam"> + The spotlight's attenuation. </constant> <constant name="LIGHT_PARAM_CONTACT_SHADOW_SIZE" value="7" enum="LightParam"> + Scales the shadow color. </constant> <constant name="LIGHT_PARAM_SHADOW_MAX_DISTANCE" value="8" enum="LightParam"> </constant> @@ -1973,6 +2212,7 @@ <constant name="LIGHT_PARAM_SHADOW_BIAS_SPLIT_SCALE" value="14" enum="LightParam"> </constant> <constant name="LIGHT_PARAM_MAX" value="15" enum="LightParam"> + The light parameters endpoint. Used internally. </constant> <constant name="VIEWPORT_UPDATE_DISABLED" value="0" enum="ViewportUpdateMode"> </constant> @@ -1983,28 +2223,40 @@ <constant name="VIEWPORT_UPDATE_ALWAYS" value="3" enum="ViewportUpdateMode"> </constant> <constant name="VIEWPORT_CLEAR_ALWAYS" value="0" enum="ViewportClearMode"> + The viewport is always cleared before drawing. </constant> <constant name="VIEWPORT_CLEAR_NEVER" value="1" enum="ViewportClearMode"> + The viewport is never cleared before drawing. </constant> <constant name="VIEWPORT_CLEAR_ONLY_NEXT_FRAME" value="2" enum="ViewportClearMode"> + The viewport is cleared once, then the clear mode is set to [VIEWPORT_CLEAR_NEVER]. </constant> <constant name="VIEWPORT_MSAA_DISABLED" value="0" enum="ViewportMSAA"> + Multisample antialiasing is disabled. </constant> <constant name="VIEWPORT_MSAA_2X" value="1" enum="ViewportMSAA"> + Multisample antialiasing is set to 2X. </constant> <constant name="VIEWPORT_MSAA_4X" value="2" enum="ViewportMSAA"> + Multisample antialiasing is set to 4X. </constant> <constant name="VIEWPORT_MSAA_8X" value="3" enum="ViewportMSAA"> + Multisample antialiasing is set to 8X. </constant> <constant name="VIEWPORT_MSAA_16X" value="4" enum="ViewportMSAA"> + Multisample antialiasing is set to 16X. </constant> <constant name="VIEWPORT_USAGE_2D" value="0" enum="ViewportUsage"> + The Viewport does not render 3D but samples. </constant> <constant name="VIEWPORT_USAGE_2D_NO_SAMPLING" value="1" enum="ViewportUsage"> + The Viewport does not render 3D and does not sample. </constant> <constant name="VIEWPORT_USAGE_3D" value="2" enum="ViewportUsage"> + The Viewport renders 3D with effects. </constant> <constant name="VIEWPORT_USAGE_3D_NO_EFFECTS" value="3" enum="ViewportUsage"> + The Viewport renders 3D but without effects. </constant> <constant name="VIEWPORT_RENDER_INFO_OBJECTS_IN_FRAME" value="0" enum="ViewportRenderInfo"> </constant> @@ -2019,14 +2271,19 @@ <constant name="VIEWPORT_RENDER_INFO_DRAW_CALLS_IN_FRAME" value="5" enum="ViewportRenderInfo"> </constant> <constant name="VIEWPORT_RENDER_INFO_MAX" value="6" enum="ViewportRenderInfo"> + Marks end of VIEWPORT_RENDER_INFO* constants. Used internally. </constant> <constant name="VIEWPORT_DEBUG_DRAW_DISABLED" value="0" enum="ViewportDebugDraw"> + Debug draw is disabled. Default setting. </constant> <constant name="VIEWPORT_DEBUG_DRAW_UNSHADED" value="1" enum="ViewportDebugDraw"> + Debug draw sets objects to unshaded. </constant> <constant name="VIEWPORT_DEBUG_DRAW_OVERDRAW" value="2" enum="ViewportDebugDraw"> + Overwrites clear color to [code](0,0,0,0)[/code]. </constant> <constant name="VIEWPORT_DEBUG_DRAW_WIREFRAME" value="3" enum="ViewportDebugDraw"> + Debug draw draws objects in wireframe. </constant> <constant name="SCENARIO_DEBUG_DISABLED" value="0" enum="ScenarioDebugMode"> </constant> @@ -2037,38 +2294,53 @@ <constant name="SCENARIO_DEBUG_SHADELESS" value="3" enum="ScenarioDebugMode"> </constant> <constant name="INSTANCE_NONE" value="0" enum="InstanceType"> + The instance does not have a type. </constant> <constant name="INSTANCE_MESH" value="1" enum="InstanceType"> + The instance is a mesh. </constant> <constant name="INSTANCE_MULTIMESH" value="2" enum="InstanceType"> + The instance is a multimesh. </constant> <constant name="INSTANCE_IMMEDIATE" value="3" enum="InstanceType"> + The instance is an immediate geometry. </constant> <constant name="INSTANCE_PARTICLES" value="4" enum="InstanceType"> + The instance is a particle emitter. </constant> <constant name="INSTANCE_LIGHT" value="5" enum="InstanceType"> + The instance is a light. </constant> <constant name="INSTANCE_REFLECTION_PROBE" value="6" enum="InstanceType"> </constant> <constant name="INSTANCE_GI_PROBE" value="7" enum="InstanceType"> </constant> <constant name="INSTANCE_MAX" value="8" enum="InstanceType"> + The max value for INSTANCE_* constants, used internally. </constant> <constant name="INSTANCE_GEOMETRY_MASK" value="30" enum="InstanceType"> + A combination of the flags of geometry instances (mesh, multimesh, immediate and particles). </constant> <constant name="NINE_PATCH_STRETCH" value="0" enum="NinePatchAxisMode"> + The nine patch gets stretched where needed. </constant> <constant name="NINE_PATCH_TILE" value="1" enum="NinePatchAxisMode"> + The nine patch gets filled with tiles where needed. </constant> <constant name="NINE_PATCH_TILE_FIT" value="2" enum="NinePatchAxisMode"> + The nine patch gets filled with tiles where needed and stretches them a bit if needed. </constant> <constant name="CANVAS_LIGHT_MODE_ADD" value="0" enum="CanvasLightMode"> + Adds light color additive to the canvas. </constant> <constant name="CANVAS_LIGHT_MODE_SUB" value="1" enum="CanvasLightMode"> + Adds light color subtractive to the canvas. </constant> <constant name="CANVAS_LIGHT_MODE_MIX" value="2" enum="CanvasLightMode"> + The light adds color depending on transparency. </constant> <constant name="CANVAS_LIGHT_MODE_MASK" value="3" enum="CanvasLightMode"> + The light adds color depending on mask. </constant> <constant name="CANVAS_LIGHT_FILTER_NONE" value="0" enum="CanvasLightShadowFilter"> </constant> @@ -2083,34 +2355,46 @@ <constant name="CANVAS_LIGHT_FILTER_PCF13" value="5" enum="CanvasLightShadowFilter"> </constant> <constant name="CANVAS_OCCLUDER_POLYGON_CULL_DISABLED" value="0" enum="CanvasOccluderPolygonCullMode"> + Culling of the canvas occluder is disabled. </constant> <constant name="CANVAS_OCCLUDER_POLYGON_CULL_CLOCKWISE" value="1" enum="CanvasOccluderPolygonCullMode"> + Culling of the canvas occluder is clockwise. </constant> <constant name="CANVAS_OCCLUDER_POLYGON_CULL_COUNTER_CLOCKWISE" value="2" enum="CanvasOccluderPolygonCullMode"> + Culling of the canvas occluder is counterclockwise. </constant> <constant name="INFO_OBJECTS_IN_FRAME" value="0" enum="RenderInfo"> + The amount of objects in the frame. </constant> <constant name="INFO_VERTICES_IN_FRAME" value="1" enum="RenderInfo"> + The amount of vertices in the frame. </constant> <constant name="INFO_MATERIAL_CHANGES_IN_FRAME" value="2" enum="RenderInfo"> + The amount of modified materials in the frame. </constant> <constant name="INFO_SHADER_CHANGES_IN_FRAME" value="3" enum="RenderInfo"> + The amount of shader rebinds in the frame. </constant> <constant name="INFO_SURFACE_CHANGES_IN_FRAME" value="4" enum="RenderInfo"> + The amount of surface changes in the frame. </constant> <constant name="INFO_DRAW_CALLS_IN_FRAME" value="5" enum="RenderInfo"> + The amount of draw calls in frame. </constant> <constant name="INFO_USAGE_VIDEO_MEM_TOTAL" value="6" enum="RenderInfo"> </constant> <constant name="INFO_VIDEO_MEM_USED" value="7" enum="RenderInfo"> + The amount of vertex memory and texture memory used. </constant> <constant name="INFO_TEXTURE_MEM_USED" value="8" enum="RenderInfo"> + The amount of texture memory used. </constant> <constant name="INFO_VERTEX_MEM_USED" value="9" enum="RenderInfo"> + The amount of vertex memory used. </constant> <constant name="FEATURE_SHADERS" value="0" enum="Features"> </constant> <constant name="FEATURE_MULTITHREADED" value="1" enum="Features"> </constant> </constants> -</class> +</class>
\ No newline at end of file diff --git a/drivers/gles3/rasterizer_canvas_gles3.cpp b/drivers/gles3/rasterizer_canvas_gles3.cpp index 0839f930c9..309497c938 100644 --- a/drivers/gles3/rasterizer_canvas_gles3.cpp +++ b/drivers/gles3/rasterizer_canvas_gles3.cpp @@ -527,7 +527,9 @@ void RasterizerCanvasGLES3::_canvas_item_render_commands(Item *p_item, Item *cur _draw_generic(GL_TRIANGLE_STRIP, pline->triangles.size(), pline->triangles.ptr(), NULL, pline->triangle_colors.ptr(), pline->triangle_colors.size() == 1); #ifdef GLES_OVER_GL glEnable(GL_LINE_SMOOTH); - if (pline->lines.size()) { + if (pline->multiline) { + //needs to be different + } else { _draw_generic(GL_LINE_LOOP, pline->lines.size(), pline->lines.ptr(), NULL, pline->line_colors.ptr(), pline->line_colors.size() == 1); } glDisable(GL_LINE_SMOOTH); @@ -538,7 +540,23 @@ void RasterizerCanvasGLES3::_canvas_item_render_commands(Item *p_item, Item *cur if (pline->antialiased) glEnable(GL_LINE_SMOOTH); #endif - _draw_generic(GL_LINE_STRIP, pline->lines.size(), pline->lines.ptr(), NULL, pline->line_colors.ptr(), pline->line_colors.size() == 1); + + if (pline->multiline) { + int todo = pline->lines.size() / 2; + int max_per_call = data.polygon_buffer_size / (sizeof(real_t) * 4); + int offset = 0; + + while (todo) { + int to_draw = MIN(max_per_call, todo); + _draw_generic(GL_LINES, to_draw * 2, &pline->lines.ptr()[offset], NULL, pline->line_colors.size() == 1 ? pline->line_colors.ptr() : &pline->line_colors.ptr()[offset], pline->line_colors.size() == 1); + todo -= to_draw; + offset += to_draw * 2; + } + + } else { + + _draw_generic(GL_LINES, pline->lines.size(), pline->lines.ptr(), NULL, pline->line_colors.ptr(), pline->line_colors.size() == 1); + } #ifdef GLES_OVER_GL if (pline->antialiased) @@ -1705,6 +1723,7 @@ void RasterizerCanvasGLES3::initialize() { glBindBuffer(GL_ARRAY_BUFFER, data.polygon_buffer); glBufferData(GL_ARRAY_BUFFER, poly_size, NULL, GL_DYNAMIC_DRAW); //allocate max size glBindBuffer(GL_ARRAY_BUFFER, 0); + data.polygon_buffer_size = poly_size; //quad arrays for (int i = 0; i < 4; i++) { diff --git a/drivers/gles3/shader_compiler_gles3.cpp b/drivers/gles3/shader_compiler_gles3.cpp index 325df8e4f1..05381da9b9 100644 --- a/drivers/gles3/shader_compiler_gles3.cpp +++ b/drivers/gles3/shader_compiler_gles3.cpp @@ -81,6 +81,16 @@ static int _get_datatype_size(SL::DataType p_type) { ERR_FAIL_V(0); } +static String _interpstr(SL::DataInterpolation p_interp) { + + switch (p_interp) { + case SL::INTERPOLATION_FLAT: return "flat "; + case SL::INTERPOLATION_NO_PERSPECTIVE: return "noperspective "; + case SL::INTERPOLATION_SMOOTH: return "smooth "; + } + return ""; +} + static String _prestr(SL::DataPrecision p_pres) { switch (p_pres) { @@ -383,12 +393,13 @@ String ShaderCompilerGLES3::_dump_node_code(SL::Node *p_node, int p_level, Gener for (Map<StringName, SL::ShaderNode::Varying>::Element *E = pnode->varyings.front(); E; E = E->next()) { String vcode; + String interp_mode = _interpstr(E->get().interpolation); vcode += _prestr(E->get().precission); vcode += _typestr(E->get().type); vcode += " " + _mkid(E->key()); vcode += ";\n"; - r_gen_code.vertex_global += "out " + vcode; - r_gen_code.fragment_global += "in " + vcode; + r_gen_code.vertex_global += interp_mode + "out " + vcode; + r_gen_code.fragment_global += interp_mode + "in " + vcode; } Map<StringName, String> function_code; diff --git a/drivers/gles3/shaders/particles.glsl b/drivers/gles3/shaders/particles.glsl index a62c124dfe..fbee08c0fe 100644 --- a/drivers/gles3/shaders/particles.glsl +++ b/drivers/gles3/shaders/particles.glsl @@ -116,7 +116,7 @@ void main() { #endif } - } else { + } else if(delta > 0.0) { if (restart_phase >= prev_system_phase) { restart=true; #ifdef USE_FRACTIONAL_DELTA diff --git a/editor/animation_editor.cpp b/editor/animation_editor.cpp index 1d70f8ba55..c6757ba98f 100644 --- a/editor/animation_editor.cpp +++ b/editor/animation_editor.cpp @@ -1124,6 +1124,8 @@ void AnimationKeyEditor::_track_editor_draw() { Ref<Texture> add_key_icon = get_icon("TrackAddKey", "EditorIcons"); Ref<Texture> add_key_icon_hl = get_icon("TrackAddKeyHl", "EditorIcons"); Ref<Texture> down_icon = get_icon("select_arrow", "Tree"); + Ref<Texture> checked = get_icon("checked", "Tree"); + Ref<Texture> unchecked = get_icon("unchecked", "Tree"); Ref<Texture> wrap_icon[2] = { get_icon("InterpWrapClamp", "EditorIcons"), @@ -1170,6 +1172,7 @@ void AnimationKeyEditor::_track_editor_draw() { v_scroll->set_page(fit); } + int left_check_ofs = checked->get_width(); int settings_limit = size.width - right_separator_ofs; int name_limit = settings_limit * name_column_ratio; @@ -1332,6 +1335,7 @@ void AnimationKeyEditor::_track_editor_draw() { valid_type = obj->get_static_property_type_indexed(leftover_path, &prop_exists); } + // Draw background color of the whole track if (/*mouse_over.over!=MouseOver::OVER_NONE &&*/ idx == mouse_over.track) { Color sepc = hover_color; te->draw_rect(Rect2(ofs + Point2(0, y), Size2(size.width, h - 1)), sepc); @@ -1343,14 +1347,20 @@ void AnimationKeyEditor::_track_editor_draw() { te->draw_rect(Rect2(ofs + Point2(0, y), Size2(size.width - 1, h - 1)), tc); } - te->draw_texture(type_icon[animation->track_get_type(idx)], ofs + Point2(0, y + (h - type_icon[0]->get_height()) / 2).floor()); + // Draw track enabled state check box + Ref<Texture> check_box = animation->track_is_enabled(idx) ? checked : unchecked; + te->draw_texture(check_box, ofs + Point2(0, y + (h - checked->get_height()) / 2).floor()); + + // Draw track type glyph and node path + te->draw_texture(type_icon[animation->track_get_type(idx)], ofs + Point2(left_check_ofs + sep, y + (h - type_icon[0]->get_height()) / 2).floor()); NodePath np = animation->track_get_path(idx); Node *n = root ? root->get_node(np) : (Node *)NULL; Color ncol = color; if (n && editor_selection->is_selected(n)) ncol = track_select_color; - te->draw_string(font, Point2(ofs + Point2(type_icon[0]->get_width() + sep, y + font->get_ascent() + (sep / 2))).floor(), np, ncol, name_limit - (type_icon[0]->get_width() + sep) - 5); + te->draw_string(font, Point2(ofs + Point2(left_check_ofs + sep + type_icon[0]->get_width() + sep, y + font->get_ascent() + (sep / 2))).floor(), np, ncol, name_limit - (type_icon[0]->get_width() + sep) - 5); + // Draw separator line below track area if (!obj) te->draw_line(ofs + Point2(0, y + h / 2), ofs + Point2(name_limit, y + h / 2), invalid_path_color); @@ -1798,6 +1808,7 @@ void AnimationKeyEditor::_track_editor_gui_input(const Ref<InputEvent> &p_input) Ref<Texture> down_icon = get_icon("select_arrow", "Tree"); Ref<Texture> hsize_icon = get_icon("Hsize", "EditorIcons"); Ref<Texture> add_key_icon = get_icon("TrackAddKey", "EditorIcons"); + Ref<Texture> check_icon = get_icon("checked", "Tree"); Ref<Texture> wrap_icon[2] = { get_icon("InterpWrapClamp", "EditorIcons"), @@ -1832,6 +1843,7 @@ void AnimationKeyEditor::_track_editor_gui_input(const Ref<InputEvent> &p_input) v_scroll->set_page(fit); } + int left_check_ofs = check_icon->get_width(); int settings_limit = size.width - right_separator_ofs; int name_limit = settings_limit * name_column_ratio; @@ -2092,7 +2104,12 @@ void AnimationKeyEditor::_track_editor_gui_input(const Ref<InputEvent> &p_input) return; } - if (mpos.x < name_limit - (type_icon[0]->get_width() / 2.0)) { + if (mpos.x < left_check_ofs) { + // Checkbox on the very left to enable/disable tracks. + + animation->track_set_enabled(idx, !animation->track_is_enabled(idx)); + + } else if (mpos.x < name_limit - (type_icon[0]->get_width() / 2.0)) { //name column // area @@ -2103,7 +2120,7 @@ void AnimationKeyEditor::_track_editor_gui_input(const Ref<InputEvent> &p_input) return; } - Rect2 area(ofs.x, ofs.y + ((int(mpos.y) / h) + 1) * h, name_limit, h); + Rect2 area(ofs.x + left_check_ofs + sep, ofs.y + ((int(mpos.y) / h) + 1) * h, name_limit - left_check_ofs - sep, h); track_name->set_text(animation->track_get_path(idx)); track_name->set_position(te->get_global_position() + area.position); track_name->set_size(area.size); diff --git a/editor/editor_plugin.cpp b/editor/editor_plugin.cpp index a39e4d6efb..5c4c2b694f 100644 --- a/editor/editor_plugin.cpp +++ b/editor/editor_plugin.cpp @@ -565,12 +565,12 @@ void EditorPlugin::save_global_state() {} void EditorPlugin::add_import_plugin(const Ref<EditorImportPlugin> &p_importer) { ResourceFormatImporter::get_singleton()->add_importer(p_importer); - EditorFileSystem::get_singleton()->scan(); + EditorFileSystem::get_singleton()->call_deferred("scan"); } void EditorPlugin::remove_import_plugin(const Ref<EditorImportPlugin> &p_importer) { ResourceFormatImporter::get_singleton()->remove_importer(p_importer); - EditorFileSystem::get_singleton()->scan(); + EditorFileSystem::get_singleton()->call_deferred("scan"); } void EditorPlugin::add_export_plugin(const Ref<EditorExportPlugin> &p_exporter) { @@ -587,7 +587,6 @@ void EditorPlugin::add_scene_import_plugin(const Ref<EditorSceneImporter> &p_imp void EditorPlugin::remove_scene_import_plugin(const Ref<EditorSceneImporter> &p_importer) { ResourceImporterScene::get_singleton()->remove_importer(p_importer); - } void EditorPlugin::set_window_layout(Ref<ConfigFile> p_layout) { diff --git a/editor/editor_settings.cpp b/editor/editor_settings.cpp index 04e09abcea..d199b27b83 100644 --- a/editor/editor_settings.cpp +++ b/editor/editor_settings.cpp @@ -348,7 +348,7 @@ void EditorSettings::_load_defaults(Ref<ConfigFile> p_extra_config) { _initial_set("text_editor/files/autosave_interval_secs", 0); _initial_set("text_editor/cursor/block_caret", false); - _initial_set("text_editor/cursor/caret_blink", false); + _initial_set("text_editor/cursor/caret_blink", true); _initial_set("text_editor/cursor/caret_blink_speed", 0.65); hints["text_editor/cursor/caret_blink_speed"] = PropertyInfo(Variant::REAL, "text_editor/cursor/caret_blink_speed", PROPERTY_HINT_RANGE, "0.1, 10, 0.1"); diff --git a/editor/filesystem_dock.cpp b/editor/filesystem_dock.cpp index ca6571fdda..9ece36ea80 100644 --- a/editor/filesystem_dock.cpp +++ b/editor/filesystem_dock.cpp @@ -806,6 +806,39 @@ void FileSystemDock::_try_move_item(const FileOrFolder &p_item, const String &p_ memdelete(da); } +void FileSystemDock::_try_duplicate_item(const FileOrFolder &p_item, const String &p_new_path) const { + //Ensure folder paths end with "/" + String old_path = (p_item.is_file || p_item.path.ends_with("/")) ? p_item.path : (p_item.path + "/"); + String new_path = (p_item.is_file || p_new_path.ends_with("/")) ? p_new_path : (p_new_path + "/"); + + if (new_path == old_path) { + return; + } else if (old_path == "res://") { + EditorNode::get_singleton()->add_io_error(TTR("Cannot move/rename resources root.")); + return; + } else if (!p_item.is_file && new_path.begins_with(old_path)) { + //This check doesn't erroneously catch renaming to a longer name as folder paths always end with "/" + EditorNode::get_singleton()->add_io_error(TTR("Cannot move a folder into itself.\n") + old_path + "\n"); + return; + } + + DirAccess *da = DirAccess::create(DirAccess::ACCESS_RESOURCES); + print_line("Duplicating " + old_path + " -> " + new_path); + Error err = da->copy(old_path, new_path); + if (err == OK) { + //Move/Rename any corresponding import settings too + if (p_item.is_file && FileAccess::exists(old_path + ".import")) { + err = da->copy(old_path + ".import", new_path + ".import"); + if (err != OK) { + EditorNode::get_singleton()->add_io_error(TTR("Error duplicating:\n") + old_path + ".import\n"); + } + } + } else { + EditorNode::get_singleton()->add_io_error(TTR("Error duplicating:\n") + old_path + "\n"); + } + memdelete(da); +} + void FileSystemDock::_update_dependencies_after_move(const Map<String, String> &p_renames) const { //The following code assumes that the following holds: // 1) EditorFileSystem contains the old paths/folder structure from before the rename/move. @@ -888,6 +921,39 @@ void FileSystemDock::_rename_operation_confirm() { _rescan(); } +void FileSystemDock::_duplicate_operation_confirm() { + + String new_name = duplicate_dialog_text->get_text().strip_edges(); + if (new_name.length() == 0) { + EditorNode::get_singleton()->show_warning(TTR("No name provided.")); + return; + } else if (new_name.find("/") != -1 || new_name.find("\\") != -1 || new_name.find(":") != -1) { + EditorNode::get_singleton()->show_warning(TTR("Name contains invalid characters.")); + return; + } + + String old_path = to_duplicate.path.ends_with("/") ? to_duplicate.path.substr(0, to_duplicate.path.length() - 1) : to_rename.path; + String new_path = old_path.get_base_dir().plus_file(new_name); + if (old_path == new_path) { + return; + } + + //Present a more user friendly warning for name conflict + DirAccess *da = DirAccess::create(DirAccess::ACCESS_RESOURCES); + if (da->file_exists(new_path) || da->dir_exists(new_path)) { + EditorNode::get_singleton()->show_warning(TTR("A file or folder with this name already exists.")); + memdelete(da); + return; + } + memdelete(da); + + _try_duplicate_item(to_duplicate, new_name); + + //Rescan everything + print_line("call rescan!"); + _rescan(); +} + void FileSystemDock::_move_operation_confirm(const String &p_to_path) { Map<String, String> renames; @@ -1003,6 +1069,27 @@ void FileSystemDock::_file_option(int p_option) { //2) warn } } break; + case FILE_DUPLICATE: { + int idx = files->get_current(); + if (idx < 0 || idx >= files->get_item_count()) + break; + + to_duplicate.path = files->get_item_metadata(idx); + to_duplicate.is_file = !to_duplicate.path.ends_with("/"); + if (to_duplicate.is_file) { + String name = to_duplicate.path.get_file(); + duplicate_dialog->set_title(TTR("Duplicating file:") + " " + name); + duplicate_dialog_text->set_text(name); + duplicate_dialog_text->select(0, name.find_last(".")); + } else { + String name = to_duplicate.path.substr(0, to_duplicate.path.length() - 1).get_file(); + duplicate_dialog->set_title(TTR("Duplicating folder:") + " " + name); + duplicate_dialog_text->set_text(name); + duplicate_dialog_text->select(0, name.length()); + } + duplicate_dialog->popup_centered_minsize(Size2(250, 80) * EDSCALE); + duplicate_dialog_text->grab_focus(); + } break; case FILE_INFO: { } break; @@ -1441,10 +1528,14 @@ void FileSystemDock::_files_list_rmb_select(int p_item, const Vector2 &p_pos) { if (!all_files_scenes && filenames.size() == 1) { file_options->add_item(TTR("Open"), FILE_OPEN); file_options->add_separator(); + } + + if (filenames.size() == 1) { file_options->add_item(TTR("Edit Dependencies.."), FILE_DEPENDENCIES); file_options->add_item(TTR("View Owners.."), FILE_OWNERS); file_options->add_separator(); } + } else if (all_folders && foldernames.size() > 0) { file_options->add_item(TTR("Open"), FILE_OPEN); file_options->add_separator(); @@ -1455,6 +1546,7 @@ void FileSystemDock::_files_list_rmb_select(int p_item, const Vector2 &p_pos) { if (num_items == 1) { file_options->add_item(TTR("Copy Path"), FILE_COPY_PATH); file_options->add_item(TTR("Rename.."), FILE_RENAME); + file_options->add_item(TTR("Duplicate.."), FILE_DUPLICATE); } file_options->add_item(TTR("Move To.."), FILE_MOVE); file_options->add_item(TTR("Delete"), FILE_REMOVE); @@ -1566,6 +1658,7 @@ void FileSystemDock::_bind_methods() { ClassDB::bind_method(D_METHOD("_make_dir_confirm"), &FileSystemDock::_make_dir_confirm); ClassDB::bind_method(D_METHOD("_move_operation_confirm"), &FileSystemDock::_move_operation_confirm); ClassDB::bind_method(D_METHOD("_rename_operation_confirm"), &FileSystemDock::_rename_operation_confirm); + ClassDB::bind_method(D_METHOD("_duplicate_operation_confirm"), &FileSystemDock::_duplicate_operation_confirm); ClassDB::bind_method(D_METHOD("_search_changed"), &FileSystemDock::_search_changed); @@ -1739,6 +1832,17 @@ FileSystemDock::FileSystemDock(EditorNode *p_editor) { rename_dialog->register_text_enter(rename_dialog_text); rename_dialog->connect("confirmed", this, "_rename_operation_confirm"); + duplicate_dialog = memnew(ConfirmationDialog); + VBoxContainer *duplicate_dialog_vb = memnew(VBoxContainer); + duplicate_dialog->add_child(duplicate_dialog_vb); + + duplicate_dialog_text = memnew(LineEdit); + duplicate_dialog_vb->add_margin_child(TTR("Name:"), duplicate_dialog_text); + duplicate_dialog->get_ok()->set_text(TTR("Duplicate")); + add_child(duplicate_dialog); + duplicate_dialog->register_text_enter(duplicate_dialog_text); + duplicate_dialog->connect("confirmed", this, "_duplicate_operation_confirm"); + make_dir_dialog = memnew(ConfirmationDialog); make_dir_dialog->set_title(TTR("Create Folder")); VBoxContainer *make_folder_dialog_vb = memnew(VBoxContainer); diff --git a/editor/filesystem_dock.h b/editor/filesystem_dock.h index b004b1974d..bc8d835ba1 100644 --- a/editor/filesystem_dock.h +++ b/editor/filesystem_dock.h @@ -70,6 +70,7 @@ private: FILE_MOVE, FILE_RENAME, FILE_REMOVE, + FILE_DUPLICATE, FILE_REIMPORT, FILE_INFO, FILE_NEW_FOLDER, @@ -120,6 +121,8 @@ private: EditorDirDialog *move_dialog; ConfirmationDialog *rename_dialog; LineEdit *rename_dialog_text; + ConfirmationDialog *duplicate_dialog; + LineEdit *duplicate_dialog_text; ConfirmationDialog *make_dir_dialog; LineEdit *make_dir_dialog_text; @@ -136,6 +139,7 @@ private: is_file(p_is_file) {} }; FileOrFolder to_rename; + FileOrFolder to_duplicate; Vector<FileOrFolder> to_move; Vector<String> history; @@ -172,10 +176,12 @@ private: void _get_all_files_in_dir(EditorFileSystemDirectory *efsd, Vector<String> &files) const; void _find_remaps(EditorFileSystemDirectory *efsd, const Map<String, String> &renames, Vector<String> &to_remaps) const; void _try_move_item(const FileOrFolder &p_item, const String &p_new_path, Map<String, String> &p_renames) const; + void _try_duplicate_item(const FileOrFolder &p_item, const String &p_new_path) const; void _update_dependencies_after_move(const Map<String, String> &p_renames) const; void _make_dir_confirm(); void _rename_operation_confirm(); + void _duplicate_operation_confirm(); void _move_operation_confirm(const String &p_to_path); void _file_option(int p_option); diff --git a/editor/import/resource_importer_scene.cpp b/editor/import/resource_importer_scene.cpp index 4ef8ec48a0..08d2897250 100644 --- a/editor/import/resource_importer_scene.cpp +++ b/editor/import/resource_importer_scene.cpp @@ -47,8 +47,6 @@ #include "scene/resources/ray_shape.h" #include "scene/resources/sphere_shape.h" - - uint32_t EditorSceneImporter::get_import_flags() const { if (get_script_instance()) { @@ -60,80 +58,73 @@ uint32_t EditorSceneImporter::get_import_flags() const { void EditorSceneImporter::get_extensions(List<String> *r_extensions) const { if (get_script_instance()) { - Array arr= get_script_instance()->call("_get_extensions"); - for(int i=0;i<arr.size();i++) { + Array arr = get_script_instance()->call("_get_extensions"); + for (int i = 0; i < arr.size(); i++) { r_extensions->push_back(arr[i]); } return; } ERR_FAIL(); - } Node *EditorSceneImporter::import_scene(const String &p_path, uint32_t p_flags, int p_bake_fps, List<String> *r_missing_deps, Error *r_err) { if (get_script_instance()) { - return get_script_instance()->call("_import_scene",p_path,p_flags,p_bake_fps); + return get_script_instance()->call("_import_scene", p_path, p_flags, p_bake_fps); } ERR_FAIL_V(NULL); - } -Ref<Animation> EditorSceneImporter::import_animation(const String &p_path, uint32_t p_flags,int p_bake_fps) { +Ref<Animation> EditorSceneImporter::import_animation(const String &p_path, uint32_t p_flags, int p_bake_fps) { if (get_script_instance()) { - return get_script_instance()->call("_import_animation",p_path,p_flags); + return get_script_instance()->call("_import_animation", p_path, p_flags); } ERR_FAIL_V(NULL); - } //for documenters, these functions are useful when an importer calls an external conversion helper (like, fbx2gltf), //and you want to load the resulting file -Node* EditorSceneImporter::import_scene_from_other_importer(const String &p_path, uint32_t p_flags, int p_bake_fps) { - - return ResourceImporterScene::get_singleton()->import_scene_from_other_importer(this,p_path,p_flags,p_bake_fps); +Node *EditorSceneImporter::import_scene_from_other_importer(const String &p_path, uint32_t p_flags, int p_bake_fps) { + return ResourceImporterScene::get_singleton()->import_scene_from_other_importer(this, p_path, p_flags, p_bake_fps); } Ref<Animation> EditorSceneImporter::import_animation_from_other_importer(const String &p_path, uint32_t p_flags, int p_bake_fps) { - return ResourceImporterScene::get_singleton()->import_animation_from_other_importer(this,p_path,p_flags,p_bake_fps); - + return ResourceImporterScene::get_singleton()->import_animation_from_other_importer(this, p_path, p_flags, p_bake_fps); } void EditorSceneImporter::_bind_methods() { - ClassDB::bind_method(D_METHOD("import_scene_from_other_importer","path","flags","bake_fps"),&EditorSceneImporter::import_scene_from_other_importer); - ClassDB::bind_method(D_METHOD("import_animation_from_other_importer","path","flags","bake_fps"),&EditorSceneImporter::import_animation_from_other_importer); + ClassDB::bind_method(D_METHOD("import_scene_from_other_importer", "path", "flags", "bake_fps"), &EditorSceneImporter::import_scene_from_other_importer); + ClassDB::bind_method(D_METHOD("import_animation_from_other_importer", "path", "flags", "bake_fps"), &EditorSceneImporter::import_animation_from_other_importer); BIND_VMETHOD(MethodInfo(Variant::INT, "_get_import_flags")); BIND_VMETHOD(MethodInfo(Variant::ARRAY, "_get_extensions")); - MethodInfo mi = MethodInfo(Variant::OBJECT, "_import_scene",PropertyInfo(Variant::STRING, "path"), PropertyInfo(Variant::INT, "flags"), PropertyInfo(Variant::INT, "bake_fps")); - mi.return_val.class_name="Node"; + MethodInfo mi = MethodInfo(Variant::OBJECT, "_import_scene", PropertyInfo(Variant::STRING, "path"), PropertyInfo(Variant::INT, "flags"), PropertyInfo(Variant::INT, "bake_fps")); + mi.return_val.class_name = "Node"; BIND_VMETHOD(mi); - mi = MethodInfo(Variant::OBJECT, "_import_animation",PropertyInfo(Variant::STRING, "path"), PropertyInfo(Variant::INT, "flags"), PropertyInfo(Variant::INT, "bake_fps")); - mi.return_val.class_name="Animation"; + mi = MethodInfo(Variant::OBJECT, "_import_animation", PropertyInfo(Variant::STRING, "path"), PropertyInfo(Variant::INT, "flags"), PropertyInfo(Variant::INT, "bake_fps")); + mi.return_val.class_name = "Animation"; BIND_VMETHOD(mi); - BIND_CONSTANT( IMPORT_SCENE ); - BIND_CONSTANT( IMPORT_ANIMATION ); - BIND_CONSTANT( IMPORT_ANIMATION_DETECT_LOOP ); - BIND_CONSTANT( IMPORT_ANIMATION_OPTIMIZE ); - BIND_CONSTANT( IMPORT_ANIMATION_FORCE_ALL_TRACKS_IN_ALL_CLIPS ); - BIND_CONSTANT( IMPORT_ANIMATION_KEEP_VALUE_TRACKS ); - BIND_CONSTANT( IMPORT_GENERATE_TANGENT_ARRAYS ); - BIND_CONSTANT( IMPORT_FAIL_ON_MISSING_DEPENDENCIES ); - BIND_CONSTANT( IMPORT_MATERIALS_IN_INSTANCES ); - BIND_CONSTANT( IMPORT_USE_COMPRESSION ); - + BIND_CONSTANT(IMPORT_SCENE); + BIND_CONSTANT(IMPORT_ANIMATION); + BIND_CONSTANT(IMPORT_ANIMATION_DETECT_LOOP); + BIND_CONSTANT(IMPORT_ANIMATION_OPTIMIZE); + BIND_CONSTANT(IMPORT_ANIMATION_FORCE_ALL_TRACKS_IN_ALL_CLIPS); + BIND_CONSTANT(IMPORT_ANIMATION_KEEP_VALUE_TRACKS); + BIND_CONSTANT(IMPORT_GENERATE_TANGENT_ARRAYS); + BIND_CONSTANT(IMPORT_FAIL_ON_MISSING_DEPENDENCIES); + BIND_CONSTANT(IMPORT_MATERIALS_IN_INSTANCES); + BIND_CONSTANT(IMPORT_USE_COMPRESSION); } - ///////////////////////////////// void EditorScenePostImport::_bind_methods() { @@ -201,6 +192,10 @@ bool ResourceImporterScene::get_option_visibility(const String &p_option, const return false; } + if (p_option == "meshes/lightmap_texel_size" && int(p_options["meshes/light_baking"]) < 2) { + return false; + } + return true; } @@ -961,6 +956,36 @@ static String _make_extname(const String &p_str) { return ext_name; } +void ResourceImporterScene::_find_meshes(Node *p_node, Map<Ref<ArrayMesh>, Transform> &meshes) { + + List<PropertyInfo> pi; + p_node->get_property_list(&pi); + + MeshInstance *mi = Object::cast_to<MeshInstance>(p_node); + + if (mi) { + + Ref<ArrayMesh> mesh = mi->get_mesh(); + + if (mesh.is_valid() && !meshes.has(mesh)) { + Spatial *s = mi; + while (s->get_parent_spatial()) { + s = s->get_parent_spatial(); + } + + if (s == mi) { + meshes[mesh] = s->get_transform(); + } else { + meshes[mesh] = s->get_transform() * mi->get_relative_transform(s); + } + } + } + for (int i = 0; i < p_node->get_child_count(); i++) { + + _find_meshes(p_node->get_child(i), meshes); + } +} + void ResourceImporterScene::_make_external_resources(Node *p_node, const String &p_base_path, bool p_make_animations, bool p_keep_animations, bool p_make_materials, bool p_keep_materials, bool p_make_meshes, Map<Ref<Animation>, Ref<Animation> > &p_animations, Map<Ref<Material>, Ref<Material> > &p_materials, Map<Ref<ArrayMesh>, Ref<ArrayMesh> > &p_meshes) { List<PropertyInfo> pi; @@ -1140,7 +1165,8 @@ void ResourceImporterScene::get_import_options(List<ImportOption> *r_options, in r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL, "meshes/compress"), true)); r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL, "meshes/ensure_tangents"), true)); r_options->push_back(ImportOption(PropertyInfo(Variant::INT, "meshes/storage", PROPERTY_HINT_ENUM, "Built-In,Files"), meshes_out ? 1 : 0)); - r_options->push_back(ImportOption(PropertyInfo(Variant::INT, "meshes/light_baking", PROPERTY_HINT_ENUM, "Disabled,Enable"), 0)); + r_options->push_back(ImportOption(PropertyInfo(Variant::INT, "meshes/light_baking", PROPERTY_HINT_ENUM, "Disabled,Enable,Gen Lightmaps"), 0)); + r_options->push_back(ImportOption(PropertyInfo(Variant::REAL, "meshes/lightmap_texel_size", PROPERTY_HINT_RANGE, "0.001,100,0.001"), 0.05)); r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL, "external_files/store_in_subdir"), false)); r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL, "animation/import", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_UPDATE_ALL_IF_MODIFIED), true)); r_options->push_back(ImportOption(PropertyInfo(Variant::REAL, "animation/fps", PROPERTY_HINT_RANGE, "1,120,1"), 15)); @@ -1171,17 +1197,16 @@ void ResourceImporterScene::_replace_owner(Node *p_node, Node *p_scene, Node *p_ Node *n = p_node->get_child(i); _replace_owner(n, p_scene, p_new_owner); } - } -Node* ResourceImporterScene::import_scene_from_other_importer(EditorSceneImporter *p_exception,const String &p_path, uint32_t p_flags, int p_bake_fps) { +Node *ResourceImporterScene::import_scene_from_other_importer(EditorSceneImporter *p_exception, const String &p_path, uint32_t p_flags, int p_bake_fps) { Ref<EditorSceneImporter> importer; String ext = p_path.get_extension().to_lower(); for (Set<Ref<EditorSceneImporter> >::Element *E = importers.front(); E; E = E->next()) { - if (E->get().ptr()==p_exception) + if (E->get().ptr() == p_exception) continue; List<String> extensions; E->get()->get_extensions(&extensions); @@ -1199,42 +1224,41 @@ Node* ResourceImporterScene::import_scene_from_other_importer(EditorSceneImporte break; } - ERR_FAIL_COND_V(!importer.is_valid(),NULL); + ERR_FAIL_COND_V(!importer.is_valid(), NULL); List<String> missing; Error err; - return importer->import_scene(p_path,p_flags,p_bake_fps,&missing,&err); + return importer->import_scene(p_path, p_flags, p_bake_fps, &missing, &err); } -Ref<Animation> ResourceImporterScene::import_animation_from_other_importer(EditorSceneImporter *p_exception,const String &p_path, uint32_t p_flags, int p_bake_fps) { - +Ref<Animation> ResourceImporterScene::import_animation_from_other_importer(EditorSceneImporter *p_exception, const String &p_path, uint32_t p_flags, int p_bake_fps) { - Ref<EditorSceneImporter> importer; - String ext = p_path.get_extension().to_lower(); + Ref<EditorSceneImporter> importer; + String ext = p_path.get_extension().to_lower(); - for (Set<Ref<EditorSceneImporter> >::Element *E = importers.front(); E; E = E->next()) { + for (Set<Ref<EditorSceneImporter> >::Element *E = importers.front(); E; E = E->next()) { - if (E->get().ptr()==p_exception) - continue; - List<String> extensions; - E->get()->get_extensions(&extensions); + if (E->get().ptr() == p_exception) + continue; + List<String> extensions; + E->get()->get_extensions(&extensions); - for (List<String>::Element *F = extensions.front(); F; F = F->next()) { + for (List<String>::Element *F = extensions.front(); F; F = F->next()) { - if (F->get().to_lower() == ext) { + if (F->get().to_lower() == ext) { - importer = E->get(); - break; - } - } + importer = E->get(); + break; + } + } - if (importer.is_valid()) - break; - } + if (importer.is_valid()) + break; + } - ERR_FAIL_COND_V(!importer.is_valid(),NULL); + ERR_FAIL_COND_V(!importer.is_valid(), NULL); - return importer->import_animation(p_path,p_flags,p_bake_fps); + return importer->import_animation(p_path, p_flags, p_bake_fps); } Error ResourceImporterScene::import(const String &p_source_file, const String &p_save_path, const Map<StringName, Variant> &p_options, List<String> *r_platform_variants, List<String> *r_gen_files) { @@ -1371,6 +1395,37 @@ Error ResourceImporterScene::import(const String &p_source_file, const String &p } } + if (light_bake_mode == 2 /* || generate LOD */) { + + Map<Ref<ArrayMesh>, Transform> meshes; + _find_meshes(scene, meshes); + + if (light_bake_mode == 2) { + + float texel_size = p_options["meshes/lightmap_texel_size"]; + texel_size = MAX(0.001, texel_size); + + EditorProgress progress("gen_lightmaps", TTR("Generating Lightmaps"), meshes.size()); + int step = 0; + for (Map<Ref<ArrayMesh>, Transform>::Element *E = meshes.front(); E; E = E->next()) { + + Ref<ArrayMesh> mesh = E->key(); + String name = mesh->get_name(); + if (name == "") { //should not happen but.. + name = "Mesh " + itos(step); + } + + progress.step(TTR("Generating for Mesh: ") + name + " (" + itos(step) + "/" + itos(meshes.size()) + ")", step); + + Error err = mesh->lightmap_unwrap(E->get(), texel_size); + if (err != OK) { + EditorNode::add_io_error("Mesh '" + name + "' failed lightmap generation. Please fix geometry."); + } + step++; + } + } + } + if (external_animations || external_materials || external_meshes) { Map<Ref<Animation>, Ref<Animation> > anim_map; Map<Ref<Material>, Ref<Material> > mat_map; diff --git a/editor/import/resource_importer_scene.h b/editor/import/resource_importer_scene.h index fc6ce05fa4..933585a48c 100644 --- a/editor/import/resource_importer_scene.h +++ b/editor/import/resource_importer_scene.h @@ -40,13 +40,13 @@ class Material; class EditorSceneImporter : public Reference { GDCLASS(EditorSceneImporter, Reference); -protected: +protected: static void _bind_methods(); - - Node* import_scene_from_other_importer(const String &p_path, uint32_t p_flags, int p_bake_fps); + Node *import_scene_from_other_importer(const String &p_path, uint32_t p_flags, int p_bake_fps); Ref<Animation> import_animation_from_other_importer(const String &p_path, uint32_t p_flags, int p_bake_fps); + public: enum ImportFlags { IMPORT_SCENE = 1, @@ -62,11 +62,10 @@ public: }; - virtual uint32_t get_import_flags() const; virtual void get_extensions(List<String> *r_extensions) const; virtual Node *import_scene(const String &p_path, uint32_t p_flags, int p_bake_fps, List<String> *r_missing_deps, Error *r_err = NULL); - virtual Ref<Animation> import_animation(const String &p_path, uint32_t p_flags,int p_bake_fps); + virtual Ref<Animation> import_animation(const String &p_path, uint32_t p_flags, int p_bake_fps); EditorSceneImporter() {} }; @@ -136,6 +135,8 @@ public: virtual bool get_option_visibility(const String &p_option, const Map<StringName, Variant> &p_options) const; virtual int get_import_order() const { return 100; } //after everything + void _find_meshes(Node *p_node, Map<Ref<ArrayMesh>, Transform> &meshes); + void _make_external_resources(Node *p_node, const String &p_base_path, bool p_make_animations, bool p_keep_animations, bool p_make_materials, bool p_keep_materials, bool p_make_meshes, Map<Ref<Animation>, Ref<Animation> > &p_animations, Map<Ref<Material>, Ref<Material> > &p_materials, Map<Ref<ArrayMesh>, Ref<ArrayMesh> > &p_meshes); Node *_fix_node(Node *p_node, Node *p_root, Map<Ref<ArrayMesh>, Ref<Shape> > &collision_map, LightBakeMode p_light_bake_mode); @@ -147,8 +148,8 @@ public: virtual Error import(const String &p_source_file, const String &p_save_path, const Map<StringName, Variant> &p_options, List<String> *r_platform_variants, List<String> *r_gen_files = NULL); - Node* import_scene_from_other_importer(EditorSceneImporter *p_exception,const String &p_path, uint32_t p_flags, int p_bake_fps); - Ref<Animation> import_animation_from_other_importer(EditorSceneImporter *p_exception,const String &p_path, uint32_t p_flags, int p_bake_fps); + Node *import_scene_from_other_importer(EditorSceneImporter *p_exception, const String &p_path, uint32_t p_flags, int p_bake_fps); + Ref<Animation> import_animation_from_other_importer(EditorSceneImporter *p_exception, const String &p_path, uint32_t p_flags, int p_bake_fps); ResourceImporterScene(); }; diff --git a/editor/plugins/asset_library_editor_plugin.cpp b/editor/plugins/asset_library_editor_plugin.cpp index eee54f3cd2..3ab8f318a7 100644 --- a/editor/plugins/asset_library_editor_plugin.cpp +++ b/editor/plugins/asset_library_editor_plugin.cpp @@ -915,6 +915,11 @@ void EditorAssetLibrary::_search(int p_page) { _api_request("asset", REQUESTING_SEARCH, args); } +void EditorAssetLibrary::_search_text_entered(const String &p_text) { + + _search(); +} + HBoxContainer *EditorAssetLibrary::_make_pages(int p_page, int p_page_count, int p_page_len, int p_total_items, int p_current_items) { HBoxContainer *hbc = memnew(HBoxContainer); @@ -1280,6 +1285,7 @@ void EditorAssetLibrary::_bind_methods() { ClassDB::bind_method("_select_category", &EditorAssetLibrary::_select_category); ClassDB::bind_method("_image_request_completed", &EditorAssetLibrary::_image_request_completed); ClassDB::bind_method("_search", &EditorAssetLibrary::_search, DEFVAL(0)); + ClassDB::bind_method("_search_text_entered", &EditorAssetLibrary::_search_text_entered); ClassDB::bind_method("_install_asset", &EditorAssetLibrary::_install_asset); ClassDB::bind_method("_manage_plugins", &EditorAssetLibrary::_manage_plugins); ClassDB::bind_method("_asset_open", &EditorAssetLibrary::_asset_open); @@ -1309,7 +1315,7 @@ EditorAssetLibrary::EditorAssetLibrary(bool p_templates_only) { filter = memnew(LineEdit); search_hb->add_child(filter); filter->set_h_size_flags(SIZE_EXPAND_FILL); - filter->connect("text_entered", this, "_search"); + filter->connect("text_entered", this, "_search_text_entered"); search = memnew(Button(TTR("Search"))); search->connect("pressed", this, "_search"); search_hb->add_child(search); diff --git a/editor/plugins/asset_library_editor_plugin.h b/editor/plugins/asset_library_editor_plugin.h index 90d597e70a..5536fbb2ec 100644 --- a/editor/plugins/asset_library_editor_plugin.h +++ b/editor/plugins/asset_library_editor_plugin.h @@ -284,6 +284,7 @@ class EditorAssetLibrary : public PanelContainer { void _search(int p_page = 0); void _rerun_search(int p_ignore); + void _search_text_entered(const String &p_text = ""); void _api_request(const String &p_request, RequestType p_request_type, const String &p_arguments = ""); void _http_request_completed(int p_status, int p_code, const PoolStringArray &headers, const PoolByteArray &p_data); void _http_download_completed(int p_status, int p_code, const PoolStringArray &headers, const PoolByteArray &p_data); diff --git a/editor/plugins/canvas_item_editor_plugin.cpp b/editor/plugins/canvas_item_editor_plugin.cpp index 8eee9c7e7c..150c184e90 100644 --- a/editor/plugins/canvas_item_editor_plugin.cpp +++ b/editor/plugins/canvas_item_editor_plugin.cpp @@ -4342,6 +4342,9 @@ CanvasItemEditor::CanvasItemEditor(EditorNode *p_editor) { drag = DRAG_NONE; bone_last_frame = 0; additive_selection = false; + + // Update the menus checkboxes + call_deferred("set_state", get_state()); } CanvasItemEditor *CanvasItemEditor::singleton = NULL; @@ -4486,15 +4489,24 @@ void CanvasItemEditorViewport::_create_nodes(Node *parent, Node *child, String & Ref<Texture> texture = Ref<Texture>(Object::cast_to<Texture>(ResourceCache::get(path))); Size2 texture_size = texture->get_size(); - editor_data->get_undo_redo().add_do_method(parent, "add_child", child); - editor_data->get_undo_redo().add_do_method(child, "set_owner", editor->get_edited_scene()); - editor_data->get_undo_redo().add_do_reference(child); - editor_data->get_undo_redo().add_undo_method(parent, "remove_child", child); + if (parent) { + editor_data->get_undo_redo().add_do_method(parent, "add_child", child); + editor_data->get_undo_redo().add_do_method(child, "set_owner", editor->get_edited_scene()); + editor_data->get_undo_redo().add_do_reference(child); + editor_data->get_undo_redo().add_undo_method(parent, "remove_child", child); + } else { // if we haven't parent, lets try to make a child as a parent. + editor_data->get_undo_redo().add_do_method(editor, "set_edited_scene", child); + editor_data->get_undo_redo().add_do_method(child, "set_owner", editor->get_edited_scene()); + editor_data->get_undo_redo().add_do_reference(child); + editor_data->get_undo_redo().add_undo_method(editor, "set_edited_scene", (Object *)NULL); + } - String new_name = parent->validate_child_name(child); - ScriptEditorDebugger *sed = ScriptEditor::get_singleton()->get_debugger(); - editor_data->get_undo_redo().add_do_method(sed, "live_debug_create_node", editor->get_edited_scene()->get_path_to(parent), child->get_class(), new_name); - editor_data->get_undo_redo().add_undo_method(sed, "live_debug_remove_node", NodePath(String(editor->get_edited_scene()->get_path_to(parent)) + "/" + new_name)); + if (parent) { + String new_name = parent->validate_child_name(child); + ScriptEditorDebugger *sed = ScriptEditor::get_singleton()->get_debugger(); + editor_data->get_undo_redo().add_do_method(sed, "live_debug_create_node", editor->get_edited_scene()->get_path_to(parent), child->get_class(), new_name); + editor_data->get_undo_redo().add_undo_method(sed, "live_debug_remove_node", NodePath(String(editor->get_edited_scene()->get_path_to(parent)) + "/" + new_name)); + } // handle with different property for texture String property = "texture"; @@ -4527,8 +4539,8 @@ void CanvasItemEditorViewport::_create_nodes(Node *parent, Node *child, String & } // locate at preview position - Point2 pos; - if (parent->has_method("get_global_position")) { + Point2 pos = Point2(0, 0); + if (parent && parent->has_method("get_global_position")) { pos = parent->call("get_global_position"); } Transform2D trans = canvas->get_canvas_transform(); @@ -4689,6 +4701,18 @@ bool CanvasItemEditorViewport::can_drop_data(const Point2 &p_point, const Varian return false; } +void CanvasItemEditorViewport::_show_resource_type_selector() { + List<BaseButton *> btn_list; + button_group->get_buttons(&btn_list); + + for (int i = 0; i < btn_list.size(); i++) { + CheckBox *check = Object::cast_to<CheckBox>(btn_list[i]); + check->set_pressed(check->get_text() == default_type); + } + selector->set_title(vformat(TTR("Add %s"), default_type)); + selector->popup_centered_minsize(); +} + void CanvasItemEditorViewport::drop_data(const Point2 &p_point, const Variant &p_data) { bool is_shift = Input::get_singleton()->is_key_pressed(KEY_SHIFT); bool is_alt = Input::get_singleton()->is_key_pressed(KEY_ALT); @@ -4705,10 +4729,8 @@ void CanvasItemEditorViewport::drop_data(const Point2 &p_point, const Variant &p if (root_node) { list.push_back(root_node); } else { - accept->get_ok()->set_text(TTR("OK :(")); - accept->set_text(TTR("No parent to instance a child at.")); - accept->popup_centered_minsize(); - _remove_preview(); + drop_pos = p_point; + _show_resource_type_selector(); return; } } @@ -4727,15 +4749,7 @@ void CanvasItemEditorViewport::drop_data(const Point2 &p_point, const Variant &p drop_pos = p_point; if (is_alt) { - List<BaseButton *> btn_list; - button_group->get_buttons(&btn_list); - - for (int i = 0; i < btn_list.size(); i++) { - CheckBox *check = Object::cast_to<CheckBox>(btn_list[i]); - check->set_pressed(check->get_text() == default_type); - } - selector->set_title(vformat(TTR("Add %s"), default_type)); - selector->popup_centered_minsize(); + _show_resource_type_selector(); } else { _perform_drop_data(); } diff --git a/editor/plugins/canvas_item_editor_plugin.h b/editor/plugins/canvas_item_editor_plugin.h index 457833e1a7..4be09a16e9 100644 --- a/editor/plugins/canvas_item_editor_plugin.h +++ b/editor/plugins/canvas_item_editor_plugin.h @@ -578,6 +578,7 @@ class CanvasItemEditorViewport : public Control { void _create_nodes(Node *parent, Node *child, String &path, const Point2 &p_point); bool _create_instance(Node *parent, String &path, const Point2 &p_point); void _perform_drop_data(); + void _show_resource_type_selector(); static void _bind_methods(); diff --git a/editor/plugins/mesh_instance_editor_plugin.cpp b/editor/plugins/mesh_instance_editor_plugin.cpp index 84fc0cecf2..9d116349c0 100644 --- a/editor/plugins/mesh_instance_editor_plugin.cpp +++ b/editor/plugins/mesh_instance_editor_plugin.cpp @@ -195,7 +195,139 @@ void MeshInstanceEditor::_menu_option(int p_option) { outline_dialog->popup_centered(Vector2(200, 90)); } break; + case MENU_OPTION_CREATE_UV2: { + + Ref<ArrayMesh> mesh = node->get_mesh(); + if (!mesh.is_valid()) { + err_dialog->set_text(TTR("Contained Mesh is not of type ArrayMesh.")); + err_dialog->popup_centered_minsize(); + return; + } + + Error err = mesh->lightmap_unwrap(node->get_global_transform()); + if (err != OK) { + err_dialog->set_text(TTR("UV Unwrap failed, mesh may not be manifold?")); + err_dialog->popup_centered_minsize(); + return; + } + + } break; + case MENU_OPTION_DEBUG_UV1: { + Ref<Mesh> mesh = node->get_mesh(); + if (!mesh.is_valid()) { + err_dialog->set_text(TTR("No mesh to debug.")); + err_dialog->popup_centered_minsize(); + return; + } + _create_uv_lines(0); + } break; + case MENU_OPTION_DEBUG_UV2: { + Ref<Mesh> mesh = node->get_mesh(); + if (!mesh.is_valid()) { + err_dialog->set_text(TTR("No mesh to debug.")); + err_dialog->popup_centered_minsize(); + return; + } + _create_uv_lines(1); + } break; + } +} + +struct MeshInstanceEditorEdgeSort { + + Vector2 a; + Vector2 b; + + bool operator<(const MeshInstanceEditorEdgeSort &p_b) const { + if (a == p_b.a) + return b < p_b.b; + else + return a < p_b.a; + } + + MeshInstanceEditorEdgeSort() {} + MeshInstanceEditorEdgeSort(const Vector2 &p_a, const Vector2 &p_b) { + if (p_a < p_b) { + a = p_a; + b = p_b; + } else { + b = p_a; + a = p_b; + } + } +}; + +void MeshInstanceEditor::_create_uv_lines(int p_layer) { + + Ref<Mesh> mesh = node->get_mesh(); + ERR_FAIL_COND(!mesh.is_valid()); + + Set<MeshInstanceEditorEdgeSort> edges; + uv_lines.clear(); + for (int i = 0; i < mesh->get_surface_count(); i++) { + if (mesh->surface_get_primitive_type(i) != Mesh::PRIMITIVE_TRIANGLES) + continue; + Array a = mesh->surface_get_arrays(i); + + PoolVector<Vector2> uv = a[p_layer == 0 ? Mesh::ARRAY_TEX_UV : Mesh::ARRAY_TEX_UV2]; + if (uv.size() == 0) { + err_dialog->set_text(TTR("Model has no UV in this layer")); + err_dialog->popup_centered_minsize(); + return; + } + + PoolVector<Vector2>::Read r = uv.read(); + + PoolVector<int> indices = a[Mesh::ARRAY_INDEX]; + PoolVector<int>::Read ri; + + int ic; + bool use_indices; + + if (indices.size()) { + ic = indices.size(); + ri = indices.read(); + use_indices = true; + } else { + ic = uv.size(); + use_indices = false; + } + + for (int j = 0; j < ic; j += 3) { + + for (int k = 0; k < 3; k++) { + + MeshInstanceEditorEdgeSort edge; + if (use_indices) { + edge.a = r[ri[j + k]]; + edge.b = r[ri[j + ((k + 1) % 3)]]; + } else { + edge.a = r[j + k]; + edge.b = r[j + ((k + 1) % 3)]; + } + + if (edges.has(edge)) + continue; + + uv_lines.push_back(edge.a); + uv_lines.push_back(edge.b); + edges.insert(edge); + } + } } + + debug_uv_dialog->popup_centered_minsize(); +} + +void MeshInstanceEditor::_debug_uv_draw() { + + if (uv_lines.size() == 0) + return; + + debug_uv->set_clip_contents(true); + debug_uv->draw_rect(Rect2(Vector2(), debug_uv->get_size()), Color(0.2, 0.2, 0.0)); + debug_uv->draw_set_transform(Vector2(), 0, debug_uv->get_size()); + debug_uv->draw_multiline(uv_lines, Color(1.0, 0.8, 0.7)); } void MeshInstanceEditor::_create_outline_mesh() { @@ -244,6 +376,7 @@ void MeshInstanceEditor::_bind_methods() { ClassDB::bind_method("_menu_option", &MeshInstanceEditor::_menu_option); ClassDB::bind_method("_create_outline_mesh", &MeshInstanceEditor::_create_outline_mesh); + ClassDB::bind_method("_debug_uv_draw", &MeshInstanceEditor::_debug_uv_draw); } MeshInstanceEditor::MeshInstanceEditor() { @@ -263,6 +396,10 @@ MeshInstanceEditor::MeshInstanceEditor() { options->get_popup()->add_item(TTR("Create Navigation Mesh"), MENU_OPTION_CREATE_NAVMESH); options->get_popup()->add_separator(); options->get_popup()->add_item(TTR("Create Outline Mesh.."), MENU_OPTION_CREATE_OUTLINE_MESH); + options->get_popup()->add_separator(); + options->get_popup()->add_item(TTR("View UV1"), MENU_OPTION_DEBUG_UV1); + options->get_popup()->add_item(TTR("View UV2"), MENU_OPTION_DEBUG_UV2); + options->get_popup()->add_item(TTR("Unwrap UV2 for Lightmap/AO"), MENU_OPTION_CREATE_UV2); options->get_popup()->connect("id_pressed", this, "_menu_option"); @@ -286,6 +423,14 @@ MeshInstanceEditor::MeshInstanceEditor() { err_dialog = memnew(AcceptDialog); add_child(err_dialog); + + debug_uv_dialog = memnew(AcceptDialog); + debug_uv_dialog->set_title("UV Channel Debug"); + add_child(debug_uv_dialog); + debug_uv = memnew(Control); + debug_uv->set_custom_minimum_size(Size2(600, 600) * EDSCALE); + debug_uv->connect("draw", this, "_debug_uv_draw"); + debug_uv_dialog->add_child(debug_uv); } void MeshInstanceEditorPlugin::edit(Object *p_object) { diff --git a/editor/plugins/mesh_instance_editor_plugin.h b/editor/plugins/mesh_instance_editor_plugin.h index fa851458ce..68c149f98a 100644 --- a/editor/plugins/mesh_instance_editor_plugin.h +++ b/editor/plugins/mesh_instance_editor_plugin.h @@ -47,6 +47,9 @@ class MeshInstanceEditor : public Node { MENU_OPTION_CREATE_CONVEX_COLLISION_SHAPE, MENU_OPTION_CREATE_NAVMESH, MENU_OPTION_CREATE_OUTLINE_MESH, + MENU_OPTION_CREATE_UV2, + MENU_OPTION_DEBUG_UV1, + MENU_OPTION_DEBUG_UV2, }; MeshInstance *node; @@ -58,11 +61,18 @@ class MeshInstanceEditor : public Node { AcceptDialog *err_dialog; + AcceptDialog *debug_uv_dialog; + Control *debug_uv; + Vector<Vector2> uv_lines; + void _menu_option(int p_option); void _create_outline_mesh(); + void _create_uv_lines(int p_layer); friend class MeshInstanceEditorPlugin; + void _debug_uv_draw(); + protected: void _node_removed(Node *p_node); static void _bind_methods(); diff --git a/editor/plugins/script_text_editor.cpp b/editor/plugins/script_text_editor.cpp index 6a869aaadb..95f2739927 100644 --- a/editor/plugins/script_text_editor.cpp +++ b/editor/plugins/script_text_editor.cpp @@ -1015,14 +1015,9 @@ void ScriptTextEditor::_edit_option(int p_op) { tx->end_complex_operation(); tx->update(); } break; - case EDIT_FOLD_LINE: { + case EDIT_TOGGLE_FOLD_LINE: { - tx->fold_line(tx->cursor_get_line()); - tx->update(); - } break; - case EDIT_UNFOLD_LINE: { - - tx->unfold_line(tx->cursor_get_line()); + tx->toggle_fold_line(tx->cursor_get_line()); tx->update(); } break; case EDIT_FOLD_ALL_LINES: { @@ -1517,13 +1512,9 @@ void ScriptTextEditor::_make_context_menu(bool p_selection, bool p_color, bool p context_menu->add_shortcut(ED_GET_SHORTCUT("script_text_editor/indent_right"), EDIT_INDENT_RIGHT); context_menu->add_shortcut(ED_GET_SHORTCUT("script_text_editor/toggle_comment"), EDIT_TOGGLE_COMMENT); } - if (p_can_fold) { - // can fold - context_menu->add_shortcut(ED_GET_SHORTCUT("script_text_editor/fold_line"), EDIT_FOLD_LINE); - } else if (p_is_folded) { - // can unfold - context_menu->add_shortcut(ED_GET_SHORTCUT("script_text_editor/unfold_line"), EDIT_UNFOLD_LINE); - } + if (p_can_fold || p_is_folded) + context_menu->add_shortcut(ED_GET_SHORTCUT("script_text_editor/toggle_fold_line"), EDIT_TOGGLE_FOLD_LINE); + if (p_color) { context_menu->add_separator(); context_menu->add_item(TTR("Pick Color"), EDIT_PICK_COLOR); @@ -1587,9 +1578,8 @@ ScriptTextEditor::ScriptTextEditor() { edit_menu->get_popup()->add_shortcut(ED_GET_SHORTCUT("script_text_editor/delete_line"), EDIT_DELETE_LINE); edit_menu->get_popup()->add_shortcut(ED_GET_SHORTCUT("script_text_editor/toggle_comment"), EDIT_TOGGLE_COMMENT); edit_menu->get_popup()->add_shortcut(ED_GET_SHORTCUT("script_text_editor/clone_down"), EDIT_CLONE_DOWN); - edit_menu->get_popup()->add_shortcut(ED_GET_SHORTCUT("script_text_editor/fold_line"), EDIT_FOLD_LINE); + edit_menu->get_popup()->add_shortcut(ED_GET_SHORTCUT("script_text_editor/toggle_fold_line"), EDIT_TOGGLE_FOLD_LINE); edit_menu->get_popup()->add_shortcut(ED_GET_SHORTCUT("script_text_editor/fold_all_lines"), EDIT_FOLD_ALL_LINES); - edit_menu->get_popup()->add_shortcut(ED_GET_SHORTCUT("script_text_editor/unfold_line"), EDIT_UNFOLD_LINE); edit_menu->get_popup()->add_shortcut(ED_GET_SHORTCUT("script_text_editor/unfold_all_lines"), EDIT_UNFOLD_ALL_LINES); edit_menu->get_popup()->add_separator(); #ifdef OSX_ENABLED @@ -1668,8 +1658,7 @@ void ScriptTextEditor::register_editor() { ED_SHORTCUT("script_text_editor/indent_right", TTR("Indent Right"), 0); ED_SHORTCUT("script_text_editor/toggle_comment", TTR("Toggle Comment"), KEY_MASK_CMD | KEY_K); ED_SHORTCUT("script_text_editor/clone_down", TTR("Clone Down"), KEY_MASK_CMD | KEY_B); - ED_SHORTCUT("script_text_editor/fold_line", TTR("Fold Line"), KEY_MASK_ALT | KEY_LEFT); - ED_SHORTCUT("script_text_editor/unfold_line", TTR("Unfold Line"), KEY_MASK_ALT | KEY_RIGHT); + ED_SHORTCUT("script_text_editor/toggle_fold_line", TTR("Fold/Unfold Line"), KEY_MASK_ALT | KEY_F); ED_SHORTCUT("script_text_editor/fold_all_lines", TTR("Fold All Lines"), 0); ED_SHORTCUT("script_text_editor/unfold_all_lines", TTR("Unfold All Lines"), 0); #ifdef OSX_ENABLED diff --git a/editor/plugins/script_text_editor.h b/editor/plugins/script_text_editor.h index 722015ef3e..e3b81e7c3f 100644 --- a/editor/plugins/script_text_editor.h +++ b/editor/plugins/script_text_editor.h @@ -91,8 +91,7 @@ class ScriptTextEditor : public ScriptEditorBase { EDIT_TO_UPPERCASE, EDIT_TO_LOWERCASE, EDIT_CAPITALIZE, - EDIT_FOLD_LINE, - EDIT_UNFOLD_LINE, + EDIT_TOGGLE_FOLD_LINE, EDIT_FOLD_ALL_LINES, EDIT_UNFOLD_ALL_LINES, SEARCH_FIND, diff --git a/editor/plugins/tile_set_editor_plugin.cpp b/editor/plugins/tile_set_editor_plugin.cpp index eb2faa1ab1..b8c57fd959 100644 --- a/editor/plugins/tile_set_editor_plugin.cpp +++ b/editor/plugins/tile_set_editor_plugin.cpp @@ -343,7 +343,7 @@ AutotileEditor::AutotileEditor(EditorNode *p_editor) { split->add_child(property_editor); helper = memnew(AutotileEditorHelper(this)); - property_editor->edit(helper); + property_editor->call_deferred("edit", helper); // Editor diff --git a/editor/property_editor.cpp b/editor/property_editor.cpp index eed1efaf9c..1d709b250a 100644 --- a/editor/property_editor.cpp +++ b/editor/property_editor.cpp @@ -430,24 +430,19 @@ bool CustomPropertyEditor::edit(Object *p_owner, const String &p_name, Variant:: } else if (hint == PROPERTY_HINT_LAYERS_2D_PHYSICS || hint == PROPERTY_HINT_LAYERS_2D_RENDER || hint == PROPERTY_HINT_LAYERS_3D_PHYSICS || hint == PROPERTY_HINT_LAYERS_3D_RENDER) { - String title; String basename; switch (hint) { case PROPERTY_HINT_LAYERS_2D_RENDER: basename = "layer_names/2d_render"; - title = "2D Render Layers"; break; case PROPERTY_HINT_LAYERS_2D_PHYSICS: basename = "layer_names/2d_physics"; - title = "2D Physics Layers"; break; case PROPERTY_HINT_LAYERS_3D_RENDER: basename = "layer_names/3d_render"; - title = "3D Render Layers"; break; case PROPERTY_HINT_LAYERS_3D_PHYSICS: basename = "layer_names/3d_physics"; - title = "3D Physics Layers"; break; } @@ -469,11 +464,7 @@ bool CustomPropertyEditor::edit(Object *p_owner, const String &p_name, Variant:: show(); - value_label[0]->set_text(title); - value_label[0]->show(); - value_label[0]->set_position(Vector2(4, 4) * EDSCALE); - - checks20gc->set_position(Vector2(4, 4) * EDSCALE + Vector2(0, value_label[0]->get_size().height + 4 * EDSCALE)); + checks20gc->set_position(Vector2(4, 4) * EDSCALE); checks20gc->set_size(checks20gc->get_minimum_size()); set_size(Vector2(4, 4) * EDSCALE + checks20gc->get_position() + checks20gc->get_size()); @@ -656,7 +647,7 @@ bool CustomPropertyEditor::edit(Object *p_owner, const String &p_name, Variant:: } } - if (type) + if (type != Variant::NIL) property_select->select_property_from_basic_type(type, v); updating = false; @@ -2811,13 +2802,12 @@ void PropertyEditor::update_tree() { TreeItem *sep = tree->create_item(root); current_category = sep; String type = p.name; - //* + if (has_icon(type, "EditorIcons")) sep->set_icon(0, get_icon(type, "EditorIcons")); else sep->set_icon(0, get_icon("Object", "EditorIcons")); - //*/ sep->set_text(0, type); sep->set_expand_right(0, true); sep->set_selectable(0, false); @@ -2943,38 +2933,36 @@ void PropertyEditor::update_tree() { } if (use_doc_hints) { - StringName setter; - StringName type; - if (ClassDB::get_setter_and_type_for_property(obj->get_class_name(), p.name, type, setter)) { - String descr; - bool found = false; - Map<StringName, Map<StringName, String> >::Element *E = descr_cache.find(type); - if (E) { + StringName classname = obj->get_class_name(); + StringName propname = p.name; + String descr; + bool found = false; - Map<StringName, String>::Element *F = E->get().find(setter); - if (F) { - found = true; - descr = F->get(); - } + Map<StringName, Map<StringName, String> >::Element *E = descr_cache.find(classname); + if (E) { + Map<StringName, String>::Element *F = E->get().find(propname); + if (F) { + found = true; + descr = F->get(); } - if (!found) { + } - DocData *dd = EditorHelp::get_doc_data(); - Map<String, DocData::ClassDoc>::Element *E = dd->class_list.find(type); - if (E) { - for (int i = 0; i < E->get().methods.size(); i++) { - if (E->get().methods[i].name == setter.operator String()) { - descr = E->get().methods[i].description.strip_edges().word_wrap(80); - } + if (!found) { + DocData *dd = EditorHelp::get_doc_data(); + Map<String, DocData::ClassDoc>::Element *E = dd->class_list.find(classname); + if (E) { + for (int i = 0; i < E->get().properties.size(); i++) { + if (E->get().properties[i].name == propname.operator String()) { + descr = E->get().properties[i].description.strip_edges().word_wrap(80); } } - - descr_cache[type][setter] = descr; } - item->set_tooltip(0, TTR("Property:") + " " + p.name + "\n\n" + descr); + descr_cache[classname][propname] = descr; } + + item->set_tooltip(0, TTR("Property:") + " " + p.name + "\n\n" + descr); } Dictionary d; diff --git a/editor/property_selector.cpp b/editor/property_selector.cpp index 86de7c56e1..77b73e4635 100644 --- a/editor/property_selector.cpp +++ b/editor/property_selector.cpp @@ -363,23 +363,6 @@ void PropertySelector::_item_selected() { at_class = ClassDB::get_parent_class(at_class); } - - if (text == String()) { - - StringName setter; - StringName type; - if (ClassDB::get_setter_and_type_for_property(class_type, name, type, setter)) { - Map<String, DocData::ClassDoc>::Element *E = dd->class_list.find(type); - if (E) { - for (int i = 0; i < E->get().methods.size(); i++) { - if (E->get().methods[i].name == setter.operator String()) { - text = E->get().methods[i].description; - } - } - } - } - } - } else { String at_class = class_type; @@ -516,6 +499,7 @@ void PropertySelector::select_property_from_script(const Ref<Script> &p_script, search_box->grab_focus(); _update_search(); } + void PropertySelector::select_property_from_basic_type(Variant::Type p_type, const String &p_current) { ERR_FAIL_COND(p_type == Variant::NIL); diff --git a/main/main.cpp b/main/main.cpp index b2f091e76a..1328807121 100644 --- a/main/main.cpp +++ b/main/main.cpp @@ -819,7 +819,7 @@ Error Main::setup(const char *execpath, int argc, char *argv[], bool p_second_ph OS::get_singleton()->_allow_hidpi = GLOBAL_DEF("display/window/dpi/allow_hidpi", false); } - use_vsync = GLOBAL_DEF("display/window/vsync/use_vsync", true); + video_mode.use_vsync = GLOBAL_DEF("display/window/vsync/use_vsync", true); GLOBAL_DEF("rendering/quality/intended_usage/framebuffer_allocation", 2); GLOBAL_DEF("rendering/quality/intended_usage/framebuffer_allocation.mobile", 3); @@ -993,8 +993,6 @@ Error Main::setup2(Thread::ID p_main_tid_override) { // also init our arvr_server from here arvr_server = memnew(ARVRServer); - OS::get_singleton()->set_use_vsync(use_vsync); - register_core_singletons(); MAIN_PRINT("Main: Setup Logo"); diff --git a/modules/bullet/bullet_physics_server.cpp b/modules/bullet/bullet_physics_server.cpp index 26c879fddb..339dccce33 100644 --- a/modules/bullet/bullet_physics_server.cpp +++ b/modules/bullet/bullet_physics_server.cpp @@ -723,15 +723,15 @@ void BulletPhysicsServer::body_set_axis_velocity(RID p_body, const Vector3 &p_ax body->set_linear_velocity(v); } -void BulletPhysicsServer::body_set_axis_lock(RID p_body, PhysicsServer::BodyAxisLock p_lock) { +void BulletPhysicsServer::body_set_axis_lock(RID p_body, int axis, bool p_lock) { RigidBodyBullet *body = rigid_body_owner.get(p_body); ERR_FAIL_COND(!body); - body->set_axis_lock(p_lock); + body->set_axis_lock(axis, p_lock); } -PhysicsServer::BodyAxisLock BulletPhysicsServer::body_get_axis_lock(RID p_body) const { +bool BulletPhysicsServer::body_get_axis_lock(RID p_body) const { const RigidBodyBullet *body = rigid_body_owner.get(p_body); - ERR_FAIL_COND_V(!body, BODY_AXIS_LOCK_DISABLED); + ERR_FAIL_COND_V(!body, 0); return body->get_axis_lock(); } diff --git a/modules/bullet/bullet_physics_server.h b/modules/bullet/bullet_physics_server.h index ad8137ee2f..ed5acb9041 100644 --- a/modules/bullet/bullet_physics_server.h +++ b/modules/bullet/bullet_physics_server.h @@ -226,8 +226,8 @@ public: virtual void body_apply_torque_impulse(RID p_body, const Vector3 &p_impulse); virtual void body_set_axis_velocity(RID p_body, const Vector3 &p_axis_velocity); - virtual void body_set_axis_lock(RID p_body, BodyAxisLock p_lock); - virtual BodyAxisLock body_get_axis_lock(RID p_body) const; + virtual void body_set_axis_lock(RID p_body, int axis, bool p_lock); + virtual bool body_get_axis_lock(RID p_body) const; virtual void body_add_collision_exception(RID p_body, RID p_body_b); virtual void body_remove_collision_exception(RID p_body, RID p_body_b); diff --git a/modules/bullet/rigid_body_bullet.cpp b/modules/bullet/rigid_body_bullet.cpp index b134bd3a36..843bdab31f 100644 --- a/modules/bullet/rigid_body_bullet.cpp +++ b/modules/bullet/rigid_body_bullet.cpp @@ -277,7 +277,7 @@ RigidBodyBullet::RigidBodyBullet() : setupBulletCollisionObject(btBody); set_mode(PhysicsServer::BODY_MODE_RIGID); - set_axis_lock(PhysicsServer::BODY_AXIS_LOCK_DISABLED); + set_axis_lock(0, locked_axis[0]); areasWhereIam.resize(maxAreasWhereIam); for (int i = areasWhereIam.size() - 1; 0 <= i; --i) { @@ -498,25 +498,25 @@ void RigidBodyBullet::set_mode(PhysicsServer::BodyMode p_mode) { switch (p_mode) { case PhysicsServer::BODY_MODE_KINEMATIC: mode = PhysicsServer::BODY_MODE_KINEMATIC; - set_axis_lock(axis_lock); // Reload axis lock + set_axis_lock(0, locked_axis[0]); // Reload axis lock _internal_set_mass(0); init_kinematic_utilities(); break; case PhysicsServer::BODY_MODE_STATIC: mode = PhysicsServer::BODY_MODE_STATIC; - set_axis_lock(axis_lock); // Reload axis lock + set_axis_lock(0, locked_axis[0]); // Reload axis lock _internal_set_mass(0); break; case PhysicsServer::BODY_MODE_RIGID: { mode = PhysicsServer::BODY_MODE_RIGID; - set_axis_lock(axis_lock); // Reload axis lock + set_axis_lock(0, locked_axis[0]); // Reload axis lock _internal_set_mass(0 == mass ? 1 : mass); scratch_space_override_modificator(); break; } case PhysicsServer::BODY_MODE_CHARACTER: { mode = PhysicsServer::BODY_MODE_CHARACTER; - set_axis_lock(axis_lock); // Reload axis lock + set_axis_lock(0, locked_axis[0]); // Reload axis lock _internal_set_mass(0 == mass ? 1 : mass); scratch_space_override_modificator(); break; @@ -655,22 +655,14 @@ Vector3 RigidBodyBullet::get_applied_torque() const { return gTotTorq; } -void RigidBodyBullet::set_axis_lock(PhysicsServer::BodyAxisLock p_lock) { - axis_lock = p_lock; +void RigidBodyBullet::set_axis_lock(int axis, bool p_lock) { + locked_axis[axis] = p_lock; - if (PhysicsServer::BODY_AXIS_LOCK_DISABLED == axis_lock) { - btBody->setLinearFactor(btVector3(1., 1., 1.)); + btBody->setLinearFactor(btVector3(locked_axis[0] ? 0 : 1., locked_axis[1] ? 0 : 1., locked_axis[2] ? 0 : 1.)); + if (locked_axis[0] || locked_axis[1] || locked_axis[2]) + btBody->setAngularFactor(btVector3(locked_axis[0] ? 1. : 0, locked_axis[1] ? 1. : 0, locked_axis[2] ? 1. : 0)); + else btBody->setAngularFactor(btVector3(1., 1., 1.)); - } else if (PhysicsServer::BODY_AXIS_LOCK_X == axis_lock) { - btBody->setLinearFactor(btVector3(0., 1., 1.)); - btBody->setAngularFactor(btVector3(1., 0., 0.)); - } else if (PhysicsServer::BODY_AXIS_LOCK_Y == axis_lock) { - btBody->setLinearFactor(btVector3(1., 0., 1.)); - btBody->setAngularFactor(btVector3(0., 1., 0.)); - } else if (PhysicsServer::BODY_AXIS_LOCK_Z == axis_lock) { - btBody->setLinearFactor(btVector3(1., 1., 0.)); - btBody->setAngularFactor(btVector3(0., 0., 1.)); - } if (PhysicsServer::BODY_MODE_CHARACTER == mode) { /// When character lock angular @@ -678,17 +670,8 @@ void RigidBodyBullet::set_axis_lock(PhysicsServer::BodyAxisLock p_lock) { } } -PhysicsServer::BodyAxisLock RigidBodyBullet::get_axis_lock() const { - btVector3 vec = btBody->getLinearFactor(); - if (0. == vec.x()) { - return PhysicsServer::BODY_AXIS_LOCK_X; - } else if (0. == vec.y()) { - return PhysicsServer::BODY_AXIS_LOCK_Y; - } else if (0. == vec.z()) { - return PhysicsServer::BODY_AXIS_LOCK_Z; - } else { - return PhysicsServer::BODY_AXIS_LOCK_DISABLED; - } +bool RigidBodyBullet::get_axis_lock() const { + return locked_axis; } void RigidBodyBullet::set_continuous_collision_detection(bool p_enable) { diff --git a/modules/bullet/rigid_body_bullet.h b/modules/bullet/rigid_body_bullet.h index c54b5784b5..fde8b21e17 100644 --- a/modules/bullet/rigid_body_bullet.h +++ b/modules/bullet/rigid_body_bullet.h @@ -184,7 +184,7 @@ private: KinematicUtilities *kinematic_utilities; PhysicsServer::BodyMode mode; - PhysicsServer::BodyAxisLock axis_lock; + bool locked_axis[3] = { false, false, false }; GodotMotionState *godotMotionState; btRigidBody *btBody; real_t mass; @@ -269,8 +269,8 @@ public: void set_applied_torque(const Vector3 &p_torque); Vector3 get_applied_torque() const; - void set_axis_lock(PhysicsServer::BodyAxisLock p_lock); - PhysicsServer::BodyAxisLock get_axis_lock() const; + void set_axis_lock(int axis, bool p_lock); + bool get_axis_lock() const; /// Doc: /// http://www.bulletphysics.org/mediawiki-1.5.8/index.php?title=Anti_tunneling_by_Motion_Clamping diff --git a/modules/gdnative/register_types.cpp b/modules/gdnative/register_types.cpp index 365def75bc..1cb35ec006 100644 --- a/modules/gdnative/register_types.cpp +++ b/modules/gdnative/register_types.cpp @@ -99,12 +99,16 @@ static Set<String> get_gdnative_singletons(EditorFileSystemDirectory *p_dir) { } static void actual_discoverer_handler() { + EditorFileSystemDirectory *dir = EditorFileSystem::get_singleton()->get_filesystem(); Set<String> file_paths = get_gdnative_singletons(dir); bool changed = false; - Array current_files = ProjectSettings::get_singleton()->get("gdnative/singletons"); + Array current_files; + if (ProjectSettings::get_singleton()->has_setting("gdnative/singletons")) { + current_files = ProjectSettings::get_singleton()->get("gdnative/singletons"); + } Array files; files.resize(file_paths.size()); int i = 0; @@ -128,7 +132,6 @@ static void actual_discoverer_handler() { if (changed) { ProjectSettings::get_singleton()->set("gdnative/singletons", files); - ProjectSettings::get_singleton()->save(); } } diff --git a/modules/gdscript/gdscript_parser.cpp b/modules/gdscript/gdscript_parser.cpp index e48b03968b..599f204184 100644 --- a/modules/gdscript/gdscript_parser.cpp +++ b/modules/gdscript/gdscript_parser.cpp @@ -3389,6 +3389,10 @@ void GDScriptParser::_parse_class(ClassNode *p_class) { _set_error("Can't export null type."); return; } + if (type == Variant::OBJECT) { + _set_error("Can't export raw object type."); + return; + } current_export.type = type; current_export.usage |= PROPERTY_USAGE_SCRIPT_VARIABLE; tokenizer->advance(); diff --git a/modules/thekla_unwrap/SCsub b/modules/thekla_unwrap/SCsub index 2b1349a15f..1d4b086848 100644 --- a/modules/thekla_unwrap/SCsub +++ b/modules/thekla_unwrap/SCsub @@ -47,7 +47,8 @@ if env['builtin_thekla_atlas']: "nvmesh/param/SingleFaceMap.cpp", "nvmesh/param/Util.cpp", "nvmesh/weld/VertexWeld.cpp", - "nvmesh/weld/Snap.cpp" + "nvmesh/weld/Snap.cpp", + "thekla/thekla_atlas.cpp" ] thirdparty_sources = [thirdparty_dir + file for file in thirdparty_sources] diff --git a/modules/thekla_unwrap/register_types.cpp b/modules/thekla_unwrap/register_types.cpp index 8a9f8341e8..01b834f8cb 100644 --- a/modules/thekla_unwrap/register_types.cpp +++ b/modules/thekla_unwrap/register_types.cpp @@ -28,7 +28,88 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ #include "register_types.h" +#include "thirdparty/thekla_atlas/thekla/thekla_atlas.h" +#include <stdio.h> +#include <stdlib.h> +extern bool (*array_mesh_lightmap_unwrap_callback)(float p_texel_size, const float *p_vertices, const float *p_normals, int p_vertex_count, const int *p_indices, const int *p_face_materials, int p_index_count, float **r_uv, int **r_vertex, int *r_vertex_count, int **r_index, int *r_index_count, int *r_size_hint_x, int *r_size_hint_y); -void register_thekla_unwrap_types() {} +bool thekla_mesh_lightmap_unwrap_callback(float p_texel_size, const float *p_vertices, const float *p_normals, int p_vertex_count, const int *p_indices, const int *p_face_materials, int p_index_count, float **r_uv, int **r_vertex, int *r_vertex_count, int **r_index, int *r_index_count, int *r_size_hint_x, int *r_size_hint_y) { -void unregister_thekla_unwrap_types() {} + //set up input mesh + Thekla::Atlas_Input_Mesh input_mesh; + input_mesh.face_array = new Thekla::Atlas_Input_Face[p_index_count / 3]; + for (int i = 0; i < p_index_count / 3; i++) { + input_mesh.face_array[i].vertex_index[0] = p_indices[i * 3 + 0]; + input_mesh.face_array[i].vertex_index[1] = p_indices[i * 3 + 1]; + input_mesh.face_array[i].vertex_index[2] = p_indices[i * 3 + 2]; + printf("face %i - %i, %i, %i - mat %i\n", i, input_mesh.face_array[i].vertex_index[0], input_mesh.face_array[i].vertex_index[1], input_mesh.face_array[i].vertex_index[2], p_face_materials[i]); + input_mesh.face_array[i].material_index = p_face_materials[i]; + } + input_mesh.vertex_array = new Thekla::Atlas_Input_Vertex[p_vertex_count]; + for (int i = 0; i < p_vertex_count; i++) { + input_mesh.vertex_array[i].first_colocal = i; //wtf + for (int j = 0; j < 3; j++) { + input_mesh.vertex_array[i].position[j] = p_vertices[i * 3 + j]; + input_mesh.vertex_array[i].normal[j] = p_normals[i * 3 + j]; + } + input_mesh.vertex_array[i].uv[0] = 0; + input_mesh.vertex_array[i].uv[1] = 0; + printf("vertex %i - %f, %f, %f\n", i, input_mesh.vertex_array[i].position[0], input_mesh.vertex_array[i].position[1], input_mesh.vertex_array[i].position[2]); + printf("normal %i - %f, %f, %f\n", i, input_mesh.vertex_array[i].normal[0], input_mesh.vertex_array[i].normal[1], input_mesh.vertex_array[i].normal[2]); + } + input_mesh.face_count = p_index_count / 3; + input_mesh.vertex_count = p_vertex_count; + + //set up options + Thekla::Atlas_Options options; + Thekla::atlas_set_default_options(&options); + options.packer_options.witness.packing_quality = 1; + options.packer_options.witness.texel_area = 1.0 / p_texel_size; + + //generate + Thekla::Atlas_Error err; + Thekla::Atlas_Output_Mesh *output = atlas_generate(&input_mesh, &options, &err); + + delete[] input_mesh.face_array; + delete[] input_mesh.vertex_array; + + if (err != Thekla::Atlas_Error_Success) { + printf("error with atlas\n"); + } else { + *r_vertex = (int *)malloc(sizeof(int) * output->vertex_count); + *r_uv = (float *)malloc(sizeof(float) * output->vertex_count * 3); + *r_index = (int *)malloc(sizeof(int) * output->index_count); + + // printf("w: %i, h: %i\n", output->atlas_width, output->atlas_height); + for (int i = 0; i < output->vertex_count; i++) { + (*r_vertex)[i] = output->vertex_array[i].xref; + (*r_uv)[i * 2 + 0] = output->vertex_array[i].uv[0] / output->atlas_width; + (*r_uv)[i * 2 + 1] = output->vertex_array[i].uv[1] / output->atlas_height; + // printf("uv: %f,%f\n", (*r_uv)[i * 2 + 0], (*r_uv)[i * 2 + 1]); + } + *r_vertex_count = output->vertex_count; + + for (int i = 0; i < output->index_count; i++) { + (*r_index)[i] = output->index_array[i]; + } + + *r_index_count = output->index_count; + + *r_size_hint_x = output->atlas_height; + *r_size_hint_y = output->atlas_width; + } + + if (output) { + atlas_free(output); + } + + return err == Thekla::Atlas_Error_Success; +} + +void register_thekla_unwrap_types() { + + array_mesh_lightmap_unwrap_callback = thekla_mesh_lightmap_unwrap_callback; +} + +void unregister_thekla_unwrap_types() { +} diff --git a/modules/visual_script/visual_script.cpp b/modules/visual_script/visual_script.cpp index bb6c32e9e0..53d93798d9 100644 --- a/modules/visual_script/visual_script.cpp +++ b/modules/visual_script/visual_script.cpp @@ -2047,6 +2047,7 @@ void VisualScriptInstance::create(const Ref<VisualScript> &p_script, Object *p_o function.argument_count = func_node->get_argument_count(); function.max_stack += function.argument_count; function.flow_stack_size = func_node->is_stack_less() ? 0 : func_node->get_stack_size(); + max_input_args = MAX(max_input_args, function.argument_count); } //multiple passes are required to set up this complex thing.. diff --git a/platform/haiku/os_haiku.cpp b/platform/haiku/os_haiku.cpp index ef5a065107..f7196755af 100644 --- a/platform/haiku/os_haiku.cpp +++ b/platform/haiku/os_haiku.cpp @@ -105,6 +105,7 @@ void OS_Haiku::initialize(const VideoMode &p_desired, int p_video_driver, int p_ context_gl = memnew(ContextGL_Haiku(window)); context_gl->initialize(); context_gl->make_current(); + context_gl->set_use_vsync(current_video_mode.use_vsync); /* Port to GLES 3 rasterizer */ //rasterizer = memnew(RasterizerGLES2); diff --git a/platform/osx/os_osx.mm b/platform/osx/os_osx.mm index 6cc8be250d..75d0bd1648 100644 --- a/platform/osx/os_osx.mm +++ b/platform/osx/os_osx.mm @@ -1089,6 +1089,8 @@ void OS_OSX::initialize(const VideoMode &p_desired, int p_video_driver, int p_au [context makeCurrentContext]; + set_use_vsync(p_desired.use_vsync); + [NSApp activateIgnoringOtherApps:YES]; _update_window(); diff --git a/platform/uwp/os_uwp.cpp b/platform/uwp/os_uwp.cpp index 1655caf04b..659f162724 100644 --- a/platform/uwp/os_uwp.cpp +++ b/platform/uwp/os_uwp.cpp @@ -241,6 +241,7 @@ void OSUWP::initialize(const VideoMode &p_desired, int p_video_driver, int p_aud RasterizerGLES3::register_config(); RasterizerGLES3::make_current(); + gl_context->set_use_vsync(vm.use_vsync); visual_server = memnew(VisualServerRaster); // FIXME: Reimplement threaded rendering? Or remove? diff --git a/platform/windows/export/export.cpp b/platform/windows/export/export.cpp index 5301aa9e95..1b6a8f4a60 100644 --- a/platform/windows/export/export.cpp +++ b/platform/windows/export/export.cpp @@ -28,11 +28,135 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ #include "editor/editor_export.h" +#include "editor/editor_settings.h" +#include "os/file_access.h" +#include "os/os.h" #include "platform/windows/logo.gen.h" +class EditorExportPlatformWindows : public EditorExportPlatformPC { + +public: + virtual Error export_project(const Ref<EditorExportPreset> &p_preset, bool p_debug, const String &p_path, int p_flags = 0); + virtual void get_export_options(List<ExportOption> *r_options); +}; + +Error EditorExportPlatformWindows::export_project(const Ref<EditorExportPreset> &p_preset, bool p_debug, const String &p_path, int p_flags) { + Error err = EditorExportPlatformPC::export_project(p_preset, p_debug, p_path, p_flags); + + if (err != OK) { + return err; + } + + String rcedit_path = EditorSettings::get_singleton()->get("export/windows/rcedit"); + + if (rcedit_path == String()) { + return OK; + } + + if (!FileAccess::exists(rcedit_path)) { + ERR_PRINTS("Could not find rcedit executable at " + rcedit_path + ", aborting."); + return ERR_FILE_NOT_FOUND; + } + +#ifndef WINDOWS_ENABLED + // On non-Windows we need WINE to run rcedit + String wine_path = EditorSettings::get_singleton()->get("export/windows/wine"); + + if (wine_path != String() && !FileAccess::exists(wine_path)) { + ERR_PRINTS("Could not find wine executable at " + wine_path + ", aborting."); + return ERR_FILE_NOT_FOUND; + } + + if (wine_path == String()) { + wine_path = "wine"; // try to run wine from PATH + } +#endif + + String icon_path = p_preset->get("application/icon"); + String file_verion = p_preset->get("application/file_version"); + String product_version = p_preset->get("application/product_version"); + String company_name = p_preset->get("application/company_name"); + String product_name = p_preset->get("application/product_name"); + String file_description = p_preset->get("application/file_description"); + String copyright = p_preset->get("application/copyright"); + String trademarks = p_preset->get("application/trademarks"); + String comments = p_preset->get("application/comments"); + + List<String> args; + args.push_back(p_path); + if (icon_path != String()) { + args.push_back("--set-icon"); + args.push_back(icon_path); + } + if (file_verion != String()) { + args.push_back("--set-file-version"); + args.push_back(file_verion); + } + if (product_version != String()) { + args.push_back("--set-product-version"); + args.push_back(product_version); + } + if (company_name != String()) { + args.push_back("--set-version-string"); + args.push_back("CompanyName"); + args.push_back(company_name); + } + if (product_name != String()) { + args.push_back("--set-version-string"); + args.push_back("ProductName"); + args.push_back(product_name); + } + if (file_description != String()) { + args.push_back("--set-version-string"); + args.push_back("FileDescription"); + args.push_back(file_description); + } + if (copyright != String()) { + args.push_back("--set-version-string"); + args.push_back("LegalCopyright"); + args.push_back(copyright); + } + if (trademarks != String()) { + args.push_back("--set-version-string"); + args.push_back("LegalTrademarks"); + args.push_back(trademarks); + } + +#ifdef WINDOWS_ENABLED + OS::get_singleton()->execute(rcedit_path, args, true); +#else + // On non-Windows we need WINE to run rcedit + args.push_front(rcedit_path); + OS::get_singleton()->execute(wine_path, args, true); +#endif + + return OK; +} + +void EditorExportPlatformWindows::get_export_options(List<ExportOption> *r_options) { + EditorExportPlatformPC::get_export_options(r_options); + + r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "application/icon", PROPERTY_HINT_GLOBAL_FILE, "*.ico"), String())); + r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "application/file_version"), String())); + r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "application/product_version"), String())); + r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "application/company_name"), String())); + r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "application/product_name"), String())); + r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "application/file_description"), String())); + r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "application/copyright"), String())); + r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "application/trademarks"), String())); +} + void register_windows_exporter() { - Ref<EditorExportPlatformPC> platform; + EDITOR_DEF("export/windows/rcedit", ""); + EditorSettings::get_singleton()->add_property_hint(PropertyInfo(Variant::STRING, "export/windows/rcedit", PROPERTY_HINT_GLOBAL_FILE, "*.exe")); +#ifndef WINDOWS_ENABLED + // On non-Windows we need WINE to run rcedit + EDITOR_DEF("export/windows/wine", ""); + EditorSettings::get_singleton()->add_property_hint(PropertyInfo(Variant::STRING, "export/windows/wine", PROPERTY_HINT_GLOBAL_FILE)); +#endif + + Ref<EditorExportPlatformWindows> platform; platform.instance(); Ref<Image> img = memnew(Image(_windows_logo)); diff --git a/platform/windows/os_windows.cpp b/platform/windows/os_windows.cpp index 79a760f055..41730d33af 100644 --- a/platform/windows/os_windows.cpp +++ b/platform/windows/os_windows.cpp @@ -1074,6 +1074,8 @@ void OS_Windows::initialize(const VideoMode &p_desired, int p_video_driver, int RasterizerGLES3::register_config(); RasterizerGLES3::make_current(); + + gl_context->set_use_vsync(video_mode.use_vsync); #endif visual_server = memnew(VisualServerRaster); diff --git a/platform/x11/os_x11.cpp b/platform/x11/os_x11.cpp index c210a03688..49a2f14bef 100644 --- a/platform/x11/os_x11.cpp +++ b/platform/x11/os_x11.cpp @@ -286,6 +286,8 @@ void OS_X11::initialize(const VideoMode &p_desired, int p_video_driver, int p_au RasterizerGLES3::make_current(); + context_gl->set_use_vsync(current_videomode.use_vsync); + #endif visual_server = memnew(VisualServerRaster); @@ -510,15 +512,14 @@ void OS_X11::initialize(const VideoMode &p_desired, int p_video_driver, int p_au power_manager = memnew(PowerX11); XEvent xevent; - while (XCheckIfEvent(x11_display, &xevent, _check_window_events, NULL)) { - _window_changed(&xevent); + while (XPending(x11_display) > 0) { + XNextEvent(x11_display, &xevent); + if (xevent.type == ConfigureNotify) { + _window_changed(&xevent); + } } } -int OS_X11::_check_window_events(Display *display, XEvent *event, char *arg) { - if (event->type == ConfigureNotify) return 1; - return 0; -} void OS_X11::xim_destroy_callback(::XIM im, ::XPointer client_data, ::XPointer call_data) { diff --git a/platform/x11/os_x11.h b/platform/x11/os_x11.h index 84dff2e089..244c69ee2b 100644 --- a/platform/x11/os_x11.h +++ b/platform/x11/os_x11.h @@ -199,7 +199,6 @@ protected: virtual void set_main_loop(MainLoop *p_main_loop); void _window_changed(XEvent *xevent); - static int _check_window_events(Display *display, XEvent *xevent, char *arg); public: virtual String get_name(); diff --git a/scene/2d/canvas_item.cpp b/scene/2d/canvas_item.cpp index 768d5185d7..82123d12ac 100644 --- a/scene/2d/canvas_item.cpp +++ b/scene/2d/canvas_item.cpp @@ -623,6 +623,29 @@ void CanvasItem::draw_polyline_colors(const Vector<Point2> &p_points, const Vect VisualServer::get_singleton()->canvas_item_add_polyline(canvas_item, p_points, p_colors, p_width, p_antialiased); } + +void CanvasItem::draw_multiline(const Vector<Point2> &p_points, const Color &p_color, float p_width, bool p_antialiased) { + + if (!drawing) { + ERR_EXPLAIN("Drawing is only allowed inside NOTIFICATION_DRAW, _draw() function or 'draw' signal."); + ERR_FAIL(); + } + + Vector<Color> colors; + colors.push_back(p_color); + VisualServer::get_singleton()->canvas_item_add_multiline(canvas_item, p_points, colors, p_width, p_antialiased); +} + +void CanvasItem::draw_multiline_colors(const Vector<Point2> &p_points, const Vector<Color> &p_colors, float p_width, bool p_antialiased) { + + if (!drawing) { + ERR_EXPLAIN("Drawing is only allowed inside NOTIFICATION_DRAW, _draw() function or 'draw' signal."); + ERR_FAIL(); + } + + VisualServer::get_singleton()->canvas_item_add_multiline(canvas_item, p_points, p_colors, p_width, p_antialiased); +} + void CanvasItem::draw_rect(const Rect2 &p_rect, const Color &p_color, bool p_filled) { if (!drawing) { @@ -979,6 +1002,8 @@ void CanvasItem::_bind_methods() { ClassDB::bind_method(D_METHOD("draw_line", "from", "to", "color", "width", "antialiased"), &CanvasItem::draw_line, DEFVAL(1.0), DEFVAL(false)); ClassDB::bind_method(D_METHOD("draw_polyline", "points", "color", "width", "antialiased"), &CanvasItem::draw_polyline, DEFVAL(1.0), DEFVAL(false)); ClassDB::bind_method(D_METHOD("draw_polyline_colors", "points", "colors", "width", "antialiased"), &CanvasItem::draw_polyline_colors, DEFVAL(1.0), DEFVAL(false)); + ClassDB::bind_method(D_METHOD("draw_multiline", "points", "color", "width", "antialiased"), &CanvasItem::draw_multiline, DEFVAL(1.0), DEFVAL(false)); + ClassDB::bind_method(D_METHOD("draw_multiline_colors", "points", "colors", "width", "antialiased"), &CanvasItem::draw_multiline_colors, DEFVAL(1.0), DEFVAL(false)); ClassDB::bind_method(D_METHOD("draw_rect", "rect", "color", "filled"), &CanvasItem::draw_rect, DEFVAL(true)); ClassDB::bind_method(D_METHOD("draw_circle", "position", "radius", "color"), &CanvasItem::draw_circle); ClassDB::bind_method(D_METHOD("draw_texture", "texture", "position", "modulate", "normal_map"), &CanvasItem::draw_texture, DEFVAL(Color(1, 1, 1, 1)), DEFVAL(Variant())); diff --git a/scene/2d/canvas_item.h b/scene/2d/canvas_item.h index ccbb528d6f..2384c0f370 100644 --- a/scene/2d/canvas_item.h +++ b/scene/2d/canvas_item.h @@ -268,6 +268,8 @@ public: void draw_line(const Point2 &p_from, const Point2 &p_to, const Color &p_color, float p_width = 1.0, bool p_antialiased = false); void draw_polyline(const Vector<Point2> &p_points, const Color &p_color, float p_width = 1.0, bool p_antialiased = false); void draw_polyline_colors(const Vector<Point2> &p_points, const Vector<Color> &p_colors, float p_width = 1.0, bool p_antialiased = false); + void draw_multiline(const Vector<Point2> &p_points, const Color &p_color, float p_width = 1.0, bool p_antialiased = false); + void draw_multiline_colors(const Vector<Point2> &p_points, const Vector<Color> &p_colors, float p_width = 1.0, bool p_antialiased = false); void draw_rect(const Rect2 &p_rect, const Color &p_color, bool p_filled = true); void draw_circle(const Point2 &p_pos, float p_radius, const Color &p_color); void draw_texture(const Ref<Texture> &p_texture, const Point2 &p_pos, const Color &p_modulate = Color(1, 1, 1, 1), const Ref<Texture> &p_normal_map = Ref<Texture>()); diff --git a/scene/2d/path_2d.cpp b/scene/2d/path_2d.cpp index e1c7331393..4029ef137b 100644 --- a/scene/2d/path_2d.cpp +++ b/scene/2d/path_2d.cpp @@ -107,34 +107,56 @@ void PathFollow2D::_update_transform() { if (!c.is_valid()) return; - if (delta_offset == 0) { - return; - } - - float o = offset; + float path_length = c->get_baked_length(); + float bounded_offset = offset; if (loop) - o = Math::fposmod(o, c->get_baked_length()); - - Vector2 pos = c->interpolate_baked(o, cubic); + bounded_offset = Math::fposmod(bounded_offset, path_length); + else + bounded_offset = CLAMP(bounded_offset, 0, path_length); - Vector2 displacement_offset = Vector2(h_offset, v_offset); + Vector2 pos = c->interpolate_baked(bounded_offset, cubic); if (rotate) { + float ahead = bounded_offset + lookahead; + + if (loop && ahead >= path_length) { + // If our lookahead will loop, we need to check if the path is closed. + int point_count = c->get_point_count(); + if (point_count > 0) { + Vector2 start_point = c->get_point_position(0); + Vector2 end_point = c->get_point_position(point_count - 1); + if (start_point == end_point) { + // Since the path is closed we want to 'smooth off' + // the corner at the start/end. + // So we wrap the lookahead back round. + ahead = Math::fmod(ahead, path_length); + } + } + } + + Vector2 ahead_pos = c->interpolate_baked(ahead, cubic); - Vector2 t_prev = (pos - c->interpolate_baked(o - delta_offset, cubic)).normalized(); - Vector2 t_next = (c->interpolate_baked(o + delta_offset, cubic) - pos).normalized(); + Vector2 tangent_to_curve; + if (ahead_pos == pos) { + // This will happen at the end of non-looping or non-closed paths. + // We'll try a look behind instead, in order to get a meaningful angle. + tangent_to_curve = + (pos - c->interpolate_baked(bounded_offset - lookahead, cubic)).normalized(); + } else { + tangent_to_curve = (ahead_pos - pos).normalized(); + } - float angle = t_prev.angle_to(t_next); + Vector2 normal_of_curve = -tangent_to_curve.tangent(); - set_rotation(get_rotation() + angle); + pos += tangent_to_curve * h_offset; + pos += normal_of_curve * v_offset; - Vector2 n = t_next; - Vector2 t = -n.tangent(); - pos += n * h_offset + t * v_offset; + set_rotation(tangent_to_curve.angle()); } else { - pos += displacement_offset; + pos.x += h_offset; + pos.y += v_offset; } set_position(pos); @@ -185,6 +207,8 @@ bool PathFollow2D::_set(const StringName &p_name, const Variant &p_value) { set_cubic_interpolation(p_value); } else if (String(p_name) == "loop") { set_loop(p_value); + } else if (String(p_name) == "lookahead") { + set_lookahead(p_value); } else return false; @@ -207,6 +231,8 @@ bool PathFollow2D::_get(const StringName &p_name, Variant &r_ret) const { r_ret = cubic; } else if (String(p_name) == "loop") { r_ret = loop; + } else if (String(p_name) == "lookahead") { + r_ret = lookahead; } else return false; @@ -224,6 +250,7 @@ void PathFollow2D::_get_property_list(List<PropertyInfo> *p_list) const { p_list->push_back(PropertyInfo(Variant::BOOL, "rotate")); p_list->push_back(PropertyInfo(Variant::BOOL, "cubic_interp")); p_list->push_back(PropertyInfo(Variant::BOOL, "loop")); + p_list->push_back(PropertyInfo(Variant::REAL, "lookahead", PROPERTY_HINT_RANGE, "0.001,1024.0,0.001")); } String PathFollow2D::get_configuration_warning() const { @@ -263,7 +290,7 @@ void PathFollow2D::_bind_methods() { } void PathFollow2D::set_offset(float p_offset) { - delta_offset = p_offset - offset; + offset = p_offset; if (path) _update_transform(); @@ -314,6 +341,16 @@ float PathFollow2D::get_unit_offset() const { return 0; } +void PathFollow2D::set_lookahead(float p_lookahead) { + + lookahead = p_lookahead; +} + +float PathFollow2D::get_lookahead() const { + + return lookahead; +} + void PathFollow2D::set_rotate(bool p_rotate) { rotate = p_rotate; @@ -338,11 +375,11 @@ bool PathFollow2D::has_loop() const { PathFollow2D::PathFollow2D() { offset = 0; - delta_offset = 0; h_offset = 0; v_offset = 0; path = NULL; rotate = true; cubic = true; loop = true; + lookahead = 4; } diff --git a/scene/2d/path_2d.h b/scene/2d/path_2d.h index f5ba3a3d32..88a0abdea9 100644 --- a/scene/2d/path_2d.h +++ b/scene/2d/path_2d.h @@ -60,9 +60,9 @@ public: private: Path2D *path; real_t offset; - real_t delta_offset; // change in offset since last _update_transform real_t h_offset; real_t v_offset; + real_t lookahead; bool cubic; bool loop; bool rotate; @@ -90,6 +90,9 @@ public: void set_unit_offset(float p_unit_offset); float get_unit_offset() const; + void set_lookahead(float p_lookahead); + float get_lookahead() const; + void set_loop(bool p_loop); bool has_loop() const; diff --git a/scene/2d/tile_map.cpp b/scene/2d/tile_map.cpp index c0d0a6e011..5a32a3d0f0 100644 --- a/scene/2d/tile_map.cpp +++ b/scene/2d/tile_map.cpp @@ -513,16 +513,13 @@ void TileMap::_update_dirty_quadrants() { } Ref<OccluderPolygon2D> occluder; - Vector2 occluder_ofs; if (tile_set->tile_get_is_autotile(c.id)) { occluder = tile_set->autotile_get_light_occluder(c.id, Vector2(c.autotile_coord_x, c.autotile_coord_y)); - occluder_ofs = tile_set->tile_get_occluder_offset(c.id); } else { occluder = tile_set->tile_get_light_occluder(c.id); - occluder_ofs = Vector2(); } if (occluder.is_valid()) { - + Vector2 occluder_ofs = tile_set->tile_get_occluder_offset(c.id); Transform2D xform; xform.set_origin(offset.floor() + q.pos); _fix_cell_transform(xform, c, occluder_ofs + center_ofs, s); @@ -968,14 +965,14 @@ void TileMap::_set_tile_data(const PoolVector<int> &p_data) { int c = p_data.size(); PoolVector<int>::Read r = p_data.read(); - int offset = (format == FORMAT_2_1_5) ? 3 : 2; + int offset = (format == FORMAT_2) ? 3 : 2; clear(); for (int i = 0; i < c; i += offset) { const uint8_t *ptr = (const uint8_t *)&r[i]; uint8_t local[12]; - for (int j = 0; j < ((format == FORMAT_2_1_5) ? 12 : 8); j++) + for (int j = 0; j < ((format == FORMAT_2) ? 12 : 8); j++) local[j] = ptr[j]; #ifdef BIG_ENDIAN_ENABLED @@ -985,7 +982,7 @@ void TileMap::_set_tile_data(const PoolVector<int> &p_data) { SWAP(local[4], local[7]); SWAP(local[5], local[6]); //TODO: ask someone to check this... - if (FORMAT == FORMAT_2_1_5) { + if (FORMAT == FORMAT_2) { SWAP(local[8], local[11]); SWAP(local[9], local[10]); } @@ -1000,7 +997,7 @@ void TileMap::_set_tile_data(const PoolVector<int> &p_data) { v &= (1 << 29) - 1; int16_t coord_x; int16_t coord_y; - if (format == FORMAT_2_1_5) { + if (format == FORMAT_2) { coord_x = decode_uint16(&local[8]); coord_y = decode_uint16(&local[10]); } @@ -1018,6 +1015,8 @@ PoolVector<int> TileMap::_get_tile_data() const { data.resize(tile_map.size() * 3); PoolVector<int>::Write w = data.write(); + format = FORMAT_2; + int idx = 0; for (const Map<PosKey, Cell>::Element *E = tile_map.front(); E; E = E->next()) { uint8_t *ptr = (uint8_t *)&w[idx]; @@ -1298,7 +1297,7 @@ bool TileMap::_set(const StringName &p_name, const Variant &p_value) { bool TileMap::_get(const StringName &p_name, Variant &r_ret) const { if (p_name == "format") { - r_ret = FORMAT_2_1_5; + r_ret = FORMAT_2; return true; } else if (p_name == "tile_data") { r_ret = _get_tile_data(); @@ -1594,7 +1593,7 @@ TileMap::TileMap() { y_sort_mode = false; occluder_light_mask = 1; clip_uv = false; - format = FORMAT_2_1_4; //Always initialize with the lowest format + format = FORMAT_1; //Always initialize with the lowest format fp_adjust = 0.00001; tile_origin = TILE_ORIGIN_TOP_LEFT; diff --git a/scene/2d/tile_map.h b/scene/2d/tile_map.h index edc9de0543..11d9915cb6 100644 --- a/scene/2d/tile_map.h +++ b/scene/2d/tile_map.h @@ -61,8 +61,8 @@ public: private: enum DataFormat { - FORMAT_2_1_4 = 0, - FORMAT_2_1_5 + FORMAT_1 = 0, + FORMAT_2 }; Ref<TileSet> tile_set; @@ -178,7 +178,7 @@ private: float bounce; uint32_t collision_layer; uint32_t collision_mask; - DataFormat format; + mutable DataFormat format; TileOrigin tile_origin; diff --git a/scene/3d/gi_probe.cpp b/scene/3d/gi_probe.cpp index 8e2f87738a..ff5cb41135 100644 --- a/scene/3d/gi_probe.cpp +++ b/scene/3d/gi_probe.cpp @@ -1284,8 +1284,11 @@ void GIProbe::bake(Node *p_from_node, bool p_create_visual_debug) { _create_debug_mesh(&baker); } else { - Ref<GIProbeData> probe_data; - probe_data.instance(); + Ref<GIProbeData> probe_data = get_probe_data(); + + if(probe_data.is_null()) + probe_data.instance(); + probe_data->set_bounds(AABB(-extents, extents * 2.0)); probe_data->set_cell_size(baker.po2_bounds.size[longest_axis] / baker.axis_cell_size[longest_axis]); probe_data->set_dynamic_data(data); diff --git a/scene/3d/physics_body.cpp b/scene/3d/physics_body.cpp index f2f00bb617..8c9f59e267 100644 --- a/scene/3d/physics_body.cpp +++ b/scene/3d/physics_body.cpp @@ -734,15 +734,31 @@ bool RigidBody::is_contact_monitor_enabled() const { return contact_monitor != NULL; } -void RigidBody::set_axis_lock(AxisLock p_lock) { +void RigidBody::set_axis_lock_x(bool p_lock) { + RigidBody::locked_axis[0] = p_lock; + PhysicsServer::get_singleton()->body_set_axis_lock(get_rid(), 0, locked_axis[0]); +} + +void RigidBody::set_axis_lock_y(bool p_lock) { + RigidBody::locked_axis[1] = p_lock; + PhysicsServer::get_singleton()->body_set_axis_lock(get_rid(), 1, locked_axis[1]); +} + +void RigidBody::set_axis_lock_z(bool p_lock) { + RigidBody::locked_axis[2] = p_lock; + PhysicsServer::get_singleton()->body_set_axis_lock(get_rid(), 2, locked_axis[2]); +} - axis_lock = p_lock; - PhysicsServer::get_singleton()->body_set_axis_lock(get_rid(), PhysicsServer::BodyAxisLock(axis_lock)); +bool RigidBody::get_axis_lock_x() const { + return RigidBody::locked_axis[0]; } -RigidBody::AxisLock RigidBody::get_axis_lock() const { +bool RigidBody::get_axis_lock_y() const { + return RigidBody::locked_axis[1]; +} - return axis_lock; +bool RigidBody::get_axis_lock_z() const { + return RigidBody::locked_axis[2]; } Array RigidBody::get_colliding_bodies() const { @@ -837,8 +853,12 @@ void RigidBody::_bind_methods() { ClassDB::bind_method(D_METHOD("_body_enter_tree"), &RigidBody::_body_enter_tree); ClassDB::bind_method(D_METHOD("_body_exit_tree"), &RigidBody::_body_exit_tree); - ClassDB::bind_method(D_METHOD("set_axis_lock", "axis_lock"), &RigidBody::set_axis_lock); - ClassDB::bind_method(D_METHOD("get_axis_lock"), &RigidBody::get_axis_lock); + ClassDB::bind_method(D_METHOD("set_axis_lock_x", "axis_lock_x"), &RigidBody::set_axis_lock_x); + ClassDB::bind_method(D_METHOD("set_axis_lock_y", "axis_lock_y"), &RigidBody::set_axis_lock_y); + ClassDB::bind_method(D_METHOD("set_axis_lock_z", "axis_lock_z"), &RigidBody::set_axis_lock_z); + ClassDB::bind_method(D_METHOD("get_axis_lock_x"), &RigidBody::get_axis_lock_x); + ClassDB::bind_method(D_METHOD("get_axis_lock_y"), &RigidBody::get_axis_lock_y); + ClassDB::bind_method(D_METHOD("get_axis_lock_z"), &RigidBody::get_axis_lock_z); ClassDB::bind_method(D_METHOD("get_colliding_bodies"), &RigidBody::get_colliding_bodies); @@ -856,7 +876,10 @@ void RigidBody::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::BOOL, "contact_monitor"), "set_contact_monitor", "is_contact_monitor_enabled"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "sleeping"), "set_sleeping", "is_sleeping"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "can_sleep"), "set_can_sleep", "is_able_to_sleep"); - ADD_PROPERTY(PropertyInfo(Variant::INT, "axis_lock", PROPERTY_HINT_ENUM, "Disabled,Lock X,Lock Y,Lock Z"), "set_axis_lock", "get_axis_lock"); + ADD_GROUP("Axis Lock", "axis_lock_"); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "axis_lock_x"), "set_axis_lock_x", "get_axis_lock_x"); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "axis_lock_y"), "set_axis_lock_y", "get_axis_lock_y"); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "axis_lock_z"), "set_axis_lock_z", "get_axis_lock_z"); ADD_GROUP("Linear", "linear_"); ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "linear_velocity"), "set_linear_velocity", "get_linear_velocity"); ADD_PROPERTY(PropertyInfo(Variant::REAL, "linear_damp", PROPERTY_HINT_RANGE, "-1,128,0.01"), "set_linear_damp", "get_linear_damp"); @@ -874,11 +897,6 @@ void RigidBody::_bind_methods() { BIND_ENUM_CONSTANT(MODE_STATIC); BIND_ENUM_CONSTANT(MODE_CHARACTER); BIND_ENUM_CONSTANT(MODE_KINEMATIC); - - BIND_ENUM_CONSTANT(AXIS_LOCK_DISABLED); - BIND_ENUM_CONSTANT(AXIS_LOCK_X); - BIND_ENUM_CONSTANT(AXIS_LOCK_Y); - BIND_ENUM_CONSTANT(AXIS_LOCK_Z); } RigidBody::RigidBody() : @@ -904,8 +922,6 @@ RigidBody::RigidBody() : contact_monitor = NULL; can_sleep = true; - axis_lock = AXIS_LOCK_DISABLED; - PhysicsServer::get_singleton()->body_set_force_integration_callback(get_rid(), this, "_direct_state_changed"); } @@ -952,6 +968,12 @@ bool KinematicBody::move_and_collide(const Vector3 &p_motion, Collision &r_colli r_collision.local_shape = result.collision_local_shape; } + for (int i = 0; i < 3; i++) { + if (locked_axis[i]) { + result.motion[i] = 0; + } + } + gt.origin += result.motion; set_global_transform(gt); @@ -960,9 +982,16 @@ bool KinematicBody::move_and_collide(const Vector3 &p_motion, Collision &r_colli Vector3 KinematicBody::move_and_slide(const Vector3 &p_linear_velocity, const Vector3 &p_floor_direction, float p_slope_stop_min_velocity, int p_max_slides, float p_floor_max_angle) { - Vector3 motion = (floor_velocity + p_linear_velocity) * get_physics_process_delta_time(); Vector3 lv = p_linear_velocity; + for (int i = 0; i < 3; i++) { + if (locked_axis[i]) { + lv[i] = 0; + } + } + + Vector3 motion = (floor_velocity + lv) * get_physics_process_delta_time(); + on_floor = false; on_ceiling = false; on_wall = false; @@ -1008,6 +1037,12 @@ Vector3 KinematicBody::move_and_slide(const Vector3 &p_linear_velocity, const Ve motion = motion.slide(n); lv = lv.slide(n); + for (int i = 0; i < 3; i++) { + if (locked_axis[i]) { + lv[i] = 0; + } + } + colliders.push_back(collision); } else { @@ -1047,6 +1082,33 @@ bool KinematicBody::test_move(const Transform &p_from, const Vector3 &p_motion) return PhysicsServer::get_singleton()->body_test_motion(get_rid(), p_from, p_motion); } +void KinematicBody::set_axis_lock_x(bool p_lock) { + KinematicBody::locked_axis[0] = p_lock; + PhysicsServer::get_singleton()->body_set_axis_lock(get_rid(), 0, locked_axis[0]); +} + +void KinematicBody::set_axis_lock_y(bool p_lock) { + KinematicBody::locked_axis[1] = p_lock; + PhysicsServer::get_singleton()->body_set_axis_lock(get_rid(), 1, locked_axis[1]); +} + +void KinematicBody::set_axis_lock_z(bool p_lock) { + KinematicBody::locked_axis[2] = p_lock; + PhysicsServer::get_singleton()->body_set_axis_lock(get_rid(), 2, locked_axis[2]); +} + +bool KinematicBody::get_axis_lock_x() const { + return KinematicBody::locked_axis[0]; +} + +bool KinematicBody::get_axis_lock_y() const { + return KinematicBody::locked_axis[1]; +} + +bool KinematicBody::get_axis_lock_z() const { + return KinematicBody::locked_axis[2]; +} + void KinematicBody::set_safe_margin(float p_margin) { margin = p_margin; @@ -1095,12 +1157,24 @@ void KinematicBody::_bind_methods() { ClassDB::bind_method(D_METHOD("is_on_wall"), &KinematicBody::is_on_wall); ClassDB::bind_method(D_METHOD("get_floor_velocity"), &KinematicBody::get_floor_velocity); + ClassDB::bind_method(D_METHOD("set_axis_lock_x", "axis_lock_x"), &KinematicBody::set_axis_lock_x); + ClassDB::bind_method(D_METHOD("set_axis_lock_y", "axis_lock_y"), &KinematicBody::set_axis_lock_y); + ClassDB::bind_method(D_METHOD("set_axis_lock_z", "axis_lock_z"), &KinematicBody::set_axis_lock_z); + ClassDB::bind_method(D_METHOD("get_axis_lock_x"), &KinematicBody::get_axis_lock_x); + ClassDB::bind_method(D_METHOD("get_axis_lock_y"), &KinematicBody::get_axis_lock_y); + ClassDB::bind_method(D_METHOD("get_axis_lock_z"), &KinematicBody::get_axis_lock_z); + ClassDB::bind_method(D_METHOD("set_safe_margin", "pixels"), &KinematicBody::set_safe_margin); ClassDB::bind_method(D_METHOD("get_safe_margin"), &KinematicBody::get_safe_margin); ClassDB::bind_method(D_METHOD("get_slide_count"), &KinematicBody::get_slide_count); ClassDB::bind_method(D_METHOD("get_slide_collision", "slide_idx"), &KinematicBody::_get_slide_collision); + ADD_GROUP("Axis Lock", "axis_lock_"); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "axis_lock_x"), "set_axis_lock_x", "get_axis_lock_x"); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "axis_lock_y"), "set_axis_lock_y", "get_axis_lock_y"); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "axis_lock_z"), "set_axis_lock_z", "get_axis_lock_z"); + ADD_PROPERTY(PropertyInfo(Variant::REAL, "collision/safe_margin", PROPERTY_HINT_RANGE, "0.001,256,0.001"), "set_safe_margin", "get_safe_margin"); } diff --git a/scene/3d/physics_body.h b/scene/3d/physics_body.h index f88b3860dc..57b120ef63 100644 --- a/scene/3d/physics_body.h +++ b/scene/3d/physics_body.h @@ -114,13 +114,6 @@ public: MODE_KINEMATIC, }; - enum AxisLock { - AXIS_LOCK_DISABLED, - AXIS_LOCK_X, - AXIS_LOCK_Y, - AXIS_LOCK_Z, - }; - private: bool can_sleep; PhysicsDirectBodyState *state; @@ -139,7 +132,7 @@ private: bool sleeping; bool ccd; - AxisLock axis_lock; + bool locked_axis[3] = { false, false, false }; int max_contacts_reported; @@ -245,8 +238,12 @@ public: void set_use_continuous_collision_detection(bool p_enable); bool is_using_continuous_collision_detection() const; - void set_axis_lock(AxisLock p_lock); - AxisLock get_axis_lock() const; + void set_axis_lock_x(bool p_lock); + void set_axis_lock_y(bool p_lock); + void set_axis_lock_z(bool p_lock); + bool get_axis_lock_x() const; + bool get_axis_lock_y() const; + bool get_axis_lock_z() const; Array get_colliding_bodies() const; @@ -259,7 +256,6 @@ public: }; VARIANT_ENUM_CAST(RigidBody::Mode); -VARIANT_ENUM_CAST(RigidBody::AxisLock); class KinematicCollision; @@ -281,6 +277,8 @@ public: }; private: + bool locked_axis[3] = { false, false, false }; + float margin; Vector3 floor_velocity; @@ -303,6 +301,13 @@ public: bool move_and_collide(const Vector3 &p_motion, Collision &r_collision); bool test_move(const Transform &p_from, const Vector3 &p_motion); + void set_axis_lock_x(bool p_lock); + void set_axis_lock_y(bool p_lock); + void set_axis_lock_z(bool p_lock); + bool get_axis_lock_x() const; + bool get_axis_lock_y() const; + bool get_axis_lock_z() const; + void set_safe_margin(float p_margin); float get_safe_margin() const; diff --git a/scene/animation/animation_player.cpp b/scene/animation/animation_player.cpp index f3e750d0da..91aa069060 100644 --- a/scene/animation/animation_player.cpp +++ b/scene/animation/animation_player.cpp @@ -364,6 +364,9 @@ void AnimationPlayer::_animation_process_animation(AnimationData *p_anim, float if (!nc) // no node cache for this track, skip it continue; + if (!a->track_is_enabled(i)) + continue; // do nothing if the track is disabled + if (a->track_get_key_count(i) == 0) continue; // do nothing if track is empty @@ -1324,9 +1327,7 @@ void AnimationPlayer::_bind_methods() { ClassDB::bind_method(D_METHOD("get_root"), &AnimationPlayer::get_root); ClassDB::bind_method(D_METHOD("seek", "seconds", "update"), &AnimationPlayer::seek, DEFVAL(false)); - ClassDB::bind_method(D_METHOD("advance", "delta"), &AnimationPlayer::advance); - ClassDB::bind_method(D_METHOD("get_anim_position"), &AnimationPlayer::get_current_animation_position); - ClassDB::bind_method(D_METHOD("get_anim_length"), &AnimationPlayer::get_current_animation_length); + ClassDB::bind_method(D_METHOD("get_position"), &AnimationPlayer::get_current_animation_position); ClassDB::bind_method(D_METHOD("find_animation", "animation"), &AnimationPlayer::find_animation); @@ -1335,6 +1336,11 @@ void AnimationPlayer::_bind_methods() { ClassDB::bind_method(D_METHOD("set_animation_process_mode", "mode"), &AnimationPlayer::set_animation_process_mode); ClassDB::bind_method(D_METHOD("get_animation_process_mode"), &AnimationPlayer::get_animation_process_mode); + ClassDB::bind_method(D_METHOD("get_current_animation_position"), &AnimationPlayer::get_current_animation_position); + ClassDB::bind_method(D_METHOD("get_current_animation_length"), &AnimationPlayer::get_current_animation_length); + + ClassDB::bind_method(D_METHOD("advance", "delta"), &AnimationPlayer::advance); + ADD_GROUP("Playback Options", "playback_"); ADD_PROPERTY(PropertyInfo(Variant::INT, "playback_process_mode", PROPERTY_HINT_ENUM, "Physics,Idle"), "set_animation_process_mode", "get_animation_process_mode"); ADD_PROPERTY(PropertyInfo(Variant::REAL, "playback_default_blend_time", PROPERTY_HINT_RANGE, "0,4096,0.01"), "set_default_blend_time", "get_default_blend_time"); @@ -1343,7 +1349,7 @@ void AnimationPlayer::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::STRING, "autoplay"), "set_autoplay", "get_autoplay"); ADD_PROPERTY(PropertyInfo(Variant::REAL, "speed_scale"), "set_speed_scale", "get_speed_scale"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "active"), "set_active", "is_active"); - ADD_PROPERTY(PropertyInfo(Variant::STRING, "current_anim"), "set_current_anim", "get_current_anim"); + ADD_PROPERTY(PropertyInfo(Variant::STRING, "current_animation"), "set_current_animation", "get_current_animation"); ADD_SIGNAL(MethodInfo("animation_finished", PropertyInfo(Variant::STRING, "name"))); ADD_SIGNAL(MethodInfo("animation_changed", PropertyInfo(Variant::STRING, "old_name"), PropertyInfo(Variant::STRING, "new_name"))); diff --git a/scene/animation/animation_tree_player.cpp b/scene/animation/animation_tree_player.cpp index 23eccec82f..32f82fe6b8 100644 --- a/scene/animation/animation_tree_player.cpp +++ b/scene/animation/animation_tree_player.cpp @@ -831,7 +831,7 @@ void AnimationTreePlayer::_process_animation(float p_delta) { for (List<AnimationNode::TrackRef>::Element *E = anim_list->tref.front(); E; E = E->next()) { AnimationNode::TrackRef &tr = E->get(); - if (tr.track == NULL || tr.local_track < 0 || tr.weight < CMP_EPSILON) + if (tr.track == NULL || tr.local_track < 0 || tr.weight < CMP_EPSILON || !a->track_is_enabled(tr.local_track)) continue; switch (a->track_get_type(tr.local_track)) { @@ -1796,6 +1796,10 @@ void AnimationTreePlayer::_bind_methods() { ADD_GROUP("Playback", "playback_"); ADD_PROPERTY(PropertyInfo(Variant::INT, "playback_process_mode", PROPERTY_HINT_ENUM, "Physics,Idle"), "set_animation_process_mode", "get_animation_process_mode"); + ADD_PROPERTY(PropertyInfo(Variant::NODE_PATH, "master_player"), "set_master_player", "get_master_player"); + ADD_PROPERTY(PropertyInfo(Variant::NODE_PATH, "base_path"), "set_base_path", "get_base_path"); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "active"), "set_active", "is_active"); + BIND_ENUM_CONSTANT(NODE_OUTPUT); BIND_ENUM_CONSTANT(NODE_ANIMATION); BIND_ENUM_CONSTANT(NODE_ONESHOT); diff --git a/scene/gui/file_dialog.cpp b/scene/gui/file_dialog.cpp index 8af499fd96..6af869c503 100644 --- a/scene/gui/file_dialog.cpp +++ b/scene/gui/file_dialog.cpp @@ -603,6 +603,14 @@ void FileDialog::set_current_path(const String &p_path) { } } +void FileDialog::set_mode_overrides_title(bool p_override) { + mode_overrides_title = p_override; +} + +bool FileDialog::is_mode_overriding_title() const { + return mode_overrides_title; +} + void FileDialog::set_mode(Mode p_mode) { mode = p_mode; @@ -610,27 +618,32 @@ void FileDialog::set_mode(Mode p_mode) { case MODE_OPEN_FILE: get_ok()->set_text(RTR("Open")); - set_title(RTR("Open a File")); + if (mode_overrides_title) + set_title(RTR("Open a File")); makedir->hide(); break; case MODE_OPEN_FILES: get_ok()->set_text(RTR("Open")); - set_title(RTR("Open File(s)")); + if (mode_overrides_title) + set_title(RTR("Open File(s)")); makedir->hide(); break; case MODE_OPEN_DIR: get_ok()->set_text(RTR("Select Current Folder")); - set_title(RTR("Open a Directory")); + if (mode_overrides_title) + set_title(RTR("Open a Directory")); makedir->show(); break; case MODE_OPEN_ANY: get_ok()->set_text(RTR("Open")); - set_title(RTR("Open a File or Directory")); + if (mode_overrides_title) + set_title(RTR("Open a File or Directory")); makedir->show(); break; case MODE_SAVE_FILE: get_ok()->set_text(RTR("Save")); - set_title(RTR("Save a File")); + if (mode_overrides_title) + set_title(RTR("Save a File")); makedir->show(); break; } @@ -760,6 +773,8 @@ void FileDialog::_bind_methods() { ClassDB::bind_method(D_METHOD("set_current_dir", "dir"), &FileDialog::set_current_dir); ClassDB::bind_method(D_METHOD("set_current_file", "file"), &FileDialog::set_current_file); ClassDB::bind_method(D_METHOD("set_current_path", "path"), &FileDialog::set_current_path); + ClassDB::bind_method(D_METHOD("set_mode_overrides_title", "override"), &FileDialog::set_mode_overrides_title); + ClassDB::bind_method(D_METHOD("is_mode_overriding_title"), &FileDialog::is_mode_overriding_title); ClassDB::bind_method(D_METHOD("set_mode", "mode"), &FileDialog::set_mode); ClassDB::bind_method(D_METHOD("get_mode"), &FileDialog::get_mode); ClassDB::bind_method(D_METHOD("get_vbox"), &FileDialog::get_vbox); @@ -791,6 +806,7 @@ void FileDialog::_bind_methods() { BIND_ENUM_CONSTANT(ACCESS_USERDATA); BIND_ENUM_CONSTANT(ACCESS_FILESYSTEM); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "mode_overrides_title"), "set_mode_overrides_title", "is_mode_overriding_title"); ADD_PROPERTY(PropertyInfo(Variant::INT, "mode", PROPERTY_HINT_ENUM, "Open one,Open many,Open folder,Open any,Save"), "set_mode", "get_mode"); ADD_PROPERTY(PropertyInfo(Variant::INT, "access", PROPERTY_HINT_ENUM, "Resources,User data,File system"), "set_access", "get_access"); ADD_PROPERTY(PropertyInfo(Variant::POOL_STRING_ARRAY, "filters"), "set_filters", "get_filters"); @@ -814,6 +830,8 @@ FileDialog::FileDialog() { show_hidden_files = default_show_hidden_files; + mode_overrides_title = true; + VBoxContainer *vbc = memnew(VBoxContainer); add_child(vbc); diff --git a/scene/gui/file_dialog.h b/scene/gui/file_dialog.h index ca3d9f54b2..c8c1f23105 100644 --- a/scene/gui/file_dialog.h +++ b/scene/gui/file_dialog.h @@ -92,6 +92,8 @@ private: Vector<String> filters; + bool mode_overrides_title; + static bool default_show_hidden_files; bool show_hidden_files; @@ -143,6 +145,9 @@ public: void set_current_file(const String &p_file); void set_current_path(const String &p_path); + void set_mode_overrides_title(bool p_override); + bool is_mode_overriding_title() const; + void set_mode(Mode p_mode); Mode get_mode() const; diff --git a/scene/gui/text_edit.cpp b/scene/gui/text_edit.cpp index 7ff85716a5..e5169089f2 100644 --- a/scene/gui/text_edit.cpp +++ b/scene/gui/text_edit.cpp @@ -4646,6 +4646,16 @@ void TextEdit::unfold_line(int p_line) { update(); } +void TextEdit::toggle_fold_line(int p_line) { + + ERR_FAIL_INDEX(p_line, text.size()); + + if (!is_folded(p_line)) + fold_line(p_line); + else + unfold_line(p_line); +} + int TextEdit::get_line_count() const { return text.size(); @@ -5461,6 +5471,7 @@ void TextEdit::_bind_methods() { ClassDB::bind_method(D_METHOD("unhide_all_lines"), &TextEdit::unhide_all_lines); ClassDB::bind_method(D_METHOD("fold_line", "line"), &TextEdit::fold_line); ClassDB::bind_method(D_METHOD("unfold_line", "line"), &TextEdit::unfold_line); + ClassDB::bind_method(D_METHOD("toggle_fold_line", "line"), &TextEdit::toggle_fold_line); ClassDB::bind_method(D_METHOD("can_fold", "line"), &TextEdit::can_fold); ClassDB::bind_method(D_METHOD("is_folded", "line"), &TextEdit::is_folded); diff --git a/scene/gui/text_edit.h b/scene/gui/text_edit.h index e5dc2da7c7..dd305d5822 100644 --- a/scene/gui/text_edit.h +++ b/scene/gui/text_edit.h @@ -436,6 +436,7 @@ public: bool is_folded(int p_line) const; void fold_line(int p_line); void unfold_line(int p_line); + void toggle_fold_line(int p_line); String get_text(); String get_line(int line) const; diff --git a/scene/resources/animation.cpp b/scene/resources/animation.cpp index ebbd2d35c3..4544549f94 100644 --- a/scene/resources/animation.cpp +++ b/scene/resources/animation.cpp @@ -77,6 +77,8 @@ bool Animation::_set(const StringName &p_name, const Variant &p_value) { track_set_interpolation_loop_wrap(track, p_value); else if (what == "imported") track_set_imported(track, p_value); + else if (what == "enabled") + track_set_enabled(track, p_value); else if (what == "keys" || what == "key_values") { if (track_get_type(track) == TYPE_TRANSFORM) { @@ -247,6 +249,8 @@ bool Animation::_get(const StringName &p_name, Variant &r_ret) const { r_ret = track_get_interpolation_loop_wrap(track); else if (what == "imported") r_ret = track_is_imported(track); + else if (what == "enabled") + r_ret = track_is_enabled(track); else if (what == "keys") { if (track_get_type(track) == TYPE_TRANSFORM) { @@ -391,6 +395,7 @@ void Animation::_get_property_list(List<PropertyInfo> *p_list) const { p_list->push_back(PropertyInfo(Variant::INT, "tracks/" + itos(i) + "/interp", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR)); p_list->push_back(PropertyInfo(Variant::BOOL, "tracks/" + itos(i) + "/loop_wrap", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR)); p_list->push_back(PropertyInfo(Variant::BOOL, "tracks/" + itos(i) + "/imported", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR)); + p_list->push_back(PropertyInfo(Variant::BOOL, "tracks/" + itos(i) + "/enabled", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR)); p_list->push_back(PropertyInfo(Variant::ARRAY, "tracks/" + itos(i) + "/keys", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR)); } } @@ -1575,6 +1580,19 @@ bool Animation::track_is_imported(int p_track) const { return tracks[p_track]->imported; } +void Animation::track_set_enabled(int p_track, bool p_enabled) { + + ERR_FAIL_INDEX(p_track, tracks.size()); + tracks[p_track]->enabled = p_enabled; + emit_changed(); +} + +bool Animation::track_is_enabled(int p_track) const { + + ERR_FAIL_INDEX_V(p_track, tracks.size(), false); + return tracks[p_track]->enabled; +} + void Animation::track_move_down(int p_track) { if (p_track > 0 && p_track < tracks.size()) { @@ -1603,6 +1621,7 @@ void Animation::copy_track(int src_track, Ref<Animation> p_to_animation) { p_to_animation->track_set_path(dst_track, track_get_path(src_track)); p_to_animation->track_set_imported(dst_track, track_is_imported(src_track)); + p_to_animation->track_set_enabled(dst_track, track_is_enabled(src_track)); p_to_animation->track_set_interpolation_type(dst_track, track_get_interpolation_type(src_track)); p_to_animation->track_set_interpolation_loop_wrap(dst_track, track_get_interpolation_loop_wrap(src_track)); for (int i = 0; i < track_get_key_count(src_track); i++) { @@ -1626,6 +1645,9 @@ void Animation::_bind_methods() { ClassDB::bind_method(D_METHOD("track_set_imported", "idx", "imported"), &Animation::track_set_imported); ClassDB::bind_method(D_METHOD("track_is_imported", "idx"), &Animation::track_is_imported); + ClassDB::bind_method(D_METHOD("track_set_enabled", "idx", "enabled"), &Animation::track_set_enabled); + ClassDB::bind_method(D_METHOD("track_is_enabled", "idx"), &Animation::track_is_enabled); + ClassDB::bind_method(D_METHOD("transform_track_insert_key", "idx", "time", "location", "rotation", "scale"), &Animation::transform_track_insert_key); ClassDB::bind_method(D_METHOD("track_insert_key", "idx", "time", "key", "transition"), &Animation::track_insert_key, DEFVAL(1)); ClassDB::bind_method(D_METHOD("track_remove_key", "idx", "key_idx"), &Animation::track_remove_key); diff --git a/scene/resources/animation.h b/scene/resources/animation.h index c96beeb01f..1f468b29b5 100644 --- a/scene/resources/animation.h +++ b/scene/resources/animation.h @@ -67,10 +67,12 @@ private: bool loop_wrap; NodePath path; // path to something bool imported; + bool enabled; Track() { interpolation = INTERPOLATION_LINEAR; imported = false; loop_wrap = true; + enabled = true; } virtual ~Track() {} }; @@ -239,6 +241,9 @@ public: void track_set_imported(int p_track, bool p_imported); bool track_is_imported(int p_track) const; + void track_set_enabled(int p_track, bool p_enabled); + bool track_is_enabled(int p_track) const; + int transform_track_insert_key(int p_track, float p_time, const Vector3 p_loc, const Quat &p_rot = Quat(), const Vector3 &p_scale = Vector3()); void track_insert_key(int p_track, float p_time, const Variant &p_key, float p_transition = 1); void track_set_key_transition(int p_track, int p_key_idx, float p_transition); diff --git a/scene/resources/mesh.cpp b/scene/resources/mesh.cpp index 0a886c25b1..0b352efca2 100644 --- a/scene/resources/mesh.cpp +++ b/scene/resources/mesh.cpp @@ -28,10 +28,14 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ #include "mesh.h" + +#include "pair.h" #include "scene/resources/concave_polygon_shape.h" #include "scene/resources/convex_polygon_shape.h" #include "surface_tool.h" +#include <stdlib.h> + void Mesh::_clear_triangle_mesh() const { triangle_mesh.unref(); @@ -413,8 +417,21 @@ Ref<Mesh> Mesh::create_outline(float p_margin) const { return newmesh; } +void Mesh::set_lightmap_size_hint(const Vector2 &p_size) { + lightmap_size_hint = p_size; +} + +Size2 Mesh::get_lightmap_size_hint() const { + return lightmap_size_hint; +} + void Mesh::_bind_methods() { + ClassDB::bind_method(D_METHOD("set_lightmap_size_hint", "size"), &Mesh::set_lightmap_size_hint); + ClassDB::bind_method(D_METHOD("get_lightmap_size_hint"), &Mesh::get_lightmap_size_hint); + + ADD_PROPERTYNZ(PropertyInfo(Variant::VECTOR2, "lightmap_size_hint"), "set_lightmap_size_hint", "get_lightmap_size_hint"); + BIND_ENUM_CONSTANT(PRIMITIVE_POINTS); BIND_ENUM_CONSTANT(PRIMITIVE_LINES); BIND_ENUM_CONSTANT(PRIMITIVE_LINE_STRIP); @@ -1035,6 +1052,200 @@ void ArrayMesh::regen_normalmaps() { } } +//dirty hack +bool (*array_mesh_lightmap_unwrap_callback)(float p_texel_size, const float *p_vertices, const float *p_normals, int p_vertex_count, const int *p_indices, const int *p_face_materials, int p_index_count, float **r_uv, int **r_vertex, int *r_vertex_count, int **r_index, int *r_index_count, int *r_size_hint_x, int *r_size_hint_y) = NULL; + +struct ArrayMeshLightmapSurface { + + Ref<Material> material; + Vector<SurfaceTool::Vertex> vertices; + Mesh::PrimitiveType primitive; + uint32_t format; +}; + +Error ArrayMesh::lightmap_unwrap(const Transform &p_base_transform, float p_texel_size) { + + ERR_FAIL_COND_V(!array_mesh_lightmap_unwrap_callback, ERR_UNCONFIGURED); + ERR_EXPLAIN("Can't unwrap mesh with blend shapes"); + ERR_FAIL_COND_V(blend_shapes.size() != 0, ERR_UNAVAILABLE); + + Vector<float> vertices; + Vector<float> normals; + Vector<int> indices; + Vector<int> face_materials; + Vector<float> uv; + Vector<Pair<int, int> > uv_index; + + Vector<ArrayMeshLightmapSurface> surfaces; + for (int i = 0; i < get_surface_count(); i++) { + ArrayMeshLightmapSurface s; + s.primitive = surface_get_primitive_type(i); + + if (s.primitive != Mesh::PRIMITIVE_TRIANGLES) { + ERR_EXPLAIN("Only triangles are supported for lightmap unwrap"); + ERR_FAIL_V(ERR_UNAVAILABLE); + } + s.format = surface_get_format(i); + if (!(s.format & ARRAY_FORMAT_NORMAL)) { + ERR_EXPLAIN("Normals are required for lightmap unwrap"); + ERR_FAIL_V(ERR_UNAVAILABLE); + } + + Array arrays = surface_get_arrays(i); + s.material = surface_get_material(i); + s.vertices = SurfaceTool::create_vertex_array_from_triangle_arrays(arrays); + + PoolVector<Vector3> rvertices = arrays[Mesh::ARRAY_VERTEX]; + int vc = rvertices.size(); + PoolVector<Vector3>::Read r = rvertices.read(); + + PoolVector<Vector3> rnormals = arrays[Mesh::ARRAY_NORMAL]; + PoolVector<Vector3>::Read rn = rnormals.read(); + + int vertex_ofs = vertices.size() / 3; + + vertices.resize((vertex_ofs + vc) * 3); + normals.resize((vertex_ofs + vc) * 3); + uv_index.resize(vertex_ofs + vc); + + for (int j = 0; j < vc; j++) { + + Vector3 v = p_base_transform.xform(r[j]); + + vertices[(j + vertex_ofs) * 3 + 0] = v.x; + vertices[(j + vertex_ofs) * 3 + 1] = v.y; + vertices[(j + vertex_ofs) * 3 + 2] = v.z; + normals[(j + vertex_ofs) * 3 + 0] = rn[j].x; + normals[(j + vertex_ofs) * 3 + 1] = rn[j].y; + normals[(j + vertex_ofs) * 3 + 2] = rn[j].z; + uv_index[j + vertex_ofs] = Pair<int, int>(i, j); + } + + PoolVector<int> rindices = arrays[Mesh::ARRAY_INDEX]; + int ic = rindices.size(); + int index_ofs = indices.size(); + + if (ic == 0) { + indices.resize(index_ofs + vc); + face_materials.resize((index_ofs + vc) / 3); + for (int j = 0; j < vc; j++) { + indices[index_ofs + j] = vertex_ofs + j; + } + for (int j = 0; j < vc / 3; j++) { + face_materials[(index_ofs / 3) + j] = i; + } + + } else { + PoolVector<int>::Read ri = rindices.read(); + indices.resize(index_ofs + ic); + face_materials.resize((index_ofs + ic) / 3); + for (int j = 0; j < ic; j++) { + indices[index_ofs + j] = vertex_ofs + ri[j]; + } + for (int j = 0; j < ic / 3; j++) { + face_materials[(index_ofs / 3) + j] = i; + } + } + + surfaces.push_back(s); + } + + //unwrap + + float *gen_uvs; + int *gen_vertices; + int *gen_indices; + int gen_vertex_count; + int gen_index_count; + int size_x; + int size_y; + + bool ok = array_mesh_lightmap_unwrap_callback(p_texel_size, vertices.ptr(), normals.ptr(), vertices.size() / 3, indices.ptr(), face_materials.ptr(), indices.size(), &gen_uvs, &gen_vertices, &gen_vertex_count, &gen_indices, &gen_index_count, &size_x, &size_y); + + if (!ok) { + return ERR_CANT_CREATE; + } + + //remove surfaces + while (get_surface_count()) { + surface_remove(0); + } + + //create surfacetools for each surface.. + Vector<Ref<SurfaceTool> > surfaces_tools; + + for (int i = 0; i < surfaces.size(); i++) { + Ref<SurfaceTool> st; + st.instance(); + st->begin(Mesh::PRIMITIVE_TRIANGLES); + st->set_material(surfaces[i].material); + surfaces_tools.push_back(st); //stay there + } + + print_line("gen indices: " + itos(gen_index_count)); + //go through all indices + for (int i = 0; i < gen_index_count; i += 3) { + + ERR_FAIL_INDEX_V(gen_vertices[gen_indices[i + 0]], uv_index.size(), ERR_BUG); + ERR_FAIL_INDEX_V(gen_vertices[gen_indices[i + 1]], uv_index.size(), ERR_BUG); + ERR_FAIL_INDEX_V(gen_vertices[gen_indices[i + 2]], uv_index.size(), ERR_BUG); + + ERR_FAIL_COND_V(uv_index[gen_vertices[gen_indices[i + 0]]].first != uv_index[gen_vertices[gen_indices[i + 1]]].first || uv_index[gen_vertices[gen_indices[i + 0]]].first != uv_index[gen_vertices[gen_indices[i + 2]]].first, ERR_BUG); + + int surface = uv_index[gen_vertices[gen_indices[i + 0]]].first; + + for (int j = 0; j < 3; j++) { + + int vertex_idx = gen_vertices[gen_indices[i + j]]; + + SurfaceTool::Vertex v = surfaces[surface].vertices[uv_index[gen_vertices[gen_indices[i + j]]].second]; + + if (surfaces[surface].format & ARRAY_FORMAT_COLOR) { + surfaces_tools[surface]->add_color(v.color); + } + if (surfaces[surface].format & ARRAY_FORMAT_TEX_UV) { + surfaces_tools[surface]->add_uv(v.uv); + } + if (surfaces[surface].format & ARRAY_FORMAT_NORMAL) { + surfaces_tools[surface]->add_normal(v.normal); + } + if (surfaces[surface].format & ARRAY_FORMAT_TANGENT) { + Plane t; + t.normal = v.tangent; + t.d = v.binormal.dot(v.normal.cross(v.tangent)) < 0 ? -1 : 1; + surfaces_tools[surface]->add_tangent(t); + } + if (surfaces[surface].format & ARRAY_FORMAT_BONES) { + surfaces_tools[surface]->add_bones(v.bones); + } + if (surfaces[surface].format & ARRAY_FORMAT_WEIGHTS) { + surfaces_tools[surface]->add_weights(v.weights); + } + + Vector2 uv2(gen_uvs[gen_indices[i + j] * 2 + 0], gen_uvs[gen_indices[i + j] * 2 + 1]); + surfaces_tools[surface]->add_uv2(uv2); + + surfaces_tools[surface]->add_vertex(v.vertex); + } + } + + //free stuff + ::free(gen_vertices); + ::free(gen_indices); + ::free(gen_uvs); + + //generate surfaces + + for (int i = 0; i < surfaces_tools.size(); i++) { + surfaces_tools[i]->index(); + surfaces_tools[i]->commit(Ref<ArrayMesh>((ArrayMesh *)this), surfaces[i].format); + } + + set_lightmap_size_hint(Size2(size_x, size_y)); + + return OK; +} + void ArrayMesh::_bind_methods() { ClassDB::bind_method(D_METHOD("add_blend_shape", "name"), &ArrayMesh::add_blend_shape); diff --git a/scene/resources/mesh.h b/scene/resources/mesh.h index b85a6a84af..ea38ebf2ff 100644 --- a/scene/resources/mesh.h +++ b/scene/resources/mesh.h @@ -43,6 +43,8 @@ class Mesh : public Resource { GDCLASS(Mesh, Resource); mutable Ref<TriangleMesh> triangle_mesh; //cached + Size2 lightmap_size_hint; + protected: void _clear_triangle_mesh() const; @@ -138,6 +140,9 @@ public: virtual AABB get_aabb() const = 0; + void set_lightmap_size_hint(const Vector2 &p_size); + Size2 get_lightmap_size_hint() const; + Mesh(); }; @@ -216,6 +221,8 @@ public: void center_geometry(); void regen_normalmaps(); + Error lightmap_unwrap(const Transform &p_base_transform = Transform(), float p_texel_size = 0.05); + virtual void reload_from_file(); ArrayMesh(); diff --git a/scene/resources/surface_tool.cpp b/scene/resources/surface_tool.cpp index bf89e704bc..352418e65c 100644 --- a/scene/resources/surface_tool.cpp +++ b/scene/resources/surface_tool.cpp @@ -101,6 +101,7 @@ void SurfaceTool::add_vertex(const Vector3 &p_vertex) { vtx.color = last_color; vtx.normal = last_normal; vtx.uv = last_uv; + vtx.uv2 = last_uv2; vtx.weights = last_weights; vtx.bones = last_bones; vtx.tangent = last_tangent.normal; @@ -401,7 +402,7 @@ Array SurfaceTool::commit_to_arrays() { return a; } -Ref<ArrayMesh> SurfaceTool::commit(const Ref<ArrayMesh> &p_existing) { +Ref<ArrayMesh> SurfaceTool::commit(const Ref<ArrayMesh> &p_existing, uint32_t p_flags) { Ref<ArrayMesh> mesh; if (p_existing.is_valid()) @@ -418,7 +419,7 @@ Ref<ArrayMesh> SurfaceTool::commit(const Ref<ArrayMesh> &p_existing) { Array a = commit_to_arrays(); - mesh->add_surface_from_arrays(primitive, a); + mesh->add_surface_from_arrays(primitive, a, Array(), p_flags); if (material.is_valid()) mesh->surface_set_material(surface, material); @@ -482,6 +483,113 @@ void SurfaceTool::_create_list(const Ref<Mesh> &p_existing, int p_surface, List< _create_list_from_arrays(arr, r_vertex, r_index, lformat); } +Vector<SurfaceTool::Vertex> SurfaceTool::create_vertex_array_from_triangle_arrays(const Array &p_arrays) { + + Vector<SurfaceTool::Vertex> ret; + + PoolVector<Vector3> varr = p_arrays[VS::ARRAY_VERTEX]; + PoolVector<Vector3> narr = p_arrays[VS::ARRAY_NORMAL]; + PoolVector<float> tarr = p_arrays[VS::ARRAY_TANGENT]; + PoolVector<Color> carr = p_arrays[VS::ARRAY_COLOR]; + PoolVector<Vector2> uvarr = p_arrays[VS::ARRAY_TEX_UV]; + PoolVector<Vector2> uv2arr = p_arrays[VS::ARRAY_TEX_UV2]; + PoolVector<int> barr = p_arrays[VS::ARRAY_BONES]; + PoolVector<float> warr = p_arrays[VS::ARRAY_WEIGHTS]; + + int vc = varr.size(); + + if (vc == 0) + return ret; + int lformat = 0; + + PoolVector<Vector3>::Read rv; + if (varr.size()) { + lformat |= VS::ARRAY_FORMAT_VERTEX; + rv = varr.read(); + } + PoolVector<Vector3>::Read rn; + if (narr.size()) { + lformat |= VS::ARRAY_FORMAT_NORMAL; + rn = narr.read(); + } + PoolVector<float>::Read rt; + if (tarr.size()) { + lformat |= VS::ARRAY_FORMAT_TANGENT; + rt = tarr.read(); + } + PoolVector<Color>::Read rc; + if (carr.size()) { + lformat |= VS::ARRAY_FORMAT_COLOR; + rc = carr.read(); + } + + PoolVector<Vector2>::Read ruv; + if (uvarr.size()) { + lformat |= VS::ARRAY_FORMAT_TEX_UV; + ruv = uvarr.read(); + } + + PoolVector<Vector2>::Read ruv2; + if (uv2arr.size()) { + lformat |= VS::ARRAY_FORMAT_TEX_UV2; + ruv2 = uv2arr.read(); + } + + PoolVector<int>::Read rb; + if (barr.size()) { + lformat |= VS::ARRAY_FORMAT_BONES; + rb = barr.read(); + } + + PoolVector<float>::Read rw; + if (warr.size()) { + lformat |= VS::ARRAY_FORMAT_WEIGHTS; + rw = warr.read(); + } + + for (int i = 0; i < vc; i++) { + + Vertex v; + if (lformat & VS::ARRAY_FORMAT_VERTEX) + v.vertex = varr[i]; + if (lformat & VS::ARRAY_FORMAT_NORMAL) + v.normal = narr[i]; + if (lformat & VS::ARRAY_FORMAT_TANGENT) { + Plane p(tarr[i * 4 + 0], tarr[i * 4 + 1], tarr[i * 4 + 2], tarr[i * 4 + 3]); + v.tangent = p.normal; + v.binormal = p.normal.cross(v.tangent).normalized() * p.d; + } + if (lformat & VS::ARRAY_FORMAT_COLOR) + v.color = carr[i]; + if (lformat & VS::ARRAY_FORMAT_TEX_UV) + v.uv = uvarr[i]; + if (lformat & VS::ARRAY_FORMAT_TEX_UV2) + v.uv2 = uv2arr[i]; + if (lformat & VS::ARRAY_FORMAT_BONES) { + Vector<int> b; + b.resize(4); + b[0] = barr[i * 4 + 0]; + b[1] = barr[i * 4 + 1]; + b[2] = barr[i * 4 + 2]; + b[3] = barr[i * 4 + 3]; + v.bones = b; + } + if (lformat & VS::ARRAY_FORMAT_WEIGHTS) { + Vector<float> w; + w.resize(4); + w[0] = warr[i * 4 + 0]; + w[1] = warr[i * 4 + 1]; + w[2] = warr[i * 4 + 2]; + w[3] = warr[i * 4 + 3]; + v.weights = w; + } + + ret.push_back(v); + } + + return ret; +} + void SurfaceTool::_create_list_from_arrays(Array arr, List<Vertex> *r_vertex, List<int> *r_index, int &lformat) { PoolVector<Vector3> varr = arr[VS::ARRAY_VERTEX]; @@ -882,7 +990,7 @@ void SurfaceTool::_bind_methods() { ClassDB::bind_method(D_METHOD("create_from", "existing", "surface"), &SurfaceTool::create_from); ClassDB::bind_method(D_METHOD("append_from", "existing", "surface", "transform"), &SurfaceTool::append_from); - ClassDB::bind_method(D_METHOD("commit", "existing"), &SurfaceTool::commit, DEFVAL(Variant())); + ClassDB::bind_method(D_METHOD("commit", "existing"), &SurfaceTool::commit, DEFVAL(Variant()), DEFVAL(Mesh::ARRAY_COMPRESS_DEFAULT)); } SurfaceTool::SurfaceTool() { diff --git a/scene/resources/surface_tool.h b/scene/resources/surface_tool.h index cdaac643de..b180ffe260 100644 --- a/scene/resources/surface_tool.h +++ b/scene/resources/surface_tool.h @@ -127,10 +127,11 @@ public: List<Vertex> &get_vertex_array() { return vertex_array; } void create_from_triangle_arrays(const Array &p_arrays); + static Vector<Vertex> create_vertex_array_from_triangle_arrays(const Array &p_arrays); Array commit_to_arrays(); void create_from(const Ref<Mesh> &p_existing, int p_surface); void append_from(const Ref<Mesh> &p_existing, int p_surface, const Transform &p_xform); - Ref<ArrayMesh> commit(const Ref<ArrayMesh> &p_existing = Ref<ArrayMesh>()); + Ref<ArrayMesh> commit(const Ref<ArrayMesh> &p_existing = Ref<ArrayMesh>(), uint32_t p_flags = Mesh::ARRAY_COMPRESS_DEFAULT); SurfaceTool(); }; diff --git a/scene/resources/tile_set.cpp b/scene/resources/tile_set.cpp index 6fab597d2b..1a46353fe3 100644 --- a/scene/resources/tile_set.cpp +++ b/scene/resources/tile_set.cpp @@ -83,7 +83,7 @@ bool TileSet::_set(const StringName &p_name, const Variant &p_value) { } } } else if (what == "occluder_map") { - tile_map[id].autotile_data.ocludder_map.clear(); + tile_map[id].autotile_data.occluder_map.clear(); Array p = p_value; Vector2 last_coord; while (p.size() > 0) { @@ -194,7 +194,7 @@ bool TileSet::_get(const StringName &p_name, Variant &r_ret) const { r_ret = p; } else if (what == "occluder_map") { Array p; - for (Map<Vector2, Ref<OccluderPolygon2D> >::Element *E = tile_map[id].autotile_data.ocludder_map.front(); E; E = E->next()) { + for (Map<Vector2, Ref<OccluderPolygon2D> >::Element *E = tile_map[id].autotile_data.occluder_map.front(); E; E = E->next()) { p.push_back(E->key()); p.push_back(E->value()); } @@ -643,20 +643,20 @@ Ref<OccluderPolygon2D> TileSet::tile_get_light_occluder(int p_id) const { void TileSet::autotile_set_light_occluder(int p_id, const Ref<OccluderPolygon2D> &p_light_occluder, const Vector2 &p_coord) { ERR_FAIL_COND(!tile_map.has(p_id)); if (p_light_occluder.is_null()) { - if (tile_map[p_id].autotile_data.ocludder_map.has(p_coord)) { - tile_map[p_id].autotile_data.ocludder_map.erase(p_coord); + if (tile_map[p_id].autotile_data.occluder_map.has(p_coord)) { + tile_map[p_id].autotile_data.occluder_map.erase(p_coord); } } else { - tile_map[p_id].autotile_data.ocludder_map[p_coord] = p_light_occluder; + tile_map[p_id].autotile_data.occluder_map[p_coord] = p_light_occluder; } } Ref<OccluderPolygon2D> TileSet::autotile_get_light_occluder(int p_id, const Vector2 &p_coord) const { ERR_FAIL_COND_V(!tile_map.has(p_id), Ref<OccluderPolygon2D>()); - if (!tile_map[p_id].autotile_data.ocludder_map.has(p_coord)) { + if (!tile_map[p_id].autotile_data.occluder_map.has(p_coord)) { return Ref<OccluderPolygon2D>(); } else { - return tile_map[p_id].autotile_data.ocludder_map[p_coord]; + return tile_map[p_id].autotile_data.occluder_map[p_coord]; } } @@ -688,7 +688,7 @@ const Map<Vector2, Ref<OccluderPolygon2D> > &TileSet::autotile_get_light_oclusio static Map<Vector2, Ref<OccluderPolygon2D> > dummy; ERR_FAIL_COND_V(!tile_map.has(p_id), dummy); - return tile_map[p_id].autotile_data.ocludder_map; + return tile_map[p_id].autotile_data.occluder_map; } void TileSet::autotile_set_navigation_polygon(int p_id, const Ref<NavigationPolygon> &p_navigation_polygon, const Vector2 &p_coord) { diff --git a/scene/resources/tile_set.h b/scene/resources/tile_set.h index 4d2b02f54b..deac583f62 100644 --- a/scene/resources/tile_set.h +++ b/scene/resources/tile_set.h @@ -76,7 +76,7 @@ public: Size2 size; Vector2 icon_coord; Map<Vector2, uint16_t> flags; - Map<Vector2, Ref<OccluderPolygon2D> > ocludder_map; + Map<Vector2, Ref<OccluderPolygon2D> > occluder_map; Map<Vector2, Ref<NavigationPolygon> > navpoly_map; Map<Vector2, int> priority_map; diff --git a/servers/physics/body_sw.cpp b/servers/physics/body_sw.cpp index 5057c6ab9d..bba4d7a147 100644 --- a/servers/physics/body_sw.cpp +++ b/servers/physics/body_sw.cpp @@ -559,32 +559,30 @@ void BodySW::integrate_velocities(real_t p_step) { if (fi_callback) get_space()->body_add_to_state_query_list(&direct_state_query_list); - if (mode == PhysicsServer::BODY_MODE_KINEMATIC) { - - _set_transform(new_transform, false); - _set_inv_transform(new_transform.affine_inverse()); - if (contacts.size() == 0 && linear_velocity == Vector3() && angular_velocity == Vector3()) - set_active(false); //stopped moving, deactivate - - return; - } - //apply axis lock - if (axis_lock != PhysicsServer::BODY_AXIS_LOCK_DISABLED) { - - int axis = axis_lock - 1; + if (locked_axis[0] || locked_axis[1] || locked_axis[2]) { for (int i = 0; i < 3; i++) { - if (i == axis) { + if (locked_axis[i]) { linear_velocity[i] = 0; biased_linear_velocity[i] = 0; + new_transform.origin[i] = get_transform().origin[i]; } else { - angular_velocity[i] = 0; biased_angular_velocity[i] = 0; } } } + if (mode == PhysicsServer::BODY_MODE_KINEMATIC) { + + _set_transform(new_transform, false); + _set_inv_transform(new_transform.affine_inverse()); + if (contacts.size() == 0 && linear_velocity == Vector3() && angular_velocity == Vector3()) + set_active(false); //stopped moving, deactivate + + return; + } + Vector3 total_angular_velocity = angular_velocity + biased_angular_velocity; real_t ang_vel = total_angular_velocity.length(); @@ -775,7 +773,6 @@ BodySW::BodySW() : continuous_cd = false; can_sleep = false; fi_callback = NULL; - axis_lock = PhysicsServer::BODY_AXIS_LOCK_DISABLED; } BodySW::~BodySW() { diff --git a/servers/physics/body_sw.h b/servers/physics/body_sw.h index 738d99c764..aab6def1a9 100644 --- a/servers/physics/body_sw.h +++ b/servers/physics/body_sw.h @@ -53,7 +53,7 @@ class BodySW : public CollisionObjectSW { real_t angular_damp; real_t gravity_scale; - PhysicsServer::BodyAxisLock axis_lock; + bool locked_axis[3] = { false, false, false }; real_t kinematic_safe_margin; real_t _inv_mass; @@ -288,8 +288,8 @@ public: _FORCE_INLINE_ Vector3 get_gravity() const { return gravity; } _FORCE_INLINE_ real_t get_bounce() const { return bounce; } - _FORCE_INLINE_ void set_axis_lock(PhysicsServer::BodyAxisLock p_lock) { axis_lock = p_lock; } - _FORCE_INLINE_ PhysicsServer::BodyAxisLock get_axis_lock() const { return axis_lock; } + _FORCE_INLINE_ void set_axis_lock(int axis, bool lock) { locked_axis[axis] = lock; } + _FORCE_INLINE_ bool get_axis_lock() const { return locked_axis; } void integrate_forces(real_t p_step); void integrate_velocities(real_t p_step); diff --git a/servers/physics/physics_server_sw.cpp b/servers/physics/physics_server_sw.cpp index ce63d84617..2909308366 100644 --- a/servers/physics/physics_server_sw.cpp +++ b/servers/physics/physics_server_sw.cpp @@ -794,19 +794,19 @@ void PhysicsServerSW::body_set_axis_velocity(RID p_body, const Vector3 &p_axis_v body->wakeup(); }; -void PhysicsServerSW::body_set_axis_lock(RID p_body, BodyAxisLock p_lock) { +void PhysicsServerSW::body_set_axis_lock(RID p_body, int axis, bool lock) { BodySW *body = body_owner.get(p_body); ERR_FAIL_COND(!body); - body->set_axis_lock(p_lock); + body->set_axis_lock(axis, lock); body->wakeup(); } -PhysicsServerSW::BodyAxisLock PhysicsServerSW::body_get_axis_lock(RID p_body) const { +bool PhysicsServerSW::body_get_axis_lock(RID p_body) const { const BodySW *body = body_owner.get(p_body); - ERR_FAIL_COND_V(!body, BODY_AXIS_LOCK_DISABLED); + ERR_FAIL_COND_V(!body, 0); return body->get_axis_lock(); } diff --git a/servers/physics/physics_server_sw.h b/servers/physics/physics_server_sw.h index fa754a1c8f..fea6e34ebd 100644 --- a/servers/physics/physics_server_sw.h +++ b/servers/physics/physics_server_sw.h @@ -203,8 +203,8 @@ public: virtual void body_apply_torque_impulse(RID p_body, const Vector3 &p_impulse); virtual void body_set_axis_velocity(RID p_body, const Vector3 &p_axis_velocity); - virtual void body_set_axis_lock(RID p_body, BodyAxisLock p_lock); - virtual BodyAxisLock body_get_axis_lock(RID p_body) const; + virtual void body_set_axis_lock(RID p_body, int axis, bool p_lock); + virtual bool body_get_axis_lock(RID p_body) const; virtual void body_add_collision_exception(RID p_body, RID p_body_b); virtual void body_remove_collision_exception(RID p_body, RID p_body_b); diff --git a/servers/physics_server.cpp b/servers/physics_server.cpp index f693622ede..9a9b20bf28 100644 --- a/servers/physics_server.cpp +++ b/servers/physics_server.cpp @@ -472,7 +472,7 @@ void PhysicsServer::_bind_methods() { ClassDB::bind_method(D_METHOD("body_apply_torque_impulse", "body", "impulse"), &PhysicsServer::body_apply_torque_impulse); ClassDB::bind_method(D_METHOD("body_set_axis_velocity", "body", "axis_velocity"), &PhysicsServer::body_set_axis_velocity); - ClassDB::bind_method(D_METHOD("body_set_axis_lock", "body", "axis"), &PhysicsServer::body_set_axis_lock); + ClassDB::bind_method(D_METHOD("body_set_axis_lock", "body", "axis", "lock"), &PhysicsServer::body_set_axis_lock); ClassDB::bind_method(D_METHOD("body_get_axis_lock", "body"), &PhysicsServer::body_get_axis_lock); ClassDB::bind_method(D_METHOD("body_add_collision_exception", "body", "excepted_body"), &PhysicsServer::body_add_collision_exception); @@ -702,11 +702,6 @@ void PhysicsServer::_bind_methods() { BIND_ENUM_CONSTANT(SPACE_PARAM_BODY_TIME_TO_SLEEP); BIND_ENUM_CONSTANT(SPACE_PARAM_BODY_ANGULAR_VELOCITY_DAMP_RATIO); BIND_ENUM_CONSTANT(SPACE_PARAM_CONSTRAINT_DEFAULT_BIAS); - - BIND_ENUM_CONSTANT(BODY_AXIS_LOCK_DISABLED); - BIND_ENUM_CONSTANT(BODY_AXIS_LOCK_X); - BIND_ENUM_CONSTANT(BODY_AXIS_LOCK_Y); - BIND_ENUM_CONSTANT(BODY_AXIS_LOCK_Z); } PhysicsServer::PhysicsServer() { diff --git a/servers/physics_server.h b/servers/physics_server.h index 4886317224..66c3a0afc4 100644 --- a/servers/physics_server.h +++ b/servers/physics_server.h @@ -421,15 +421,8 @@ public: virtual void body_apply_torque_impulse(RID p_body, const Vector3 &p_impulse) = 0; virtual void body_set_axis_velocity(RID p_body, const Vector3 &p_axis_velocity) = 0; - enum BodyAxisLock { - BODY_AXIS_LOCK_DISABLED, - BODY_AXIS_LOCK_X, - BODY_AXIS_LOCK_Y, - BODY_AXIS_LOCK_Z, - }; - - virtual void body_set_axis_lock(RID p_body, BodyAxisLock p_lock) = 0; - virtual BodyAxisLock body_get_axis_lock(RID p_body) const = 0; + virtual void body_set_axis_lock(RID p_body, int axis, bool lock) = 0; + virtual bool body_get_axis_lock(RID p_body) const = 0; //fix virtual void body_add_collision_exception(RID p_body, RID p_body_b) = 0; @@ -692,7 +685,6 @@ VARIANT_ENUM_CAST(PhysicsServer::AreaSpaceOverrideMode); VARIANT_ENUM_CAST(PhysicsServer::BodyMode); VARIANT_ENUM_CAST(PhysicsServer::BodyParameter); VARIANT_ENUM_CAST(PhysicsServer::BodyState); -VARIANT_ENUM_CAST(PhysicsServer::BodyAxisLock); VARIANT_ENUM_CAST(PhysicsServer::PinJointParam); VARIANT_ENUM_CAST(PhysicsServer::JointType); VARIANT_ENUM_CAST(PhysicsServer::HingeJointParam); diff --git a/servers/visual/rasterizer.h b/servers/visual/rasterizer.h index 0ee70878dc..df41c3b5ce 100644 --- a/servers/visual/rasterizer.h +++ b/servers/visual/rasterizer.h @@ -636,6 +636,7 @@ public: struct CommandPolyLine : public Command { bool antialiased; + bool multiline; Vector<Point2> triangles; Vector<Color> triangle_colors; Vector<Point2> lines; @@ -643,6 +644,7 @@ public: CommandPolyLine() { type = TYPE_POLYLINE; antialiased = false; + multiline = false; } }; diff --git a/servers/visual/shader_language.cpp b/servers/visual/shader_language.cpp index 4de902af58..e10a57c571 100644 --- a/servers/visual/shader_language.cpp +++ b/servers/visual/shader_language.cpp @@ -254,6 +254,9 @@ const ShaderLanguage::KeyWord ShaderLanguage::keyword_list[] = { { TK_TYPE_ISAMPLER2D, "isampler2D" }, { TK_TYPE_USAMPLER2D, "usampler2D" }, { TK_TYPE_SAMPLERCUBE, "samplerCube" }, + { TK_INTERPOLATION_FLAT, "flat" }, + { TK_INTERPOLATION_NO_PERSPECTIVE, "noperspective" }, + { TK_INTERPOLATION_SMOOTH, "smooth" }, { TK_PRECISION_LOW, "lowp" }, { TK_PRECISION_MID, "mediump" }, { TK_PRECISION_HIGH, "highp" }, @@ -658,6 +661,24 @@ ShaderLanguage::DataType ShaderLanguage::get_token_datatype(TokenType p_type) { return DataType(p_type - TK_TYPE_VOID); } +bool ShaderLanguage::is_token_interpolation(TokenType p_type) { + + return ( + p_type == TK_INTERPOLATION_FLAT || + p_type == TK_INTERPOLATION_NO_PERSPECTIVE || + p_type == TK_INTERPOLATION_SMOOTH); +} + +ShaderLanguage::DataInterpolation ShaderLanguage::get_token_interpolation(TokenType p_type) { + + if (p_type == TK_INTERPOLATION_FLAT) + return INTERPOLATION_FLAT; + else if (p_type == TK_INTERPOLATION_NO_PERSPECTIVE) + return INTERPOLATION_NO_PERSPECTIVE; + else + return INTERPOLATION_SMOOTH; +} + bool ShaderLanguage::is_token_precision(TokenType p_type) { return ( @@ -3576,10 +3597,16 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct bool uniform = tk.type == TK_UNIFORM; DataPrecision precision = PRECISION_DEFAULT; + DataInterpolation interpolation = INTERPOLATION_SMOOTH; DataType type; StringName name; tk = _get_token(); + if (is_token_interpolation(tk.type)) { + interpolation = get_token_interpolation(tk.type); + tk = _get_token(); + } + if (is_token_precision(tk.type)) { precision = get_token_precision(tk.type); tk = _get_token(); @@ -3777,6 +3804,7 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct ShaderNode::Varying varying; varying.type = type; varying.precission = precision; + varying.interpolation = interpolation; shader->varyings[name] = varying; tk = _get_token(); diff --git a/servers/visual/shader_language.h b/servers/visual/shader_language.h index 7a7f6dd71c..e092bf931f 100644 --- a/servers/visual/shader_language.h +++ b/servers/visual/shader_language.h @@ -72,6 +72,9 @@ public: TK_TYPE_ISAMPLER2D, TK_TYPE_USAMPLER2D, TK_TYPE_SAMPLERCUBE, + TK_INTERPOLATION_FLAT, + TK_INTERPOLATION_NO_PERSPECTIVE, + TK_INTERPOLATION_SMOOTH, TK_PRECISION_LOW, TK_PRECISION_MID, TK_PRECISION_HIGH, @@ -192,6 +195,12 @@ public: PRECISION_DEFAULT, }; + enum DataInterpolation { + INTERPOLATION_FLAT, + INTERPOLATION_NO_PERSPECTIVE, + INTERPOLATION_SMOOTH, + }; + enum Operator { OP_EQUAL, OP_NOT_EQUAL, @@ -431,6 +440,7 @@ public: struct Varying { DataType type; + DataInterpolation interpolation; DataPrecision precission; }; @@ -511,6 +521,8 @@ public: static bool is_token_datatype(TokenType p_type); static DataType get_token_datatype(TokenType p_type); + static bool is_token_interpolation(TokenType p_type); + static DataInterpolation get_token_interpolation(TokenType p_type); static bool is_token_precision(TokenType p_type); static DataPrecision get_token_precision(TokenType p_type); static String get_datatype_name(DataType p_type); diff --git a/servers/visual/visual_server_canvas.cpp b/servers/visual/visual_server_canvas.cpp index 31c09dc23d..0fed9cc961 100644 --- a/servers/visual/visual_server_canvas.cpp +++ b/servers/visual/visual_server_canvas.cpp @@ -416,6 +416,7 @@ void VisualServerCanvas::canvas_item_add_polyline(RID p_item, const Vector<Point ERR_FAIL_COND(!pline); pline->antialiased = p_antialiased; + pline->multiline = false; if (p_width <= 1) { pline->lines = p_points; @@ -486,6 +487,90 @@ void VisualServerCanvas::canvas_item_add_polyline(RID p_item, const Vector<Point canvas_item->commands.push_back(pline); } +void VisualServerCanvas::canvas_item_add_multiline(RID p_item, const Vector<Point2> &p_points, const Vector<Color> &p_colors, float p_width, bool p_antialiased) { + + ERR_FAIL_COND(p_points.size() < 2); + Item *canvas_item = canvas_item_owner.getornull(p_item); + ERR_FAIL_COND(!canvas_item); + + Item::CommandPolyLine *pline = memnew(Item::CommandPolyLine); + ERR_FAIL_COND(!pline); + + pline->antialiased = false; //todo + pline->multiline = true; + + // if (p_width <= 1) { + pline->lines = p_points; + pline->line_colors = p_colors; + if (pline->line_colors.size() == 0) { + pline->line_colors.push_back(Color(1, 1, 1, 1)); + } else if (pline->line_colors.size() > 1 && pline->line_colors.size() != pline->lines.size()) { + pline->line_colors.resize(1); + } +#if 0 +//width not yet + } else { + //make a trianglestrip for drawing the line... + Vector2 prev_t; + pline->triangles.resize(p_points.size() * 2); + if (p_antialiased) { + pline->lines.resize(p_points.size() * 2); + } + + if (p_colors.size() == 0) { + pline->triangle_colors.push_back(Color(1, 1, 1, 1)); + if (p_antialiased) { + pline->line_colors.push_back(Color(1, 1, 1, 1)); + } + } + if (p_colors.size() == 1) { + pline->triangle_colors = p_colors; + pline->line_colors = p_colors; + } else { + pline->triangle_colors.resize(pline->triangles.size()); + pline->line_colors.resize(pline->lines.size()); + } + + for (int i = 0; i < p_points.size(); i++) { + + Vector2 t; + if (i == p_points.size() - 1) { + t = prev_t; + } else { + t = (p_points[i + 1] - p_points[i]).normalized().tangent(); + if (i == 0) { + prev_t = t; + } + } + + Vector2 tangent = ((t + prev_t).normalized()) * p_width * 0.5; + + if (p_antialiased) { + pline->lines[i] = p_points[i] + tangent; + pline->lines[p_points.size() * 2 - i - 1] = p_points[i] - tangent; + if (pline->line_colors.size() > 1) { + pline->line_colors[i] = p_colors[i]; + pline->line_colors[p_points.size() * 2 - i - 1] = p_colors[i]; + } + } + + pline->triangles[i * 2 + 0] = p_points[i] + tangent; + pline->triangles[i * 2 + 1] = p_points[i] - tangent; + + if (pline->triangle_colors.size() > 1) { + + pline->triangle_colors[i * 2 + 0] = p_colors[i]; + pline->triangle_colors[i * 2 + 1] = p_colors[i]; + } + + prev_t = t; + } + } +#endif + canvas_item->rect_dirty = true; + canvas_item->commands.push_back(pline); +} + void VisualServerCanvas::canvas_item_add_rect(RID p_item, const Rect2 &p_rect, const Color &p_color) { Item *canvas_item = canvas_item_owner.getornull(p_item); diff --git a/servers/visual/visual_server_canvas.h b/servers/visual/visual_server_canvas.h index a92370f1f0..3143ac847f 100644 --- a/servers/visual/visual_server_canvas.h +++ b/servers/visual/visual_server_canvas.h @@ -172,6 +172,7 @@ public: void canvas_item_add_line(RID p_item, const Point2 &p_from, const Point2 &p_to, const Color &p_color, float p_width = 1.0, bool p_antialiased = false); void canvas_item_add_polyline(RID p_item, const Vector<Point2> &p_points, const Vector<Color> &p_colors, float p_width = 1.0, bool p_antialiased = false); + void canvas_item_add_multiline(RID p_item, const Vector<Point2> &p_points, const Vector<Color> &p_colors, float p_width = 1.0, bool p_antialiased = false); void canvas_item_add_rect(RID p_item, const Rect2 &p_rect, const Color &p_color); void canvas_item_add_circle(RID p_item, const Point2 &p_pos, float p_radius, const Color &p_color); void canvas_item_add_texture_rect(RID p_item, const Rect2 &p_rect, RID p_texture, bool p_tile = false, const Color &p_modulate = Color(1, 1, 1), bool p_transpose = false, RID p_normal_map = RID()); diff --git a/servers/visual/visual_server_raster.h b/servers/visual/visual_server_raster.h index 9223d81e32..d843c443a2 100644 --- a/servers/visual/visual_server_raster.h +++ b/servers/visual/visual_server_raster.h @@ -551,6 +551,7 @@ public: BIND6(canvas_item_add_line, RID, const Point2 &, const Point2 &, const Color &, float, bool) BIND5(canvas_item_add_polyline, RID, const Vector<Point2> &, const Vector<Color> &, float, bool) + BIND5(canvas_item_add_multiline, RID, const Vector<Point2> &, const Vector<Color> &, float, bool) BIND3(canvas_item_add_rect, RID, const Rect2 &, const Color &) BIND4(canvas_item_add_circle, RID, const Point2 &, float, const Color &) BIND7(canvas_item_add_texture_rect, RID, const Rect2 &, RID, bool, const Color &, bool, RID) diff --git a/servers/visual/visual_server_scene.cpp b/servers/visual/visual_server_scene.cpp index eef4720d22..dde69eedd3 100644 --- a/servers/visual/visual_server_scene.cpp +++ b/servers/visual/visual_server_scene.cpp @@ -2283,7 +2283,7 @@ void VisualServerScene::_bake_gi_probe_light(const GIProbeDataHeader *header, co if (angle > light_cache.spot_angle) continue; - float d = CLAMP(angle / light_cache.spot_angle, 1, 0); + float d = CLAMP(angle / light_cache.spot_angle, 0, 1); att *= powf(1.0 - d, light_cache.spot_attenuation); } diff --git a/servers/visual/visual_server_wrap_mt.h b/servers/visual/visual_server_wrap_mt.h index b58b1d917e..94f450c024 100644 --- a/servers/visual/visual_server_wrap_mt.h +++ b/servers/visual/visual_server_wrap_mt.h @@ -467,6 +467,7 @@ public: FUNC6(canvas_item_add_line, RID, const Point2 &, const Point2 &, const Color &, float, bool) FUNC5(canvas_item_add_polyline, RID, const Vector<Point2> &, const Vector<Color> &, float, bool) + FUNC5(canvas_item_add_multiline, RID, const Vector<Point2> &, const Vector<Color> &, float, bool) FUNC3(canvas_item_add_rect, RID, const Rect2 &, const Color &) FUNC4(canvas_item_add_circle, RID, const Point2 &, float, const Color &) FUNC7(canvas_item_add_texture_rect, RID, const Rect2 &, RID, bool, const Color &, bool, RID) diff --git a/servers/visual_server.h b/servers/visual_server.h index 350097c1b5..de5ef7da0a 100644 --- a/servers/visual_server.h +++ b/servers/visual_server.h @@ -815,6 +815,7 @@ public: virtual void canvas_item_add_line(RID p_item, const Point2 &p_from, const Point2 &p_to, const Color &p_color, float p_width = 1.0, bool p_antialiased = false) = 0; virtual void canvas_item_add_polyline(RID p_item, const Vector<Point2> &p_points, const Vector<Color> &p_colors, float p_width = 1.0, bool p_antialiased = false) = 0; + virtual void canvas_item_add_multiline(RID p_item, const Vector<Point2> &p_points, const Vector<Color> &p_colors, float p_width = 1.0, bool p_antialiased = false) = 0; virtual void canvas_item_add_rect(RID p_item, const Rect2 &p_rect, const Color &p_color) = 0; virtual void canvas_item_add_circle(RID p_item, const Point2 &p_pos, float p_radius, const Color &p_color) = 0; virtual void canvas_item_add_texture_rect(RID p_item, const Rect2 &p_rect, RID p_texture, bool p_tile = false, const Color &p_modulate = Color(1, 1, 1), bool p_transpose = false, RID p_normal_map = RID()) = 0; diff --git a/thirdparty/thekla_atlas/nvmesh/param/Atlas.cpp b/thirdparty/thekla_atlas/nvmesh/param/Atlas.cpp index 4e41e76695..98f92cef96 100644 --- a/thirdparty/thekla_atlas/nvmesh/param/Atlas.cpp +++ b/thirdparty/thekla_atlas/nvmesh/param/Atlas.cpp @@ -38,6 +38,7 @@ using namespace nv; /// Ctor. Atlas::Atlas() { + failed=false; } // Dtor. @@ -100,6 +101,7 @@ void Atlas::extractCharts(const HalfEdge::Mesh * mesh) void Atlas::computeCharts(const HalfEdge::Mesh * mesh, const SegmentationSettings & settings, const Array<uint> & unchartedMaterialArray) { + failed=false; MeshCharts * meshCharts = new MeshCharts(mesh); meshCharts->computeCharts(settings, unchartedMaterialArray); addMeshCharts(meshCharts); @@ -235,6 +237,8 @@ float Atlas::packCharts(int quality, float texelsPerUnit, bool blockAlign, bool { AtlasPacker packer(this); packer.packCharts(quality, texelsPerUnit, blockAlign, conservative); + if (hasFailed()) + return 0; return packer.computeAtlasUtilization(); } diff --git a/thirdparty/thekla_atlas/nvmesh/param/Atlas.h b/thirdparty/thekla_atlas/nvmesh/param/Atlas.h index 8b478207e3..41cfaea9cb 100644 --- a/thirdparty/thekla_atlas/nvmesh/param/Atlas.h +++ b/thirdparty/thekla_atlas/nvmesh/param/Atlas.h @@ -64,9 +64,12 @@ namespace nv // Pack charts in the smallest possible rectangle. float packCharts(int quality, float texelArea, bool blockAlign, bool conservative); + void setFailed() { failed = true; } + bool hasFailed() const { return failed; } private: + bool failed; Array<MeshCharts *> m_meshChartsArray; }; diff --git a/thirdparty/thekla_atlas/nvmesh/param/AtlasPacker.cpp b/thirdparty/thekla_atlas/nvmesh/param/AtlasPacker.cpp index f2156899ae..5ce452cb9e 100644 --- a/thirdparty/thekla_atlas/nvmesh/param/AtlasPacker.cpp +++ b/thirdparty/thekla_atlas/nvmesh/param/AtlasPacker.cpp @@ -152,7 +152,7 @@ AtlasPacker::~AtlasPacker() } // This should compute convex hull and use rotating calipers to find the best box. Currently it uses a brute force method. -static void computeBoundingBox(Chart * chart, Vector2 * majorAxis, Vector2 * minorAxis, Vector2 * minCorner, Vector2 * maxCorner) +static bool computeBoundingBox(Chart * chart, Vector2 * majorAxis, Vector2 * minorAxis, Vector2 * minCorner, Vector2 * maxCorner) { // Compute list of boundary points. Array<Vector2> points(16); @@ -184,6 +184,9 @@ static void computeBoundingBox(Chart * chart, Vector2 * majorAxis, Vector2 * min #if 1 Array<Vector2> hull; + if (points.size()==0) { + return false; + } convexHull(points, hull, 0.00001f); @@ -373,6 +376,8 @@ static void computeBoundingBox(Chart * chart, Vector2 * majorAxis, Vector2 * min } }*/ #endif + + return true; } @@ -431,7 +436,10 @@ void AtlasPacker::packCharts(int quality, float texelsPerUnit, bool blockAligned // Compute bounding box of chart. Vector2 majorAxis, minorAxis, origin, end; - computeBoundingBox(chart, &majorAxis, &minorAxis, &origin, &end); + if (!computeBoundingBox(chart, &majorAxis, &minorAxis, &origin, &end)) { + m_atlas->setFailed(); + return; + } nvCheck(isFinite(majorAxis) && isFinite(minorAxis) && isFinite(origin)); diff --git a/thirdparty/thekla_atlas/thekla/thekla_atlas.cpp b/thirdparty/thekla_atlas/thekla/thekla_atlas.cpp new file mode 100644 index 0000000000..d6f0accf54 --- /dev/null +++ b/thirdparty/thekla_atlas/thekla/thekla_atlas.cpp @@ -0,0 +1,271 @@ + +#include "thekla_atlas.h" + +#include <cfloat> + +#include "nvmesh/halfedge/Edge.h" +#include "nvmesh/halfedge/Mesh.h" +#include "nvmesh/halfedge/Face.h" +#include "nvmesh/halfedge/Vertex.h" +#include "nvmesh/param/Atlas.h" + +#include "nvmath/Vector.inl" +#include "nvmath/ftoi.h" + +#include "nvcore/Array.inl" + + +using namespace Thekla; +using namespace nv; + + +inline Atlas_Output_Mesh * set_error(Atlas_Error * error, Atlas_Error code) { + if (error) *error = code; + return NULL; +} + + + +static void input_to_mesh(const Atlas_Input_Mesh * input, HalfEdge::Mesh * mesh, Atlas_Error * error) { + + Array<uint> canonicalMap; + canonicalMap.reserve(input->vertex_count); + + for (int i = 0; i < input->vertex_count; i++) { + const Atlas_Input_Vertex & input_vertex = input->vertex_array[i]; + const float * pos = input_vertex.position; + const float * nor = input_vertex.normal; + const float * tex = input_vertex.uv; + + HalfEdge::Vertex * vertex = mesh->addVertex(Vector3(pos[0], pos[1], pos[2])); + vertex->nor.set(nor[0], nor[1], nor[2]); + vertex->tex.set(tex[0], tex[1]); + + canonicalMap.append(input_vertex.first_colocal); + } + + mesh->linkColocalsWithCanonicalMap(canonicalMap); + + + const int face_count = input->face_count; + + int non_manifold_faces = 0; + for (int i = 0; i < face_count; i++) { + const Atlas_Input_Face & input_face = input->face_array[i]; + + int v0 = input_face.vertex_index[0]; + int v1 = input_face.vertex_index[1]; + int v2 = input_face.vertex_index[2]; + + HalfEdge::Face * face = mesh->addFace(v0, v1, v2); + if (face != NULL) { + face->material = input_face.material_index; + } + else { + non_manifold_faces++; + } + } + + mesh->linkBoundary(); + + if (non_manifold_faces != 0 && error != NULL) { + *error = Atlas_Error_Invalid_Mesh_Non_Manifold; + } +} + +static Atlas_Output_Mesh * mesh_atlas_to_output(const HalfEdge::Mesh * mesh, const Atlas & atlas, Atlas_Error * error) { + + Atlas_Output_Mesh * output = new Atlas_Output_Mesh; + + const MeshCharts * charts = atlas.meshAt(0); + + // Allocate vertices. + const int vertex_count = charts->vertexCount(); + output->vertex_count = vertex_count; + output->vertex_array = new Atlas_Output_Vertex[vertex_count]; + + int w = 0; + int h = 0; + + // Output vertices. + const int chart_count = charts->chartCount(); + for (int i = 0; i < chart_count; i++) { + const Chart * chart = charts->chartAt(i); + uint vertexOffset = charts->vertexCountBeforeChartAt(i); + + const uint chart_vertex_count = chart->vertexCount(); + for (uint v = 0; v < chart_vertex_count; v++) { + Atlas_Output_Vertex & output_vertex = output->vertex_array[vertexOffset + v]; + + uint original_vertex = chart->mapChartVertexToOriginalVertex(v); + output_vertex.xref = original_vertex; + + Vector2 uv = chart->chartMesh()->vertexAt(v)->tex; + output_vertex.uv[0] = uv.x; + output_vertex.uv[1] = uv.y; + w = max(w, ftoi_ceil(uv.x)); + h = max(h, ftoi_ceil(uv.y)); + } + } + + const int face_count = mesh->faceCount(); + output->index_count = face_count * 3; + output->index_array = new int[face_count * 3]; + + // Set face indices. + for (int f = 0; f < face_count; f++) { + uint c = charts->faceChartAt(f); + uint i = charts->faceIndexWithinChartAt(f); + uint vertexOffset = charts->vertexCountBeforeChartAt(c); + + const Chart * chart = charts->chartAt(c); + nvDebugCheck(chart->faceAt(i) == f); + + const HalfEdge::Face * face = chart->chartMesh()->faceAt(i); + const HalfEdge::Edge * edge = face->edge; + + output->index_array[3*f+0] = vertexOffset + edge->vertex->id; + output->index_array[3*f+1] = vertexOffset + edge->next->vertex->id; + output->index_array[3*f+2] = vertexOffset + edge->next->next->vertex->id; + } + + *error = Atlas_Error_Success; + output->atlas_width = w; + output->atlas_height = h; + + return output; +} + + +void Thekla::atlas_set_default_options(Atlas_Options * options) { + if (options != NULL) { + // These are the default values we use on The Witness. + + options->charter = Atlas_Charter_Default; + options->charter_options.witness.proxy_fit_metric_weight = 2.0f; + options->charter_options.witness.roundness_metric_weight = 0.01f; + options->charter_options.witness.straightness_metric_weight = 6.0f; + options->charter_options.witness.normal_seam_metric_weight = 4.0f; + options->charter_options.witness.texture_seam_metric_weight = 0.5f; + options->charter_options.witness.max_chart_area = FLT_MAX; + options->charter_options.witness.max_boundary_length = FLT_MAX; + + options->mapper = Atlas_Mapper_Default; + + options->packer = Atlas_Packer_Default; + options->packer_options.witness.packing_quality = 0; + options->packer_options.witness.texel_area = 8; + options->packer_options.witness.block_align = true; + options->packer_options.witness.conservative = false; + } +} + + +Atlas_Output_Mesh * Thekla::atlas_generate(const Atlas_Input_Mesh * input, const Atlas_Options * options, Atlas_Error * error) { + // Validate args. + if (input == NULL || options == NULL || error == NULL) return set_error(error, Atlas_Error_Invalid_Args); + + // Validate options. + if (options->charter != Atlas_Charter_Witness) { + return set_error(error, Atlas_Error_Invalid_Options); + } + if (options->charter == Atlas_Charter_Witness) { + // @@ Validate input options! + } + + if (options->mapper != Atlas_Mapper_LSCM) { + return set_error(error, Atlas_Error_Invalid_Options); + } + if (options->mapper == Atlas_Mapper_LSCM) { + // No options. + } + + if (options->packer != Atlas_Packer_Witness) { + return set_error(error, Atlas_Error_Invalid_Options); + } + if (options->packer == Atlas_Packer_Witness) { + // @@ Validate input options! + } + + // Validate input mesh. + for (int i = 0; i < input->face_count; i++) { + int v0 = input->face_array[i].vertex_index[0]; + int v1 = input->face_array[i].vertex_index[1]; + int v2 = input->face_array[i].vertex_index[2]; + + if (v0 < 0 || v0 >= input->vertex_count || + v1 < 0 || v1 >= input->vertex_count || + v2 < 0 || v2 >= input->vertex_count) + { + return set_error(error, Atlas_Error_Invalid_Mesh); + } + } + + + // Build half edge mesh. + AutoPtr<HalfEdge::Mesh> mesh(new HalfEdge::Mesh); + + input_to_mesh(input, mesh.ptr(), error); + + if (*error == Atlas_Error_Invalid_Mesh) { + return NULL; + } + + Atlas atlas; + + // Charter. + if (options->charter == Atlas_Charter_Extract) { + return set_error(error, Atlas_Error_Not_Implemented); + } + else if (options->charter == Atlas_Charter_Witness) { + SegmentationSettings segmentation_settings; + segmentation_settings.proxyFitMetricWeight = options->charter_options.witness.proxy_fit_metric_weight; + segmentation_settings.roundnessMetricWeight = options->charter_options.witness.roundness_metric_weight; + segmentation_settings.straightnessMetricWeight = options->charter_options.witness.straightness_metric_weight; + segmentation_settings.normalSeamMetricWeight = options->charter_options.witness.normal_seam_metric_weight; + segmentation_settings.textureSeamMetricWeight = options->charter_options.witness.texture_seam_metric_weight; + segmentation_settings.maxChartArea = options->charter_options.witness.max_chart_area; + segmentation_settings.maxBoundaryLength = options->charter_options.witness.max_boundary_length; + + Array<uint> uncharted_materials; + atlas.computeCharts(mesh.ptr(), segmentation_settings, uncharted_materials); + } + + if (atlas.hasFailed()) + return NULL; + + // Mapper. + if (options->mapper == Atlas_Mapper_LSCM) { + atlas.parameterizeCharts(); + } + + if (atlas.hasFailed()) + return NULL; + + // Packer. + if (options->packer == Atlas_Packer_Witness) { + int packing_quality = options->packer_options.witness.packing_quality; + float texel_area = options->packer_options.witness.texel_area; + int block_align = options->packer_options.witness.block_align; + int conservative = options->packer_options.witness.conservative; + + /*float utilization =*/ atlas.packCharts(packing_quality, texel_area, block_align, conservative); + } + + if (atlas.hasFailed()) + return NULL; + + + // Build output mesh. + return mesh_atlas_to_output(mesh.ptr(), atlas, error); +} + + +void Thekla::atlas_free(Atlas_Output_Mesh * output) { + if (output != NULL) { + delete [] output->vertex_array; + delete [] output->index_array; + delete output; + } +} + diff --git a/thirdparty/thekla_atlas/thekla/thekla_atlas.h b/thirdparty/thekla_atlas/thekla/thekla_atlas.h new file mode 100644 index 0000000000..1d0716e781 --- /dev/null +++ b/thirdparty/thekla_atlas/thekla/thekla_atlas.h @@ -0,0 +1,116 @@ + +// Thekla Atlas Generator + +namespace Thekla { + +enum Atlas_Charter { + Atlas_Charter_Witness, // Options: threshold + Atlas_Charter_Extract, // Options: --- + Atlas_Charter_Default = Atlas_Charter_Witness +}; + +enum Atlas_Mapper { + Atlas_Mapper_LSCM, // Options: --- + Atlas_Mapper_Default = Atlas_Mapper_LSCM +}; + +enum Atlas_Packer { + Atlas_Packer_Witness, // Options: texel_area + Atlas_Packer_Default = Atlas_Packer_Witness +}; + +struct Atlas_Options { + Atlas_Charter charter; + union { + struct { + float proxy_fit_metric_weight; + float roundness_metric_weight; + float straightness_metric_weight; + float normal_seam_metric_weight; + float texture_seam_metric_weight; + float max_chart_area; + float max_boundary_length; + } witness; + struct { + } extract; + } charter_options; + + Atlas_Mapper mapper; + union { + } mapper_options; + + Atlas_Packer packer; + union { + struct { + int packing_quality; + float texel_area; // This is not really texel area, but 1 / texel width? + bool block_align; // Align charts to 4x4 blocks. + bool conservative; // Pack charts with extra padding. + } witness; + } packer_options; +}; + +struct Atlas_Input_Vertex { + float position[3]; + float normal[3]; + float uv[2]; + int first_colocal; +}; + +struct Atlas_Input_Face { + int vertex_index[3]; + int material_index; +}; + +struct Atlas_Input_Mesh { + int vertex_count; + int face_count; + Atlas_Input_Vertex * vertex_array; + Atlas_Input_Face * face_array; +}; + +struct Atlas_Output_Vertex { + float uv[2]; + int xref; // Index of input vertex from which this output vertex originated. +}; + +struct Atlas_Output_Mesh { + int atlas_width; + int atlas_height; + int vertex_count; + int index_count; + Atlas_Output_Vertex * vertex_array; + int * index_array; +}; + +enum Atlas_Error { + Atlas_Error_Success, + Atlas_Error_Invalid_Args, + Atlas_Error_Invalid_Options, + Atlas_Error_Invalid_Mesh, + Atlas_Error_Invalid_Mesh_Non_Manifold, + Atlas_Error_Not_Implemented, +}; + +void atlas_set_default_options(Atlas_Options * options); + +Atlas_Output_Mesh * atlas_generate(const Atlas_Input_Mesh * input, const Atlas_Options * options, Atlas_Error * error); + +void atlas_free(Atlas_Output_Mesh * output); + + +/* + +Should we represent the input mesh with an opaque structure that simply holds pointers to the user data? That would allow us to avoid having to copy attributes to an intermediate representation. + +struct Atlas_Input_Mesh; + +void mesh_set_vertex_position(Atlas_Input_Mesh * mesh, float * ptr, int stride); +void mesh_set_vertex_normal(Atlas_Input_Mesh * mesh, float * ptr, int stride); +void mesh_set_vertex_uv(Mesh * mesh, float * ptr, int stride); + +void mesh_set_index(Mesh * mesh, int * ptr); +*/ + +} // Thekla namespace + |