diff options
184 files changed, 4843 insertions, 1100 deletions
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index a9ada58e64..6cb52cf5ff 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -87,7 +87,7 @@ rebase -i`` and relevant help about rebasing or ammending commits on the Internet). This git style guide has some good practices to have in mind: -https://github.com/agis-/git-style-guide +[Git Style Guide](https://github.com/agis-/git-style-guide) #### Format your commit logs with readability in mind diff --git a/core/class_db.cpp b/core/class_db.cpp index 12310f6151..57e88044b5 100644 --- a/core/class_db.cpp +++ b/core/class_db.cpp @@ -187,6 +187,25 @@ MethodDefinition D_METHOD(const char *p_name, const char *p_arg1, const char *p_ return md; } +MethodDefinition D_METHOD(const char *p_name, const char *p_arg1, const char *p_arg2, const char *p_arg3, const char *p_arg4, const char *p_arg5, const char *p_arg6, const char *p_arg7, const char *p_arg8, const char *p_arg9, const char *p_arg10, const char *p_arg11) { + + MethodDefinition md; + md.name = StaticCString::create(p_name); + md.args.resize(11); + md.args[0] = StaticCString::create(p_arg1); + md.args[1] = StaticCString::create(p_arg2); + md.args[2] = StaticCString::create(p_arg3); + md.args[3] = StaticCString::create(p_arg4); + md.args[4] = StaticCString::create(p_arg5); + md.args[5] = StaticCString::create(p_arg6); + md.args[6] = StaticCString::create(p_arg7); + md.args[7] = StaticCString::create(p_arg8); + md.args[8] = StaticCString::create(p_arg9); + md.args[9] = StaticCString::create(p_arg10); + md.args[10] = StaticCString::create(p_arg11); + return md; +} + #endif ClassDB::APIType ClassDB::current_api = API_CORE; diff --git a/core/class_db.h b/core/class_db.h index 5910a2ce01..24db4c61bb 100644 --- a/core/class_db.h +++ b/core/class_db.h @@ -66,6 +66,7 @@ MethodDefinition D_METHOD(const char *p_name, const char *p_arg1, const char *p_ MethodDefinition D_METHOD(const char *p_name, const char *p_arg1, const char *p_arg2, const char *p_arg3, const char *p_arg4, const char *p_arg5, const char *p_arg6, const char *p_arg7, const char *p_arg8); MethodDefinition D_METHOD(const char *p_name, const char *p_arg1, const char *p_arg2, const char *p_arg3, const char *p_arg4, const char *p_arg5, const char *p_arg6, const char *p_arg7, const char *p_arg8, const char *p_arg9); MethodDefinition D_METHOD(const char *p_name, const char *p_arg1, const char *p_arg2, const char *p_arg3, const char *p_arg4, const char *p_arg5, const char *p_arg6, const char *p_arg7, const char *p_arg8, const char *p_arg9, const char *p_arg10); +MethodDefinition D_METHOD(const char *p_name, const char *p_arg1, const char *p_arg2, const char *p_arg3, const char *p_arg4, const char *p_arg5, const char *p_arg6, const char *p_arg7, const char *p_arg8, const char *p_arg9, const char *p_arg10, const char *p_arg11); #else diff --git a/core/io/logger.cpp b/core/io/logger.cpp index ad6371f1e1..ce2ce44b1d 100644 --- a/core/io/logger.cpp +++ b/core/io/logger.cpp @@ -110,7 +110,7 @@ void RotatedFileLogger::close_file() { void RotatedFileLogger::clear_old_backups() { int max_backups = max_files - 1; // -1 for the current file - String basename = base_path.get_basename(); + String basename = base_path.get_file().get_basename(); String extension = "." + base_path.get_extension(); DirAccess *da = DirAccess::open(base_path.get_base_dir()); @@ -122,7 +122,7 @@ void RotatedFileLogger::clear_old_backups() { String f = da->get_next(); Set<String> backups; while (f != String()) { - if (!da->current_is_dir() && f.begins_with(basename) && f.ends_with(extension) && f != base_path) { + if (!da->current_is_dir() && f.begins_with(basename) && f.ends_with(extension) && f != base_path.get_file()) { backups.insert(f); } f = da->get_next(); @@ -149,7 +149,7 @@ void RotatedFileLogger::rotate_file() { char timestamp[21]; OS::Date date = OS::get_singleton()->get_date(); OS::Time time = OS::get_singleton()->get_time(); - sprintf(timestamp, "-%04d-%02d-%02d-%02d-%02d-%02d", date.year, date.month, date.day + 1, time.hour, time.min, time.sec); + sprintf(timestamp, "-%04d-%02d-%02d-%02d-%02d-%02d", date.year, date.month, date.day, time.hour, time.min, time.sec); String backup_name = base_path.get_basename() + timestamp + "." + base_path.get_extension(); diff --git a/core/make_binders.py b/core/make_binders.py index 6468c029f0..6f42c6e8eb 100644 --- a/core/make_binders.py +++ b/core/make_binders.py @@ -244,7 +244,7 @@ def make_version(template, nargs, argmax, const, ret): def run(target, source, env): - versions = 10 + versions = 11 versions_ext = 6 text = "" text_ext = "" diff --git a/core/script_debugger_remote.cpp b/core/script_debugger_remote.cpp index 4653ade294..2feb068ecb 100644 --- a/core/script_debugger_remote.cpp +++ b/core/script_debugger_remote.cpp @@ -855,15 +855,19 @@ void ScriptDebuggerRemote::_print_handler(void *p_this, const String &p_string) } sdr->char_count += allowed_chars; - - if (sdr->char_count >= sdr->max_cps) { - s += "\n[output overflow, print less text!]\n"; - } + bool overflowed = sdr->char_count >= sdr->max_cps; sdr->mutex->lock(); if (!sdr->locking && sdr->tcp_client->is_connected_to_host()) { + if (overflowed) + s += "[...]"; + sdr->output_strings.push_back(s); + + if (overflowed) { + sdr->output_strings.push_back("[output overflow, print less text!]"); + } } sdr->mutex->unlock(); } diff --git a/core/variant.h b/core/variant.h index e0d0bf05c8..45066af401 100644 --- a/core/variant.h +++ b/core/variant.h @@ -99,15 +99,15 @@ public: _RID, OBJECT, DICTIONARY, - ARRAY, // 20 + ARRAY, // arrays - POOL_BYTE_ARRAY, + POOL_BYTE_ARRAY, // 20 POOL_INT_ARRAY, POOL_REAL_ARRAY, POOL_STRING_ARRAY, - POOL_VECTOR2_ARRAY, // 25 - POOL_VECTOR3_ARRAY, + POOL_VECTOR2_ARRAY, + POOL_VECTOR3_ARRAY, // 25 POOL_COLOR_ARRAY, VARIANT_MAX diff --git a/core/variant_op.cpp b/core/variant_op.cpp index 03ec336291..6362090902 100644 --- a/core/variant_op.cpp +++ b/core/variant_op.cpp @@ -1655,13 +1655,13 @@ Variant Variant::get_named(const StringName &p_index, bool *r_valid) const { } else if (p_index == CoreStringNames::singleton->a) { return v->a; } else if (p_index == CoreStringNames::singleton->r8) { - return v->r * 255.0; + return int(v->r * 255.0); } else if (p_index == CoreStringNames::singleton->g8) { - return v->g * 255.0; + return int(v->g * 255.0); } else if (p_index == CoreStringNames::singleton->b8) { - return v->b * 255.0; + return int(v->b * 255.0); } else if (p_index == CoreStringNames::singleton->a8) { - return v->a * 255.0; + return int(v->a * 255.0); } else if (p_index == CoreStringNames::singleton->h) { return v->get_h(); } else if (p_index == CoreStringNames::singleton->s) { diff --git a/doc/classes/ConeTwistJoint.xml b/doc/classes/ConeTwistJoint.xml index 67c7cc4cfe..78655c496d 100644 --- a/doc/classes/ConeTwistJoint.xml +++ b/doc/classes/ConeTwistJoint.xml @@ -1,8 +1,12 @@ <?xml version="1.0" encoding="UTF-8" ?> <class name="ConeTwistJoint" inherits="Joint" category="Core" version="3.0.alpha.custom_build"> <brief_description> + A twist joint between two 3D bodies </brief_description> <description> + The joint can rotate the bodies across an axis defined by the local x-axes of the [Joint]. + The twist axis is initiated as the x-axis of the [Joint]. + Once the Bodies swing, the twist axis is calculated as the middle of the x-axes of the Joint in the local space of the two Bodies. </description> <tutorials> </tutorials> @@ -30,28 +34,49 @@ </methods> <members> <member name="bias" type="float" setter="set_param" getter="get_param"> + The speed with which the swing or twist will take place. + The higher, the faster. </member> <member name="relaxation" type="float" setter="set_param" getter="get_param"> + Defines, how fast the swing- and twist-speed-difference on both sides gets synced. </member> <member name="softness" type="float" setter="set_param" getter="get_param"> + The ease with which the joint starts to twist. If it's too low, it takes more force to start twisting the joint. </member> <member name="swing_span" type="float" setter="_set_swing_span" getter="_get_swing_span"> + Swing is rotation from side to side, around the axis perpendicular to the twist axis. + The swing span defines, how much rotation will not get corrected allong the swing axis. + Could be defined as looseness in the [ConeTwistJoint]. + If below 0.05, this behaviour is locked. Default value: [code]PI/4[/code]. </member> <member name="twist_span" type="float" setter="_set_twist_span" getter="_get_twist_span"> + Twist is the rotation around the twist axis, this value defined how far the joint can twist. + Twist is locked if below 0.05. </member> </members> <constants> <constant name="PARAM_SWING_SPAN" value="0"> + Swing is rotation from side to side, around the axis perpendicular to the twist axis. + The swing span defines, how much rotation will not get corrected allong the swing axis. + Could be defined as looseness in the [ConeTwistJoint]. + If below 0.05, this behaviour is locked. Default value: [code]PI/4[/code]. </constant> <constant name="PARAM_TWIST_SPAN" value="1"> + Twist is the rotation around the twist axis, this value defined how far the joint can twist. + Twist is locked if below 0.05. </constant> <constant name="PARAM_BIAS" value="2"> + The speed with which the swing or twist will take place. + The higher, the faster. </constant> <constant name="PARAM_SOFTNESS" value="3"> + The ease with which the joint starts to twist. If it's too low, it takes more force to start twisting the joint. </constant> <constant name="PARAM_RELAXATION" value="4"> + Defines, how fast the swing- and twist-speed-difference on both sides gets synced. </constant> <constant name="PARAM_MAX" value="5"> + End flag of PARAM_* constants, used internally. </constant> </constants> </class> diff --git a/doc/classes/EditorInterface.xml b/doc/classes/EditorInterface.xml index 203c96516b..23a937791c 100644 --- a/doc/classes/EditorInterface.xml +++ b/doc/classes/EditorInterface.xml @@ -1,8 +1,10 @@ <?xml version="1.0" encoding="UTF-8" ?> <class name="EditorInterface" inherits="Node" category="Core" version="3.0.alpha.custom_build"> <brief_description> + Editor interface and main components. </brief_description> <description> + Editor interface. Allows saving and (re-)loading scenes, rendering mesh previews, inspecting and editing resources and objects and provides access to [EditorSettings], [EditorFileSystem], [EditorResourcePreview]\ er, [ScriptEditor], the editor viewport, as well as information about scenes. Also see [EditorPlugin] and [EditorScript]. </description> <tutorials> </tutorials> @@ -15,60 +17,70 @@ <argument index="0" name="resource" type="Resource"> </argument> <description> + Edits the given [Resource]. </description> </method> <method name="get_base_control"> <return type="Control"> </return> <description> + Returns the base [Control]. </description> </method> <method name="get_edited_scene_root"> <return type="Node"> </return> <description> + Returns the edited scene's root [Node]. </description> </method> <method name="get_editor_settings"> <return type="EditorSettings"> </return> <description> + Returns the [EditorSettings]. </description> </method> <method name="get_editor_viewport"> <return type="Control"> </return> <description> + Returns the editor [Viewport]. </description> </method> <method name="get_open_scenes" qualifiers="const"> <return type="Array"> </return> <description> + Returns an [Array] of the currently opened scenes. </description> </method> <method name="get_resource_filesystem"> <return type="EditorFileSystem"> </return> <description> + Returns the [EditorFileSystem]. </description> </method> <method name="get_resource_previewer"> <return type="EditorResourcePreview"> </return> <description> + Returns the [EditorResourcePreview]\ er. </description> </method> <method name="get_script_editor"> <return type="ScriptEditor"> </return> <description> + Returns the [ScriptEditor]. </description> </method> <method name="get_selection"> <return type="EditorSelection"> </return> <description> + Returns the [EditorSelection]. </description> </method> <method name="inspect_object"> @@ -79,6 +91,7 @@ <argument index="1" name="for_property" type="String" default=""""> </argument> <description> + Shows the given property on the given [code]object[/code] in the Editor's Inspector dock. </description> </method> <method name="make_mesh_previews"> @@ -89,6 +102,7 @@ <argument index="1" name="preview_size" type="int"> </argument> <description> + Returns mesh previews rendered at the given size as an [Array] of [Texture]\ s. </description> </method> <method name="open_scene_from_path"> @@ -97,6 +111,7 @@ <argument index="0" name="scene_filepath" type="String"> </argument> <description> + Opens the scene at the given path. </description> </method> <method name="reload_scene_from_path"> @@ -105,12 +120,14 @@ <argument index="0" name="scene_filepath" type="String"> </argument> <description> + Reloads the scene at the given path. </description> </method> <method name="save_scene"> <return type="int" enum="Error"> </return> <description> + Saves the scene. Returns either OK or ERR_CANT_CREATE. See [@Global Scope] constants. </description> </method> <method name="save_scene_as"> @@ -121,6 +138,7 @@ <argument index="1" name="with_preview" type="bool" default="true"> </argument> <description> + Saves the scene as a file at [code]path[/code]. </description> </method> </methods> diff --git a/doc/classes/EditorScript.xml b/doc/classes/EditorScript.xml index 48cf3e9843..9e774345a2 100644 --- a/doc/classes/EditorScript.xml +++ b/doc/classes/EditorScript.xml @@ -1,10 +1,19 @@ <?xml version="1.0" encoding="UTF-8" ?> <class name="EditorScript" inherits="Reference" category="Core" version="3.0.alpha.custom_build"> <brief_description> - Simple script to perform changes in the currently edited scene. + Base script that can be used to add extension functions to the editor. </brief_description> <description> - This script can be run from the Scene -> Run Script menu option. + Scripts extending this class and implementing its [code]_run()[/code] method can be executed from the Script Editor's [code]File -> Run[/code] menu option (or by pressing [code]CTRL+Shift+X[/code]) while the editor is running. This is useful for adding custom in-editor functionality to Godot. For more complex additions, consider using [EditorPlugin]\ s instead. Note that extending scripts need to have [code]tool mode[/code] enabled. + Example script: + [codeblock] + tool + extends EditorScript + + func _run(): + print("Hello from the Godot Editor!") + [/codeblock] + Note that the script is run in the Editor context, which means the output is visible in the console window started with the Editor (STDOUT) instead of the usual Godot *Output* dock. </description> <tutorials> </tutorials> @@ -15,6 +24,7 @@ <return type="void"> </return> <description> + This method is executed by the Editor when [code]File -> Run[/code] is used. </description> </method> <method name="add_root_node"> @@ -29,12 +39,14 @@ <return type="EditorInterface"> </return> <description> + Returns the [EditorInterface] singleton instance. </description> </method> <method name="get_scene"> <return type="Node"> </return> <description> + Returns the Editor's currently active scene. </description> </method> </methods> diff --git a/doc/classes/Generic6DOFJoint.xml b/doc/classes/Generic6DOFJoint.xml index 4b782e994a..89ec1fd836 100644 --- a/doc/classes/Generic6DOFJoint.xml +++ b/doc/classes/Generic6DOFJoint.xml @@ -1,8 +1,10 @@ <?xml version="1.0" encoding="UTF-8" ?> <class name="Generic6DOFJoint" inherits="Joint" category="Core" version="3.0.alpha.custom_build"> <brief_description> + The generic 6 degrees of freedom joint can implement a variety of joint-types by locking certain axes' rotation or translation. </brief_description> <description> + The first 3 dof axes are linear axes, which represent translation of Bodies, and the latter 3 dof axes represent the angular motion. Each axis can be either locked, or limited. </description> <tutorials> </tutorials> @@ -120,146 +122,217 @@ </methods> <members> <member name="angular_limit_x/damping" type="float" setter="set_param_x" getter="get_param_x"> + The amount of rotational damping across the x-axis. + The lower, the longer an impulse from one side takes to travel to the other side. </member> <member name="angular_limit_x/enabled" type="bool" setter="set_flag_x" getter="get_flag_x"> + If [code]true[/code] rotation across the x-axis is enabled. </member> <member name="angular_limit_x/erp" type="float" setter="set_param_x" getter="get_param_x"> + When rotating across x-axis, this error tolerance factor defines how much the correction gets slowed down. The lower, the slower. </member> <member name="angular_limit_x/force_limit" type="float" setter="set_param_x" getter="get_param_x"> + The maximum amount of force that can occur, when rotating arround x-axis. </member> <member name="angular_limit_x/lower_angle" type="float" setter="_set_angular_lo_limit_x" getter="_get_angular_lo_limit_x"> + The minimum rotation in negative direction to break loose and rotate arround the x-axis. </member> <member name="angular_limit_x/restitution" type="float" setter="set_param_x" getter="get_param_x"> + The amount of rotational restitution across the x-axis. The lower, the more restitution occurs. </member> <member name="angular_limit_x/softness" type="float" setter="set_param_x" getter="get_param_x"> + The speed of all rotations across the x-axis. </member> <member name="angular_limit_x/upper_angle" type="float" setter="_set_angular_hi_limit_x" getter="_get_angular_hi_limit_x"> + The minimum rotation in positive direction to break loose and rotate arround the x-axis. </member> <member name="angular_limit_y/damping" type="float" setter="set_param_y" getter="get_param_y"> + The amount of rotational damping across the y-axis. The lower, the more dampening occurs. </member> <member name="angular_limit_y/enabled" type="bool" setter="set_flag_y" getter="get_flag_y"> + If [code]true[/code] rotation across the y-axis is enabled. </member> <member name="angular_limit_y/erp" type="float" setter="set_param_y" getter="get_param_y"> + When rotating across y-axis, this error tolerance factor defines how much the correction gets slowed down. The lower, the slower. </member> <member name="angular_limit_y/force_limit" type="float" setter="set_param_y" getter="get_param_y"> + The maximum amount of force that can occur, when rotating arround y-axis. </member> <member name="angular_limit_y/lower_angle" type="float" setter="_set_angular_lo_limit_y" getter="_get_angular_lo_limit_y"> + The minimum rotation in negative direction to break loose and rotate arround the y-axis. </member> <member name="angular_limit_y/restitution" type="float" setter="set_param_y" getter="get_param_y"> + The amount of rotational restitution across the y-axis. The lower, the more restitution occurs. </member> <member name="angular_limit_y/softness" type="float" setter="set_param_y" getter="get_param_y"> + The speed of all rotations across the y-axis. </member> <member name="angular_limit_y/upper_angle" type="float" setter="_set_angular_hi_limit_y" getter="_get_angular_hi_limit_y"> + The minimum rotation in positive direction to break loose and rotate arround the y-axis. </member> <member name="angular_limit_z/damping" type="float" setter="set_param_z" getter="get_param_z"> + The amount of rotational damping across the z-axis. The lower, the more dampening occurs. </member> <member name="angular_limit_z/enabled" type="bool" setter="set_flag_z" getter="get_flag_z"> + If [code]true[/code] rotation across the z-axis is enabled. </member> <member name="angular_limit_z/erp" type="float" setter="set_param_z" getter="get_param_z"> + When rotating across z-axis, this error tolerance factor defines how much the correction gets slowed down. The lower, the slower. </member> <member name="angular_limit_z/force_limit" type="float" setter="set_param_z" getter="get_param_z"> + The maximum amount of force that can occur, when rotating arround z-axis. </member> <member name="angular_limit_z/lower_angle" type="float" setter="_set_angular_lo_limit_z" getter="_get_angular_lo_limit_z"> + The minimum rotation in negative direction to break loose and rotate arround the z-axis. </member> <member name="angular_limit_z/restitution" type="float" setter="set_param_z" getter="get_param_z"> + The amount of rotational restitution across the z-axis. The lower, the more restitution occurs. </member> <member name="angular_limit_z/softness" type="float" setter="set_param_z" getter="get_param_z"> + The speed of all rotations across the z-axis. </member> <member name="angular_limit_z/upper_angle" type="float" setter="_set_angular_hi_limit_z" getter="_get_angular_hi_limit_z"> + The minimum rotation in positive direction to break loose and rotate arround the z-axis. </member> <member name="angular_motor_x/enabled" type="bool" setter="set_flag_x" getter="get_flag_x"> + If [code]true[/code] a rotating motor at the x-axis is enabled. </member> <member name="angular_motor_x/force_limit" type="float" setter="set_param_x" getter="get_param_x"> + Maximum acceleration for the motor at the x-axis. </member> <member name="angular_motor_x/target_velocity" type="float" setter="set_param_x" getter="get_param_x"> + Target speed for the motor at the x-axis. </member> <member name="angular_motor_y/enabled" type="bool" setter="set_flag_y" getter="get_flag_y"> + If [code]true[/code] a rotating motor at the y-axis is enabled. </member> <member name="angular_motor_y/force_limit" type="float" setter="set_param_y" getter="get_param_y"> + Maximum acceleration for the motor at the y-axis. </member> <member name="angular_motor_y/target_velocity" type="float" setter="set_param_y" getter="get_param_y"> + Target speed for the motor at the y-axis. </member> <member name="angular_motor_z/enabled" type="bool" setter="set_flag_z" getter="get_flag_z"> + If [code]true[/code] a rotating motor at the z-axis is enabled. </member> <member name="angular_motor_z/force_limit" type="float" setter="set_param_z" getter="get_param_z"> + Maximum acceleration for the motor at the z-axis. </member> <member name="angular_motor_z/target_velocity" type="float" setter="set_param_z" getter="get_param_z"> + Target speed for the motor at the z-axis. </member> <member name="linear_limit_x/damping" type="float" setter="set_param_x" getter="get_param_x"> + The amount of damping that happens at the x-motion. </member> <member name="linear_limit_x/enabled" type="bool" setter="set_flag_x" getter="get_flag_x"> + If [code]true[/code] the linear motion across the x-axis is enabled. </member> <member name="linear_limit_x/lower_distance" type="float" setter="set_param_x" getter="get_param_x"> + The minimum difference between the pivot points' x-axis. </member> <member name="linear_limit_x/restitution" type="float" setter="set_param_x" getter="get_param_x"> + The amount of restitution on the x-axis movement The lower, the more momentum gets lost. </member> <member name="linear_limit_x/softness" type="float" setter="set_param_x" getter="get_param_x"> + A factor applied to the movement across the x-axis The lower, the slower the movement. </member> <member name="linear_limit_x/upper_distance" type="float" setter="set_param_x" getter="get_param_x"> + The maximum difference between the pivot points' x-axis. </member> <member name="linear_limit_y/damping" type="float" setter="set_param_y" getter="get_param_y"> + The amount of damping that happens at the y-motion. </member> <member name="linear_limit_y/enabled" type="bool" setter="set_flag_y" getter="get_flag_y"> + If [code]true[/code] the linear motion across the y-axis is enabled. </member> <member name="linear_limit_y/lower_distance" type="float" setter="set_param_y" getter="get_param_y"> + The minimum difference between the pivot points' y-axis. </member> <member name="linear_limit_y/restitution" type="float" setter="set_param_y" getter="get_param_y"> + The amount of restitution on the y-axis movement The lower, the more momentum gets lost. </member> <member name="linear_limit_y/softness" type="float" setter="set_param_y" getter="get_param_y"> + A factor applied to the movement across the y-axis The lower, the slower the movement. </member> <member name="linear_limit_y/upper_distance" type="float" setter="set_param_y" getter="get_param_y"> + The maximum difference between the pivot points' y-axis. </member> <member name="linear_limit_z/damping" type="float" setter="set_param_z" getter="get_param_z"> + The amount of damping that happens at the z-motion. </member> <member name="linear_limit_z/enabled" type="bool" setter="set_flag_z" getter="get_flag_z"> + If [code]true[/code] the linear motion across the z-axis is enabled. </member> <member name="linear_limit_z/lower_distance" type="float" setter="set_param_z" getter="get_param_z"> + The minimum difference between the pivot points' z-axis. </member> <member name="linear_limit_z/restitution" type="float" setter="set_param_z" getter="get_param_z"> + The amount of restitution on the z-axis movement The lower, the more momentum gets lost. </member> <member name="linear_limit_z/softness" type="float" setter="set_param_z" getter="get_param_z"> + A factor applied to the movement across the z-axis The lower, the slower the movement. </member> <member name="linear_limit_z/upper_distance" type="float" setter="set_param_z" getter="get_param_z"> + The maximum difference between the pivot points' z-axis. </member> </members> <constants> <constant name="PARAM_LINEAR_LOWER_LIMIT" value="0"> + The minimum difference between the pivot points' axes. </constant> <constant name="PARAM_LINEAR_UPPER_LIMIT" value="1"> + The maximum difference between the pivot points' axes. </constant> <constant name="PARAM_LINEAR_LIMIT_SOFTNESS" value="2"> + A factor applied to the movement across the axes The lower, the slower the movement. </constant> <constant name="PARAM_LINEAR_RESTITUTION" value="3"> + The amount of restitution on the axes movement The lower, the more momentum gets lost. </constant> <constant name="PARAM_LINEAR_DAMPING" value="4"> + The amount of damping that happens at the linear motion across the axes. </constant> <constant name="PARAM_ANGULAR_LOWER_LIMIT" value="5"> + The minimum rotation in negative direction to break loose and rotate arround the axes. </constant> <constant name="PARAM_ANGULAR_UPPER_LIMIT" value="6"> + The minimum rotation in positive direction to break loose and rotate arround the axes. </constant> <constant name="PARAM_ANGULAR_LIMIT_SOFTNESS" value="7"> + The speed of all rotations across the axes. </constant> <constant name="PARAM_ANGULAR_DAMPING" value="8"> + The amount of rotational damping across the axes. The lower, the more dampening occurs. </constant> <constant name="PARAM_ANGULAR_RESTITUTION" value="9"> + The amount of rotational restitution across the axes. The lower, the more restitution occurs. </constant> <constant name="PARAM_ANGULAR_FORCE_LIMIT" value="10"> + The maximum amount of force that can occur, when rotating arround the axes. </constant> <constant name="PARAM_ANGULAR_ERP" value="11"> + When rotating across the axes, this error tolerance factor defines how much the correction gets slowed down. The lower, the slower. </constant> <constant name="PARAM_ANGULAR_MOTOR_TARGET_VELOCITY" value="12"> + Target speed for the motor at the axes. </constant> <constant name="PARAM_ANGULAR_MOTOR_FORCE_LIMIT" value="13"> + Maximum acceleration for the motor at the axes. </constant> <constant name="PARAM_MAX" value="14"> + End flag of PARAM_* constants, used internally. </constant> <constant name="FLAG_ENABLE_LINEAR_LIMIT" value="0"> + If [code]set[/code] there is linear motion possible within the given limits. </constant> <constant name="FLAG_ENABLE_ANGULAR_LIMIT" value="1"> + If [code]set[/code] there is rotational motion possible. </constant> <constant name="FLAG_ENABLE_MOTOR" value="2"> + If [code]set[/code] there is a rotational motor across these axes. </constant> <constant name="FLAG_MAX" value="3"> + End flag of FLAG_* constants, used internally. </constant> </constants> </class> diff --git a/doc/classes/HingeJoint.xml b/doc/classes/HingeJoint.xml index ae3693c3a4..d18e63f8a3 100644 --- a/doc/classes/HingeJoint.xml +++ b/doc/classes/HingeJoint.xml @@ -1,8 +1,10 @@ <?xml version="1.0" encoding="UTF-8" ?> <class name="HingeJoint" inherits="Joint" category="Core" version="3.0.alpha.custom_build"> <brief_description> + A hinge between two 3D bodies. </brief_description> <description> + Normaly uses the z-axis of body A as the hinge axis, another axis can be specified when adding it manually though. </description> <tutorials> </tutorials> @@ -48,50 +50,70 @@ </methods> <members> <member name="angular_limit/bias" type="float" setter="set_param" getter="get_param"> + The speed with which the rotation across the axis perpendicular to the hinge gets corrected. </member> <member name="angular_limit/enable" type="bool" setter="set_flag" getter="get_flag"> + If [code]true[/code] the hinges maximum and minimum rotation, defined by [member angular_limit/lower] and [member angular_limit/upper] has effects. </member> <member name="angular_limit/lower" type="float" setter="_set_lower_limit" getter="_get_lower_limit"> + The minimum rotation. only active if [member angular_limit/enable] is [code]true[/code]. </member> <member name="angular_limit/relaxation" type="float" setter="set_param" getter="get_param"> + The lower this value, the more the rotation gets slowed down. </member> <member name="angular_limit/softness" type="float" setter="set_param" getter="get_param"> </member> <member name="angular_limit/upper" type="float" setter="_set_upper_limit" getter="_get_upper_limit"> + The maximum rotation. only active if [member angular_limit/enable] is [code]true[/code]. </member> <member name="motor/enable" type="bool" setter="set_flag" getter="get_flag"> + When activated, a motor turns the hinge. </member> <member name="motor/max_impulse" type="float" setter="set_param" getter="get_param"> + Maximum acceleration for the motor. </member> <member name="motor/target_velocity" type="float" setter="set_param" getter="get_param"> + Target speed for the motor. </member> <member name="params/bias" type="float" setter="set_param" getter="get_param"> + The speed with wich the two bodies get pulled together when they move in different directions. </member> </members> <constants> <constant name="PARAM_BIAS" value="0"> + The speed with wich the two bodies get pulled together when they move in different directions. </constant> <constant name="PARAM_LIMIT_UPPER" value="1"> + The maximum rotation. only active if [member angular_limit/enable] is [code]true[/code]. </constant> <constant name="PARAM_LIMIT_LOWER" value="2"> + The minimum rotation. only active if [member angular_limit/enable] is [code]true[/code]. </constant> <constant name="PARAM_LIMIT_BIAS" value="3"> + The speed with which the rotation across the axis perpendicular to the hinge gets corrected. </constant> <constant name="PARAM_LIMIT_SOFTNESS" value="4"> </constant> <constant name="PARAM_LIMIT_RELAXATION" value="5"> + The lower this value, the more the rotation gets slowed down. </constant> <constant name="PARAM_MOTOR_TARGET_VELOCITY" value="6"> + Target speed for the motor. </constant> <constant name="PARAM_MOTOR_MAX_IMPULSE" value="7"> + Maximum acceleration for the motor. </constant> <constant name="PARAM_MAX" value="8"> + End flag of PARAM_* constants, used internally. </constant> <constant name="FLAG_USE_LIMIT" value="0"> + If [code]true[/code] the hinges maximum and minimum rotation, defined by [member angular_limit/lower] and [member angular_limit/upper] has effects. </constant> <constant name="FLAG_ENABLE_MOTOR" value="1"> + When activated, a motor turns the hinge. </constant> <constant name="FLAG_MAX" value="2"> + End flag of FLAG_* constants, used internally. </constant> </constants> </class> diff --git a/doc/classes/Joint.xml b/doc/classes/Joint.xml index 2e7d24aac1..901f84fe5e 100644 --- a/doc/classes/Joint.xml +++ b/doc/classes/Joint.xml @@ -1,8 +1,10 @@ <?xml version="1.0" encoding="UTF-8" ?> <class name="Joint" inherits="Spatial" category="Core" version="3.0.alpha.custom_build"> <brief_description> + Base class for all 3D joints </brief_description> <description> + All 3D joints link two nodes, has a priority, and can decide if the two bodies of the nodes should be able to collide with each other </description> <tutorials> </tutorials> @@ -68,12 +70,16 @@ </methods> <members> <member name="collision/exclude_nodes" type="bool" setter="set_exclude_nodes_from_collision" getter="get_exclude_nodes_from_collision"> + If [code]true[/code] the two bodies of the nodes are not able to collide with each other. </member> <member name="nodes/node_a" type="NodePath" setter="set_node_a" getter="get_node_a"> + The [Node], the first side of the Joint attaches to. </member> <member name="nodes/node_b" type="NodePath" setter="set_node_b" getter="get_node_b"> + The [Node], the second side of the Joint attaches to. </member> <member name="solver/priority" type="int" setter="set_solver_priority" getter="get_solver_priority"> + The order in wich the solver is executed compared to the other [Joints], the lower, the earlier. </member> </members> <constants> diff --git a/doc/classes/Particles2D.xml b/doc/classes/Particles2D.xml index b2c63ea0c3..cfc907b727 100644 --- a/doc/classes/Particles2D.xml +++ b/doc/classes/Particles2D.xml @@ -286,7 +286,7 @@ </methods> <members> <member name="amount" type="int" setter="set_amount" getter="get_amount"> - Number of particles to emit. + Number of particles emitted in one emission cycle. </member> <member name="draw_order" type="int" setter="set_draw_order" getter="get_draw_order" enum="Particles2D.DrawOrder"> Particle draw order. Uses [code]DRAW_ORDER_*[/code] values. Default value: [code]DRAW_ORDER_INDEX[/code]. @@ -295,7 +295,7 @@ If [code]true[/code] particles are being emitted. Default value: [code]true[/code]. </member> <member name="explosiveness" type="float" setter="set_explosiveness_ratio" getter="get_explosiveness_ratio"> - Time ratio between each emission. If [code]0[/code] particles are emitted continuously. If [code]1[/code] all particles are emitted simultaneously. Default value: [code]0[/code]. + How rapidly particles in an emission cycle are emitted. If greater than [code]0[/code], there will be a gap in emissions before the next cycle begins. Default value: [code]0[/code]. </member> <member name="fixed_fps" type="int" setter="set_fixed_fps" getter="get_fixed_fps"> </member> @@ -313,18 +313,19 @@ <member name="normal_map" type="Texture" setter="set_normal_map" getter="get_normal_map"> </member> <member name="one_shot" type="bool" setter="set_one_shot" getter="get_one_shot"> - If [code]true[/code] only [code]amount[/code] particles will be emitted. Default value: [code]false[/code]. + If [code]true[/code] only one emission cycle occurs. If set [code]true[/code] during a cycle, emission will stop at the cycle's end. Default value: [code]false[/code]. </member> <member name="preprocess" type="float" setter="set_pre_process_time" getter="get_pre_process_time"> + Particle system starts as if it had already run for this many seconds. </member> <member name="process_material" type="Material" setter="set_process_material" getter="get_process_material"> [Material] for processing particles. Can be a [ParticlesMaterial] or a [ShaderMaterial]. </member> <member name="randomness" type="float" setter="set_randomness_ratio" getter="get_randomness_ratio"> - Emission randomness ratio. Default value: [code]0[/code]. + Emission lifetime randomness ratio. Default value: [code]0[/code]. </member> <member name="speed_scale" type="float" setter="set_speed_scale" getter="get_speed_scale"> - Speed scaling ratio. Default value: [code]1[/code]. + Particle system's running speed scaling ratio. Default value: [code]1[/code]. </member> <member name="texture" type="Texture" setter="set_texture" getter="get_texture"> Particle texture. If [code]null[/code] particles will be squares. @@ -333,6 +334,7 @@ Number of vertical frames in [code]texture[/code]. </member> <member name="visibility_rect" type="Rect2" setter="set_visibility_rect" getter="get_visibility_rect"> + Editor visibility helper. </member> </members> <constants> diff --git a/doc/classes/Physics2DServer.xml b/doc/classes/Physics2DServer.xml index 37e1567891..edc46a53d0 100644 --- a/doc/classes/Physics2DServer.xml +++ b/doc/classes/Physics2DServer.xml @@ -21,7 +21,7 @@ <argument index="2" name="transform" type="Transform2D" default="Transform2D( 1, 0, 0, 1, 0, 0 )"> </argument> <description> - Add a shape to the area, along with a transform matrix. Shapes are usually referenced by their index, so you should track which shape has a given index. + Adds a shape to the area, along with a transform matrix. Shapes are usually referenced by their index, so you should track which shape has a given index. </description> </method> <method name="area_attach_object_instance_id"> @@ -32,7 +32,7 @@ <argument index="1" name="id" type="int"> </argument> <description> - Assign the area to a descendant of [Object], so it can exist in the node tree. + Assigns the area to a descendant of [Object], so it can exist in the node tree. </description> </method> <method name="area_clear_shapes"> @@ -41,14 +41,14 @@ <argument index="0" name="area" type="RID"> </argument> <description> - Remove all shapes from an area. It does not delete the shapes, so they can be reassigned later. + Removes all shapes from an area. It does not delete the shapes, so they can be reassigned later. </description> </method> <method name="area_create"> <return type="RID"> </return> <description> - Create an [Area2D]. + Creates an [Area2D]. </description> </method> <method name="area_get_object_instance_id" qualifiers="const"> @@ -57,7 +57,7 @@ <argument index="0" name="area" type="RID"> </argument> <description> - Get the instance ID of the object the area is assigned to. + Gets the instance ID of the object the area is assigned to. </description> </method> <method name="area_get_param" qualifiers="const"> @@ -68,7 +68,7 @@ <argument index="1" name="param" type="int" enum="Physics2DServer.AreaParameter"> </argument> <description> - Return an area parameter value. + Returns an area parameter value. A list of available parameters is on the AREA_PARAM_* constants. </description> </method> <method name="area_get_shape" qualifiers="const"> @@ -79,7 +79,7 @@ <argument index="1" name="shape_idx" type="int"> </argument> <description> - Return the [RID] of the nth shape of an area. + Returns the [RID] of the nth shape of an area. </description> </method> <method name="area_get_shape_count" qualifiers="const"> @@ -88,7 +88,7 @@ <argument index="0" name="area" type="RID"> </argument> <description> - Return the number of shapes assigned to an area. + Returns the number of shapes assigned to an area. </description> </method> <method name="area_get_shape_transform" qualifiers="const"> @@ -99,7 +99,7 @@ <argument index="1" name="shape_idx" type="int"> </argument> <description> - Return the transform matrix of a shape within an area. + Returns the transform matrix of a shape within an area. </description> </method> <method name="area_get_space" qualifiers="const"> @@ -108,7 +108,7 @@ <argument index="0" name="area" type="RID"> </argument> <description> - Return the space assigned to the area. + Returns the space assigned to the area. </description> </method> <method name="area_get_space_override_mode" qualifiers="const"> @@ -117,7 +117,7 @@ <argument index="0" name="area" type="RID"> </argument> <description> - Return the space override mode for the area. + Returns the space override mode for the area. </description> </method> <method name="area_get_transform" qualifiers="const"> @@ -126,7 +126,7 @@ <argument index="0" name="area" type="RID"> </argument> <description> - Return the transform matrix for an area. + Returns the transform matrix for an area. </description> </method> <method name="area_remove_shape"> @@ -137,7 +137,7 @@ <argument index="1" name="shape_idx" type="int"> </argument> <description> - Remove a shape from an area. It does not delete the shape, so it can be reassigned later. + Removes a shape from an area. It does not delete the shape, so it can be reassigned later. </description> </method> <method name="area_set_collision_layer"> @@ -148,7 +148,7 @@ <argument index="1" name="layer" type="int"> </argument> <description> - Assign the area to one or many physics layers. + Assigns the area to one or many physics layers. </description> </method> <method name="area_set_collision_mask"> @@ -159,7 +159,7 @@ <argument index="1" name="mask" type="int"> </argument> <description> - Set which physics layers the area will monitor. + Sets which physics layers the area will monitor. </description> </method> <method name="area_set_monitor_callback"> @@ -172,7 +172,7 @@ <argument index="2" name="method" type="String"> </argument> <description> - Set the function to call when any body/area enters or exits the area. This callback will be called for any object interacting with the area, and takes five parameters: + Sets the function to call when any body/area enters or exits the area. This callback will be called for any object interacting with the area, and takes five parameters: 1: AREA_BODY_ADDED or AREA_BODY_REMOVED, depending on whether the object entered or exited the area. 2: [RID] of the object that entered/exited the area. 3: Instance ID of the object that entered/exited the area. @@ -190,7 +190,7 @@ <argument index="2" name="value" type="Variant"> </argument> <description> - Set the value for an area parameter. A list of available parameters is on the AREA_PARAM_* constants. + Sets the value for an area parameter. A list of available parameters is on the AREA_PARAM_* constants. </description> </method> <method name="area_set_shape"> @@ -203,7 +203,7 @@ <argument index="2" name="shape" type="RID"> </argument> <description> - Substitute a given area shape by another. The old shape is selected by its index, the new one by its [RID]. + Substitutes a given area shape by another. The old shape is selected by its index, the new one by its [RID]. </description> </method> <method name="area_set_shape_disabled"> @@ -216,6 +216,7 @@ <argument index="2" name="disable" type="bool"> </argument> <description> + Disables a given shape in this area if [code]disable is true[/code] </description> </method> <method name="area_set_shape_transform"> @@ -228,7 +229,7 @@ <argument index="2" name="transform" type="Transform2D"> </argument> <description> - Set the transform matrix for an area shape. + Sets the transform matrix for an area shape. </description> </method> <method name="area_set_space"> @@ -239,7 +240,7 @@ <argument index="1" name="space" type="RID"> </argument> <description> - Assign a space to the area. + Assigns a space to the area. </description> </method> <method name="area_set_space_override_mode"> @@ -250,7 +251,7 @@ <argument index="1" name="mode" type="int" enum="Physics2DServer.AreaSpaceOverrideMode"> </argument> <description> - Set the space override mode for the area. The modes are described in the constants AREA_SPACE_OVERRIDE_*. + Sets the space override mode for the area. The modes are described in the constants AREA_SPACE_OVERRIDE_*. </description> </method> <method name="area_set_transform"> @@ -261,7 +262,7 @@ <argument index="1" name="transform" type="Transform2D"> </argument> <description> - Set the transform matrix for an area. + Sets the transform matrix for an area. </description> </method> <method name="body_add_collision_exception"> @@ -272,7 +273,7 @@ <argument index="1" name="excepted_body" type="RID"> </argument> <description> - Add a body to the list of bodies exempt from collisions. + Adds a body to the list of bodies exempt from collisions. </description> </method> <method name="body_add_force"> @@ -285,7 +286,7 @@ <argument index="2" name="force" type="Vector2"> </argument> <description> - Add a positioned force to the applied force and torque. As with [method body_apply_impulse], both the force and the offset from the body origin are in global coordinates. A force differs from an impulse in that, while the two are forces, the impulse clears itself after being applied. + Adds a positioned force to the applied force and torque. As with [method body_apply_impulse], both the force and the offset from the body origin are in global coordinates. A force differs from an impulse in that, while the two are forces, the impulse clears itself after being applied. </description> </method> <method name="body_add_shape"> @@ -298,7 +299,7 @@ <argument index="2" name="transform" type="Transform2D" default="Transform2D( 1, 0, 0, 1, 0, 0 )"> </argument> <description> - Add a shape to the body, along with a transform matrix. Shapes are usually referenced by their index, so you should track which shape has a given index. + Adds a shape to the body, along with a transform matrix. Shapes are usually referenced by their index, so you should track which shape has a given index. </description> </method> <method name="body_apply_impulse"> @@ -311,7 +312,7 @@ <argument index="2" name="impulse" type="Vector2"> </argument> <description> - Add a positioned impulse to the applied force and torque. Both the force and the offset from the body origin are in global coordinates. + Adds a positioned impulse to the applied force and torque. Both the force and the offset from the body origin are in global coordinates. </description> </method> <method name="body_attach_object_instance_id"> @@ -322,7 +323,7 @@ <argument index="1" name="id" type="int"> </argument> <description> - Assign the area to a descendant of [Object], so it can exist in the node tree. + Assigns the area to a descendant of [Object], so it can exist in the node tree. </description> </method> <method name="body_clear_shapes"> @@ -331,7 +332,7 @@ <argument index="0" name="body" type="RID"> </argument> <description> - Remove all shapes from a body. + Removes all shapes from a body. </description> </method> <method name="body_create"> @@ -342,7 +343,7 @@ <argument index="1" name="init_sleeping" type="bool" default="false"> </argument> <description> - Create a physics body. The first parameter can be any value from constants BODY_MODE*, for the type of body created. Additionally, the body can be created in sleeping state to save processing time. + Creates a physics body. The first parameter can be any value from constants BODY_MODE*, for the type of body created. Additionally, the body can be created in sleeping state to save processing time. </description> </method> <method name="body_get_collision_layer" qualifiers="const"> @@ -351,7 +352,7 @@ <argument index="0" name="body" type="RID"> </argument> <description> - Return the physics layer or layers a body belongs to. + Returns the physics layer or layers a body belongs to. </description> </method> <method name="body_get_collision_mask" qualifiers="const"> @@ -360,7 +361,7 @@ <argument index="0" name="body" type="RID"> </argument> <description> - Return the physics layer or layers a body can collide with. + Returns the physics layer or layers a body can collide with. </description> </method> <method name="body_get_continuous_collision_detection_mode" qualifiers="const"> @@ -369,7 +370,7 @@ <argument index="0" name="body" type="RID"> </argument> <description> - Return the continuous collision detection mode. + Returns the continuous collision detection mode. </description> </method> <method name="body_get_direct_state"> @@ -378,6 +379,7 @@ <argument index="0" name="body" type="RID"> </argument> <description> + Returns the [Physics2DDirectBodyState] of the body. </description> </method> <method name="body_get_max_contacts_reported" qualifiers="const"> @@ -386,7 +388,7 @@ <argument index="0" name="body" type="RID"> </argument> <description> - Return the maximum contacts that can be reported. See [method body_set_max_contacts_reported]. + Returns the maximum contacts that can be reported. See [method body_set_max_contacts_reported]. </description> </method> <method name="body_get_mode" qualifiers="const"> @@ -395,7 +397,7 @@ <argument index="0" name="body" type="RID"> </argument> <description> - Return the body mode. + Returns the body mode. </description> </method> <method name="body_get_object_instance_id" qualifiers="const"> @@ -404,7 +406,7 @@ <argument index="0" name="body" type="RID"> </argument> <description> - Get the instance ID of the object the area is assigned to. + Gets the instance ID of the object the area is assigned to. </description> </method> <method name="body_get_param" qualifiers="const"> @@ -415,7 +417,7 @@ <argument index="1" name="param" type="int" enum="Physics2DServer.BodyParameter"> </argument> <description> - Return the value of a body parameter. + Returns the value of a body parameter. A list of available parameters is on the BODY_PARAM_* constants. </description> </method> <method name="body_get_shape" qualifiers="const"> @@ -426,7 +428,7 @@ <argument index="1" name="shape_idx" type="int"> </argument> <description> - Return the [RID] of the nth shape of a body. + Returns the [RID] of the nth shape of a body. </description> </method> <method name="body_get_shape_count" qualifiers="const"> @@ -435,7 +437,7 @@ <argument index="0" name="body" type="RID"> </argument> <description> - Return the number of shapes assigned to a body. + Returns the number of shapes assigned to a body. </description> </method> <method name="body_get_shape_metadata" qualifiers="const"> @@ -446,7 +448,7 @@ <argument index="1" name="shape_idx" type="int"> </argument> <description> - Return the metadata of a shape of a body. + Returns the metadata of a shape of a body. </description> </method> <method name="body_get_shape_transform" qualifiers="const"> @@ -457,7 +459,7 @@ <argument index="1" name="shape_idx" type="int"> </argument> <description> - Return the transform matrix of a body shape. + Returns the transform matrix of a body shape. </description> </method> <method name="body_get_space" qualifiers="const"> @@ -466,7 +468,7 @@ <argument index="0" name="body" type="RID"> </argument> <description> - Return the [RID] of the space assigned to a body. + Returns the [RID] of the space assigned to a body. </description> </method> <method name="body_get_state" qualifiers="const"> @@ -477,7 +479,7 @@ <argument index="1" name="state" type="int" enum="Physics2DServer.BodyState"> </argument> <description> - Return a body state. + Returns a body state. </description> </method> <method name="body_is_omitting_force_integration" qualifiers="const"> @@ -486,7 +488,7 @@ <argument index="0" name="body" type="RID"> </argument> <description> - Return whether a body uses a callback function to calculate its own physics (see [method body_set_force_integration_callback]). + Returns whether a body uses a callback function to calculate its own physics (see [method body_set_force_integration_callback]). </description> </method> <method name="body_remove_collision_exception"> @@ -497,7 +499,7 @@ <argument index="1" name="excepted_body" type="RID"> </argument> <description> - Remove a body from the list of bodies exempt from collisions. + Removes a body from the list of bodies exempt from collisions. </description> </method> <method name="body_remove_shape"> @@ -508,7 +510,7 @@ <argument index="1" name="shape_idx" type="int"> </argument> <description> - Remove a shape from a body. The shape is not deleted, so it can be reused afterwards. + Removes a shape from a body. The shape is not deleted, so it can be reused afterwards. </description> </method> <method name="body_set_axis_velocity"> @@ -519,7 +521,7 @@ <argument index="1" name="axis_velocity" type="Vector2"> </argument> <description> - Set an axis velocity. The velocity in the given vector axis will be set as the given vector length. This is useful for jumping behavior. + Sets an axis velocity. The velocity in the given vector axis will be set as the given vector length. This is useful for jumping behavior. </description> </method> <method name="body_set_collision_layer"> @@ -530,7 +532,7 @@ <argument index="1" name="layer" type="int"> </argument> <description> - Set the physics layer or layers a body belongs to. + Sets the physics layer or layers a body belongs to. </description> </method> <method name="body_set_collision_mask"> @@ -541,7 +543,7 @@ <argument index="1" name="mask" type="int"> </argument> <description> - Set the physics layer or layers a body can collide with. + Sets the physics layer or layers a body can collide with. </description> </method> <method name="body_set_continuous_collision_detection_mode"> @@ -552,7 +554,7 @@ <argument index="1" name="mode" type="int" enum="Physics2DServer.CCDMode"> </argument> <description> - Set the continuous collision detection mode from any of the CCD_MODE_* constants. + Sets the continuous collision detection mode from any of the CCD_MODE_* constants. Continuous collision detection tries to predict where a moving body will collide, instead of moving it and correcting its movement if it collided. </description> </method> @@ -568,7 +570,7 @@ <argument index="3" name="userdata" type="Variant" default="null"> </argument> <description> - Set the function used to calculate physics for an object, if that object allows it (see [method body_set_omit_force integration]). + Sets the function used to calculate physics for an object, if that object allows it (see [method body_set_omit_force integration]). </description> </method> <method name="body_set_max_contacts_reported"> @@ -579,7 +581,7 @@ <argument index="1" name="amount" type="int"> </argument> <description> - Set the maximum contacts to report. Bodies can keep a log of the contacts with other bodies, this is enabled by setting the maximum amount of contacts reported to a number greater than 0. + Sets the maximum contacts to report. Bodies can keep a log of the contacts with other bodies, this is enabled by setting the maximum amount of contacts reported to a number greater than 0. </description> </method> <method name="body_set_mode"> @@ -590,7 +592,7 @@ <argument index="1" name="mode" type="int" enum="Physics2DServer.BodyMode"> </argument> <description> - Set the body mode, from one of the constants BODY_MODE*. + Sets the body mode, from one of the constants BODY_MODE*. </description> </method> <method name="body_set_omit_force_integration"> @@ -601,7 +603,7 @@ <argument index="1" name="enable" type="bool"> </argument> <description> - Set whether a body uses a callback function to calculate its own physics (see [method body_set_force_integration_callback]). + Sets whether a body uses a callback function to calculate its own physics (see [method body_set_force_integration_callback]). </description> </method> <method name="body_set_param"> @@ -614,7 +616,7 @@ <argument index="2" name="value" type="float"> </argument> <description> - Set a body parameter (see BODY_PARAM* constants). + Sets a body parameter. A list of available parameters is on the BODY_PARAM_* constants. </description> </method> <method name="body_set_shape"> @@ -627,7 +629,7 @@ <argument index="2" name="shape" type="RID"> </argument> <description> - Substitute a given body shape by another. The old shape is selected by its index, the new one by its [RID]. + Substitutes a given body shape by another. The old shape is selected by its index, the new one by its [RID]. </description> </method> <method name="body_set_shape_as_one_way_collision"> @@ -640,6 +642,7 @@ <argument index="2" name="enable" type="bool"> </argument> <description> + Enables one way collision on body if [code]enable is true[/code]. </description> </method> <method name="body_set_shape_disabled"> @@ -652,6 +655,7 @@ <argument index="2" name="disable" type="bool"> </argument> <description> + Disables shape in body if [code]disable is true[/code]. </description> </method> <method name="body_set_shape_metadata"> @@ -664,7 +668,7 @@ <argument index="2" name="metadata" type="Variant"> </argument> <description> - Set metadata of a shape within a body. This metadata is different from [method Object.set_meta], and can be retrieved on shape queries. + Sets metadata of a shape within a body. This metadata is different from [method Object.set_meta], and can be retrieved on shape queries. </description> </method> <method name="body_set_shape_transform"> @@ -677,7 +681,7 @@ <argument index="2" name="transform" type="Transform2D"> </argument> <description> - Set the transform matrix for a body shape. + Sets the transform matrix for a body shape. </description> </method> <method name="body_set_space"> @@ -688,7 +692,7 @@ <argument index="1" name="space" type="RID"> </argument> <description> - Assign a space to the body (see [method create_space]). + Assigns a space to the body (see [method create_space]). </description> </method> <method name="body_set_state"> @@ -701,7 +705,7 @@ <argument index="2" name="value" type="Variant"> </argument> <description> - Set a body state (see BODY_STATE* constants). + Sets a body state (see BODY_STATE* constants). </description> </method> <method name="body_test_motion"> @@ -718,7 +722,7 @@ <argument index="4" name="result" type="Physics2DTestMotionResult" default="null"> </argument> <description> - Return whether a body can move from a given point in a given direction. Apart from the boolean return value, a [Physics2DTestMotionResult] can be passed to return additional information in. + Returns whether a body can move from a given point in a given direction. Apart from the boolean return value, a [Physics2DTestMotionResult] can be passed to return additional information in. </description> </method> <method name="damped_spring_joint_create"> @@ -733,7 +737,7 @@ <argument index="3" name="body_b" type="RID"> </argument> <description> - Create a damped spring joint between two bodies. If not specified, the second body is assumed to be the joint itself. + Creates a damped spring joint between two bodies. If not specified, the second body is assumed to be the joint itself. </description> </method> <method name="damped_string_joint_get_param" qualifiers="const"> @@ -744,7 +748,7 @@ <argument index="1" name="param" type="int" enum="Physics2DServer.DampedStringParam"> </argument> <description> - Return the value of a damped spring joint parameter. + Returns the value of a damped spring joint parameter. </description> </method> <method name="damped_string_joint_set_param"> @@ -757,7 +761,7 @@ <argument index="2" name="value" type="float"> </argument> <description> - Set a damped spring joint parameter. Parameters are explained in the DAMPED_STRING* constants. + Sets a damped spring joint parameter. Parameters are explained in the DAMPED_STRING* constants. </description> </method> <method name="free_rid"> @@ -766,7 +770,7 @@ <argument index="0" name="rid" type="RID"> </argument> <description> - Destroy any of the objects created by Physics2DServer. If the [RID] passed is not one of the objects that can be created by Physics2DServer, an error will be sent to the console. + Destroys any of the objects created by Physics2DServer. If the [RID] passed is not one of the objects that can be created by Physics2DServer, an error will be sent to the console. </description> </method> <method name="get_process_info"> @@ -775,7 +779,7 @@ <argument index="0" name="process_info" type="int" enum="Physics2DServer.ProcessInfo"> </argument> <description> - Return information about the current state of the 2D physics engine. The states are listed under the INFO_* constants. + Returns information about the current state of the 2D physics engine. The states are listed under the INFO_* constants. </description> </method> <method name="groove_joint_create"> @@ -792,7 +796,7 @@ <argument index="4" name="body_b" type="RID"> </argument> <description> - Create a groove joint between two bodies. If not specified, the bodyies are assumed to be the joint itself. + Creates a groove joint between two bodies. If not specified, the bodyies are assumed to be the joint itself. </description> </method> <method name="joint_get_param" qualifiers="const"> @@ -803,7 +807,7 @@ <argument index="1" name="param" type="int" enum="Physics2DServer.JointParam"> </argument> <description> - Return the value of a joint parameter. + Returns the value of a joint parameter. </description> </method> <method name="joint_get_type" qualifiers="const"> @@ -812,7 +816,7 @@ <argument index="0" name="joint" type="RID"> </argument> <description> - Return the type of a joint (see JOINT_* constants). + Returns the type of a joint (see JOINT_* constants). </description> </method> <method name="joint_set_param"> @@ -825,7 +829,7 @@ <argument index="2" name="value" type="float"> </argument> <description> - Set a joint parameter. Parameters are explained in the JOINT_PARAM* constants. + Sets a joint parameter. Parameters are explained in the JOINT_PARAM* constants. </description> </method> <method name="pin_joint_create"> @@ -838,7 +842,7 @@ <argument index="2" name="body_b" type="RID"> </argument> <description> - Create a pin joint between two bodies. If not specified, the second body is assumed to be the joint itself. + Creates a pin joint between two bodies. If not specified, the second body is assumed to be the joint itself. </description> </method> <method name="set_active"> @@ -847,7 +851,7 @@ <argument index="0" name="active" type="bool"> </argument> <description> - Activate or deactivate the 2D physics engine. + Activates or deactivates the 2D physics engine. </description> </method> <method name="shape_create"> @@ -856,7 +860,7 @@ <argument index="0" name="type" type="int" enum="Physics2DServer.ShapeType"> </argument> <description> - Create a shape of type SHAPE_*. Does not assign it to a body or an area. To do so, you must use [method area_set_shape] or [method body_set_shape]. + Creates a shape of type SHAPE_*. Does not assign it to a body or an area. To do so, you must use [method area_set_shape] or [method body_set_shape]. </description> </method> <method name="shape_get_data" qualifiers="const"> @@ -865,7 +869,7 @@ <argument index="0" name="shape" type="RID"> </argument> <description> - Return the shape data. + Returns the shape data. </description> </method> <method name="shape_get_type" qualifiers="const"> @@ -874,7 +878,7 @@ <argument index="0" name="shape" type="RID"> </argument> <description> - Return the type of shape (see SHAPE_* constants). + Returns the type of shape (see SHAPE_* constants). </description> </method> <method name="shape_set_data"> @@ -885,14 +889,14 @@ <argument index="1" name="data" type="Variant"> </argument> <description> - Set the shape data that defines its shape and size. The data to be passed depends on the kind of shape created [method shape_get_type]. + Sets the shape data that defines its shape and size. The data to be passed depends on the kind of shape created [method shape_get_type]. </description> </method> <method name="space_create"> <return type="RID"> </return> <description> - Create a space. A space is a collection of parameters for the physics engine that can be assigned to an area or a body. It can be assigned to an area with [method area_set_space], or to a body with [method body_set_space]. + Creates a space. A space is a collection of parameters for the physics engine that can be assigned to an area or a body. It can be assigned to an area with [method area_set_space], or to a body with [method body_set_space]. </description> </method> <method name="space_get_direct_state"> @@ -901,7 +905,7 @@ <argument index="0" name="space" type="RID"> </argument> <description> - Return the state of a space, a [Physics2DDirectSpaceState]. This object can be used to make collision/intersection queries. + Returns the state of a space, a [Physics2DDirectSpaceState]. This object can be used to make collision/intersection queries. </description> </method> <method name="space_get_param" qualifiers="const"> @@ -912,7 +916,7 @@ <argument index="1" name="param" type="int" enum="Physics2DServer.SpaceParameter"> </argument> <description> - Return the value of a space parameter. + Returns the value of a space parameter. </description> </method> <method name="space_is_active" qualifiers="const"> @@ -921,7 +925,7 @@ <argument index="0" name="space" type="RID"> </argument> <description> - Return whether the space is active. + Returns whether the space is active. </description> </method> <method name="space_set_active"> @@ -932,7 +936,7 @@ <argument index="1" name="active" type="bool"> </argument> <description> - Mark a space as active. It will not have an effect, unless it is assigned to an area or body. + Marks a space as active. It will not have an effect, unless it is assigned to an area or body. </description> </method> <method name="space_set_param"> @@ -945,7 +949,7 @@ <argument index="2" name="value" type="float"> </argument> <description> - Set the value for a space parameter. A list of available parameters is on the SPACE_PARAM_* constants. + Sets the value for a space parameter. A list of available parameters is on the SPACE_PARAM_* constants. </description> </method> </methods> @@ -960,8 +964,10 @@ Constant to set/get the maximum distance a shape can penetrate another shape before it is considered a collision. </constant> <constant name="SPACE_PARAM_BODY_LINEAR_VELOCITY_SLEEP_THRESHOLD" value="3"> + Constant to set/get the threshold linear velocity of activity. A body marked as potentially inactive for both linear and angular velocity will be put to sleep after the time given. </constant> <constant name="SPACE_PARAM_BODY_ANGULAR_VELOCITY_SLEEP_THRESHOLD" value="4"> + Constant to set/get the threshold angular velocity of activity. A body marked as potentially inactive for both linear and angular velocity will be put to sleep after the time given. </constant> <constant name="SPACE_PARAM_BODY_TIME_TO_SLEEP" value="5"> Constant to set/get the maximum time of activity. A body marked as potentially inactive for both linear and angular velocity will be put to sleep after this time. @@ -985,7 +991,7 @@ This is the constant for creating capsule shapes. A capsule shape is defined by a radius and a length. It can be used for intersections and inside/outside checks. </constant> <constant name="SHAPE_CONVEX_POLYGON" value="6"> - This is the constant for creating convex polygon shapes. A polygon is defined by a list of points. It can be used for intersections and inside/outside checks. Unlike the method [method CollisionPolygon2D.set_polygon], polygons modified with [method shape_set_data] do not verify that the points supplied form, in fact, a convex polygon. + This is the constant for creating convex polygon shapes. A polygon is defined by a list of points. It can be used for intersections and inside/outside checks. Unlike the method [method CollisionPolygon2D.set_polygon], polygons modified with [method shape_set_data] do not verify that the points supplied form is a convex polygon. </constant> <constant name="SHAPE_CONCAVE_POLYGON" value="7"> This is the constant for creating concave polygon shapes. A polygon is defined by a list of points. It can be used for intersections checks, but not for inside/outside checks. diff --git a/doc/classes/Physics2DServerSW.xml b/doc/classes/Physics2DServerSW.xml index a8645c0b96..67fd7a21d8 100644 --- a/doc/classes/Physics2DServerSW.xml +++ b/doc/classes/Physics2DServerSW.xml @@ -4,7 +4,7 @@ Software implementation of [Physics2DServer]. </brief_description> <description> - Software implementation of [Physics2DServer]. This class exposes no new methods or properties and should not be used, as [Physics2DServer] automatically selects the best implementation available. + This class exposes no new methods or properties and should not be used, as [Physics2DServer] automatically selects the best implementation available. </description> <tutorials> </tutorials> diff --git a/doc/classes/PhysicsServer.xml b/doc/classes/PhysicsServer.xml index e6c81825ad..12c1abccc6 100644 --- a/doc/classes/PhysicsServer.xml +++ b/doc/classes/PhysicsServer.xml @@ -1,8 +1,10 @@ <?xml version="1.0" encoding="UTF-8" ?> <class name="PhysicsServer" inherits="Object" category="Core" version="3.0.alpha.custom_build"> <brief_description> + Server interface for low level physics access. </brief_description> <description> + Everything related to physics in 3D. </description> <tutorials> </tutorials> @@ -19,6 +21,7 @@ <argument index="2" name="transform" type="Transform" default="Transform( 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0 )"> </argument> <description> + Adds a shape to the area, along with a transform matrix. Shapes are usually referenced by their index, so you should track which shape has a given index. </description> </method> <method name="area_attach_object_instance_id"> @@ -29,6 +32,7 @@ <argument index="1" name="id" type="int"> </argument> <description> + Assigns the area to a descendant of [Object], so it can exist in the node tree. </description> </method> <method name="area_clear_shapes"> @@ -37,12 +41,14 @@ <argument index="0" name="area" type="RID"> </argument> <description> + Removes all shapes from an area. It does not delete the shapes, so they can be reassigned later. </description> </method> <method name="area_create"> <return type="RID"> </return> <description> + Creates an [Area]. </description> </method> <method name="area_get_object_instance_id" qualifiers="const"> @@ -51,6 +57,7 @@ <argument index="0" name="area" type="RID"> </argument> <description> + Gets the instance ID of the object the area is assigned to. </description> </method> <method name="area_get_param" qualifiers="const"> @@ -61,6 +68,7 @@ <argument index="1" name="param" type="int" enum="PhysicsServer.AreaParameter"> </argument> <description> + Returns an area parameter value. A list of available parameters is on the AREA_PARAM_* constants. </description> </method> <method name="area_get_shape" qualifiers="const"> @@ -71,6 +79,7 @@ <argument index="1" name="shape_idx" type="int"> </argument> <description> + Returns the [RID] of the nth shape of an area. </description> </method> <method name="area_get_shape_count" qualifiers="const"> @@ -79,6 +88,7 @@ <argument index="0" name="area" type="RID"> </argument> <description> + Returns the number of shapes assigned to an area. </description> </method> <method name="area_get_shape_transform" qualifiers="const"> @@ -89,6 +99,7 @@ <argument index="1" name="shape_idx" type="int"> </argument> <description> + Returns the transform matrix of a shape within an area. </description> </method> <method name="area_get_space" qualifiers="const"> @@ -97,6 +108,7 @@ <argument index="0" name="area" type="RID"> </argument> <description> + Returns the space assigned to the area. </description> </method> <method name="area_get_space_override_mode" qualifiers="const"> @@ -105,6 +117,7 @@ <argument index="0" name="area" type="RID"> </argument> <description> + Returns the space override mode for the area. </description> </method> <method name="area_get_transform" qualifiers="const"> @@ -113,6 +126,7 @@ <argument index="0" name="area" type="RID"> </argument> <description> + Returns the transform matrix for an area. </description> </method> <method name="area_is_ray_pickable" qualifiers="const"> @@ -121,6 +135,7 @@ <argument index="0" name="area" type="RID"> </argument> <description> + If [code]true[/code] area collides with rays. </description> </method> <method name="area_remove_shape"> @@ -131,6 +146,7 @@ <argument index="1" name="shape_idx" type="int"> </argument> <description> + Removes a shape from an area. It does not delete the shape, so it can be reassigned later. </description> </method> <method name="area_set_collision_layer"> @@ -141,6 +157,7 @@ <argument index="1" name="layer" type="int"> </argument> <description> + Assigns the area to one or many physics layers. </description> </method> <method name="area_set_collision_mask"> @@ -151,6 +168,7 @@ <argument index="1" name="mask" type="int"> </argument> <description> + Sets which physics layers the area will monitor. </description> </method> <method name="area_set_monitor_callback"> @@ -163,6 +181,12 @@ <argument index="2" name="method" type="String"> </argument> <description> + Sets the function to call when any body/area enters or exits the area. This callback will be called for any object interacting with the area, and takes five parameters: + 1: AREA_BODY_ADDED or AREA_BODY_REMOVED, depending on whether the object entered or exited the area. + 2: [RID] of the object that entered/exited the area. + 3: Instance ID of the object that entered/exited the area. + 4: The shape index of the object that entered/exited the area. + 5: The shape index of the area where the object entered/exited. </description> </method> <method name="area_set_param"> @@ -175,6 +199,7 @@ <argument index="2" name="value" type="Variant"> </argument> <description> + Sets the value for an area parameter. A list of available parameters is on the AREA_PARAM_* constants. </description> </method> <method name="area_set_ray_pickable"> @@ -185,6 +210,7 @@ <argument index="1" name="enable" type="bool"> </argument> <description> + Sets object pickable with rays. </description> </method> <method name="area_set_shape"> @@ -197,6 +223,7 @@ <argument index="2" name="shape" type="RID"> </argument> <description> + Substitutes a given area shape by another. The old shape is selected by its index, the new one by its [RID]. </description> </method> <method name="area_set_shape_transform"> @@ -209,6 +236,7 @@ <argument index="2" name="transform" type="Transform"> </argument> <description> + Sets the transform matrix for an area shape. </description> </method> <method name="area_set_space"> @@ -219,6 +247,7 @@ <argument index="1" name="space" type="RID"> </argument> <description> + Assigns a space to the area. </description> </method> <method name="area_set_space_override_mode"> @@ -229,6 +258,7 @@ <argument index="1" name="mode" type="int" enum="PhysicsServer.AreaSpaceOverrideMode"> </argument> <description> + Sets the space override mode for the area. The modes are described in the constants AREA_SPACE_OVERRIDE_*. </description> </method> <method name="area_set_transform"> @@ -239,6 +269,7 @@ <argument index="1" name="transform" type="Transform"> </argument> <description> + Sets the transform matrix for an area. </description> </method> <method name="body_add_collision_exception"> @@ -249,6 +280,7 @@ <argument index="1" name="excepted_body" type="RID"> </argument> <description> + Adds a body to the list of bodies exempt from collisions. </description> </method> <method name="body_add_shape"> @@ -261,6 +293,7 @@ <argument index="2" name="transform" type="Transform" default="Transform( 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0 )"> </argument> <description> + Adds a shape to the body, along with a transform matrix. Shapes are usually referenced by their index, so you should track which shape has a given index. </description> </method> <method name="body_apply_impulse"> @@ -273,6 +306,7 @@ <argument index="2" name="impulse" type="Vector3"> </argument> <description> + Gives the body a push at a [code]position[/code] in the direction of the [code]impulse[/code]. </description> </method> <method name="body_apply_torque_impulse"> @@ -283,6 +317,7 @@ <argument index="1" name="impulse" type="Vector3"> </argument> <description> + Gives the body a push to rotate it. </description> </method> <method name="body_attach_object_instance_id"> @@ -293,6 +328,7 @@ <argument index="1" name="id" type="int"> </argument> <description> + Assigns the area to a descendant of [Object], so it can exist in the node tree. </description> </method> <method name="body_clear_shapes"> @@ -301,6 +337,7 @@ <argument index="0" name="body" type="RID"> </argument> <description> + Removes all shapes from a body. </description> </method> <method name="body_create"> @@ -311,6 +348,7 @@ <argument index="1" name="init_sleeping" type="bool" default="false"> </argument> <description> + Creates a physics body. The first parameter can be any value from constants BODY_MODE*, for the type of body created. Additionally, the body can be created in sleeping state to save processing time. </description> </method> <method name="body_get_axis_lock" qualifiers="const"> @@ -319,6 +357,7 @@ <argument index="0" name="body" type="RID"> </argument> <description> + Gets the information, which Axis is locked if any. The can be any calue from the constants BODY_AXIS_LOCK* </description> </method> <method name="body_get_collision_layer" qualifiers="const"> @@ -327,6 +366,7 @@ <argument index="0" name="body" type="RID"> </argument> <description> + Returns the physics layer or layers a body belongs to. </description> </method> <method name="body_get_collision_mask" qualifiers="const"> @@ -335,14 +375,16 @@ <argument index="0" name="body" type="RID"> </argument> <description> - </description> - </method> - <method name="body_get_direct_state"> - <return type="PhysicsDirectBodyState"> - </return> - <argument index="0" name="body" type="RID"> - </argument> - <description> + Returns the physics layer or layers a body can collide with. +- </description> +- </method> +- <method name="body_get_direct_state"> +- <return type="PhysicsDirectBodyState"> +- </return> +- <argument index="0" name="body" type="RID"> +- </argument> +- <description> + Returns the [PhysicsDirectBodyState] of the body. </description> </method> <method name="body_get_max_contacts_reported" qualifiers="const"> @@ -351,6 +393,7 @@ <argument index="0" name="body" type="RID"> </argument> <description> + Returns the maximum contacts that can be reported. See [method body_set_max_contacts_reported]. </description> </method> <method name="body_get_mode" qualifiers="const"> @@ -359,6 +402,7 @@ <argument index="0" name="body" type="RID"> </argument> <description> + Returns the body mode. </description> </method> <method name="body_get_object_instance_id" qualifiers="const"> @@ -367,6 +411,7 @@ <argument index="0" name="body" type="RID"> </argument> <description> + Gets the instance ID of the object the area is assigned to. </description> </method> <method name="body_get_param" qualifiers="const"> @@ -377,6 +422,7 @@ <argument index="1" name="param" type="int" enum="PhysicsServer.BodyParameter"> </argument> <description> + Returns the value of a body parameter. A list of available parameters is on the BODY_PARAM_* constants. </description> </method> <method name="body_get_shape" qualifiers="const"> @@ -387,6 +433,7 @@ <argument index="1" name="shape_idx" type="int"> </argument> <description> + Returns the [RID] of the nth shape of a body. </description> </method> <method name="body_get_shape_count" qualifiers="const"> @@ -395,6 +442,7 @@ <argument index="0" name="body" type="RID"> </argument> <description> + Returns the number of shapes assigned to a body. </description> </method> <method name="body_get_shape_transform" qualifiers="const"> @@ -405,6 +453,7 @@ <argument index="1" name="shape_idx" type="int"> </argument> <description> + Returns the transform matrix of a body shape. </description> </method> <method name="body_get_space" qualifiers="const"> @@ -413,6 +462,7 @@ <argument index="0" name="body" type="RID"> </argument> <description> + Returns the [RID] of the space assigned to a body. </description> </method> <method name="body_get_state" qualifiers="const"> @@ -423,6 +473,7 @@ <argument index="1" name="state" type="int" enum="PhysicsServer.BodyState"> </argument> <description> + Returns a body state. </description> </method> <method name="body_is_continuous_collision_detection_enabled" qualifiers="const"> @@ -431,6 +482,7 @@ <argument index="0" name="body" type="RID"> </argument> <description> + If [code]true[/code] the continuous collision detection mode is enabled. </description> </method> <method name="body_is_omitting_force_integration" qualifiers="const"> @@ -439,6 +491,7 @@ <argument index="0" name="body" type="RID"> </argument> <description> + Returns whether a body uses a callback function to calculate its own physics (see [method body_set_force_integration_callback]). </description> </method> <method name="body_is_ray_pickable" qualifiers="const"> @@ -447,6 +500,7 @@ <argument index="0" name="body" type="RID"> </argument> <description> + If [code]true[/code] the body can be detected by rays </description> </method> <method name="body_remove_collision_exception"> @@ -457,6 +511,8 @@ <argument index="1" name="excepted_body" type="RID"> </argument> <description> + Removes a body from the list of bodies exempt from collisions. + Continuous collision detection tries to predict where a moving body will collide, instead of moving it and correcting its movement if it collided. </description> </method> <method name="body_remove_shape"> @@ -467,6 +523,7 @@ <argument index="1" name="shape_idx" type="int"> </argument> <description> + Removes a shape from a body. The shape is not deleted, so it can be reused afterwards. </description> </method> <method name="body_set_axis_lock"> @@ -477,6 +534,7 @@ <argument index="1" name="axis" type="int" enum="PhysicsServer.BodyAxisLock"> </argument> <description> + Locks velocity along one axis to 0 and only allows rotation along this axis, can also be set to disabled which disables this functionality. </description> </method> <method name="body_set_axis_velocity"> @@ -487,6 +545,7 @@ <argument index="1" name="axis_velocity" type="Vector3"> </argument> <description> + Sets an axis velocity. The velocity in the given vector axis will be set as the given vector length. This is useful for jumping behavior. </description> </method> <method name="body_set_collision_layer"> @@ -497,6 +556,7 @@ <argument index="1" name="layer" type="int"> </argument> <description> + Sets the physics layer or layers a body belongs to. </description> </method> <method name="body_set_collision_mask"> @@ -507,6 +567,7 @@ <argument index="1" name="mask" type="int"> </argument> <description> + Sets the physics layer or layers a body can collide with. </description> </method> <method name="body_set_enable_continuous_collision_detection"> @@ -517,6 +578,8 @@ <argument index="1" name="enable" type="bool"> </argument> <description> + If [code]true[/code] the continuous collision detection mode is enabled. + Continuous collision detection tries to predict where a moving body will collide, instead of moving it and correcting its movement if it collided. </description> </method> <method name="body_set_force_integration_callback"> @@ -531,6 +594,7 @@ <argument index="3" name="userdata" type="Variant" default="null"> </argument> <description> + Sets the function used to calculate physics for an object, if that object allows it (see [method body_set_omit_force integration]). </description> </method> <method name="body_set_max_contacts_reported"> @@ -541,6 +605,7 @@ <argument index="1" name="amount" type="int"> </argument> <description> + Sets the maximum contacts to report. Bodies can keep a log of the contacts with other bodies, this is enabled by setting the maximum amount of contacts reported to a number greater than 0. </description> </method> <method name="body_set_mode"> @@ -551,6 +616,7 @@ <argument index="1" name="mode" type="int" enum="PhysicsServer.BodyMode"> </argument> <description> + Sets the body mode, from one of the constants BODY_MODE*. </description> </method> <method name="body_set_omit_force_integration"> @@ -561,6 +627,7 @@ <argument index="1" name="enable" type="bool"> </argument> <description> + Sets whether a body uses a callback function to calculate its own physics (see [method body_set_force_integration_callback]). </description> </method> <method name="body_set_param"> @@ -573,6 +640,7 @@ <argument index="2" name="value" type="float"> </argument> <description> + Sets a body parameter. A list of available parameters is on the BODY_PARAM_* constants. </description> </method> <method name="body_set_ray_pickable"> @@ -583,6 +651,7 @@ <argument index="1" name="enable" type="bool"> </argument> <description> + Sets the body pickable with rays if [code]enabled[/code] is set. </description> </method> <method name="body_set_shape"> @@ -595,6 +664,7 @@ <argument index="2" name="shape" type="RID"> </argument> <description> + Substitutes a given body shape by another. The old shape is selected by its index, the new one by its [RID]. </description> </method> <method name="body_set_shape_transform"> @@ -607,6 +677,7 @@ <argument index="2" name="transform" type="Transform"> </argument> <description> + Sets the transform matrix for a body shape. </description> </method> <method name="body_set_space"> @@ -617,6 +688,7 @@ <argument index="1" name="space" type="RID"> </argument> <description> + Assigns a space to the body (see [method create_space]). </description> </method> <method name="body_set_state"> @@ -629,6 +701,7 @@ <argument index="2" name="value" type="Variant"> </argument> <description> + Sets a body state (see BODY_STATE* constants). </description> </method> <method name="cone_twist_joint_get_param" qualifiers="const"> @@ -639,6 +712,7 @@ <argument index="1" name="param" type="int" enum="PhysicsServer.ConeTwistJointParam"> </argument> <description> + Gets a cone_twist_joint parameter (see CONE_TWIST_JOINT* constants). </description> </method> <method name="cone_twist_joint_set_param"> @@ -651,6 +725,7 @@ <argument index="2" name="value" type="float"> </argument> <description> + Sets a cone_twist_joint parameter (see CONE_TWIST_JOINT* constants). </description> </method> <method name="free_rid"> @@ -659,6 +734,7 @@ <argument index="0" name="rid" type="RID"> </argument> <description> + Destroys any of the objects created by PhysicsServer. If the [RID] passed is not one of the objects that can be created by PhysicsServer, an error will be sent to the console. </description> </method> <method name="generic_6dof_joint_get_flag"> @@ -670,7 +746,8 @@ </argument> <argument index="2" name="flag" type="int" enum="PhysicsServer.G6DOFJointAxisFlag"> </argument> - <description> + <description> + Gets a generic_6_DOF_joint flag (see G6DOF_JOINT_FLAG* constants). </description> </method> <method name="generic_6dof_joint_get_param"> @@ -683,6 +760,7 @@ <argument index="2" name="param" type="int" enum="PhysicsServer.G6DOFJointAxisParam"> </argument> <description> + Gets a generic_6_DOF_joint parameter (see G6DOF_JOINT* constants without the G6DOF_JOINT_FLAG*). </description> </method> <method name="generic_6dof_joint_set_flag"> @@ -697,6 +775,7 @@ <argument index="3" name="enable" type="bool"> </argument> <description> + Sets a generic_6_DOF_joint flag (see G6DOF_JOINT_FLAG* constants). </description> </method> <method name="generic_6dof_joint_set_param"> @@ -711,6 +790,7 @@ <argument index="3" name="value" type="float"> </argument> <description> + Sets a generic_6_DOF_joint parameter (see G6DOF_JOINT* constants without the G6DOF_JOINT_FLAG*). </description> </method> <method name="get_process_info"> @@ -719,6 +799,7 @@ <argument index="0" name="process_info" type="int" enum="PhysicsServer.ProcessInfo"> </argument> <description> + Returns an Info defined by the [ProcessInfo] input given. </description> </method> <method name="hinge_joint_get_flag" qualifiers="const"> @@ -729,6 +810,7 @@ <argument index="1" name="flag" type="int" enum="PhysicsServer.HingeJointFlag"> </argument> <description> + Gets a hinge_joint flag (see HINGE_JOINT_FLAG* constants). </description> </method> <method name="hinge_joint_get_param" qualifiers="const"> @@ -739,6 +821,7 @@ <argument index="1" name="param" type="int" enum="PhysicsServer.HingeJointParam"> </argument> <description> + Gets a hinge_joint parameter (see HINGE_JOINT* constants without the HINGE_JOINT_FLAG*). </description> </method> <method name="hinge_joint_set_flag"> @@ -751,6 +834,7 @@ <argument index="2" name="enabled" type="bool"> </argument> <description> + Sets a hinge_joint flag (see HINGE_JOINT_FLAG* constants). </description> </method> <method name="hinge_joint_set_param"> @@ -763,6 +847,7 @@ <argument index="2" name="value" type="float"> </argument> <description> + Sets a hinge_joint parameter (see HINGE_JOINT* constants without the HINGE_JOINT_FLAG*). </description> </method> <method name="joint_create_cone_twist"> @@ -777,6 +862,7 @@ <argument index="3" name="local_ref_B" type="Transform"> </argument> <description> + Creates a [ConeTwistJoint]. </description> </method> <method name="joint_create_generic_6dof"> @@ -791,6 +877,7 @@ <argument index="3" name="local_ref_B" type="Transform"> </argument> <description> + Creates a [Generic6DOFJoint]. </description> </method> <method name="joint_create_hinge"> @@ -805,6 +892,7 @@ <argument index="3" name="hinge_B" type="Transform"> </argument> <description> + Creates a [HingeJoint]. </description> </method> <method name="joint_create_pin"> @@ -819,6 +907,7 @@ <argument index="3" name="local_B" type="Vector3"> </argument> <description> + Creates a [PinJoint]. </description> </method> <method name="joint_create_slider"> @@ -833,6 +922,7 @@ <argument index="3" name="local_ref_B" type="Transform"> </argument> <description> + Creates a [SliderJoint]. </description> </method> <method name="joint_get_solver_priority" qualifiers="const"> @@ -841,6 +931,7 @@ <argument index="0" name="joint" type="RID"> </argument> <description> + Gets the priority value of the Joint. </description> </method> <method name="joint_get_type" qualifiers="const"> @@ -849,6 +940,7 @@ <argument index="0" name="joint" type="RID"> </argument> <description> + Returns the type of the Joint. </description> </method> <method name="joint_set_solver_priority"> @@ -859,6 +951,7 @@ <argument index="1" name="priority" type="int"> </argument> <description> + Sets the priority value of the Joint. </description> </method> <method name="pin_joint_get_local_a" qualifiers="const"> @@ -867,6 +960,7 @@ <argument index="0" name="joint" type="RID"> </argument> <description> + Returns position of the joint in the local space of body a of the joint. </description> </method> <method name="pin_joint_get_local_b" qualifiers="const"> @@ -875,6 +969,7 @@ <argument index="0" name="joint" type="RID"> </argument> <description> + Returns position of the joint in the local space of body b of the joint. </description> </method> <method name="pin_joint_get_param" qualifiers="const"> @@ -885,6 +980,7 @@ <argument index="1" name="param" type="int" enum="PhysicsServer.PinJointParam"> </argument> <description> + Gets a pin_joint parameter (see PIN_JOINT* constants). </description> </method> <method name="pin_joint_set_local_a"> @@ -895,6 +991,7 @@ <argument index="1" name="local_A" type="Vector3"> </argument> <description> + Sets position of the joint in the local space of body a of the joint. </description> </method> <method name="pin_joint_set_local_b"> @@ -905,6 +1002,7 @@ <argument index="1" name="local_B" type="Vector3"> </argument> <description> + Sets position of the joint in the local space of body b of the joint. </description> </method> <method name="pin_joint_set_param"> @@ -917,6 +1015,7 @@ <argument index="2" name="value" type="float"> </argument> <description> + Sets a pin_joint parameter (see PIN_JOINT* constants). </description> </method> <method name="set_active"> @@ -925,6 +1024,7 @@ <argument index="0" name="active" type="bool"> </argument> <description> + Activates or deactivates the 3D physics engine. </description> </method> <method name="shape_create"> @@ -933,6 +1033,7 @@ <argument index="0" name="type" type="int" enum="PhysicsServer.ShapeType"> </argument> <description> + Creates a shape of type SHAPE_*. Does not assign it to a body or an area. To do so, you must use [method area_set_shape] or [method body_set_shape]. </description> </method> <method name="shape_get_data" qualifiers="const"> @@ -941,6 +1042,7 @@ <argument index="0" name="shape" type="RID"> </argument> <description> + Returns the shape data. </description> </method> <method name="shape_get_type" qualifiers="const"> @@ -949,6 +1051,7 @@ <argument index="0" name="shape" type="RID"> </argument> <description> + Returns the type of shape (see SHAPE_* constants). </description> </method> <method name="shape_set_data"> @@ -959,6 +1062,7 @@ <argument index="1" name="data" type="Variant"> </argument> <description> + Sets the shape data that defines its shape and size. The data to be passed depends on the kind of shape created [method shape_get_type]. </description> </method> <method name="slider_joint_get_param" qualifiers="const"> @@ -969,6 +1073,7 @@ <argument index="1" name="param" type="int" enum="PhysicsServer.SliderJointParam"> </argument> <description> + Gets a slider_joint parameter (see SLIDER_JOINT* constants). </description> </method> <method name="slider_joint_set_param"> @@ -981,12 +1086,14 @@ <argument index="2" name="value" type="float"> </argument> <description> + Gets a slider_joint parameter (see SLIDER_JOINT* constants). </description> </method> <method name="space_create"> <return type="RID"> </return> <description> + Creates a space. A space is a collection of parameters for the physics engine that can be assigned to an area or a body. It can be assigned to an area with [method area_set_space], or to a body with [method body_set_space]. </description> </method> <method name="space_get_direct_state"> @@ -995,6 +1102,7 @@ <argument index="0" name="space" type="RID"> </argument> <description> + Returns the state of a space, a [PhysicsDirectSpaceState]. This object can be used to make collision/intersection queries. </description> </method> <method name="space_get_param" qualifiers="const"> @@ -1005,6 +1113,7 @@ <argument index="1" name="param" type="int" enum="PhysicsServer.SpaceParameter"> </argument> <description> + Returns the value of a space parameter. </description> </method> <method name="space_is_active" qualifiers="const"> @@ -1013,6 +1122,7 @@ <argument index="0" name="space" type="RID"> </argument> <description> + Returns whether the space is active. </description> </method> <method name="space_set_active"> @@ -1023,6 +1133,7 @@ <argument index="1" name="active" type="bool"> </argument> <description> + Marks a space as active. It will not have an effect, unless it is assigned to an area or body. </description> </method> <method name="space_set_param"> @@ -1035,169 +1146,256 @@ <argument index="2" name="value" type="float"> </argument> <description> + Sets the value for a space parameter. A list of available parameters is on the SPACE_PARAM_* constants. </description> </method> </methods> <constants> <constant name="JOINT_PIN" value="0"> + The [Joint] is a [PinJoint]. </constant> <constant name="JOINT_HINGE" value="1"> + The [Joint] is a [HingeJoint]. </constant> <constant name="JOINT_SLIDER" value="2"> + The [Joint] is a [SliderJoint]. </constant> <constant name="JOINT_CONE_TWIST" value="3"> + The [Joint] is a [ConeTwistJoint]. </constant> <constant name="JOINT_6DOF" value="4"> + The [Joint] is a [Generic6DOFJoint]. </constant> <constant name="PIN_JOINT_BIAS" value="0"> + The strength with which the pinned objects try to stay in positional relation to each other. + The higher, the stronger. </constant> <constant name="PIN_JOINT_DAMPING" value="1"> + The strength with which the pinned objects try to stay in velocity relation to each other. + The higher, the stronger. </constant> <constant name="PIN_JOINT_IMPULSE_CLAMP" value="2"> + If above 0, this value is the maximum value for an impulse that this Joint puts on it's ends. </constant> <constant name="HINGE_JOINT_BIAS" value="0"> + The speed with wich the two bodies get pulled together when they move in different directions. </constant> <constant name="HINGE_JOINT_LIMIT_UPPER" value="1"> + The maximum rotation across the Hinge. </constant> <constant name="HINGE_JOINT_LIMIT_LOWER" value="2"> + The minimum rotation across the Hinge. </constant> <constant name="HINGE_JOINT_LIMIT_BIAS" value="3"> + The speed with which the rotation across the axis perpendicular to the hinge gets corrected. </constant> <constant name="HINGE_JOINT_LIMIT_SOFTNESS" value="4"> </constant> <constant name="HINGE_JOINT_LIMIT_RELAXATION" value="5"> + The lower this value, the more the rotation gets slowed down. </constant> <constant name="HINGE_JOINT_MOTOR_TARGET_VELOCITY" value="6"> + Target speed for the motor. </constant> <constant name="HINGE_JOINT_MOTOR_MAX_IMPULSE" value="7"> + Maximum acceleration for the motor. </constant> <constant name="HINGE_JOINT_FLAG_USE_LIMIT" value="0"> + If [code]true[/code] the Hinge has a maximum and a minimum rotation. </constant> <constant name="HINGE_JOINT_FLAG_ENABLE_MOTOR" value="1"> + If [code]true[/code] a motor turns the Hinge </constant> <constant name="SLIDER_JOINT_LINEAR_LIMIT_UPPER" value="0"> + The maximum difference between the pivot points on their x-axis before damping happens. </constant> <constant name="SLIDER_JOINT_LINEAR_LIMIT_LOWER" value="1"> + The minimum difference between the pivot points on their x-axis before damping happens. </constant> <constant name="SLIDER_JOINT_LINEAR_LIMIT_SOFTNESS" value="2"> + A factor applied to the movement accross the slider axis once the limits get surpassed. The lower, the slower the movement. </constant> <constant name="SLIDER_JOINT_LINEAR_LIMIT_RESTITUTION" value="3"> + The amount of restitution once the limits are surpassed. The lower, the more velocityenergy gets lost. </constant> <constant name="SLIDER_JOINT_LINEAR_LIMIT_DAMPING" value="4"> + The amount of damping once the slider limits are surpassed. </constant> <constant name="SLIDER_JOINT_LINEAR_MOTION_SOFTNESS" value="5"> + A factor applied to the movement accross the slider axis as long as the slider is in the limits. The lower, the slower the movement. </constant> <constant name="SLIDER_JOINT_LINEAR_MOTION_RESTITUTION" value="6"> + The amount of restitution inside the slider limits. </constant> <constant name="SLIDER_JOINT_LINEAR_MOTION_DAMPING" value="7"> + The amount of damping inside the slider limits. </constant> <constant name="SLIDER_JOINT_LINEAR_ORTHOGONAL_SOFTNESS" value="8"> + A factor applied to the movement accross axes orthogonal to the slider. </constant> <constant name="SLIDER_JOINT_LINEAR_ORTHOGONAL_RESTITUTION" value="9"> + The amount of restitution when movement is accross axes orthogonal to the slider. </constant> <constant name="SLIDER_JOINT_LINEAR_ORTHOGONAL_DAMPING" value="10"> + The amount of damping when movement is accross axes orthogonal to the slider. </constant> <constant name="SLIDER_JOINT_ANGULAR_LIMIT_UPPER" value="11"> + The upper limit of rotation in the slider. </constant> <constant name="SLIDER_JOINT_ANGULAR_LIMIT_LOWER" value="12"> + The lower limit of rotation in the slider. </constant> <constant name="SLIDER_JOINT_ANGULAR_LIMIT_SOFTNESS" value="13"> + A factor applied to the all rotation once the limit is surpassed. </constant> <constant name="SLIDER_JOINT_ANGULAR_LIMIT_RESTITUTION" value="14"> + The amount of restitution of the rotation when the limit is surpassed. </constant> <constant name="SLIDER_JOINT_ANGULAR_LIMIT_DAMPING" value="15"> + The amount of damping of the rotation when the limit is surpassed. </constant> <constant name="SLIDER_JOINT_ANGULAR_MOTION_SOFTNESS" value="16"> + A factor that gets applied to the all rotation in the limits. </constant> <constant name="SLIDER_JOINT_ANGULAR_MOTION_RESTITUTION" value="17"> + The amount of restitution of the rotation in the limits. </constant> <constant name="SLIDER_JOINT_ANGULAR_MOTION_DAMPING" value="18"> + The amount of damping of the rotation in the limits. </constant> <constant name="SLIDER_JOINT_ANGULAR_ORTHOGONAL_SOFTNESS" value="19"> + A factor that gets applied to the all rotation across axes orthogonal to the slider. </constant> <constant name="SLIDER_JOINT_ANGULAR_ORTHOGONAL_RESTITUTION" value="20"> + The amount of restitution of the rotation across axes orthogonal to the slider. </constant> <constant name="SLIDER_JOINT_ANGULAR_ORTHOGONAL_DAMPING" value="21"> + The amount of damping of the rotation across axes orthogonal to the slider. </constant> <constant name="SLIDER_JOINT_MAX" value="22"> + End flag of SLIDER_JOINT_* constants, used internally. </constant> <constant name="CONE_TWIST_JOINT_SWING_SPAN" value="0"> + Swing is rotation from side to side, around the axis perpendicular to the twist axis. + The swing span defines, how much rotation will not get corrected allong the swing axis. + Could be defined as looseness in the [ConeTwistJoint]. + If below 0.05, this behaviour is locked. Default value: [code]PI/4[/code]. </constant> <constant name="CONE_TWIST_JOINT_TWIST_SPAN" value="1"> + Twist is the rotation around the twist axis, this value defined how far the joint can twist. + Twist is locked if below 0.05. </constant> <constant name="CONE_TWIST_JOINT_BIAS" value="2"> + The speed with which the swing or twist will take place. + The higher, the faster. </constant> <constant name="CONE_TWIST_JOINT_SOFTNESS" value="3"> + The ease with which the Joint twists, if it's too low, it takes more force to twist the joint. </constant> <constant name="CONE_TWIST_JOINT_RELAXATION" value="4"> + Defines, how fast the swing- and twist-speed-difference on both sides gets synced. </constant> <constant name="G6DOF_JOINT_LINEAR_LOWER_LIMIT" value="0"> + The minimum difference between the pivot points' axes. </constant> <constant name="G6DOF_JOINT_LINEAR_UPPER_LIMIT" value="1"> + The maximum difference between the pivot points' axes. </constant> <constant name="G6DOF_JOINT_LINEAR_LIMIT_SOFTNESS" value="2"> + A factor that gets applied to the movement accross the axes. The lower, the slower the movement. </constant> <constant name="G6DOF_JOINT_LINEAR_RESTITUTION" value="3"> + The amount of restitution on the axes movement. The lower, the more velocity-energy gets lost. </constant> <constant name="G6DOF_JOINT_LINEAR_DAMPING" value="4"> + The amount of damping that happens at the linear motion across the axes. </constant> <constant name="G6DOF_JOINT_ANGULAR_LOWER_LIMIT" value="5"> + The minimum rotation in negative direction to break loose and rotate arround the axes. </constant> <constant name="G6DOF_JOINT_ANGULAR_UPPER_LIMIT" value="6"> + The minimum rotation in positive direction to break loose and rotate arround the axes. </constant> <constant name="G6DOF_JOINT_ANGULAR_LIMIT_SOFTNESS" value="7"> + A factor that gets multiplied onto all rotations accross the axes. </constant> <constant name="G6DOF_JOINT_ANGULAR_DAMPING" value="8"> + The amount of rotational damping accross the axes. The lower, the more dampening occurs. </constant> <constant name="G6DOF_JOINT_ANGULAR_RESTITUTION" value="9"> + The amount of rotational restitution accross the axes. The lower, the more restitution occurs. </constant> <constant name="G6DOF_JOINT_ANGULAR_FORCE_LIMIT" value="10"> + The maximum amount of force that can occur, when rotating arround the axes. </constant> <constant name="G6DOF_JOINT_ANGULAR_ERP" value="11"> + When correcting the crossing of limits in rotation accross the axes, this error tolerance factor defines how much the correction gets slowed down. The lower, the slower. </constant> <constant name="G6DOF_JOINT_ANGULAR_MOTOR_TARGET_VELOCITY" value="12"> + Target speed for the motor at the axes. </constant> <constant name="G6DOF_JOINT_ANGULAR_MOTOR_FORCE_LIMIT" value="13"> + Maximum acceleration for the motor at the axes. </constant> <constant name="G6DOF_JOINT_FLAG_ENABLE_LINEAR_LIMIT" value="0"> + If [code]set[/code] there is linear motion possible within the given limits. </constant> <constant name="G6DOF_JOINT_FLAG_ENABLE_ANGULAR_LIMIT" value="1"> + If [code]set[/code] there is rotational motion possible. </constant> <constant name="G6DOF_JOINT_FLAG_ENABLE_MOTOR" value="2"> + If [code]set[/code] there is a rotational motor across these axes. </constant> <constant name="SHAPE_PLANE" value="0"> + The [Shape] is a [PlaneShape]. </constant> <constant name="SHAPE_RAY" value="1"> + The [Shape] is a [RayShape]. </constant> <constant name="SHAPE_SPHERE" value="2"> + The [Shape] is a [SphereShape]. </constant> <constant name="SHAPE_BOX" value="3"> + The [Shape] is a [BoxShape]. </constant> <constant name="SHAPE_CAPSULE" value="4"> + The [Shape] is a [CapsuleShape]. </constant> <constant name="SHAPE_CONVEX_POLYGON" value="5"> + The [Shape] is a [ConvexPolygonShape]. </constant> <constant name="SHAPE_CONCAVE_POLYGON" value="6"> + The [Shape] is a [ConcavePolygonShape]. </constant> <constant name="SHAPE_HEIGHTMAP" value="7"> + The [Shape] is a [HeightMapShape]. </constant> <constant name="SHAPE_CUSTOM" value="8"> + This constant is used internally by the engine. Any attempt to create this kind of shape results in an error. </constant> <constant name="AREA_PARAM_GRAVITY" value="0"> + Constant to set/get gravity strength in an area. </constant> <constant name="AREA_PARAM_GRAVITY_VECTOR" value="1"> + Constant to set/get gravity vector/center in an area. </constant> <constant name="AREA_PARAM_GRAVITY_IS_POINT" value="2"> + Constant to set/get whether the gravity vector of an area is a direction, or a center point. </constant> <constant name="AREA_PARAM_GRAVITY_DISTANCE_SCALE" value="3"> + Constant to set/get the falloff factor for point gravity of an area. The greater this value is, the faster the strength of gravity decreases with the square of distance. </constant> <constant name="AREA_PARAM_GRAVITY_POINT_ATTENUATION" value="4"> + This constant was used to set/get the falloff factor for point gravity. It has been superseded by AREA_PARAM_GRAVITY_DISTANCE_SCALE. </constant> <constant name="AREA_PARAM_LINEAR_DAMP" value="5"> + Constant to set/get the linear dampening factor of an area. </constant> <constant name="AREA_PARAM_ANGULAR_DAMP" value="6"> + Constant to set/get the angular dampening factor of an area. </constant> <constant name="AREA_PARAM_PRIORITY" value="7"> + Constant to set/get the priority (order of processing) of an area. </constant> <constant name="AREA_SPACE_OVERRIDE_DISABLED" value="0"> This area does not affect gravity/damp. These are generally areas that exist only to detect collisions, and objects entering or exiting them. @@ -1215,70 +1413,102 @@ This area replaces any gravity/damp calculated so far, but keeps calculating the rest of the areas, down to the default one. </constant> <constant name="BODY_MODE_STATIC" value="0"> + Constant for static bodies. </constant> <constant name="BODY_MODE_KINEMATIC" value="1"> + Constant for kinematic bodies. </constant> <constant name="BODY_MODE_RIGID" value="2"> + Constant for rigid bodies. </constant> <constant name="BODY_MODE_CHARACTER" value="3"> + Constant for rigid bodies in character mode. In this mode, a body can not rotate, and only its linear velocity is affected by physics. </constant> <constant name="BODY_PARAM_BOUNCE" value="0"> + Constant to set/get a body's bounce factor. </constant> <constant name="BODY_PARAM_FRICTION" value="1"> + Constant to set/get a body's friction. </constant> <constant name="BODY_PARAM_MASS" value="2"> + Constant to set/get a body's mass. </constant> <constant name="BODY_PARAM_GRAVITY_SCALE" value="3"> + Constant to set/get a body's gravity multiplier. </constant> <constant name="BODY_PARAM_ANGULAR_DAMP" value="5"> + Constant to set/get a body's angular dampening factor. </constant> <constant name="BODY_PARAM_LINEAR_DAMP" value="4"> + Constant to set/get a body's linear dampening factor. </constant> <constant name="BODY_PARAM_MAX" value="6"> + This is the last ID for body parameters. Any attempt to set this property is ignored. Any attempt to get it returns 0. </constant> <constant name="BODY_STATE_TRANSFORM" value="0"> + Constant to set/get the current transform matrix of the body. </constant> <constant name="BODY_STATE_LINEAR_VELOCITY" value="1"> + Constant to set/get the current linear velocity of the body. </constant> <constant name="BODY_STATE_ANGULAR_VELOCITY" value="2"> + Constant to set/get the current angular velocity of the body. </constant> <constant name="BODY_STATE_SLEEPING" value="3"> + Constant to sleep/wake up a body, or to get whether it is sleeping. </constant> <constant name="BODY_STATE_CAN_SLEEP" value="4"> + Constant to set/get whether the body can sleep. </constant> <constant name="AREA_BODY_ADDED" value="0"> + The value of the first parameter and area callback function receives, when an object enters one of its shapes. </constant> <constant name="AREA_BODY_REMOVED" value="1"> + The value of the first parameter and area callback function receives, when an object exits one of its shapes. </constant> <constant name="INFO_ACTIVE_OBJECTS" value="0"> + Constant to get the number of objects that are not sleeping. </constant> <constant name="INFO_COLLISION_PAIRS" value="1"> + Constant to get the number of possible collisions. </constant> <constant name="INFO_ISLAND_COUNT" value="2"> + Constant to get the number of space regions where a collision could occur. </constant> <constant name="SPACE_PARAM_CONTACT_RECYCLE_RADIUS" value="0"> + Constant to set/get the maximum distance a pair of bodies has to move before their collision status has to be recalculated. </constant> <constant name="SPACE_PARAM_CONTACT_MAX_SEPARATION" value="1"> + Constant to set/get the maximum distance a shape can be from another before they are considered separated. </constant> <constant name="SPACE_PARAM_BODY_MAX_ALLOWED_PENETRATION" value="2"> + Constant to set/get the maximum distance a shape can penetrate another shape before it is considered a collision. </constant> <constant name="SPACE_PARAM_BODY_LINEAR_VELOCITY_SLEEP_THRESHOLD" value="3"> + Constant to set/get the threshold linear velocity of activity. A body marked as potentially inactive for both linear and angular velocity will be put to sleep after the time given. </constant> <constant name="SPACE_PARAM_BODY_ANGULAR_VELOCITY_SLEEP_THRESHOLD" value="4"> + Constant to set/get the threshold angular velocity of activity. A body marked as potentially inactive for both linear and angular velocity will be put to sleep after the time given. </constant> <constant name="SPACE_PARAM_BODY_TIME_TO_SLEEP" value="5"> + Constant to set/get the maximum time of activity. A body marked as potentially inactive for both linear and angular velocity will be put to sleep after this time. </constant> <constant name="SPACE_PARAM_BODY_ANGULAR_VELOCITY_DAMP_RATIO" value="6"> </constant> <constant name="SPACE_PARAM_CONSTRAINT_DEFAULT_BIAS" value="7"> + Constant to set/get the default solver bias for all physics constraints. A solver bias is a factor controlling how much two objects "rebound", after violating a constraint, to avoid leaving them in that state because of numerical imprecision. </constant> <constant name="BODY_AXIS_LOCK_DISABLED" value="0"> + The [Body] can rotate and move freely. </constant> <constant name="BODY_AXIS_LOCK_X" value="1"> + The [Body] cannot move across x axis can only rotate across x axis. </constant> <constant name="BODY_AXIS_LOCK_Y" value="2"> + The [Body] cannot move across y axis can only rotate across y axis. </constant> <constant name="BODY_AXIS_LOCK_Z" value="3"> + The [Body] cannot move across z axis can only rotate across z axis. </constant> </constants> </class> diff --git a/doc/classes/PhysicsServerSW.xml b/doc/classes/PhysicsServerSW.xml index 7bffc23258..53e1c0057e 100644 --- a/doc/classes/PhysicsServerSW.xml +++ b/doc/classes/PhysicsServerSW.xml @@ -1,8 +1,10 @@ <?xml version="1.0" encoding="UTF-8" ?> <class name="PhysicsServerSW" inherits="PhysicsServer" category="Core" version="3.0.alpha.custom_build"> <brief_description> + Software implementation of [PhysicsServer]. </brief_description> <description> + This class exposes no new methods or properties and should not be used, as [PhysicsServer] automatically selects the best implementation available. </description> <tutorials> </tutorials> diff --git a/doc/classes/PinJoint.xml b/doc/classes/PinJoint.xml index 22aa35a0a4..1cc381b1b3 100644 --- a/doc/classes/PinJoint.xml +++ b/doc/classes/PinJoint.xml @@ -1,8 +1,10 @@ <?xml version="1.0" encoding="UTF-8" ?> <class name="PinJoint" inherits="Joint" category="Core" version="3.0.alpha.custom_build"> <brief_description> + Pin Joint for 3D Shapes. </brief_description> <description> + Pin Joint for 3D Rigid Bodies. It pins 2 bodies (rigid or static) together. </description> <tutorials> </tutorials> @@ -30,18 +32,28 @@ </methods> <members> <member name="params/bias" type="float" setter="set_param" getter="get_param"> + The force with wich the pinned objects stay in positional relation to each other. + The higher, the stronger. </member> <member name="params/damping" type="float" setter="set_param" getter="get_param"> + The force with wich the pinned objects stay in velocity relation to each other. + The higher, the stronger. </member> <member name="params/impulse_clamp" type="float" setter="set_param" getter="get_param"> + If above 0, this value is the maximum value for an impulse that this Joint produces. </member> </members> <constants> <constant name="PARAM_BIAS" value="0"> + The force with wich the pinned objects stay in positional relation to each other. + The higher, the stronger. </constant> <constant name="PARAM_DAMPING" value="1"> + The force with wich the pinned objects stay in velocity relation to each other. + The higher, the stronger. </constant> <constant name="PARAM_IMPULSE_CLAMP" value="2"> + If above 0, this value is the maximum value for an impulse that this Joint produces. </constant> </constants> </class> diff --git a/doc/classes/PinJoint2D.xml b/doc/classes/PinJoint2D.xml index 826a1684a4..009b0ec2f2 100644 --- a/doc/classes/PinJoint2D.xml +++ b/doc/classes/PinJoint2D.xml @@ -28,6 +28,7 @@ </methods> <members> <member name="softness" type="float" setter="set_softness" getter="get_softness"> + The higher this value, the more the bond to the pinned partner can flex. </member> </members> <constants> diff --git a/doc/classes/RigidBody2D.xml b/doc/classes/RigidBody2D.xml index a4faa697de..f2584de5aa 100644 --- a/doc/classes/RigidBody2D.xml +++ b/doc/classes/RigidBody2D.xml @@ -113,7 +113,7 @@ <return type="float"> </return> <description> - Return the body's moment of inertia. This is usually automatically computed from the mass and the shapes. Note that this doesn't seem to work in a [code]_ready[/code] function: it apparently has not been auto-computed yet. + Returns the body's moment of inertia. Automatically computed from associated [class CollisionShape2D]s' mass during physic frames. Inertia is not computed the same frame in which the node was added in. Therefore inertia is not computed during the [code]_ready[/code] function. </description> </method> <method name="get_linear_damp" qualifiers="const"> @@ -127,7 +127,7 @@ <return type="Vector2"> </return> <description> - Return the body linear velocity. This changes by physics granularity. See [method set_linear_velocity]. + Returns the body's linear velocity. This changes when a physics frame has passed, not during a normal update. See [method set_linear_velocity]. </description> </method> <method name="get_mass" qualifiers="const"> diff --git a/doc/classes/SliderJoint.xml b/doc/classes/SliderJoint.xml index 617390b6a4..adea8658d1 100644 --- a/doc/classes/SliderJoint.xml +++ b/doc/classes/SliderJoint.xml @@ -1,8 +1,10 @@ <?xml version="1.0" encoding="UTF-8" ?> <class name="SliderJoint" inherits="Joint" category="Core" version="3.0.alpha.custom_build"> <brief_description> + Piston kind of slider between two bodies in 3D. </brief_description> <description> + Slides across the x-axis of the [Pivot] object. </description> <tutorials> </tutorials> @@ -30,96 +32,144 @@ </methods> <members> <member name="angular_limit/damping" type="float" setter="set_param" getter="get_param"> + The amount of damping of the rotation when the limit is surpassed. + A lower damping value allows a rotation initiated by body A to travel to body B slower. </member> <member name="angular_limit/lower_angle" type="float" setter="_set_lower_limit_angular" getter="_get_lower_limit_angular"> + The lower limit of rotation in the slider. </member> <member name="angular_limit/restitution" type="float" setter="set_param" getter="get_param"> + The amount of restitution of the rotation when the limit is surpassed. + Does not affect damping. </member> <member name="angular_limit/softness" type="float" setter="set_param" getter="get_param"> + A factor applied to the all rotation once the limit is surpassed. + Makes all rotation slower when between 0 and 1. </member> <member name="angular_limit/upper_angle" type="float" setter="_set_upper_limit_angular" getter="_get_upper_limit_angular"> + The upper limit of rotation in the slider. </member> <member name="angular_motion/damping" type="float" setter="set_param" getter="get_param"> + The amount of damping of the rotation in the limits. </member> <member name="angular_motion/restitution" type="float" setter="set_param" getter="get_param"> + The amount of restitution of the rotation in the limits. </member> <member name="angular_motion/softness" type="float" setter="set_param" getter="get_param"> + A factor applied to the all rotation in the limits. </member> <member name="angular_ortho/damping" type="float" setter="set_param" getter="get_param"> + The amount of damping of the rotation across axes orthogonal to the slider. </member> <member name="angular_ortho/restitution" type="float" setter="set_param" getter="get_param"> + The amount of restitution of the rotation across axes orthogonal to the slider. </member> <member name="angular_ortho/softness" type="float" setter="set_param" getter="get_param"> + A factor applied to the all rotation across axes orthogonal to the slider. </member> <member name="linear_limit/damping" type="float" setter="set_param" getter="get_param"> + The amount of damping that happens once the limit defined by [member linear_limit/lower_distance] and [member linear_limit/upper_distance] is surpassed. </member> <member name="linear_limit/lower_distance" type="float" setter="set_param" getter="get_param"> + The minimum difference between the pivot points on their x-axis before damping happens. </member> <member name="linear_limit/restitution" type="float" setter="set_param" getter="get_param"> + The amount of restitution once the limits are surpassed. The lower, the more velocity-energy gets lost. </member> <member name="linear_limit/softness" type="float" setter="set_param" getter="get_param"> + A factor applied to the movement accross the slider axis once the limits get surpassed. The lower, the slower the movement. </member> <member name="linear_limit/upper_distance" type="float" setter="set_param" getter="get_param"> + The maximum difference between the pivot points on their x-axis before damping happens. </member> <member name="linear_motion/damping" type="float" setter="set_param" getter="get_param"> + The amount of damping inside the slider limits. </member> <member name="linear_motion/restitution" type="float" setter="set_param" getter="get_param"> + The amount of restitution inside the slider limits. </member> <member name="linear_motion/softness" type="float" setter="set_param" getter="get_param"> + A factor applied to the movement accross the slider axis as long as the slider is in the limits. The lower, the slower the movement. </member> <member name="linear_ortho/damping" type="float" setter="set_param" getter="get_param"> + The amount of damping when movement is accross axes orthogonal to the slider. </member> <member name="linear_ortho/restitution" type="float" setter="set_param" getter="get_param"> + The amount of restitution when movement is accross axes orthogonal to the slider. </member> <member name="linear_ortho/softness" type="float" setter="set_param" getter="get_param"> + A factor applied to the movement accross axes orthogonal to the slider. </member> </members> <constants> <constant name="PARAM_LINEAR_LIMIT_UPPER" value="0"> + The maximum difference between the pivot points on their x-axis before damping happens. </constant> <constant name="PARAM_LINEAR_LIMIT_LOWER" value="1"> + The minimum difference between the pivot points on their x-axis before damping happens. </constant> <constant name="PARAM_LINEAR_LIMIT_SOFTNESS" value="2"> + A factor applied to the movement accross the slider axis once the limits get surpassed. The lower, the slower the movement. </constant> <constant name="PARAM_LINEAR_LIMIT_RESTITUTION" value="3"> + The amount of restitution once the limits are surpassed. The lower, the more velocityenergy gets lost. </constant> <constant name="PARAM_LINEAR_LIMIT_DAMPING" value="4"> + The amount of damping once the slider limits are surpassed. </constant> <constant name="PARAM_LINEAR_MOTION_SOFTNESS" value="5"> + A factor applied to the movement accross the slider axis as long as the slider is in the limits. The lower, the slower the movement. </constant> <constant name="PARAM_LINEAR_MOTION_RESTITUTION" value="6"> + The amount of restitution inside the slider limits. </constant> <constant name="PARAM_LINEAR_MOTION_DAMPING" value="7"> + The amount of damping inside the slider limits. </constant> <constant name="PARAM_LINEAR_ORTHOGONAL_SOFTNESS" value="8"> + A factor applied to the movement accross axes orthogonal to the slider. </constant> <constant name="PARAM_LINEAR_ORTHOGONAL_RESTITUTION" value="9"> + The amount of restitution when movement is accross axes orthogonal to the slider. </constant> <constant name="PARAM_LINEAR_ORTHOGONAL_DAMPING" value="10"> + The amount of damping when movement is accross axes orthogonal to the slider. </constant> <constant name="PARAM_ANGULAR_LIMIT_UPPER" value="11"> + The upper limit of rotation in the slider. </constant> <constant name="PARAM_ANGULAR_LIMIT_LOWER" value="12"> + The lower limit of rotation in the slider. </constant> <constant name="PARAM_ANGULAR_LIMIT_SOFTNESS" value="13"> + A factor applied to the all rotation once the limit is surpassed. </constant> <constant name="PARAM_ANGULAR_LIMIT_RESTITUTION" value="14"> + The amount of restitution of the rotation when the limit is surpassed. </constant> <constant name="PARAM_ANGULAR_LIMIT_DAMPING" value="15"> + The amount of damping of the rotation when the limit is surpassed. </constant> <constant name="PARAM_ANGULAR_MOTION_SOFTNESS" value="16"> + A factor applied to the all rotation in the limits. </constant> <constant name="PARAM_ANGULAR_MOTION_RESTITUTION" value="17"> + The amount of restitution of the rotation in the limits. </constant> <constant name="PARAM_ANGULAR_MOTION_DAMPING" value="18"> + The amount of damping of the rotation in the limits. </constant> <constant name="PARAM_ANGULAR_ORTHOGONAL_SOFTNESS" value="19"> + A factor applied to the all rotation across axes orthogonal to the slider. </constant> <constant name="PARAM_ANGULAR_ORTHOGONAL_RESTITUTION" value="20"> + The amount of restitution of the rotation across axes orthogonal to the slider. </constant> <constant name="PARAM_ANGULAR_ORTHOGONAL_DAMPING" value="21"> + The amount of damping of the rotation across axes orthogonal to the slider. </constant> <constant name="PARAM_MAX" value="22"> + End flag of PARAM_* constants, used internally. </constant> </constants> </class> diff --git a/doc/classes/VisualScriptClassConstant.xml b/doc/classes/VisualScriptClassConstant.xml index 70e7de5dd9..0377fa8f09 100644 --- a/doc/classes/VisualScriptClassConstant.xml +++ b/doc/classes/VisualScriptClassConstant.xml @@ -1,10 +1,14 @@ <?xml version="1.0" encoding="UTF-8" ?> <class name="VisualScriptClassConstant" inherits="VisualScriptNode" category="Core" version="3.0.alpha.custom_build"> <brief_description> - A Visual Script node representing a constant from a class. + Gets a constant from a given class. </brief_description> <description> - A Visual Script node representing a constant from the classes, such as [@GlobalScope.TYPE_INT]. + This node returns a constant from a given class, such as [@GlobalScope.TYPE_INT]. See the given class' documentation for available constants. + [b]Input Ports:[/b] + none + [b]Output Ports:[/b] + - Data (variant): [code]value[/code] </description> <tutorials> </tutorials> @@ -42,10 +46,10 @@ </methods> <members> <member name="base_type" type="String" setter="set_base_type" getter="get_base_type"> - The type to get the constant from. + The constant's parent class. </member> <member name="constant" type="String" setter="set_class_constant" getter="get_class_constant"> - The name of the constant to return. + The constant to return. See the given class for its available constants. </member> </members> <constants> diff --git a/doc/classes/VisualScriptConstant.xml b/doc/classes/VisualScriptConstant.xml index 508087a928..2a704adecf 100644 --- a/doc/classes/VisualScriptConstant.xml +++ b/doc/classes/VisualScriptConstant.xml @@ -1,10 +1,14 @@ <?xml version="1.0" encoding="UTF-8" ?> <class name="VisualScriptConstant" inherits="VisualScriptNode" category="Core" version="3.0.alpha.custom_build"> <brief_description> - A Visual Script node which returns a constant value. + Gets a contant's value. </brief_description> <description> - A Visual Script node which returns the specified constant value. + This node returns a constant's value. + [b]Input Ports:[/b] + none + [b]Output Ports:[/b] + - Data (variant): [code]get[/code] </description> <tutorials> </tutorials> diff --git a/doc/classes/VisualScriptEmitSignal.xml b/doc/classes/VisualScriptEmitSignal.xml index 844b5a40ec..8d132ed321 100644 --- a/doc/classes/VisualScriptEmitSignal.xml +++ b/doc/classes/VisualScriptEmitSignal.xml @@ -1,10 +1,14 @@ <?xml version="1.0" encoding="UTF-8" ?> <class name="VisualScriptEmitSignal" inherits="VisualScriptNode" category="Core" version="3.0.alpha.custom_build"> <brief_description> - A Visual Script node which emits a specified signal. + Emits a specified signal. </brief_description> <description> - A Visual Script node which emits a specified signal when it is executed. + Emits a specified signal when it is executed. + [b]Input Ports:[/b] + - Sequence: [code]emit[/code] + [b]Output Ports:[/b] + - Sequence </description> <tutorials> </tutorials> diff --git a/doc/classes/VisualScriptIterator.xml b/doc/classes/VisualScriptIterator.xml index 74309fcf00..1f9a4fddde 100644 --- a/doc/classes/VisualScriptIterator.xml +++ b/doc/classes/VisualScriptIterator.xml @@ -1,8 +1,17 @@ <?xml version="1.0" encoding="UTF-8" ?> <class name="VisualScriptIterator" inherits="VisualScriptNode" category="Core" version="3.0.alpha.custom_build"> <brief_description> + Steps through items in a given input. </brief_description> <description> + This node steps through each item in a given input. Input can be any sequence data type, such as an [Array] or [String]. When each item has been processed, execution passed out the [code]exit[/code] Sequence port. + [b]Input Ports:[/b] + - Sequence: [code]for (elem) in (input)[/code] + - Data (variant): [code]input[/code] + [b]Output Ports:[/b] + - Sequence: [code]each[/code] + - Sequence: [code]exit[/code] + - Data (variant): [code]elem[/code] </description> <tutorials> </tutorials> diff --git a/doc/classes/VisualScriptLocalVar.xml b/doc/classes/VisualScriptLocalVar.xml index 7db550d5fe..3101b3e34b 100644 --- a/doc/classes/VisualScriptLocalVar.xml +++ b/doc/classes/VisualScriptLocalVar.xml @@ -1,8 +1,14 @@ <?xml version="1.0" encoding="UTF-8" ?> <class name="VisualScriptLocalVar" inherits="VisualScriptNode" category="Core" version="3.0.alpha.custom_build"> <brief_description> + Gets a local variable's value. </brief_description> <description> + Returns a local variable's value. "Var Name" must be supplied, with an optional type. + [b]Input Ports:[/b] + none + [b]Output Ports:[/b] + - Data (variant): [code]get[/code] </description> <tutorials> </tutorials> @@ -40,8 +46,10 @@ </methods> <members> <member name="type" type="int" setter="set_var_type" getter="get_var_type" enum="Variant.Type"> + The local variable's type. </member> <member name="var_name" type="String" setter="set_var_name" getter="get_var_name"> + The local variable's name. </member> </members> <constants> diff --git a/doc/classes/VisualScriptLocalVarSet.xml b/doc/classes/VisualScriptLocalVarSet.xml index 6e69f13383..e039a7204e 100644 --- a/doc/classes/VisualScriptLocalVarSet.xml +++ b/doc/classes/VisualScriptLocalVarSet.xml @@ -1,8 +1,16 @@ <?xml version="1.0" encoding="UTF-8" ?> <class name="VisualScriptLocalVarSet" inherits="VisualScriptNode" category="Core" version="3.0.alpha.custom_build"> <brief_description> + Changes a local variable's value. </brief_description> <description> + Changes a local variable's value to the given input. The new value is also provided on an output Data port. + [b]Input Ports:[/b] + - Sequence + - Data (variant): [code]set[/code] + [b]Output Ports:[/b] + - Sequence + - Data (variant): [code]get[/code] </description> <tutorials> </tutorials> @@ -40,8 +48,10 @@ </methods> <members> <member name="type" type="int" setter="set_var_type" getter="get_var_type" enum="Variant.Type"> + The local variable's type. </member> <member name="var_name" type="String" setter="set_var_name" getter="get_var_name"> + The local variable's name. </member> </members> <constants> diff --git a/doc/classes/VisualScriptMathConstant.xml b/doc/classes/VisualScriptMathConstant.xml index 1ef7d71e10..86744e5caf 100644 --- a/doc/classes/VisualScriptMathConstant.xml +++ b/doc/classes/VisualScriptMathConstant.xml @@ -1,8 +1,14 @@ <?xml version="1.0" encoding="UTF-8" ?> <class name="VisualScriptMathConstant" inherits="VisualScriptNode" category="Core" version="3.0.alpha.custom_build"> <brief_description> + Commonly used mathematical constants. </brief_description> <description> + Provides common math constants, such as Pi or Euler's constant, on an output Data port. + [b]Input Ports:[/b] + none + [b]Output Ports:[/b] + - Data (variant): [code]get[/code] </description> <tutorials> </tutorials> @@ -26,24 +32,33 @@ </methods> <members> <member name="constant" type="int" setter="set_math_constant" getter="get_math_constant" enum="VisualScriptMathConstant.MathConstant"> + The math constant. </member> </members> <constants> <constant name="MATH_CONSTANT_ONE" value="0"> + Unity: [code]1[/code] </constant> <constant name="MATH_CONSTANT_PI" value="1"> + Pi: [code]3.141593[/code] </constant> <constant name="MATH_CONSTANT_2PI" value="2"> + Pi times two: [code]6.283185[/code] </constant> <constant name="MATH_CONSTANT_HALF_PI" value="3"> + Pi divided by two: [code]1.570796[/code] </constant> <constant name="MATH_CONSTANT_E" value="4"> + Natural log: [code]2.718282[/code] </constant> <constant name="MATH_CONSTANT_SQRT2" value="5"> + Square root of two: [code]1.414214[/code] </constant> <constant name="MATH_CONSTANT_INF" value="6"> + Infinity: [code]inf[/code] </constant> <constant name="MATH_CONSTANT_NAN" value="7"> + Not a number: [code]nan[/code] </constant> <constant name="MATH_CONSTANT_MAX" value="8"> </constant> diff --git a/doc/classes/VisualScriptOperator.xml b/doc/classes/VisualScriptOperator.xml index 7e85af8af2..de08075af2 100644 --- a/doc/classes/VisualScriptOperator.xml +++ b/doc/classes/VisualScriptOperator.xml @@ -7,9 +7,7 @@ - Data (variant): [code]A[/code] - Data (variant): [code]B[/code] [b]Output Ports:[/b] - - Sequence: [code]true[/code] - - Sequence: [code]false[/code] - - Sequence: [code]done[/code] + - Data (variant): [code]result[/code] </description> <tutorials> </tutorials> diff --git a/doc/classes/VisualScriptPreload.xml b/doc/classes/VisualScriptPreload.xml index b68bf5546b..b683439751 100644 --- a/doc/classes/VisualScriptPreload.xml +++ b/doc/classes/VisualScriptPreload.xml @@ -1,8 +1,14 @@ <?xml version="1.0" encoding="UTF-8" ?> <class name="VisualScriptPreload" inherits="VisualScriptNode" category="Core" version="3.0.alpha.custom_build"> <brief_description> + Creates a new [Resource] or loads one from the filesystem. </brief_description> <description> + Creates a new [Resource] or loads one from the filesystem. + [b]Input Ports:[/b] + none + [b]Output Ports:[/b] + - Data (object): [code]res[/code] </description> <tutorials> </tutorials> @@ -26,6 +32,7 @@ </methods> <members> <member name="resource" type="Resource" setter="set_preload" getter="get_preload"> + The [Resource] to load. </member> </members> <constants> diff --git a/doc/classes/VisualScriptReturn.xml b/doc/classes/VisualScriptReturn.xml index 55c53e17a0..ad18e96230 100644 --- a/doc/classes/VisualScriptReturn.xml +++ b/doc/classes/VisualScriptReturn.xml @@ -1,8 +1,15 @@ <?xml version="1.0" encoding="UTF-8" ?> <class name="VisualScriptReturn" inherits="VisualScriptNode" category="Core" version="3.0.alpha.custom_build"> <brief_description> + Exits a function and returns an optional value. </brief_description> <description> + Ends the execution of a function and returns control to the calling function. Optionally, it can return a [Variant] value. + [b]Input Ports:[/b] + - Sequence + - Data (variant): [code]result[/code] (optional) + [b]Output Ports:[/b] + none </description> <tutorials> </tutorials> @@ -40,8 +47,10 @@ </methods> <members> <member name="return_enabled" type="bool" setter="set_enable_return_value" getter="is_return_value_enabled"> + If [code]true[/code] the [code]return[/code] input port is available. </member> <member name="return_type" type="int" setter="set_return_type" getter="get_return_type" enum="Variant.Type"> + The return value's data type. </member> </members> <constants> diff --git a/doc/classes/VisualScriptSelect.xml b/doc/classes/VisualScriptSelect.xml index 855da76e6c..f265c57645 100644 --- a/doc/classes/VisualScriptSelect.xml +++ b/doc/classes/VisualScriptSelect.xml @@ -1,8 +1,16 @@ <?xml version="1.0" encoding="UTF-8" ?> <class name="VisualScriptSelect" inherits="VisualScriptNode" category="Core" version="3.0.alpha.custom_build"> <brief_description> + Chooses between two input values. </brief_description> <description> + Chooses between two input values based on a Boolean condition. + [b]Input Ports:[/b] + - Data (boolean): [code]cond[/code] + - Data (variant): [code]a[/code] + - Data (variant): [code]b[/code] + [b]Output Ports:[/b] + - Data (variant): [code]out[/code] </description> <tutorials> </tutorials> @@ -26,6 +34,7 @@ </methods> <members> <member name="type" type="int" setter="set_typed" getter="get_typed" enum="Variant.Type"> + The input variables' type. </member> </members> <constants> diff --git a/doc/classes/VisualScriptSelf.xml b/doc/classes/VisualScriptSelf.xml index a60f7eee03..723b138722 100644 --- a/doc/classes/VisualScriptSelf.xml +++ b/doc/classes/VisualScriptSelf.xml @@ -1,8 +1,14 @@ <?xml version="1.0" encoding="UTF-8" ?> <class name="VisualScriptSelf" inherits="VisualScriptNode" category="Core" version="3.0.alpha.custom_build"> <brief_description> + Outputs a reference to the current instance. </brief_description> <description> + Provides a reference to the node running the visual script. + [b]Input Ports:[/b] + none + [b]Output Ports:[/b] + - Data (object): [code]instance[/code] </description> <tutorials> </tutorials> diff --git a/doc/classes/VisualScriptSequence.xml b/doc/classes/VisualScriptSequence.xml index a60c9e782b..4ea4203407 100644 --- a/doc/classes/VisualScriptSequence.xml +++ b/doc/classes/VisualScriptSequence.xml @@ -1,8 +1,16 @@ <?xml version="1.0" encoding="UTF-8" ?> <class name="VisualScriptSequence" inherits="VisualScriptNode" category="Core" version="3.0.alpha.custom_build"> <brief_description> + Executes a series of Sequence ports. </brief_description> <description> + Steps through a series of one or more output Sequence ports. The [code]current[/code] data port outputs the currently executing item. + [b]Input Ports:[/b] + - Sequence: [code]in order[/code] + [b]Output Ports:[/b] + - Sequence: [code]1[/code] + - Sequence: [code]2 - n[/code] (optional) + - Data (int): [code]current[/code] </description> <tutorials> </tutorials> @@ -26,6 +34,7 @@ </methods> <members> <member name="steps" type="int" setter="set_steps" getter="get_steps"> + The number of steps in the sequence. </member> </members> <constants> diff --git a/doc/classes/VisualScriptSwitch.xml b/doc/classes/VisualScriptSwitch.xml index 95ed737372..2540ae54cc 100644 --- a/doc/classes/VisualScriptSwitch.xml +++ b/doc/classes/VisualScriptSwitch.xml @@ -1,8 +1,19 @@ <?xml version="1.0" encoding="UTF-8" ?> <class name="VisualScriptSwitch" inherits="VisualScriptNode" category="Core" version="3.0.alpha.custom_build"> <brief_description> + Branches program flow based on a given input's value. </brief_description> <description> + Branches the flow based on an input's value. Use "Case Count" in the Inspector to set the number of branches and each comparison's optional type. + [b]Input Ports:[/b] + - Sequence: [code]'input' is[/code] + - Data (variant): [code]=[/code] + - Data (variant): [code]=[/code] (optional) + - Data (variant): [code]input[/code] + [b]Output Ports:[/b] + - Sequence + - Sequence (optional) + - Sequence: [code]done[/code] </description> <tutorials> </tutorials> diff --git a/doc/classes/VisualScriptVariableGet.xml b/doc/classes/VisualScriptVariableGet.xml index 8411933756..5b45dd0cc4 100644 --- a/doc/classes/VisualScriptVariableGet.xml +++ b/doc/classes/VisualScriptVariableGet.xml @@ -1,8 +1,14 @@ <?xml version="1.0" encoding="UTF-8" ?> <class name="VisualScriptVariableGet" inherits="VisualScriptNode" category="Core" version="3.0.alpha.custom_build"> <brief_description> + Gets a variable's value. </brief_description> <description> + Returns a variable's value. "Var Name" must be supplied, with an optional type. + [b]Input Ports:[/b] + none + [b]Output Ports:[/b] + - Data (variant): [code]value[/code] </description> <tutorials> </tutorials> @@ -26,6 +32,7 @@ </methods> <members> <member name="var_name" type="String" setter="set_variable" getter="get_variable"> + The variable's name. </member> </members> <constants> diff --git a/doc/classes/VisualScriptVariableSet.xml b/doc/classes/VisualScriptVariableSet.xml index fbe0f8e275..51f85f6881 100644 --- a/doc/classes/VisualScriptVariableSet.xml +++ b/doc/classes/VisualScriptVariableSet.xml @@ -1,8 +1,15 @@ <?xml version="1.0" encoding="UTF-8" ?> <class name="VisualScriptVariableSet" inherits="VisualScriptNode" category="Core" version="3.0.alpha.custom_build"> <brief_description> + Changes a variable's value. </brief_description> <description> + Changes a variable's value to the given input. + [b]Input Ports:[/b] + - Sequence + - Data (variant): [code]set[/code] + [b]Output Ports:[/b] + - Sequence </description> <tutorials> </tutorials> @@ -26,6 +33,7 @@ </methods> <members> <member name="var_name" type="String" setter="set_variable" getter="get_variable"> + The variable's name. </member> </members> <constants> diff --git a/doc/classes/VisualScriptWhile.xml b/doc/classes/VisualScriptWhile.xml index b49678582e..60bf161339 100644 --- a/doc/classes/VisualScriptWhile.xml +++ b/doc/classes/VisualScriptWhile.xml @@ -1,8 +1,16 @@ <?xml version="1.0" encoding="UTF-8" ?> <class name="VisualScriptWhile" inherits="VisualScriptNode" category="Core" version="3.0.alpha.custom_build"> <brief_description> + Conditional loop. </brief_description> <description> + Loops while a condition is [code]true[/code]. Execution continues out the [code]exit[/code] Sequence port when the loop terminates. + [b]Input Ports:[/b] + - Sequence: [code]while(cond)[/code] + - Data (bool): [code]cond[/code] + [b]Output Ports:[/b] + - Sequence: [code]repeat[/code] + - Sequence: [code]exit[/code] </description> <tutorials> </tutorials> diff --git a/doc/tools/doc_status.py b/doc/tools/doc_status.py index e89b49eb4d..170ded9f50 100644 --- a/doc/tools/doc_status.py +++ b/doc/tools/doc_status.py @@ -250,15 +250,16 @@ class ClassStatus: for tag in list(c): if tag.tag in ['methods']: for sub_tag in list(tag): - methods.append(sub_tag.find('name')) + methods.append(sub_tag.attrib['name']) if tag.tag in ['members']: for sub_tag in list(tag): try: - methods.remove(sub_tag.find('setter')) - methods.remove(sub_tag.find('getter')) + if(sub_tag.attrib['setter'].startswith('_') == False): + methods.remove(sub_tag.attrib['setter']) + if(sub_tag.attrib['getter'].startswith('_') == False): + methods.remove(sub_tag.attrib['getter']) except: pass - for tag in list(c): if tag.tag == 'brief_description': @@ -269,7 +270,7 @@ class ClassStatus: elif tag.tag in ['methods', 'signals']: for sub_tag in list(tag): - if sub_tag.find('name') in methods or tag.tag == 'signals': + if sub_tag.attrib['name'] in methods or tag.tag == 'signals': descr = sub_tag.find('description') status.progresses[tag.tag].increment(len(descr.text.strip()) > 0) elif tag.tag in ['constants', 'members']: diff --git a/drivers/gles3/rasterizer_scene_gles3.cpp b/drivers/gles3/rasterizer_scene_gles3.cpp index 6117c91a6a..39f027a5aa 100644 --- a/drivers/gles3/rasterizer_scene_gles3.cpp +++ b/drivers/gles3/rasterizer_scene_gles3.cpp @@ -2569,8 +2569,8 @@ void RasterizerSceneGLES3::_setup_directional_light(int p_index, const Transform ubo_data.light_direction_attenuation[3] = 1.0; ubo_data.light_params[0] = 0; - ubo_data.light_params[1] = li->light_ptr->param[VS::LIGHT_PARAM_SPECULAR]; - ubo_data.light_params[2] = 0; + ubo_data.light_params[1] = 0; + ubo_data.light_params[2] = li->light_ptr->param[VS::LIGHT_PARAM_SPECULAR]; ubo_data.light_params[3] = 0; Color shadow_color = li->light_ptr->shadow_color.to_linear(); diff --git a/drivers/gles3/rasterizer_storage_gles3.cpp b/drivers/gles3/rasterizer_storage_gles3.cpp index 44a9909bd7..296d945cda 100644 --- a/drivers/gles3/rasterizer_storage_gles3.cpp +++ b/drivers/gles3/rasterizer_storage_gles3.cpp @@ -2430,7 +2430,8 @@ void RasterizerStorageGLES3::_update_material(Material *material) { if (material->shader && material->shader->mode == VS::SHADER_SPATIAL) { - if (!material->shader->spatial.uses_alpha && material->shader->spatial.blend_mode == Shader::Spatial::BLEND_MODE_MIX) { + if (material->shader->spatial.blend_mode == Shader::Spatial::BLEND_MODE_MIX && + (!material->shader->spatial.uses_alpha || (material->shader->spatial.uses_alpha && material->shader->spatial.depth_draw_mode == Shader::Spatial::DEPTH_DRAW_ALPHA_PREPASS))) { can_cast_shadow = true; } diff --git a/drivers/windows/dir_access_windows.cpp b/drivers/windows/dir_access_windows.cpp index 8d6e78dbee..0bc4201ba3 100644 --- a/drivers/windows/dir_access_windows.cpp +++ b/drivers/windows/dir_access_windows.cpp @@ -164,7 +164,7 @@ Error DirAccessWindows::make_dir(String p_dir) { p_dir = fix_path(p_dir); if (p_dir.is_rel_path()) - p_dir = get_current_dir().plus_file(p_dir); + p_dir = current_dir.plus_file(p_dir); p_dir = p_dir.replace("/", "\\"); diff --git a/editor/animation_editor.cpp b/editor/animation_editor.cpp index 5bb10f495e..54eb695178 100644 --- a/editor/animation_editor.cpp +++ b/editor/animation_editor.cpp @@ -64,6 +64,8 @@ private: float transition; Mode mode; + LineEdit *value_edit; + void _notification(int p_what) { if (p_what == NOTIFICATION_DRAW) { @@ -144,14 +146,11 @@ private: } } - String txt = String::num(exp, 2); if (mode == MODE_DISABLED) { - txt = TTR("Disabled"); + f->draw(ci, Point2(5, 5 + f->get_ascent()), TTR("Disabled"), color); } else if (mode == MODE_MULTIPLE) { - txt += " - " + TTR("All Selection"); + f->draw(ci, Point2(5, 5 + f->get_ascent() + value_edit->get_size().height), TTR("All Selection"), color); } - - f->draw(ci, Point2(10, 10 + f->get_ascent()), txt, color); } } @@ -163,6 +162,8 @@ private: if (mode == MODE_DISABLED) return; + value_edit->release_focus(); + float rel = mm->get_relative().x; if (rel == 0) return; @@ -187,24 +188,28 @@ private: if (sg) val = -val; - transition = val; - update(); - //emit_signal("variant_changed"); - emit_signal("transition_changed", transition); + force_transition(val); } } + void _edit_value_changed(const String &p_value_str) { + + force_transition(p_value_str.to_float()); + } + public: static void _bind_methods() { //ClassDB::bind_method("_update_obj",&AnimationKeyEdit::_update_obj); ClassDB::bind_method("_gui_input", &AnimationCurveEdit::_gui_input); + ClassDB::bind_method("_edit_value_changed", &AnimationCurveEdit::_edit_value_changed); ADD_SIGNAL(MethodInfo("transition_changed")); } void set_mode(Mode p_mode) { mode = p_mode; + value_edit->set_visible(mode != MODE_DISABLED); update(); } @@ -218,7 +223,8 @@ public: } void set_transition(float p_transition) { - transition = p_transition; + transition = Math::stepify(p_transition, 0.01); + value_edit->set_text(String::num(transition)); update(); } @@ -229,9 +235,8 @@ public: void force_transition(float p_value) { if (mode == MODE_DISABLED) return; - transition = p_value; + set_transition(p_value); emit_signal("transition_changed", p_value); - update(); } AnimationCurveEdit() { @@ -239,6 +244,11 @@ public: transition = 1.0; set_default_cursor_shape(CURSOR_HSPLIT); mode = MODE_DISABLED; + + value_edit = memnew(LineEdit); + value_edit->hide(); + value_edit->connect("text_entered", this, "_edit_value_changed"); + add_child(value_edit); } }; diff --git a/editor/dependency_editor.cpp b/editor/dependency_editor.cpp index 5305c4f256..64f1c4ccb2 100644 --- a/editor/dependency_editor.cpp +++ b/editor/dependency_editor.cpp @@ -337,92 +337,142 @@ DependencyEditorOwners::DependencyEditorOwners() { /////////////////////// -void DependencyRemoveDialog::_fill_owners(EditorFileSystemDirectory *efsd) { +void DependencyRemoveDialog::_find_files_in_removed_folder(EditorFileSystemDirectory *efsd, const String &p_folder) { + if (!efsd) + return; + + for (int i = 0; i < efsd->get_subdir_count(); ++i) { + _find_files_in_removed_folder(efsd->get_subdir(i), p_folder); + } + for (int i = 0; i < efsd->get_file_count(); i++) { + String file = efsd->get_file_path(i); + ERR_FAIL_COND(all_remove_files.has(file)); //We are deleting a directory which is contained in a directory we are deleting... + all_remove_files[file] = p_folder; //Point the file to the ancestor directory we are deleting so we know what to parent it under in the tree. + } +} +void DependencyRemoveDialog::_find_all_removed_dependencies(EditorFileSystemDirectory *efsd, Vector<RemovedDependency> &p_removed) { if (!efsd) return; for (int i = 0; i < efsd->get_subdir_count(); i++) { - _fill_owners(efsd->get_subdir(i)); + _find_all_removed_dependencies(efsd->get_subdir(i), p_removed); } for (int i = 0; i < efsd->get_file_count(); i++) { + const String path = efsd->get_file_path(i); - Vector<String> deps = efsd->get_file_deps(i); - //print_line(":::"+efsd->get_file_path(i)); - Set<String> met; - for (int j = 0; j < deps.size(); j++) { - if (files.has(deps[j])) { - met.insert(deps[j]); - } - } - if (!met.size()) + //It doesn't matter if a file we are about to delete will have some of its dependencies removed too + if (all_remove_files.has(path)) continue; - exist = true; - - Ref<Texture> icon; - String type = efsd->get_file_type(i); - if (!has_icon(type, "EditorIcons")) { - icon = get_icon("Object", "EditorIcons"); - } else { - icon = get_icon(type, "EditorIcons"); + Vector<String> all_deps = efsd->get_file_deps(i); + for (int j = 0; j < all_deps.size(); ++j) { + if (all_remove_files.has(all_deps[j])) { + RemovedDependency dep; + dep.file = path; + dep.file_type = efsd->get_file_type(i); + dep.dependency = all_deps[j]; + dep.dependency_folder = all_remove_files[all_deps[j]]; + p_removed.push_back(dep); + } } + } +} - for (Set<String>::Element *E = met.front(); E; E = E->next()) { +void DependencyRemoveDialog::_build_removed_dependency_tree(const Vector<RemovedDependency> &p_removed) { + owners->clear(); + owners->create_item(); // root - String which = E->get(); - if (!files[which]) { - TreeItem *ti = owners->create_item(owners->get_root()); - ti->set_text(0, which.get_file()); - files[which] = ti; + Map<String, TreeItem *> tree_items; + for (int i = 0; i < p_removed.size(); i++) { + RemovedDependency rd = p_removed[i]; + + //Ensure that the dependency is already in the tree + if (!tree_items.has(rd.dependency)) { + if (rd.dependency_folder.length() > 0) { + //Ensure the ancestor folder is already in the tree + if (!tree_items.has(rd.dependency_folder)) { + TreeItem *folder_item = owners->create_item(owners->get_root()); + folder_item->set_text(0, rd.dependency_folder); + folder_item->set_icon(0, get_icon("Folder", "EditorIcons")); + tree_items[rd.dependency_folder] = folder_item; + } + TreeItem *dependency_item = owners->create_item(tree_items[rd.dependency_folder]); + dependency_item->set_text(0, rd.dependency); + dependency_item->set_icon(0, get_icon("Warning", "EditorIcons")); + tree_items[rd.dependency] = dependency_item; + } else { + TreeItem *dependency_item = owners->create_item(owners->get_root()); + dependency_item->set_text(0, rd.dependency); + dependency_item->set_icon(0, get_icon("Warning", "EditorIcons")); + tree_items[rd.dependency] = dependency_item; } - TreeItem *ti = owners->create_item(files[which]); - ti->set_text(0, efsd->get_file_path(i)); - ti->set_icon(0, icon); } + + //List this file under this dependency + Ref<Texture> icon = has_icon(rd.file_type, "EditorIcons") ? get_icon(rd.file_type, "EditorIcons") : get_icon("Object", "EditorIcons"); + TreeItem *file_item = owners->create_item(tree_items[rd.dependency]); + file_item->set_text(0, rd.file); + file_item->set_icon(0, icon); } } -void DependencyRemoveDialog::show(const Vector<String> &to_erase) { - - exist = false; +void DependencyRemoveDialog::show(const Vector<String> &p_folders, const Vector<String> &p_files) { + all_remove_files.clear(); + to_delete.clear(); owners->clear(); - files.clear(); - owners->create_item(); // root - for (int i = 0; i < to_erase.size(); i++) { - files[to_erase[i]] = NULL; + + for (int i = 0; i < p_folders.size(); ++i) { + String folder = p_folders[i].ends_with("/") ? p_folders[i] : (p_folders[i] + "/"); + _find_files_in_removed_folder(EditorFileSystem::get_singleton()->get_filesystem_path(folder), folder); + to_delete.push_back(folder); + } + for (int i = 0; i < p_files.size(); ++i) { + all_remove_files[p_files[i]] = String(); + to_delete.push_back(p_files[i]); } - _fill_owners(EditorFileSystem::get_singleton()->get_filesystem()); + Vector<RemovedDependency> removed_deps; + _find_all_removed_dependencies(EditorFileSystem::get_singleton()->get_filesystem(), removed_deps); + removed_deps.sort(); - if (exist) { - owners->show(); - text->set_text(TTR("The files being removed are required by other resources in order for them to work.\nRemove them anyway? (no undo)")); - popup_centered_minsize(Size2(500, 220)); - } else { + if (removed_deps.empty()) { owners->hide(); text->set_text(TTR("Remove selected files from the project? (no undo)")); popup_centered_minsize(Size2(400, 100)); + } else { + _build_removed_dependency_tree(removed_deps); + owners->show(); + text->set_text(TTR("The files being removed are required by other resources in order for them to work.\nRemove them anyway? (no undo)")); + popup_centered_minsize(Size2(500, 350)); } } void DependencyRemoveDialog::ok_pressed() { - - bool changed = false; - - for (Map<String, TreeItem *>::Element *E = files.front(); E; E = E->next()) { - - if (ResourceCache::has(E->key())) { - Resource *res = ResourceCache::get(E->key()); + bool files_only = true; + for (int i = 0; i < to_delete.size(); ++i) { + if (to_delete[i].ends_with("/")) { + files_only = false; + } else if (ResourceCache::has(to_delete[i])) { + Resource *res = ResourceCache::get(to_delete[i]); res->set_path(""); //clear reference to path } - String fpath = OS::get_singleton()->get_resource_dir() + E->key().replace_first("res://", "/"); - OS::get_singleton()->move_to_trash(fpath); - changed = true; + + String path = OS::get_singleton()->get_resource_dir() + to_delete[i].replace_first("res://", "/"); + print_line("Moving to trash: " + path); + Error err = OS::get_singleton()->move_to_trash(path); + if (err != OK) { + EditorNode::get_singleton()->add_io_error(TTR("Cannot remove:\n") + to_delete[i] + "\n"); + } } - if (changed) { + if (files_only) { + //If we only deleted files we should only need to tell the file system about the files we touched. + for (int i = 0; i < to_delete.size(); ++i) { + EditorFileSystem::get_singleton()->update_file(to_delete[i]); + } + } else { EditorFileSystem::get_singleton()->scan_changes(); } } diff --git a/editor/dependency_editor.h b/editor/dependency_editor.h index 4dfb9de268..c7e9baa5c2 100644 --- a/editor/dependency_editor.h +++ b/editor/dependency_editor.h @@ -84,14 +84,33 @@ class DependencyRemoveDialog : public ConfirmationDialog { Label *text; Tree *owners; - bool exist; - Map<String, TreeItem *> files; - void _fill_owners(EditorFileSystemDirectory *efsd); + + Map<String, String> all_remove_files; + Vector<String> to_delete; + + struct RemovedDependency { + String file; + String file_type; + String dependency; + String dependency_folder; + + bool operator<(const RemovedDependency &p_other) const { + if (dependency_folder.empty() != p_other.dependency_folder.empty()) { + return p_other.dependency_folder.empty(); + } else { + return dependency < p_other.dependency; + } + } + }; + + void _find_files_in_removed_folder(EditorFileSystemDirectory *efsd, const String &p_folder); + void _find_all_removed_dependencies(EditorFileSystemDirectory *efsd, Vector<RemovedDependency> &p_removed); + void _build_removed_dependency_tree(const Vector<RemovedDependency> &p_removed); void ok_pressed(); public: - void show(const Vector<String> &to_erase); + void show(const Vector<String> &p_folders, const Vector<String> &p_files); DependencyRemoveDialog(); }; diff --git a/editor/editor_help.cpp b/editor/editor_help.cpp index 20ffbde378..2c4d3035a4 100644 --- a/editor/editor_help.cpp +++ b/editor/editor_help.cpp @@ -1699,7 +1699,7 @@ void EditorHelp::_notification(int p_what) { case EditorSettings::NOTIFICATION_EDITOR_SETTINGS_CHANGED: { - class_desc->add_color_override("selection_color", EDITOR_DEF("text_editor/highlighting/selection_color", Color(0.2, 0.2, 1))); + class_desc->add_color_override("selection_color", get_color("text_editor/theme/selection_color", "Editor")); } break; @@ -1788,7 +1788,7 @@ EditorHelp::EditorHelp() { class_desc = memnew(RichTextLabel); vbc->add_child(class_desc); class_desc->set_v_size_flags(SIZE_EXPAND_FILL); - class_desc->add_color_override("selection_color", EDITOR_DEF("text_editor/highlighting/selection_color", Color(0.2, 0.2, 1))); + class_desc->add_color_override("selection_color", get_color("text_editor/theme/selection_color", "Editor")); class_desc->connect("meta_clicked", this, "_class_desc_select"); class_desc->connect("gui_input", this, "_class_desc_input"); } @@ -1879,7 +1879,7 @@ void EditorHelpBit::_notification(int p_what) { switch (p_what) { case EditorSettings::NOTIFICATION_EDITOR_SETTINGS_CHANGED: { - rich_text->add_color_override("selection_color", EDITOR_DEF("text_editor/highlighting/selection_color", Color(0.2, 0.2, 1))); + rich_text->add_color_override("selection_color", get_color("text_editor/theme/selection_color", "Editor")); } break; default: break; @@ -1898,6 +1898,7 @@ EditorHelpBit::EditorHelpBit() { add_child(rich_text); rich_text->set_anchors_and_margins_preset(Control::PRESET_WIDE); rich_text->connect("meta_clicked", this, "_meta_clicked"); - rich_text->add_color_override("selection_color", EDITOR_DEF("text_editor/highlighting/selection_color", Color(0.2, 0.2, 1))); + rich_text->add_color_override("selection_color", get_color("text_editor/theme/selection_color", "Editor")); + rich_text->set_override_selected_font_color(false); set_custom_minimum_size(Size2(0, 70 * EDSCALE)); } diff --git a/editor/editor_node.cpp b/editor/editor_node.cpp index 1ca88133b8..34881c8aff 100644 --- a/editor/editor_node.cpp +++ b/editor/editor_node.cpp @@ -1454,7 +1454,7 @@ void EditorNode::_edit_current() { } } else if (current_res->get_path().is_resource_file()) { if (FileAccess::exists(current_res->get_path() + ".import")) { - editable_warning = TTR("This resource was imported, so it's not editable. Change it's settings in the import panel and re-import."); + editable_warning = TTR("This resource was imported, so it's not editable. Change its settings in the import panel and then re-import."); } } } else if (is_node) { @@ -3156,12 +3156,19 @@ void EditorNode::_add_to_recent_scenes(const String &p_scene) { void EditorNode::_open_recent_scene(int p_idx) { String base = "_" + ProjectSettings::get_singleton()->get_resource_path().replace("\\", "::").replace("/", "::"); - Vector<String> rc = EDITOR_DEF(base + "/_recent_scenes", Array()); - ERR_FAIL_INDEX(p_idx, rc.size()); + if (p_idx == recent_scenes->get_item_count() - 1) { + + EditorSettings::get_singleton()->erase(base + "/_recent_scenes"); + call_deferred("_update_recent_scenes"); + } else { + + Vector<String> rc = EDITOR_DEF(base + "/_recent_scenes", Array()); + ERR_FAIL_INDEX(p_idx, rc.size()); - String path = "res://" + rc[p_idx]; - load_scene(path); + String path = "res://" + rc[p_idx]; + load_scene(path); + } } void EditorNode::_update_recent_scenes() { @@ -3169,10 +3176,15 @@ void EditorNode::_update_recent_scenes() { String base = "_" + ProjectSettings::get_singleton()->get_resource_path().replace("\\", "::").replace("/", "::"); Vector<String> rc = EDITOR_DEF(base + "/_recent_scenes", Array()); recent_scenes->clear(); + for (int i = 0; i < rc.size(); i++) { recent_scenes->add_item(rc[i], i); } + + recent_scenes->add_separator(); + recent_scenes->add_shortcut(ED_SHORTCUT("editor/clear_recent", TTR("Clear Recent Scenes"))); + recent_scenes->set_as_minsize(); } void EditorNode::_quick_opened() { @@ -4513,6 +4525,7 @@ void EditorNode::_bind_methods() { ClassDB::bind_method("_set_main_scene_state", &EditorNode::_set_main_scene_state); ClassDB::bind_method("_update_scene_tabs", &EditorNode::_update_scene_tabs); ClassDB::bind_method("_discard_changes", &EditorNode::_discard_changes); + ClassDB::bind_method("_update_recent_scenes", &EditorNode::_update_recent_scenes); ClassDB::bind_method("_prepare_history", &EditorNode::_prepare_history); ClassDB::bind_method("_select_history", &EditorNode::_select_history); @@ -5678,12 +5691,12 @@ void EditorPluginList::edit(Object *p_object) { } } -bool EditorPluginList::forward_gui_input(const Transform2D &p_canvas_xform, const Ref<InputEvent> &p_event) { +bool EditorPluginList::forward_gui_input(const Ref<InputEvent> &p_event) { bool discard = false; for (int i = 0; i < plugins_list.size(); i++) { - if (plugins_list[i]->forward_canvas_gui_input(p_canvas_xform, p_event)) { + if (plugins_list[i]->forward_canvas_gui_input(p_event)) { discard = true; } } @@ -5707,10 +5720,10 @@ bool EditorPluginList::forward_spatial_gui_input(Camera *p_camera, const Ref<Inp return discard; } -void EditorPluginList::forward_draw_over_canvas(const Transform2D &p_canvas_xform, Control *p_canvas) { +void EditorPluginList::forward_draw_over_canvas(Control *p_canvas) { for (int i = 0; i < plugins_list.size(); i++) { - plugins_list[i]->forward_draw_over_canvas(p_canvas_xform, p_canvas); + plugins_list[i]->forward_draw_over_canvas(p_canvas); } } diff --git a/editor/editor_node.h b/editor/editor_node.h index 0d1c6787cd..32d46e686b 100644 --- a/editor/editor_node.h +++ b/editor/editor_node.h @@ -812,9 +812,9 @@ public: void make_visible(bool p_visible); void edit(Object *p_object); - bool forward_gui_input(const Transform2D &p_canvas_xform, const Ref<InputEvent> &p_event); + bool forward_gui_input(const Ref<InputEvent> &p_event); bool forward_spatial_gui_input(Camera *p_camera, const Ref<InputEvent> &p_event, bool serve_when_force_input_enabled); - void forward_draw_over_canvas(const Transform2D &p_canvas_xform, Control *p_canvas); + void forward_draw_over_canvas(Control *p_canvas); void add_plugin(EditorPlugin *p_plugin); void clear(); bool empty(); diff --git a/editor/editor_plugin.cpp b/editor/editor_plugin.cpp index a528662e0f..229d6adfef 100644 --- a/editor/editor_plugin.cpp +++ b/editor/editor_plugin.cpp @@ -402,18 +402,18 @@ Ref<SpatialEditorGizmo> EditorPlugin::create_spatial_gizmo(Spatial *p_spatial) { return Ref<SpatialEditorGizmo>(); } -bool EditorPlugin::forward_canvas_gui_input(const Transform2D &p_canvas_xform, const Ref<InputEvent> &p_event) { +bool EditorPlugin::forward_canvas_gui_input(const Ref<InputEvent> &p_event) { if (get_script_instance() && get_script_instance()->has_method("forward_canvas_gui_input")) { - return get_script_instance()->call("forward_canvas_gui_input", p_canvas_xform, p_event); + return get_script_instance()->call("forward_canvas_gui_input", p_event); } return false; } -void EditorPlugin::forward_draw_over_canvas(const Transform2D &p_canvas_xform, Control *p_canvas) { +void EditorPlugin::forward_draw_over_canvas(Control *p_canvas) { if (get_script_instance() && get_script_instance()->has_method("forward_draw_over_canvas")) { - get_script_instance()->call("forward_draw_over_canvas", p_canvas_xform, p_canvas); + get_script_instance()->call("forward_draw_over_canvas", p_canvas); } } diff --git a/editor/editor_plugin.h b/editor/editor_plugin.h index 18530e9ce4..1d68eee117 100644 --- a/editor/editor_plugin.h +++ b/editor/editor_plugin.h @@ -156,8 +156,8 @@ public: void notify_scene_closed(const String &scene_filepath); virtual Ref<SpatialEditorGizmo> create_spatial_gizmo(Spatial *p_spatial); - virtual bool forward_canvas_gui_input(const Transform2D &p_canvas_xform, const Ref<InputEvent> &p_event); - virtual void forward_draw_over_canvas(const Transform2D &p_canvas_xform, Control *p_canvas); + virtual bool forward_canvas_gui_input(const Ref<InputEvent> &p_event); + virtual void forward_draw_over_canvas(Control *p_canvas); virtual bool forward_spatial_gui_input(Camera *p_camera, const Ref<InputEvent> &p_event); virtual String get_name() const; virtual bool has_main_screen() const; diff --git a/editor/editor_settings.cpp b/editor/editor_settings.cpp index b532bb793a..7c45e19f5f 100644 --- a/editor/editor_settings.cpp +++ b/editor/editor_settings.cpp @@ -719,12 +719,13 @@ void EditorSettings::_load_defaults(Ref<ConfigFile> p_extra_config) { // freelook _initial_set("editors/3d/freelook/freelook_inertia", 0.1); hints["editors/3d/freelook/freelook_inertia"] = PropertyInfo(Variant::REAL, "editors/3d/freelook/freelook_inertia", PROPERTY_HINT_RANGE, "0.0, 1, 0.01"); - _initial_set("editors/3d/freelook/freelook_base_speed", 0.1); + _initial_set("editors/3d/freelook/freelook_base_speed", 5.0); hints["editors/3d/freelook/freelook_base_speed"] = PropertyInfo(Variant::REAL, "editors/3d/freelook/freelook_base_speed", PROPERTY_HINT_RANGE, "0.0, 10, 0.01"); _initial_set("editors/3d/freelook/freelook_activation_modifier", 0); hints["editors/3d/freelook/freelook_activation_modifier"] = PropertyInfo(Variant::INT, "editors/3d/freelook/freelook_activation_modifier", PROPERTY_HINT_ENUM, "None,Shift,Alt,Meta,Ctrl"); _initial_set("editors/3d/freelook/freelook_modifier_speed_factor", 3.0); hints["editors/3d/freelook/freelook_modifier_speed_factor"] = PropertyInfo(Variant::REAL, "editors/3d/freelook/freelook_modifier_speed_factor", PROPERTY_HINT_RANGE, "0.0, 10.0, 0.1"); + _initial_set("editors/3d/freelook/freelook_speed_zoom_link", false); _initial_set("editors/2d/bone_width", 5); _initial_set("editors/2d/bone_color1", Color(1.0, 1.0, 1.0, 0.9)); diff --git a/editor/editor_themes.cpp b/editor/editor_themes.cpp index 3fc1dcb0bd..992322978e 100644 --- a/editor/editor_themes.cpp +++ b/editor/editor_themes.cpp @@ -392,7 +392,7 @@ Ref<Theme> create_editor_theme(const Ref<Theme> p_theme) { editor_register_and_generate_icons(theme, dark_theme, thumb_size); } // thumbnail size has changed, so we regenerate the medium sizes - if (p_theme != NULL && fabs(p_theme->get_constant("thumb_size", "Editor") - thumb_size) > 0.00001) { + if (p_theme != NULL && fabs((double)p_theme->get_constant("thumb_size", "Editor") - thumb_size) > 0.00001) { editor_register_and_generate_icons(p_theme, dark_theme, thumb_size, true); } @@ -972,8 +972,8 @@ Ref<Theme> create_editor_theme(const Ref<Theme> p_theme) { const Color dim_color = Color(font_color.r, font_color.g, font_color.b, 0.5); const float mono_value = mono_color.r; - const Color alpha1 = Color(mono_value, mono_value, mono_value, 0.1); - const Color alpha2 = Color(mono_value, mono_value, mono_value, 0.3); + const Color alpha1 = Color(mono_value, mono_value, mono_value, 0.07); + const Color alpha2 = Color(mono_value, mono_value, mono_value, 0.14); const Color alpha3 = Color(mono_value, mono_value, mono_value, 0.5); const Color alpha4 = Color(mono_value, mono_value, mono_value, 0.7); @@ -998,7 +998,7 @@ Ref<Theme> create_editor_theme(const Ref<Theme> p_theme) { const Color caret_color = mono_color; const Color caret_background_color = mono_color.inverted(); const Color text_selected_color = dark_color_3; - const Color selection_color = alpha3; + const Color selection_color = alpha2; const Color brace_mismatch_color = error_color; const Color current_line_color = alpha1; const Color line_length_guideline_color = warning_color; diff --git a/editor/filesystem_dock.cpp b/editor/filesystem_dock.cpp index a9d72607b4..dfd35fdd96 100644 --- a/editor/filesystem_dock.cpp +++ b/editor/filesystem_dock.cpp @@ -458,9 +458,9 @@ void FileSystemDock::_update_files(bool p_keep_selection) { if (path != "res://") { if (use_thumbnails) { - files->add_item("..", folder_thumbnail, true); + files->add_item("..", folder_thumbnail, false); } else { - files->add_item("..", get_icon("folder", "FileDialog"), true); + files->add_item("..", get_icon("folder", "FileDialog"), false); } String bd = path.get_base_dir(); @@ -567,9 +567,22 @@ void FileSystemDock::_update_files(bool p_keep_selection) { } void FileSystemDock::_select_file(int p_idx) { - - files->select(p_idx, true); - _file_option(FILE_OPEN); + String path = files->get_item_metadata(p_idx); + if (path.ends_with("/")) { + if (path != "res://") { + path = path.substr(0, path.length() - 1); + } + this->path = path; + _update_files(false); + current_path->set_text(path); + _push_to_history(); + } else { + if (ResourceLoader::get_resource_type(path) == "PackedScene") { + editor->open_request(path); + } else { + editor->load_resource(path); + } + } } void FileSystemDock::_go_to_tree() { @@ -704,18 +717,19 @@ void FileSystemDock::_push_to_history() { button_hist_next->set_disabled(history_pos + 1 == history.size()); } -void FileSystemDock::_find_inside_move_files(EditorFileSystemDirectory *efsd, Vector<String> &files) { +void FileSystemDock::_get_all_files_in_dir(EditorFileSystemDirectory *efsd, Vector<String> &files) const { + if (efsd == NULL) + return; for (int i = 0; i < efsd->get_subdir_count(); i++) { - _find_inside_move_files(efsd->get_subdir(i), files); + _get_all_files_in_dir(efsd->get_subdir(i), files); } for (int i = 0; i < efsd->get_file_count(); i++) { files.push_back(efsd->get_file_path(i)); } } -void FileSystemDock::_find_remaps(EditorFileSystemDirectory *efsd, Map<String, String> &renames, List<String> &to_remaps) { - +void FileSystemDock::_find_remaps(EditorFileSystemDirectory *efsd, const Map<String, String> &renames, Vector<String> &to_remaps) const { for (int i = 0; i < efsd->get_subdir_count(); i++) { _find_remaps(efsd->get_subdir(i), renames, to_remaps); } @@ -730,199 +744,157 @@ void FileSystemDock::_find_remaps(EditorFileSystemDirectory *efsd, Map<String, S } } -void FileSystemDock::_rename_operation(const String &p_to_path) { +void FileSystemDock::_try_move_item(const FileOrFolder &p_item, const String &p_new_path, Map<String, String> &p_renames) 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 (move_files[0] == p_to_path) { - EditorNode::get_singleton()->show_warning(TTR("Same source and destination files, doing nothing.")); + if (new_path == old_path) { return; - } - if (FileAccess::exists(p_to_path)) { - EditorNode::get_singleton()->show_warning(TTR("Target file exists, can't overwrite. Delete first.")); + } 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; } - Map<String, String> renames; - renames[move_files[0]] = p_to_path; - - List<String> remap; - - _find_remaps(EditorFileSystem::get_singleton()->get_filesystem(), renames, remap); - print_line("found files to remap: " + itos(remap.size())); - - //perform remaps - for (List<String>::Element *E = remap.front(); E; E = E->next()) { - - Error err = ResourceLoader::rename_dependencies(E->get(), renames); - print_line("remapping: " + E->get()); - - if (err != OK) { - EditorNode::get_singleton()->add_io_error("Can't rename deps for:\n" + E->get() + "\n"); - } + //Build a list of files which will have new paths as a result of this operation + Vector<String> changed_paths; + if (p_item.is_file) { + changed_paths.push_back(old_path); + } else { + _get_all_files_in_dir(EditorFileSystem::get_singleton()->get_filesystem_path(old_path), changed_paths); } - //finally, perform moves - DirAccess *da = DirAccess::create(DirAccess::ACCESS_RESOURCES); + print_line("Moving " + old_path + " -> " + new_path); + Error err = da->rename(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->rename(old_path + ".import", new_path + ".import"); + if (err != OK) { + EditorNode::get_singleton()->add_io_error(TTR("Error moving:\n") + old_path + ".import\n"); + } + } - Error err = da->rename(move_files[0], p_to_path); - print_line("moving file " + move_files[0] + " to " + p_to_path); - if (err != OK) { - EditorNode::get_singleton()->add_io_error("Error moving file:\n" + move_files[0] + "\n"); + //Only treat as a changed dependency if it was successfully moved + for (int i = 0; i < changed_paths.size(); ++i) { + p_renames[changed_paths[i]] = changed_paths[i].replace_first(old_path, new_path); + print_line(" Remap: " + changed_paths[i] + " -> " + p_renames[changed_paths[i]]); + } + } else { + EditorNode::get_singleton()->add_io_error(TTR("Error moving:\n") + old_path + "\n"); } - - //rescan everything memdelete(da); - print_line("call rescan!"); - _rescan(); } -void FileSystemDock::_move_operation(const String &p_to_path) { - - if (p_to_path == path) { - EditorNode::get_singleton()->show_warning(TTR("Same source and destination paths, doing nothing.")); - return; +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. + // 2) ResourceLoader can use the new paths without needing to call rescan. + Vector<String> remaps; + _find_remaps(EditorFileSystem::get_singleton()->get_filesystem(), p_renames, remaps); + for (int i = 0; i < remaps.size(); ++i) { + //Because we haven't called a rescan yet the found remap might still be an old path itself. + String file = p_renames.has(remaps[i]) ? p_renames[remaps[i]] : remaps[i]; + print_line("Remapping dependencies for: " + file); + Error err = ResourceLoader::rename_dependencies(file, p_renames); + if (err != OK) { + EditorNode::get_singleton()->add_io_error(TTR("Unable to update dependencies:\n") + remaps[i] + "\n"); + } } +} - //find files inside dirs to be moved - - Vector<String> inside_files; - - for (int i = 0; i < move_dirs.size(); i++) { - if (p_to_path.begins_with(move_dirs[i])) { - EditorNode::get_singleton()->show_warning(TTR("Can't move directories to within themselves.")); - return; - } +void FileSystemDock::_make_dir_confirm() { + String dir_name = make_dir_dialog_text->get_text().strip_edges(); - EditorFileSystemDirectory *efsd = EditorFileSystem::get_singleton()->get_filesystem_path(move_dirs[i]); - if (!efsd) - continue; - _find_inside_move_files(efsd, inside_files); + if (dir_name.length() == 0) { + EditorNode::get_singleton()->show_warning(TTR("No name provided")); + return; + } else if (dir_name.find("/") != -1 || dir_name.find("\\") != -1 || dir_name.find(":") != -1) { + EditorNode::get_singleton()->show_warning(TTR("Provided name contains invalid characters")); + return; } - //make list of remaps - Map<String, String> renames; - String repfrom = path == "res://" ? path : String(path + "/"); - String repto = p_to_path; - if (!repto.ends_with("/")) { - repto += "/"; + print_line("Making folder " + dir_name + " in " + path); + DirAccess *da = DirAccess::create(DirAccess::ACCESS_RESOURCES); + Error err = da->change_dir(path); + if (err == OK) { + err = da->make_dir(dir_name); } + memdelete(da); - print_line("reprfrom: " + repfrom + " repto " + repto); - - for (int i = 0; i < move_files.size(); i++) { - renames[move_files[i]] = move_files[i].replace_first(repfrom, repto); - print_line("move file " + move_files[i] + " -> " + renames[move_files[i]]); - } - for (int i = 0; i < inside_files.size(); i++) { - renames[inside_files[i]] = inside_files[i].replace_first(repfrom, repto); - print_line("inside file " + inside_files[i] + " -> " + renames[inside_files[i]]); + if (err == OK) { + print_line("call rescan!"); + _rescan(); + } else { + EditorNode::get_singleton()->show_warning(TTR("Could not create folder.")); } +} - //make list of files that will be run the remapping - List<String> remap; - - _find_remaps(EditorFileSystem::get_singleton()->get_filesystem(), renames, remap); - print_line("found files to remap: " + itos(remap.size())); - - //perform remaps - for (List<String>::Element *E = remap.front(); E; E = E->next()) { - - Error err = ResourceLoader::rename_dependencies(E->get(), renames); - print_line("remapping: " + E->get()); +void FileSystemDock::_rename_operation_confirm() { - if (err != OK) { - EditorNode::get_singleton()->add_io_error(TTR("Can't rename deps for:\n") + E->get() + "\n"); - } + String new_name = rename_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; } - //finally, perform moves + String old_path = to_rename.path.ends_with("/") ? to_rename.path.substr(0, to_rename.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); - - for (int i = 0; i < move_files.size(); i++) { - - String to = move_files[i].replace_first(repfrom, repto); - Error err = da->rename(move_files[i], to); - print_line("moving file " + move_files[i] + " to " + to); - if (err != OK) { - EditorNode::get_singleton()->add_io_error(TTR("Error moving file:\n") + move_files[i] + "\n"); - } - if (FileAccess::exists(move_files[i] + ".import")) { //move imported files too - //@todo should remove the files in .import folder - err = da->rename(move_files[i] + ".import", to + ".import"); - if (err != OK) { - EditorNode::get_singleton()->add_io_error(TTR("Error moving file:\n") + move_files[i] + ".import\n"); - } - } + 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); - for (int i = 0; i < move_dirs.size(); i++) { + Map<String, String> renames; + _try_move_item(to_rename, new_path, renames); + _update_dependencies_after_move(renames); - String mdir = move_dirs[i]; - if (mdir == "res://") - continue; + //Rescan everything + print_line("call rescan!"); + _rescan(); +} - if (mdir.ends_with("/")) { - mdir = mdir.substr(0, mdir.length() - 1); - } +void FileSystemDock::_move_operation_confirm(const String &p_to_path) { - String to = p_to_path.plus_file(mdir.get_file()); - Error err = da->rename(mdir, to); - print_line("moving dir " + mdir + " to " + to); - if (err != OK) { - EditorNode::get_singleton()->add_io_error(TTR("Error moving dir:\n") + move_dirs[i] + "\n"); - } + Map<String, String> renames; + for (int i = 0; i < to_move.size(); i++) { + String old_path = to_move[i].path.ends_with("/") ? to_move[i].path.substr(0, to_move[i].path.length() - 1) : to_move[i].path; + String new_path = p_to_path.plus_file(old_path.get_file()); + _try_move_item(to_move[i], new_path, renames); } - memdelete(da); - //rescan everything + _update_dependencies_after_move(renames); print_line("call rescan!"); _rescan(); } void FileSystemDock::_file_option(int p_option) { - switch (p_option) { - - case FILE_SHOW_IN_EXPLORER: + case FILE_SHOW_IN_EXPLORER: { + String dir = ProjectSettings::get_singleton()->globalize_path(this->path); + OS::get_singleton()->shell_open(String("file://") + dir); + } break; case FILE_OPEN: { - int idx = -1; - for (int i = 0; i < files->get_item_count(); i++) { - if (files->is_selected(i)) { - idx = i; - break; - } - } - - if (idx < 0) - return; - - String path = files->get_item_metadata(idx); - if (p_option == FILE_SHOW_IN_EXPLORER) { - String dir = ProjectSettings::get_singleton()->globalize_path(path); - dir = dir.substr(0, dir.find_last("/")); - OS::get_singleton()->shell_open(String("file://") + dir); - return; - } - - if (path.ends_with("/")) { - if (path != "res://") { - path = path.substr(0, path.length() - 1); - } - this->path = path; - _update_files(false); - current_path->set_text(path); - _push_to_history(); - } else { - - if (ResourceLoader::get_resource_type(path) == "PackedScene") { - - editor->open_request(path); - } else { - - editor->load_resource(path); - } - } + int idx = files->get_current(); + if (idx < 0 || idx >= files->get_item_count()) + break; + _select_file(idx); } break; case FILE_INSTANCE: { @@ -958,64 +930,59 @@ void FileSystemDock::_file_option(int p_option) { owners_editor->show(path); } break; case FILE_MOVE: { - - move_dirs.clear(); - move_files.clear(); - + to_move.clear(); for (int i = 0; i < files->get_item_count(); i++) { - - String path = files->get_item_metadata(i); if (!files->is_selected(i)) continue; - if (files->get_item_text(i) == "..") { - EditorNode::get_singleton()->show_warning(TTR("Can't operate on '..'")); - return; - } - - if (path.ends_with("/")) { - move_dirs.push_back(path.substr(0, path.length() - 1)); - } else { - move_files.push_back(path); - } + String path = files->get_item_metadata(i); + to_move.push_back(FileOrFolder(path, !path.ends_with("/"))); } - - if (move_dirs.empty() && move_files.size() == 1) { - - rename_dialog->clear_filters(); - rename_dialog->add_filter("*." + move_files[0].get_extension()); - rename_dialog->set_mode(EditorFileDialog::MODE_SAVE_FILE); - rename_dialog->set_current_path(move_files[0]); - rename_dialog->popup_centered_ratio(); - rename_dialog->set_title(TTR("Pick New Name and Location For:") + " " + move_files[0].get_file()); - - } else { - //just move + if (to_move.size() > 0) { move_dialog->popup_centered_ratio(); } + } break; + case FILE_RENAME: { + int idx = files->get_current(); + if (idx < 0 || idx >= files->get_item_count()) + break; + to_rename.path = files->get_item_metadata(idx); + to_rename.is_file = !to_rename.path.ends_with("/"); + if (to_rename.is_file) { + String name = to_rename.path.get_file(); + rename_dialog->set_title(TTR("Renaming file:") + " " + name); + rename_dialog_text->set_text(name); + rename_dialog_text->select(0, name.find_last(".")); + } else { + String name = to_rename.path.substr(0, to_rename.path.length() - 1).get_file(); + rename_dialog->set_title(TTR("Renaming folder:") + " " + name); + rename_dialog_text->set_text(name); + rename_dialog_text->select(0, name.length()); + } + rename_dialog->popup_centered_minsize(Size2(250, 80) * EDSCALE); + rename_dialog_text->grab_focus(); } break; case FILE_REMOVE: { - - Vector<String> torem; + Vector<String> remove_files; + Vector<String> remove_folders; for (int i = 0; i < files->get_item_count(); i++) { - String path = files->get_item_metadata(i); - if (!files->is_selected(i)) - continue; - torem.push_back(path); + if (files->is_selected(i) && path != "res://") { + if (path.ends_with("/")) { + remove_folders.push_back(path); + } else { + remove_files.push_back(path); + } + } } - if (torem.empty()) { - EditorNode::get_singleton()->show_warning(TTR("No files selected!")); - break; + if (remove_files.size() + remove_folders.size() > 0) { + remove_dialog->show(remove_folders, remove_files); + //1) find if used + //2) warn } - - remove_dialog->show(torem); - //1) find if used - //2) warn - } break; case FILE_INFO: { @@ -1052,15 +1019,20 @@ void FileSystemDock::_file_option(int p_option) { } */ - } break; - case FILE_COPY_PATH: - + case FILE_NEW_FOLDER: { + make_dir_dialog_text->set_text("new folder"); + make_dir_dialog_text->select_all(); + make_dir_dialog->popup_centered_minsize(Size2(250, 80) * EDSCALE); + make_dir_dialog_text->grab_focus(); + } break; + case FILE_COPY_PATH: { int idx = files->get_current(); if (idx < 0 || idx >= files->get_item_count()) break; String path = files->get_item_metadata(idx); OS::get_singleton()->set_clipboard(path); + } break; } } @@ -1070,26 +1042,64 @@ void FileSystemDock::_folder_option(int p_option) { TreeItem *child = item->get_children(); switch (p_option) { - - case FOLDER_EXPAND_ALL: + case FOLDER_EXPAND_ALL: { item->set_collapsed(false); while (child) { child->set_collapsed(false); child = child->get_next(); } - break; - - case FOLDER_COLLAPSE_ALL: + } break; + case FOLDER_COLLAPSE_ALL: { while (child) { child->set_collapsed(true); child = child->get_next(); } - break; - case FOLDER_SHOW_IN_EXPLORER: + } break; + case FOLDER_MOVE: { + to_move.clear(); + String fpath = item->get_metadata(tree->get_selected_column()); + if (fpath != "res://") { + fpath = fpath.ends_with("/") ? fpath.substr(0, fpath.length() - 1) : fpath; + to_move.push_back(FileOrFolder(fpath, false)); + move_dialog->popup_centered_ratio(); + } + } break; + case FOLDER_RENAME: { + to_rename.path = item->get_metadata(tree->get_selected_column()); + to_rename.is_file = false; + if (to_rename.path != "res://") { + String name = to_rename.path.ends_with("/") ? to_rename.path.substr(0, to_rename.path.length() - 1).get_file() : to_rename.path.get_file(); + rename_dialog->set_title(TTR("Renaming folder:") + " " + name); + rename_dialog_text->set_text(name); + rename_dialog_text->select(0, name.length()); + rename_dialog->popup_centered_minsize(Size2(250, 80) * EDSCALE); + rename_dialog_text->grab_focus(); + } + } break; + case FOLDER_REMOVE: { + Vector<String> remove_folders; + Vector<String> remove_files; + String path = item->get_metadata(tree->get_selected_column()); + if (path != "res://") { + remove_folders.push_back(path); + remove_dialog->show(remove_folders, remove_files); + } + } break; + case FOLDER_NEW_FOLDER: { + make_dir_dialog_text->set_text("new folder"); + make_dir_dialog_text->select_all(); + make_dir_dialog->popup_centered_minsize(Size2(250, 80) * EDSCALE); + make_dir_dialog_text->grab_focus(); + } break; + case FOLDER_COPY_PATH: { + String path = item->get_metadata(tree->get_selected_column()); + OS::get_singleton()->set_clipboard(path); + } break; + case FOLDER_SHOW_IN_EXPLORER: { String path = item->get_metadata(tree->get_selected_column()); String dir = ProjectSettings::get_singleton()->globalize_path(path); OS::get_singleton()->shell_open(String("file://") + dir); - return; + } break; } } @@ -1128,9 +1138,20 @@ void FileSystemDock::_dir_rmb_pressed(const Vector2 &p_pos) { folder_options->add_item(TTR("Expand all"), FOLDER_EXPAND_ALL); folder_options->add_item(TTR("Collapse all"), FOLDER_COLLAPSE_ALL); - folder_options->add_separator(); - folder_options->add_item(TTR("Show In File Manager"), FOLDER_SHOW_IN_EXPLORER); - + TreeItem *item = tree->get_selected(); + if (item) { + String fpath = item->get_metadata(tree->get_selected_column()); + folder_options->add_separator(); + folder_options->add_item(TTR("Copy Path"), FOLDER_COPY_PATH); + if (fpath != "res://") { + folder_options->add_item(TTR("Rename.."), FOLDER_RENAME); + folder_options->add_item(TTR("Move To.."), FOLDER_MOVE); + folder_options->add_item(TTR("Delete"), FOLDER_REMOVE); + } + folder_options->add_separator(); + folder_options->add_item(TTR("New Folder.."), FOLDER_NEW_FOLDER); + folder_options->add_item(TTR("Show In File Manager"), FOLDER_SHOW_IN_EXPLORER); + } folder_options->set_position(tree->get_global_position() + p_pos); folder_options->popup(); } @@ -1445,117 +1466,79 @@ void FileSystemDock::drop_data_fw(const Point2 &p_point, const Variant &p_data, } Vector<String> fnames = drag_data["files"]; - move_files.clear(); - move_dirs.clear(); - + to_move.clear(); for (int i = 0; i < fnames.size(); i++) { - if (fnames[i].ends_with("/")) - move_dirs.push_back(fnames[i]); - else - move_files.push_back(fnames[i]); + to_move.push_back(FileOrFolder(fnames[i], !fnames[i].ends_with("/"))); } - - _move_operation(to_dir); + _move_operation_confirm(to_dir); } } } void FileSystemDock::_files_list_rmb_select(int p_item, const Vector2 &p_pos) { - Vector<String> filenames; + //Right clicking ".." should clear current selection + if (files->get_item_text(p_item) == "..") { + for (int i = 0; i < files->get_item_count(); i++) { + files->unselect(i); + } + } - bool all_scenes = true; - bool all_can_reimport = true; - bool is_dir = false; - Set<String> types; + Vector<String> filenames; + Vector<String> foldernames; + bool all_files = true; + bool all_files_scenes = true; + bool all_folders = true; for (int i = 0; i < files->get_item_count(); i++) { - - if (!files->is_selected(i)) + if (!files->is_selected(i)) { continue; - - String path = files->get_item_metadata(i); - - if (files->get_item_text(i) == "..") { - // no operate on .. - return; } + String path = files->get_item_metadata(i); if (path.ends_with("/")) { - is_dir = true; - } - - int pos; - - EditorFileSystemDirectory *efsd = EditorFileSystem::get_singleton()->find_file(path, &pos); - - if (efsd) { - + foldernames.push_back(path); + all_files = false; } else { - all_can_reimport = false; + filenames.push_back(path); + all_folders = false; + all_files_scenes &= (EditorFileSystem::get_singleton()->get_file_type(path) == "PackedScene"); } - - filenames.push_back(path); - if (EditorFileSystem::get_singleton()->get_file_type(path) != "PackedScene") - all_scenes = false; } - if (filenames.size() == 0) - return; - file_options->clear(); file_options->set_size(Size2(1, 1)); + if (all_files && filenames.size() > 0) { + file_options->add_item(TTR("Open"), FILE_OPEN); + if (all_files_scenes) { + file_options->add_item(TTR("Instance"), FILE_INSTANCE); + } + file_options->add_separator(); - file_options->add_item(TTR("Open"), FILE_OPEN); - if (all_scenes) { - file_options->add_item(TTR("Instance"), FILE_INSTANCE); - } - - file_options->add_separator(); - - if (filenames.size() == 1 && !is_dir) { - file_options->add_item(TTR("Edit Dependencies.."), FILE_DEPENDENCIES); - file_options->add_item(TTR("View Owners.."), FILE_OWNERS); + 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(); } - if (!is_dir) { - if (filenames.size() == 1) { + int num_items = filenames.size() + foldernames.size(); + if (num_items >= 1) { + if (num_items == 1) { file_options->add_item(TTR("Copy Path"), FILE_COPY_PATH); - file_options->add_item(TTR("Rename or Move.."), FILE_MOVE); - } else { - file_options->add_item(TTR("Move To.."), FILE_MOVE); + file_options->add_item(TTR("Rename.."), FILE_RENAME); } + file_options->add_item(TTR("Move To.."), FILE_MOVE); + file_options->add_item(TTR("Delete"), FILE_REMOVE); + file_options->add_separator(); } - file_options->add_item(TTR("Delete"), FILE_REMOVE); - - //file_options->add_item(TTR("Info"),FILE_INFO); - - file_options->add_separator(); + file_options->add_item(TTR("New Folder.."), FILE_NEW_FOLDER); file_options->add_item(TTR("Show In File Manager"), FILE_SHOW_IN_EXPLORER); - if (all_can_reimport && types.size() == 1) { //all can reimport and are of the same type - - /* - bool valid=true; - Ref<EditorImportPlugin> rimp = EditorImportExport::get_singleton()->get_import_plugin_by_name(types.front()->get()); - if (rimp.is_valid()) { - - if (filenames.size()>1 && !rimp->can_reimport_multiple_files()) { - valid=false; - } - } else { - valid=false; - } - - if (valid) { - file_options->add_separator(); - file_options->add_item(TTR("Re-Import.."),FILE_REIMPORT); - } - */ - } - file_options->set_position(files->get_global_position() + p_pos); file_options->popup(); } @@ -1640,8 +1623,9 @@ void FileSystemDock::_bind_methods() { ClassDB::bind_method(D_METHOD("_dir_selected"), &FileSystemDock::_dir_selected); ClassDB::bind_method(D_METHOD("_file_option"), &FileSystemDock::_file_option); ClassDB::bind_method(D_METHOD("_folder_option"), &FileSystemDock::_folder_option); - ClassDB::bind_method(D_METHOD("_move_operation"), &FileSystemDock::_move_operation); - ClassDB::bind_method(D_METHOD("_rename_operation"), &FileSystemDock::_rename_operation); + 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("_search_changed"), &FileSystemDock::_search_changed); @@ -1796,13 +1780,30 @@ FileSystemDock::FileSystemDock(EditorNode *p_editor) { move_dialog = memnew(EditorDirDialog); add_child(move_dialog); - move_dialog->connect("dir_selected", this, "_move_operation"); + move_dialog->connect("dir_selected", this, "_move_operation_confirm"); move_dialog->get_ok()->set_text(TTR("Move")); - rename_dialog = memnew(EditorFileDialog); - rename_dialog->set_mode(EditorFileDialog::MODE_SAVE_FILE); - rename_dialog->connect("file_selected", this, "_rename_operation"); + rename_dialog = memnew(ConfirmationDialog); + VBoxContainer *rename_dialog_vb = memnew(VBoxContainer); + rename_dialog->add_child(rename_dialog_vb); + + rename_dialog_text = memnew(LineEdit); + rename_dialog_vb->add_margin_child(TTR("Name:"), rename_dialog_text); + rename_dialog->get_ok()->set_text(TTR("Rename")); add_child(rename_dialog); + rename_dialog->register_text_enter(rename_dialog_text); + rename_dialog->connect("confirmed", this, "_rename_operation_confirm"); + + make_dir_dialog = memnew(ConfirmationDialog); + make_dir_dialog->set_title(TTR("Create Folder")); + VBoxContainer *make_folder_dialog_vb = memnew(VBoxContainer); + make_dir_dialog->add_child(make_folder_dialog_vb); + + make_dir_dialog_text = memnew(LineEdit); + make_folder_dialog_vb->add_margin_child(TTR("Name:"), make_dir_dialog_text); + add_child(make_dir_dialog); + make_dir_dialog->register_text_enter(make_dir_dialog_text); + make_dir_dialog->connect("confirmed", this, "_make_dir_confirm"); updating_tree = false; initialized = false; diff --git a/editor/filesystem_dock.h b/editor/filesystem_dock.h index aec049ba43..89b250e295 100644 --- a/editor/filesystem_dock.h +++ b/editor/filesystem_dock.h @@ -32,6 +32,7 @@ #include "scene/gui/box_container.h" #include "scene/gui/control.h" +#include "scene/gui/dialogs.h" #include "scene/gui/item_list.h" #include "scene/gui/label.h" #include "scene/gui/menu_button.h" @@ -67,9 +68,11 @@ private: FILE_DEPENDENCIES, FILE_OWNERS, FILE_MOVE, + FILE_RENAME, FILE_REMOVE, FILE_REIMPORT, FILE_INFO, + FILE_NEW_FOLDER, FILE_SHOW_IN_EXPLORER, FILE_COPY_PATH }; @@ -77,7 +80,12 @@ private: enum FolderMenu { FOLDER_EXPAND_ALL, FOLDER_COLLAPSE_ALL, - FOLDER_SHOW_IN_EXPLORER + FOLDER_MOVE, + FOLDER_RENAME, + FOLDER_REMOVE, + FOLDER_NEW_FOLDER, + FOLDER_SHOW_IN_EXPLORER, + FOLDER_COPY_PATH }; VBoxContainer *scanning_vb; @@ -110,10 +118,23 @@ private: DependencyRemoveDialog *remove_dialog; EditorDirDialog *move_dialog; - EditorFileDialog *rename_dialog; + ConfirmationDialog *rename_dialog; + LineEdit *rename_dialog_text; + ConfirmationDialog *make_dir_dialog; + LineEdit *make_dir_dialog_text; - Vector<String> move_dirs; - Vector<String> move_files; + class FileOrFolder { + public: + String path; + bool is_file; + + FileOrFolder() + : path(""), is_file(false) {} + FileOrFolder(const String &p_path, bool p_is_file) + : path(p_path), is_file(p_is_file) {} + }; + FileOrFolder to_rename; + Vector<FileOrFolder> to_move; Vector<String> history; int history_pos; @@ -135,11 +156,15 @@ private: bool _create_tree(TreeItem *p_parent, EditorFileSystemDirectory *p_dir); void _thumbnail_done(const String &p_path, const Ref<Texture> &p_preview, const Variant &p_udata); - void _find_inside_move_files(EditorFileSystemDirectory *efsd, Vector<String> &files); - void _find_remaps(EditorFileSystemDirectory *efsd, Map<String, String> &renames, List<String> &to_remaps); - void _rename_operation(const String &p_to_path); - void _move_operation(const String &p_to_path); + 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 _update_dependencies_after_move(const Map<String, String> &p_renames) const; + + void _make_dir_confirm(); + void _rename_operation_confirm(); + void _move_operation_confirm(const String &p_to_path); void _file_option(int p_option); void _folder_option(int p_option); diff --git a/editor/icons/icon_viewport_speed.svg b/editor/icons/icon_viewport_speed.svg new file mode 100644 index 0000000000..e64b5a8059 --- /dev/null +++ b/editor/icons/icon_viewport_speed.svg @@ -0,0 +1,4 @@ +<svg width="16" height="16" version="1.1" viewBox="0 0 4.2333333 4.2333333" xmlns="http://www.w3.org/2000/svg"> +<path d="m1.5875 0c-0.28858 0-0.52917 0.24059-0.52917 0.52917v0.61132c-0.085589-0.051-0.18113-0.0891-0.28525-0.0853-0.34849 0.0127-0.5952 0.37346-0.48059 0.70278l0.26355 0.79066c0.048664 0.14623 0.15979 0.24805 0.29249 0.30644l-0.60927 0.40669c-0.13121 0.0845-0.22102 0.22389-0.24133 0.3633-0.020312 0.13941 0.017471 0.26985 0.087333 0.37465s0.17614 0.19045 0.31264 0.22532c0.13634 0.0348 0.29946 6e-3 0.42788-0.0827h5.159e-4l1.0852-0.72348 0.26097 0.52192c0.11682 0.23391 0.39274 0.34829 0.64079 0.26561l0.79375-0.26458-0.00775 3e-3c0.15105-0.0454 0.27732-0.15615 0.33486-0.2863 0.057538-0.13015 0.055144-0.26773 0.014986-0.38809-0.03156-0.0946-0.10972-0.1687-0.19275-0.23617 0.069099-0.0546 0.1445-0.10364 0.18035-0.19325 0.051761-0.12941 0.045257-0.29292-0.02377-0.43098l-0.26459-0.52946c-0.089407-0.17933-0.27348-0.29308-0.47335-0.29305h-0.1111c0.052029-0.0817 0.1111-0.16214 0.1111-0.26458v-0.79375c0-0.28858-0.24059-0.52917-0.52917-0.52917z" color="#000000" color-rendering="auto" dominant-baseline="auto" image-rendering="auto" shape-rendering="auto" solid-color="#000000" style="font-feature-settings:normal;font-variant-alternates:normal;font-variant-caps:normal;font-variant-ligatures:normal;font-variant-numeric:normal;font-variant-position:normal;isolation:auto;mix-blend-mode:normal;shape-padding:0;text-decoration-color:#000000;text-decoration-line:none;text-decoration-style:solid;text-indent:0;text-orientation:mixed;text-transform:none;white-space:normal"/> +<path d="m1.5875 0.26458c-0.14658 0-0.26458 0.118-0.26458 0.26459v0.79375c0 0.14658 0.118 0.26458 0.26458 0.26458h0.26458v0.262a0.26461 0.26461 0 0 0 -0.083716 0.0165l-0.5426 0.18086-0.18087-0.5426a0.26461 0.26461 0 0 0 -0.262 -0.18448 0.26461 0.26461 0 0 0 -0.2403 0.3514l0.26458 0.79375a0.26461 0.26461 0 0 0 0.33486 0.16743l0.44545-0.14831v0.16174c0 0.0108 0.00495 0.02 0.0062 0.0305l-1.2113 0.80771a0.26461 0.26461 0 1 0 0.29352 0.44028l1.3379-0.89194 0.39532 0.79014a0.26461 0.26461 0 0 0 0.32039 0.1328l0.79375-0.26458a0.26461 0.26461 0 1 0 -0.16743 -0.50175l-0.57619 0.19172-0.25787-0.51625c0.072998-0.047 0.12402-0.12495 0.12402-0.21859v-0.26458h0.36587l0.1912 0.38292a0.26461 0.26461 0 1 0 0.47336 -0.23668l-0.26458-0.52916a0.26461 0.26461 0 0 0 -0.23668 -0.14625h-0.79375v-0.26458h0.26458c0.14658 0 0.26458-0.118 0.26458-0.26458v-0.79375c0-0.14659-0.118-0.26459-0.26458-0.26459zm0 0.52917h0.26458v0.52917h-0.26458z" fill="#fff" fill-opacity=".99608"/> +</svg> diff --git a/editor/icons/icon_viewport_zoom.svg b/editor/icons/icon_viewport_zoom.svg new file mode 100644 index 0000000000..18d4ec32ce --- /dev/null +++ b/editor/icons/icon_viewport_zoom.svg @@ -0,0 +1,6 @@ +<svg width="16" height="16" version="1.1" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg"> +<g> +<path d="m6 0c-3.3019 0-6 2.6981-6 6s2.6981 6 6 6h0.00195c0.88828 0 1.737-0.2588 2.5332-0.6367l3.8281 3.8281c0.39053 0.3904 1.0235 0.3904 1.4141 0l1.4141-1.4141c0.39033-0.3905 0.39033-1.0235 0-1.414l-3.791-3.791c0.02779-0.058 0.06588-0.1109 0.0918-0.17 0.05554-0.1268 0.08414-0.2638 0.08398-0.4023h1.4238c0.55226-1e-4 0.99994-0.4477 1-1v-1h1c0.55226-1e-4 0.99994-0.4477 1-1v-2c-5.5e-5 -0.5523-0.44774-0.9999-1-1h-1v-1c-5.5e-5 -0.5523-0.44774-0.9999-1-1h-2c-0.55226 1e-4 -0.99994 0.4477-1 1v1h-0.00977c1.44e-4 -0.3151-0.14822-0.6118-0.40039-0.8008-1.0353-0.7764-2.2938-1.1967-3.5879-1.1992h-0.00195z" color="#000000" color-rendering="auto" dominant-baseline="auto" image-rendering="auto" shape-rendering="auto" solid-color="#000000" style="font-feature-settings:normal;font-variant-alternates:normal;font-variant-caps:normal;font-variant-ligatures:normal;font-variant-numeric:normal;font-variant-position:normal;isolation:auto;mix-blend-mode:normal;shape-padding:0;text-decoration-color:#000000;text-decoration-line:none;text-decoration-style:solid;text-indent:0;text-orientation:mixed;text-transform:none;white-space:normal"/> +<path d="m6 1a5 5 0 0 0 -5 5 5 5 0 0 0 5 5 5 5 0 0 0 2.752 -0.83398l4.3184 4.3184 1.4141-1.4141-4.3184-4.3184a5 5 0 0 0 0.41016 -0.75195h-0.57617v-2h-1a3 3 0 0 1 -3 3 3 3 0 0 1 -3 -3 3 3 0 0 1 3 -3 3 3 0 0 1 2 0.76758v-1.7676h0.99023a5 5 0 0 0 -2.9902 -1zm5 0v2h-2v2h2v2h2v-2h2v-2h-2v-2z" fill="#fff"/> +</g> +</svg> diff --git a/editor/plugins/abstract_polygon_2d_editor.cpp b/editor/plugins/abstract_polygon_2d_editor.cpp index 2fd74d529e..ffa4e36b5a 100644 --- a/editor/plugins/abstract_polygon_2d_editor.cpp +++ b/editor/plugins/abstract_polygon_2d_editor.cpp @@ -195,9 +195,7 @@ bool AbstractPolygon2DEditor::forward_gui_input(const Ref<InputEvent> &p_event) Transform2D xform = canvas_item_editor->get_canvas_transform() * _get_node()->get_global_transform(); Vector2 gpoint = mb->get_position(); - Vector2 cpoint = canvas_item_editor->get_canvas_transform().affine_inverse().xform(gpoint); - cpoint = canvas_item_editor->snap_point(cpoint); - cpoint = _get_node()->get_global_transform().affine_inverse().xform(cpoint); + Vector2 cpoint = _get_node()->get_global_transform().affine_inverse().xform(canvas_item_editor->snap_point(canvas_item_editor->get_canvas_transform().affine_inverse().xform(mb->get_position()))); //first check if a point is to be added (segment split) real_t grab_threshold = EDITOR_DEF("editors/poly_editor/point_grab_radius", 8); @@ -425,15 +423,14 @@ bool AbstractPolygon2DEditor::forward_gui_input(const Ref<InputEvent> &p_event) if (edited_point != -1 && (wip_active || (mm->get_button_mask() & BUTTON_MASK_LEFT))) { Vector2 gpoint = mm->get_position(); - Vector2 cpoint = canvas_item_editor->get_canvas_transform().affine_inverse().xform(gpoint); - cpoint = canvas_item_editor->snap_point(cpoint); - edited_point_pos = _get_node()->get_global_transform().affine_inverse().xform(cpoint); + Vector2 cpoint = _get_node()->get_global_transform().affine_inverse().xform(canvas_item_editor->snap_point(canvas_item_editor->get_canvas_transform().affine_inverse().xform(mm->get_position()))); + edited_point_pos = cpoint; if (!wip_active) { Vector<Vector2> vertices = _get_polygon(edited_polygon); ERR_FAIL_INDEX_V(edited_point, vertices.size(), false); - vertices[edited_point] = edited_point_pos - _get_offset(edited_polygon); + vertices[edited_point] = cpoint - _get_offset(edited_polygon); _set_polygon(edited_polygon, vertices); } @@ -444,8 +441,7 @@ bool AbstractPolygon2DEditor::forward_gui_input(const Ref<InputEvent> &p_event) return false; } -void AbstractPolygon2DEditor::_canvas_draw() { - +void AbstractPolygon2DEditor::forward_draw_over_canvas(Control *p_canvas) { if (!_get_node()) return; @@ -527,9 +523,6 @@ void AbstractPolygon2DEditor::edit(Node *p_polygon) { if (_is_empty()) _menu_option(MODE_CREATE); - if (!canvas_item_editor->get_viewport_control()->is_connected("draw", this, "_canvas_draw")) - canvas_item_editor->get_viewport_control()->connect("draw", this, "_canvas_draw"); - wip.clear(); wip_active = false; edited_point = -1; @@ -539,15 +532,11 @@ void AbstractPolygon2DEditor::edit(Node *p_polygon) { } else { _set_node(NULL); - - if (canvas_item_editor->get_viewport_control()->is_connected("draw", this, "_canvas_draw")) - canvas_item_editor->get_viewport_control()->disconnect("draw", this, "_canvas_draw"); } } void AbstractPolygon2DEditor::_bind_methods() { - ClassDB::bind_method(D_METHOD("_canvas_draw"), &AbstractPolygon2DEditor::_canvas_draw); ClassDB::bind_method(D_METHOD("_node_removed"), &AbstractPolygon2DEditor::_node_removed); ClassDB::bind_method(D_METHOD("_menu_option"), &AbstractPolygon2DEditor::_menu_option); ClassDB::bind_method(D_METHOD("_create_resource"), &AbstractPolygon2DEditor::_create_resource); diff --git a/editor/plugins/abstract_polygon_2d_editor.h b/editor/plugins/abstract_polygon_2d_editor.h index 86e14694da..3e3bff6d0d 100644 --- a/editor/plugins/abstract_polygon_2d_editor.h +++ b/editor/plugins/abstract_polygon_2d_editor.h @@ -75,7 +75,6 @@ protected: virtual void _menu_option(int p_option); void _wip_close(); - void _canvas_draw(); void _notification(int p_what); void _node_removed(Node *p_node); @@ -103,6 +102,8 @@ protected: public: bool forward_gui_input(const Ref<InputEvent> &p_event); + void forward_draw_over_canvas(Control *p_canvas); + void edit(Node *p_polygon); AbstractPolygon2DEditor(EditorNode *p_editor, bool p_wip_destructive = true); }; @@ -116,7 +117,8 @@ class AbstractPolygon2DEditorPlugin : public EditorPlugin { String klass; public: - virtual bool forward_canvas_gui_input(const Transform2D &p_canvas_xform, const Ref<InputEvent> &p_event) { return polygon_editor->forward_gui_input(p_event); } + virtual bool forward_canvas_gui_input(const Ref<InputEvent> &p_event) { return polygon_editor->forward_gui_input(p_event); } + virtual void forward_draw_over_canvas(Control *p_canvas) { polygon_editor->forward_draw_over_canvas(p_canvas); } bool has_main_screen() const { return false; } virtual String get_name() const { return klass; } diff --git a/editor/plugins/canvas_item_editor_plugin.cpp b/editor/plugins/canvas_item_editor_plugin.cpp index 3f64e75bc8..2270421eca 100644 --- a/editor/plugins/canvas_item_editor_plugin.cpp +++ b/editor/plugins/canvas_item_editor_plugin.cpp @@ -1198,14 +1198,23 @@ void CanvasItemEditor::_update_cursor() { viewport->set_default_cursor_shape(c); } -void CanvasItemEditor::_viewport_base_gui_input(const Ref<InputEvent> &p_event) { +void CanvasItemEditor::_gui_input_viewport_base(const Ref<InputEvent> &p_event) { + + Ref<InputEventMouseMotion> m = p_event; + if (m.is_valid()) { + if (!viewport_base->has_focus() && (!get_focus_owner() || !get_focus_owner()->is_text_field())) + viewport_base->call_deferred("grab_focus"); + } +} + +void CanvasItemEditor::_gui_input_viewport(const Ref<InputEvent> &p_event) { { EditorNode *en = editor; EditorPluginList *over_plugin_list = en->get_editor_plugins_over(); if (!over_plugin_list->empty()) { - bool discard = over_plugin_list->forward_gui_input(transform, p_event); + bool discard = over_plugin_list->forward_gui_input(p_event); if (discard) { accept_event(); return; @@ -1224,7 +1233,7 @@ void CanvasItemEditor::_viewport_base_gui_input(const Ref<InputEvent> &p_event) _update_scroll(0); viewport->update(); } else { - _zoom_on_position(zoom * (1 - (0.05 * b->get_factor())), viewport_scrollable->get_transform().affine_inverse().xform(b->get_position())); + _zoom_on_position(zoom * (1 - (0.05 * b->get_factor())), b->get_position()); } return; @@ -1237,7 +1246,7 @@ void CanvasItemEditor::_viewport_base_gui_input(const Ref<InputEvent> &p_event) _update_scroll(0); viewport->update(); } else { - _zoom_on_position(zoom * ((0.95 + (0.05 * b->get_factor())) / 0.95), viewport_scrollable->get_transform().affine_inverse().xform(b->get_position())); + _zoom_on_position(zoom * ((0.95 + (0.05 * b->get_factor())) / 0.95), b->get_position()); } return; @@ -1320,7 +1329,7 @@ void CanvasItemEditor::_viewport_base_gui_input(const Ref<InputEvent> &p_event) if (b->get_button_index() == BUTTON_LEFT && tool == TOOL_EDIT_PIVOT) { if (b->is_pressed()) { // Set the pivot point - Point2 mouse_pos = viewport_scrollable->get_transform().affine_inverse().xform(b->get_position()); + Point2 mouse_pos = b->get_position(); mouse_pos = transform.affine_inverse().xform(mouse_pos); mouse_pos = snap_point(mouse_pos, SNAP_DEFAULT, _get_single_item()); _edit_set_pivot(mouse_pos); @@ -1443,8 +1452,8 @@ void CanvasItemEditor::_viewport_base_gui_input(const Ref<InputEvent> &p_event) E->get().to }; - Vector2 p = Geometry::get_closest_point_to_segment_2d(viewport_scrollable->get_transform().affine_inverse().xform(b->get_position()), s); - float d = p.distance_to(viewport_scrollable->get_transform().affine_inverse().xform(b->get_position())); + Vector2 p = Geometry::get_closest_point_to_segment_2d(b->get_position(), s); + float d = p.distance_to(b->get_position()); if (d < bone_width && d < closest_dist) { Cbone = E; closest_dist = d; @@ -1506,7 +1515,7 @@ void CanvasItemEditor::_viewport_base_gui_input(const Ref<InputEvent> &p_event) CanvasItemEditorSelectedItem *se = editor_selection->get_node_editor_data<CanvasItemEditorSelectedItem>(canvas_item); ERR_FAIL_COND(!se); - Point2 click = viewport_scrollable->get_transform().affine_inverse().xform(b->get_position()); + Point2 click = b->get_position(); // Rotation if ((b->get_control() && tool == TOOL_SELECT) || tool == TOOL_ROTATE) { @@ -1561,7 +1570,7 @@ void CanvasItemEditor::_viewport_base_gui_input(const Ref<InputEvent> &p_event) } // Multiple selected items - Point2 click = viewport_scrollable->get_transform().affine_inverse().xform(b->get_position()); + Point2 click = b->get_position(); if ((b->get_alt() || tool == TOOL_MOVE) && get_item_count()) { // Drag the nodes @@ -1621,12 +1630,9 @@ void CanvasItemEditor::_viewport_base_gui_input(const Ref<InputEvent> &p_event) // Mouse motion event _update_cursor(); - if (!viewport_base->has_focus() && (!get_focus_owner() || !get_focus_owner()->is_text_field())) - viewport_base->call_deferred("grab_focus"); - if (box_selecting) { // Update box selection - box_selecting_to = transform.affine_inverse().xform(viewport_scrollable->get_transform().affine_inverse().xform(m->get_position())); + box_selecting_to = transform.affine_inverse().xform(m->get_position()); viewport->update(); return; } @@ -1672,7 +1678,7 @@ void CanvasItemEditor::_viewport_base_gui_input(const Ref<InputEvent> &p_event) } Vector2 dfrom = drag_from; - Vector2 dto = transform.affine_inverse().xform(viewport_scrollable->get_transform().affine_inverse().xform(m->get_position())); + Vector2 dto = transform.affine_inverse().xform(m->get_position()); if (canvas_item->has_meta("_edit_lock_")) continue; @@ -2159,8 +2165,8 @@ void CanvasItemEditor::_draw_grid() { Vector2 real_grid_offset; if (snap_relative && get_item_count() > 0) { Vector2 topleft = _find_topleftmost_point(); - real_grid_offset.x = fmod(topleft.x, grid_step.x * Math::pow(2.0, grid_step_multiplier)); - real_grid_offset.y = fmod(topleft.y, grid_step.y * Math::pow(2.0, grid_step_multiplier)); + real_grid_offset.x = fmod(topleft.x, grid_step.x * (real_t)Math::pow(2.0, grid_step_multiplier)); + real_grid_offset.y = fmod(topleft.y, grid_step.y * (real_t)Math::pow(2.0, grid_step_multiplier)); } else { real_grid_offset = grid_offset; } @@ -2681,9 +2687,8 @@ void CanvasItemEditor::_draw_viewport() { EditorPluginList *over_plugin_list = editor->get_editor_plugins_over(); if (!over_plugin_list->empty()) { - over_plugin_list->forward_draw_over_canvas(transform, viewport); + over_plugin_list->forward_draw_over_canvas(viewport); } - _draw_focus(); _draw_bones(); } @@ -3694,7 +3699,8 @@ void CanvasItemEditor::_bind_methods() { ClassDB::bind_method("_unhandled_key_input", &CanvasItemEditor::_unhandled_key_input); ClassDB::bind_method("_draw_viewport", &CanvasItemEditor::_draw_viewport); ClassDB::bind_method("_draw_viewport_base", &CanvasItemEditor::_draw_viewport_base); - ClassDB::bind_method("_viewport_base_gui_input", &CanvasItemEditor::_viewport_base_gui_input); + ClassDB::bind_method("_gui_input_viewport", &CanvasItemEditor::_gui_input_viewport); + ClassDB::bind_method("_gui_input_viewport_base", &CanvasItemEditor::_gui_input_viewport_base); ClassDB::bind_method("_snap_changed", &CanvasItemEditor::_snap_changed); ClassDB::bind_method(D_METHOD("_selection_result_pressed"), &CanvasItemEditor::_selection_result_pressed); ClassDB::bind_method(D_METHOD("_selection_menu_hide"), &CanvasItemEditor::_selection_menu_hide); @@ -3747,7 +3753,7 @@ CanvasItemEditor::CanvasItemEditor(EditorNode *p_editor) { palette_split->add_child(viewport_base); viewport_base->set_clip_contents(true); viewport_base->connect("draw", this, "_draw_viewport_base"); - viewport_base->connect("gui_input", this, "_viewport_base_gui_input"); + viewport_base->connect("gui_input", this, "_gui_input_viewport_base"); viewport_base->set_focus_mode(FOCUS_ALL); viewport_base->set_v_size_flags(SIZE_EXPAND_FILL); viewport_base->set_h_size_flags(SIZE_EXPAND_FILL); @@ -3771,6 +3777,7 @@ CanvasItemEditor::CanvasItemEditor(EditorNode *p_editor) { viewport->set_anchors_and_margins_preset(Control::PRESET_WIDE); viewport->set_clip_contents(true); viewport->connect("draw", this, "_draw_viewport"); + viewport->connect("gui_input", this, "_gui_input_viewport"); h_scroll = memnew(HScrollBar); viewport->add_child(h_scroll); diff --git a/editor/plugins/canvas_item_editor_plugin.h b/editor/plugins/canvas_item_editor_plugin.h index 69dc25d180..a8183ba286 100644 --- a/editor/plugins/canvas_item_editor_plugin.h +++ b/editor/plugins/canvas_item_editor_plugin.h @@ -410,10 +410,11 @@ class CanvasItemEditor : public VBoxContainer { void _draw_locks_and_groups(Node *p_node, const Transform2D &p_xform); void _draw_viewport(); - - void _viewport_base_gui_input(const Ref<InputEvent> &p_event); void _draw_viewport_base(); + void _gui_input_viewport(const Ref<InputEvent> &p_event); + void _gui_input_viewport_base(const Ref<InputEvent> &p_event); + void _focus_selection(int p_op); void _snap_if_closer(Point2 p_value, Point2 p_target_snap, Point2 &r_current_snap, bool (&r_snapped)[2], real_t rotation = 0.0, float p_radius = 10.0); diff --git a/editor/plugins/collision_polygon_2d_editor_plugin.cpp b/editor/plugins/collision_polygon_2d_editor_plugin.cpp index 00e6d617a1..00e6d617a1 100755..100644 --- a/editor/plugins/collision_polygon_2d_editor_plugin.cpp +++ b/editor/plugins/collision_polygon_2d_editor_plugin.cpp diff --git a/editor/plugins/collision_polygon_2d_editor_plugin.h b/editor/plugins/collision_polygon_2d_editor_plugin.h index edf3bbcc08..edf3bbcc08 100755..100644 --- a/editor/plugins/collision_polygon_2d_editor_plugin.h +++ b/editor/plugins/collision_polygon_2d_editor_plugin.h diff --git a/editor/plugins/collision_shape_2d_editor_plugin.cpp b/editor/plugins/collision_shape_2d_editor_plugin.cpp index 3e6165e552..005de096cd 100644 --- a/editor/plugins/collision_shape_2d_editor_plugin.cpp +++ b/editor/plugins/collision_shape_2d_editor_plugin.cpp @@ -302,7 +302,7 @@ void CollisionShape2DEditor::commit_handle(int idx, Variant &p_org) { undo_redo->commit_action(); } -bool CollisionShape2DEditor::forward_gui_input(const Ref<InputEvent> &p_event) { +bool CollisionShape2DEditor::forward_canvas_gui_input(const Ref<InputEvent> &p_event) { if (!node) { return false; @@ -317,17 +317,17 @@ bool CollisionShape2DEditor::forward_gui_input(const Ref<InputEvent> &p_event) { } Ref<InputEventMouseButton> mb = p_event; + Transform2D xform = canvas_item_editor->get_canvas_transform() * node->get_global_transform(); if (mb.is_valid()) { - Transform2D gt = canvas_item_editor->get_canvas_transform() * node->get_global_transform(); - - Point2 gpoint(mb->get_position().x, mb->get_position().y); + Vector2 gpoint = mb->get_position(); + Vector2 cpoint = node->get_global_transform().affine_inverse().xform(canvas_item_editor->snap_point(canvas_item_editor->get_canvas_transform().affine_inverse().xform(mb->get_position()))); if (mb->get_button_index() == BUTTON_LEFT) { if (mb->is_pressed()) { for (int i = 0; i < handles.size(); i++) { - if (gt.xform(handles[i]).distance_to(gpoint) < 8) { + if (xform.xform(handles[i]).distance_to(gpoint) < 8) { edit_handle = i; break; @@ -368,9 +368,7 @@ bool CollisionShape2DEditor::forward_gui_input(const Ref<InputEvent> &p_event) { return false; } - Point2 gpoint = mm->get_position(); - Point2 cpoint = canvas_item_editor->get_canvas_transform().affine_inverse().xform(gpoint); - cpoint = canvas_item_editor->snap_point(cpoint); + Vector2 cpoint = canvas_item_editor->snap_point(canvas_item_editor->get_canvas_transform().affine_inverse().xform(mm->get_position())); cpoint = node->get_global_transform().affine_inverse().xform(cpoint); set_handle(edit_handle, cpoint); @@ -416,7 +414,7 @@ void CollisionShape2DEditor::_get_current_shape_type() { canvas_item_editor->get_viewport_control()->update(); } -void CollisionShape2DEditor::_canvas_draw() { +void CollisionShape2DEditor::forward_draw_over_canvas(Control *p_canvas) { if (!node) { return; @@ -432,7 +430,6 @@ void CollisionShape2DEditor::_canvas_draw() { return; } - Control *c = canvas_item_editor->get_viewport_control(); Transform2D gt = canvas_item_editor->get_canvas_transform() * node->get_global_transform(); Ref<Texture> h = get_icon("EditorHandle", "EditorIcons"); @@ -451,8 +448,8 @@ void CollisionShape2DEditor::_canvas_draw() { handles[0] = Point2(radius, -height); handles[1] = Point2(0, -(height + radius)); - c->draw_texture(h, gt.xform(handles[0]) - size); - c->draw_texture(h, gt.xform(handles[1]) - size); + p_canvas->draw_texture(h, gt.xform(handles[0]) - size); + p_canvas->draw_texture(h, gt.xform(handles[1]) - size); } break; @@ -462,7 +459,7 @@ void CollisionShape2DEditor::_canvas_draw() { handles.resize(1); handles[0] = Point2(shape->get_radius(), 0); - c->draw_texture(h, gt.xform(handles[0]) - size); + p_canvas->draw_texture(h, gt.xform(handles[0]) - size); } break; @@ -481,8 +478,8 @@ void CollisionShape2DEditor::_canvas_draw() { handles[0] = shape->get_normal() * shape->get_d(); handles[1] = shape->get_normal() * (shape->get_d() + 30.0); - c->draw_texture(h, gt.xform(handles[0]) - size); - c->draw_texture(h, gt.xform(handles[1]) - size); + p_canvas->draw_texture(h, gt.xform(handles[0]) - size); + p_canvas->draw_texture(h, gt.xform(handles[1]) - size); } break; @@ -492,7 +489,7 @@ void CollisionShape2DEditor::_canvas_draw() { handles.resize(1); handles[0] = Point2(0, shape->get_length()); - c->draw_texture(h, gt.xform(handles[0]) - size); + p_canvas->draw_texture(h, gt.xform(handles[0]) - size); } break; @@ -504,8 +501,8 @@ void CollisionShape2DEditor::_canvas_draw() { handles[0] = Point2(ext.x, 0); handles[1] = Point2(0, -ext.y); - c->draw_texture(h, gt.xform(handles[0]) - size); - c->draw_texture(h, gt.xform(handles[1]) - size); + p_canvas->draw_texture(h, gt.xform(handles[0]) - size); + p_canvas->draw_texture(h, gt.xform(handles[1]) - size); } break; @@ -516,8 +513,8 @@ void CollisionShape2DEditor::_canvas_draw() { handles[0] = shape->get_a(); handles[1] = shape->get_b(); - c->draw_texture(h, gt.xform(handles[0]) - size); - c->draw_texture(h, gt.xform(handles[1]) - size); + p_canvas->draw_texture(h, gt.xform(handles[0]) - size); + p_canvas->draw_texture(h, gt.xform(handles[1]) - size); } break; } @@ -532,18 +529,12 @@ void CollisionShape2DEditor::edit(Node *p_node) { if (p_node) { node = Object::cast_to<CollisionShape2D>(p_node); - if (!canvas_item_editor->get_viewport_control()->is_connected("draw", this, "_canvas_draw")) - canvas_item_editor->get_viewport_control()->connect("draw", this, "_canvas_draw"); - _get_current_shape_type(); } else { edit_handle = -1; shape_type = -1; - if (canvas_item_editor->get_viewport_control()->is_connected("draw", this, "_canvas_draw")) - canvas_item_editor->get_viewport_control()->disconnect("draw", this, "_canvas_draw"); - node = NULL; } @@ -552,7 +543,6 @@ void CollisionShape2DEditor::edit(Node *p_node) { void CollisionShape2DEditor::_bind_methods() { - ClassDB::bind_method("_canvas_draw", &CollisionShape2DEditor::_canvas_draw); ClassDB::bind_method("_get_current_shape_type", &CollisionShape2DEditor::_get_current_shape_type); } diff --git a/editor/plugins/collision_shape_2d_editor_plugin.h b/editor/plugins/collision_shape_2d_editor_plugin.h index ffa91952e0..d4fbe87fb3 100644 --- a/editor/plugins/collision_shape_2d_editor_plugin.h +++ b/editor/plugins/collision_shape_2d_editor_plugin.h @@ -68,13 +68,13 @@ class CollisionShape2DEditor : public Control { void commit_handle(int idx, Variant &p_org); void _get_current_shape_type(); - void _canvas_draw(); protected: static void _bind_methods(); public: - bool forward_gui_input(const Ref<InputEvent> &p_event); + bool forward_canvas_gui_input(const Ref<InputEvent> &p_event); + void forward_draw_over_canvas(Control *p_canvas); void edit(Node *p_node); CollisionShape2DEditor(EditorNode *p_editor); @@ -87,7 +87,8 @@ class CollisionShape2DEditorPlugin : public EditorPlugin { EditorNode *editor; public: - virtual bool forward_canvas_gui_input(const Transform2D &p_canvas_xform, const Ref<InputEvent> &p_event) { return collision_shape_2d_editor->forward_gui_input(p_event); } + virtual bool forward_canvas_gui_input(const Ref<InputEvent> &p_event) { return collision_shape_2d_editor->forward_canvas_gui_input(p_event); } + virtual void forward_draw_over_canvas(Control *p_canvas) { return collision_shape_2d_editor->forward_draw_over_canvas(p_canvas); } virtual String get_name() const { return "CollisionShape2D"; } bool has_main_screen() const { return false; } diff --git a/editor/plugins/light_occluder_2d_editor_plugin.cpp b/editor/plugins/light_occluder_2d_editor_plugin.cpp index ed0bc60d2f..485657d2c9 100644 --- a/editor/plugins/light_occluder_2d_editor_plugin.cpp +++ b/editor/plugins/light_occluder_2d_editor_plugin.cpp @@ -119,9 +119,7 @@ bool LightOccluder2DEditor::forward_gui_input(const Ref<InputEvent> &p_event) { Transform2D xform = canvas_item_editor->get_canvas_transform() * node->get_global_transform(); Vector2 gpoint = mb->get_position(); - Vector2 cpoint = canvas_item_editor->get_canvas_transform().affine_inverse().xform(gpoint); - cpoint = canvas_item_editor->snap_point(cpoint); - cpoint = node->get_global_transform().affine_inverse().xform(cpoint); + Vector2 cpoint = node->get_global_transform().affine_inverse().xform(canvas_item_editor->snap_point(canvas_item_editor->get_canvas_transform().affine_inverse().xform(mb->get_position()))); Vector<Vector2> poly = Variant(node->get_occluder_polygon()->get_polygon()); @@ -319,7 +317,8 @@ bool LightOccluder2DEditor::forward_gui_input(const Ref<InputEvent> &p_event) { return false; } -void LightOccluder2DEditor::_canvas_draw() { + +void LightOccluder2DEditor::forward_draw_over_canvas(Control *p_canvas) { if (!node || !node->get_occluder_polygon().is_valid()) return; @@ -368,17 +367,12 @@ void LightOccluder2DEditor::edit(Node *p_collision_polygon) { if (p_collision_polygon) { node = Object::cast_to<LightOccluder2D>(p_collision_polygon); - if (!canvas_item_editor->get_viewport_control()->is_connected("draw", this, "_canvas_draw")) - canvas_item_editor->get_viewport_control()->connect("draw", this, "_canvas_draw"); wip.clear(); wip_active = false; edited_point = -1; canvas_item_editor->get_viewport_control()->update(); } else { node = NULL; - - if (canvas_item_editor->get_viewport_control()->is_connected("draw", this, "_canvas_draw")) - canvas_item_editor->get_viewport_control()->disconnect("draw", this, "_canvas_draw"); } } @@ -395,7 +389,6 @@ void LightOccluder2DEditor::_create_poly() { void LightOccluder2DEditor::_bind_methods() { ClassDB::bind_method(D_METHOD("_menu_option"), &LightOccluder2DEditor::_menu_option); - ClassDB::bind_method(D_METHOD("_canvas_draw"), &LightOccluder2DEditor::_canvas_draw); ClassDB::bind_method(D_METHOD("_node_removed"), &LightOccluder2DEditor::_node_removed); ClassDB::bind_method(D_METHOD("_create_poly"), &LightOccluder2DEditor::_create_poly); } @@ -430,7 +423,7 @@ LightOccluder2DEditor::LightOccluder2DEditor(EditorNode *p_editor) { void LightOccluder2DEditorPlugin::edit(Object *p_object) { - collision_polygon_editor->edit(Object::cast_to<Node>(p_object)); + light_occluder_editor->edit(Object::cast_to<Node>(p_object)); } bool LightOccluder2DEditorPlugin::handles(Object *p_object) const { @@ -441,21 +434,21 @@ bool LightOccluder2DEditorPlugin::handles(Object *p_object) const { void LightOccluder2DEditorPlugin::make_visible(bool p_visible) { if (p_visible) { - collision_polygon_editor->show(); + light_occluder_editor->show(); } else { - collision_polygon_editor->hide(); - collision_polygon_editor->edit(NULL); + light_occluder_editor->hide(); + light_occluder_editor->edit(NULL); } } LightOccluder2DEditorPlugin::LightOccluder2DEditorPlugin(EditorNode *p_node) { editor = p_node; - collision_polygon_editor = memnew(LightOccluder2DEditor(p_node)); - CanvasItemEditor::get_singleton()->add_control_to_menu_panel(collision_polygon_editor); + light_occluder_editor = memnew(LightOccluder2DEditor(p_node)); + CanvasItemEditor::get_singleton()->add_control_to_menu_panel(light_occluder_editor); - collision_polygon_editor->hide(); + light_occluder_editor->hide(); } LightOccluder2DEditorPlugin::~LightOccluder2DEditorPlugin() { diff --git a/editor/plugins/light_occluder_2d_editor_plugin.h b/editor/plugins/light_occluder_2d_editor_plugin.h index b270dcb6e5..068832d8ed 100644 --- a/editor/plugins/light_occluder_2d_editor_plugin.h +++ b/editor/plugins/light_occluder_2d_editor_plugin.h @@ -72,7 +72,6 @@ class LightOccluder2DEditor : public HBoxContainer { ConfirmationDialog *create_poly; void _wip_close(bool p_closed); - void _canvas_draw(); void _menu_option(int p_option); void _create_poly(); @@ -83,6 +82,7 @@ protected: public: Vector2 snap_point(const Vector2 &p_point) const; + void forward_draw_over_canvas(Control *p_canvas); bool forward_gui_input(const Ref<InputEvent> &p_event); void edit(Node *p_collision_polygon); LightOccluder2DEditor(EditorNode *p_editor); @@ -92,11 +92,12 @@ class LightOccluder2DEditorPlugin : public EditorPlugin { GDCLASS(LightOccluder2DEditorPlugin, EditorPlugin); - LightOccluder2DEditor *collision_polygon_editor; + LightOccluder2DEditor *light_occluder_editor; EditorNode *editor; public: - virtual bool forward_canvas_gui_input(const Transform2D &p_canvas_xform, const Ref<InputEvent> &p_event) { return collision_polygon_editor->forward_gui_input(p_event); } + virtual bool forward_canvas_gui_input(const Ref<InputEvent> &p_event) { return light_occluder_editor->forward_gui_input(p_event); } + virtual void forward_draw_over_canvas(Control *p_canvas) { return light_occluder_editor->forward_draw_over_canvas(p_canvas); } virtual String get_name() const { return "LightOccluder2D"; } bool has_main_screen() const { return false; } diff --git a/editor/plugins/line_2d_editor_plugin.cpp b/editor/plugins/line_2d_editor_plugin.cpp index ef3ee6a78f..0533aaa9c0 100644 --- a/editor/plugins/line_2d_editor_plugin.cpp +++ b/editor/plugins/line_2d_editor_plugin.cpp @@ -54,16 +54,10 @@ void Line2DEditor::_notification(int p_what) { } } -Vector2 Line2DEditor::mouse_to_local_pos(Vector2 gpos, bool alt) { - Transform2D xform = canvas_item_editor->get_canvas_transform() * node->get_global_transform(); - return !alt ? canvas_item_editor->snap_point(xform.affine_inverse().xform(gpos)) : node->get_global_transform().affine_inverse().xform(canvas_item_editor->snap_point(canvas_item_editor->get_canvas_transform().affine_inverse().xform(gpos))); -} - -int Line2DEditor::get_point_index_at(Vector2 gpos) { +int Line2DEditor::get_point_index_at(const Transform2D &xform, Vector2 gpos) { ERR_FAIL_COND_V(node == 0, -1); real_t grab_threshold = EDITOR_DEF("editors/poly_editor/point_grab_radius", 8); - Transform2D xform = canvas_item_editor->get_canvas_transform() * node->get_global_transform(); for (int i = 0; i < node->get_point_count(); ++i) { Point2 p = xform.xform(node->get_point_position(i)); @@ -75,7 +69,7 @@ int Line2DEditor::get_point_index_at(Vector2 gpos) { return -1; } -bool Line2DEditor::forward_gui_input(const Ref<InputEvent> &p_event) { +bool Line2DEditor::forward_canvas_gui_input(const Ref<InputEvent> &p_event) { if (!node) return false; @@ -88,10 +82,10 @@ bool Line2DEditor::forward_gui_input(const Ref<InputEvent> &p_event) { if (mb.is_valid()) { Vector2 gpoint = mb->get_position(); - Vector2 cpoint = mouse_to_local_pos(gpoint, mb->get_alt()); + Vector2 cpoint = node->get_global_transform().affine_inverse().xform(canvas_item_editor->snap_point(canvas_item_editor->get_canvas_transform().affine_inverse().xform(mb->get_position()))); if (mb->is_pressed() && _dragging == false) { - int i = get_point_index_at(gpoint); + int i = get_point_index_at(canvas_item_editor->get_canvas_transform() * node->get_global_transform(), gpoint); if (i != -1) { if (mb->get_button_index() == BUTTON_LEFT && !mb->get_shift() && mode == MODE_EDIT) { _dragging = true; @@ -146,7 +140,8 @@ bool Line2DEditor::forward_gui_input(const Ref<InputEvent> &p_event) { if (mm.is_valid()) { if (_dragging) { - Vector2 cpoint = mouse_to_local_pos(mm->get_position(), mm->get_alt()); + Vector2 gpoint = mm->get_position(); + Vector2 cpoint = node->get_global_transform().affine_inverse().xform(canvas_item_editor->snap_point(canvas_item_editor->get_canvas_transform().affine_inverse().xform(mm->get_position()))); node->set_point_position(action_point, cpoint); canvas_item_editor->get_viewport_control()->update(); return true; @@ -156,7 +151,7 @@ bool Line2DEditor::forward_gui_input(const Ref<InputEvent> &p_event) { return false; } -void Line2DEditor::_canvas_draw() { +void Line2DEditor::forward_draw_over_canvas(Control *p_canvas) { if (!node) return; @@ -190,13 +185,9 @@ void Line2DEditor::edit(Node *p_line2d) { if (p_line2d) { node = Object::cast_to<Line2D>(p_line2d); - if (!canvas_item_editor->get_viewport_control()->is_connected("draw", this, "_canvas_draw")) - canvas_item_editor->get_viewport_control()->connect("draw", this, "_canvas_draw"); if (!node->is_connected("visibility_changed", this, "_node_visibility_changed")) node->connect("visibility_changed", this, "_node_visibility_changed"); } else { - if (canvas_item_editor->get_viewport_control()->is_connected("draw", this, "_canvas_draw")) - canvas_item_editor->get_viewport_control()->disconnect("draw", this, "_canvas_draw"); // node may have been deleted at this point if (node && node->is_connected("visibility_changed", this, "_node_visibility_changed")) node->disconnect("visibility_changed", this, "_node_visibility_changed"); @@ -205,7 +196,6 @@ void Line2DEditor::edit(Node *p_line2d) { } void Line2DEditor::_bind_methods() { - ClassDB::bind_method(D_METHOD("_canvas_draw"), &Line2DEditor::_canvas_draw); ClassDB::bind_method(D_METHOD("_node_visibility_changed"), &Line2DEditor::_node_visibility_changed); ClassDB::bind_method(D_METHOD("_mode_selected"), &Line2DEditor::_mode_selected); } diff --git a/editor/plugins/line_2d_editor_plugin.h b/editor/plugins/line_2d_editor_plugin.h index dea0433084..6858680aed 100644 --- a/editor/plugins/line_2d_editor_plugin.h +++ b/editor/plugins/line_2d_editor_plugin.h @@ -40,27 +40,11 @@ class CanvasItemEditor; class Line2DEditor : public HBoxContainer { GDCLASS(Line2DEditor, HBoxContainer) - -public: - bool forward_gui_input(const Ref<InputEvent> &p_event); - void edit(Node *p_line2d); - Line2DEditor(EditorNode *p_editor); - -protected: - void _node_removed(Node *p_node); - void _notification(int p_what); - - Vector2 mouse_to_local_pos(Vector2 mpos); - - static void _bind_methods(); - private: void _mode_selected(int p_mode); - void _canvas_draw(); void _node_visibility_changed(); - int get_point_index_at(Vector2 gpos); - Vector2 mouse_to_local_pos(Vector2 gpos, bool alt); + int get_point_index_at(const Transform2D &xform, Vector2 gpos); UndoRedo *undo_redo; @@ -86,17 +70,26 @@ private: int action_point; Point2 moving_from; Point2 moving_screen_from; + +protected: + void _node_removed(Node *p_node); + void _notification(int p_what); + + static void _bind_methods(); + +public: + bool forward_canvas_gui_input(const Ref<InputEvent> &p_event); + void forward_draw_over_canvas(Control *p_canvas); + void edit(Node *p_line2d); + Line2DEditor(EditorNode *p_editor); }; class Line2DEditorPlugin : public EditorPlugin { GDCLASS(Line2DEditorPlugin, EditorPlugin) public: - virtual bool forward_canvas_gui_input( - const Transform2D &p_canvas_xform, - const Ref<InputEvent> &p_event) { - return line2d_editor->forward_gui_input(p_event); - } + virtual bool forward_canvas_gui_input(const Ref<InputEvent> &p_event) { return line2d_editor->forward_canvas_gui_input(p_event); } + virtual void forward_draw_over_canvas(Control *p_canvas) { return line2d_editor->forward_draw_over_canvas(p_canvas); } virtual String get_name() const { return "Line2D"; } bool has_main_screen() const { return false; } diff --git a/editor/plugins/navigation_polygon_editor_plugin.cpp b/editor/plugins/navigation_polygon_editor_plugin.cpp index 6560a8dac7..6560a8dac7 100755..100644 --- a/editor/plugins/navigation_polygon_editor_plugin.cpp +++ b/editor/plugins/navigation_polygon_editor_plugin.cpp diff --git a/editor/plugins/navigation_polygon_editor_plugin.h b/editor/plugins/navigation_polygon_editor_plugin.h index 54cc347a8c..54cc347a8c 100755..100644 --- a/editor/plugins/navigation_polygon_editor_plugin.h +++ b/editor/plugins/navigation_polygon_editor_plugin.h diff --git a/editor/plugins/path_2d_editor_plugin.cpp b/editor/plugins/path_2d_editor_plugin.cpp index df10ac8929..2174f08e23 100644 --- a/editor/plugins/path_2d_editor_plugin.cpp +++ b/editor/plugins/path_2d_editor_plugin.cpp @@ -76,10 +76,7 @@ bool Path2DEditor::forward_gui_input(const Ref<InputEvent> &p_event) { Transform2D xform = canvas_item_editor->get_canvas_transform() * node->get_global_transform(); Vector2 gpoint = mb->get_position(); - Vector2 cpoint = - !mb->get_alt() ? - canvas_item_editor->snap_point(xform.affine_inverse().xform(gpoint)) : - node->get_global_transform().affine_inverse().xform(canvas_item_editor->snap_point(canvas_item_editor->get_canvas_transform().affine_inverse().xform(gpoint))); + Vector2 cpoint = node->get_global_transform().affine_inverse().xform(canvas_item_editor->snap_point(canvas_item_editor->get_canvas_transform().affine_inverse().xform(mb->get_position()))); real_t grab_threshold = EDITOR_DEF("editors/poly_editor/point_grab_radius", 8); @@ -239,10 +236,7 @@ bool Path2DEditor::forward_gui_input(const Ref<InputEvent> &p_event) { // Handle point/control movement. Transform2D xform = canvas_item_editor->get_canvas_transform() * node->get_global_transform(); Vector2 gpoint = mm->get_position(); - Vector2 cpoint = - !mm->get_alt() ? - canvas_item_editor->snap_point(xform.affine_inverse().xform(gpoint)) : - node->get_global_transform().affine_inverse().xform(canvas_item_editor->snap_point(canvas_item_editor->get_canvas_transform().affine_inverse().xform(gpoint))); + Vector2 cpoint = node->get_global_transform().affine_inverse().xform(canvas_item_editor->snap_point(canvas_item_editor->get_canvas_transform().affine_inverse().xform(mm->get_position()))); Ref<Curve2D> curve = node->get_curve(); @@ -274,7 +268,8 @@ bool Path2DEditor::forward_gui_input(const Ref<InputEvent> &p_event) { return false; } -void Path2DEditor::_canvas_draw() { + +void Path2DEditor::forward_draw_over_canvas(Control *p_canvas) { if (!node) return; @@ -329,16 +324,11 @@ void Path2DEditor::edit(Node *p_path2d) { if (p_path2d) { node = Object::cast_to<Path2D>(p_path2d); - if (!canvas_item_editor->get_viewport_control()->is_connected("draw", this, "_canvas_draw")) - canvas_item_editor->get_viewport_control()->connect("draw", this, "_canvas_draw"); if (!node->is_connected("visibility_changed", this, "_node_visibility_changed")) node->connect("visibility_changed", this, "_node_visibility_changed"); } else { - if (canvas_item_editor->get_viewport_control()->is_connected("draw", this, "_canvas_draw")) - canvas_item_editor->get_viewport_control()->disconnect("draw", this, "_canvas_draw"); - // node may have been deleted at this point if (node && node->is_connected("visibility_changed", this, "_node_visibility_changed")) node->disconnect("visibility_changed", this, "_node_visibility_changed"); @@ -349,7 +339,6 @@ void Path2DEditor::edit(Node *p_path2d) { void Path2DEditor::_bind_methods() { //ClassDB::bind_method(D_METHOD("_menu_option"),&Path2DEditor::_menu_option); - ClassDB::bind_method(D_METHOD("_canvas_draw"), &Path2DEditor::_canvas_draw); ClassDB::bind_method(D_METHOD("_node_visibility_changed"), &Path2DEditor::_node_visibility_changed); ClassDB::bind_method(D_METHOD("_mode_selected"), &Path2DEditor::_mode_selected); } diff --git a/editor/plugins/path_2d_editor_plugin.h b/editor/plugins/path_2d_editor_plugin.h index f0f5d4d637..516e48c471 100644 --- a/editor/plugins/path_2d_editor_plugin.h +++ b/editor/plugins/path_2d_editor_plugin.h @@ -84,7 +84,6 @@ class Path2DEditor : public HBoxContainer { void _mode_selected(int p_mode); - void _canvas_draw(); void _node_visibility_changed(); friend class Path2DEditorPlugin; @@ -95,6 +94,7 @@ protected: public: bool forward_gui_input(const Ref<InputEvent> &p_event); + void forward_draw_over_canvas(Control *p_canvas); void edit(Node *p_path2d); Path2DEditor(EditorNode *p_editor); }; @@ -107,7 +107,8 @@ class Path2DEditorPlugin : public EditorPlugin { EditorNode *editor; public: - virtual bool forward_canvas_gui_input(const Transform2D &p_canvas_xform, const Ref<InputEvent> &p_event) { return path2d_editor->forward_gui_input(p_event); } + virtual bool forward_canvas_gui_input(const Ref<InputEvent> &p_event) { return path2d_editor->forward_gui_input(p_event); } + virtual void forward_draw_over_canvas(Control *p_canvas) { return path2d_editor->forward_draw_over_canvas(p_canvas); } virtual String get_name() const { return "Path2D"; } bool has_main_screen() const { return false; } diff --git a/editor/plugins/polygon_2d_editor_plugin.cpp b/editor/plugins/polygon_2d_editor_plugin.cpp index 0e8c13b067..0e8c13b067 100755..100644 --- a/editor/plugins/polygon_2d_editor_plugin.cpp +++ b/editor/plugins/polygon_2d_editor_plugin.cpp diff --git a/editor/plugins/polygon_2d_editor_plugin.h b/editor/plugins/polygon_2d_editor_plugin.h index 90da3e61c1..90da3e61c1 100755..100644 --- a/editor/plugins/polygon_2d_editor_plugin.h +++ b/editor/plugins/polygon_2d_editor_plugin.h diff --git a/editor/plugins/spatial_editor_plugin.cpp b/editor/plugins/spatial_editor_plugin.cpp index 32973db6ec..547679b056 100644 --- a/editor/plugins/spatial_editor_plugin.cpp +++ b/editor/plugins/spatial_editor_plugin.cpp @@ -63,7 +63,8 @@ #define ZOOM_MULTIPLIER 1.08 #define ZOOM_INDICATOR_DELAY_S 1.5 -#define FREELOOK_MIN_SPEED 0.1 +#define FREELOOK_MIN_SPEED 0.01 +#define FREELOOK_SPEED_MULTIPLIER 1.08 #define MIN_Z 0.01 #define MAX_Z 10000 @@ -75,34 +76,66 @@ void SpatialEditorViewport::_update_camera(float p_interp_delta) { bool is_orthogonal = camera->get_projection() == Camera::PROJECTION_ORTHOGONAL; - //when not being manipulated, move softly - float free_orbit_inertia = EDITOR_GET("editors/3d/navigation_feel/orbit_inertia"); - float free_translation_inertia = EDITOR_GET("editors/3d/navigation_feel/translation_inertia"); - //when being manipulated, move more quickly - float manip_orbit_inertia = EDITOR_GET("editors/3d/navigation_feel/manipulation_orbit_inertia"); - float manip_translation_inertia = EDITOR_GET("editors/3d/navigation_feel/manipulation_translation_inertia"); + Cursor old_camera_cursor = camera_cursor; + camera_cursor = cursor; - float zoom_inertia = EDITOR_GET("editors/3d/navigation_feel/zoom_inertia"); + if (p_interp_delta > 0) { - //determine if being manipulated - bool manipulated = (Input::get_singleton()->get_mouse_button_mask() & (2 | 4)) || Input::get_singleton()->is_key_pressed(KEY_SHIFT) || Input::get_singleton()->is_key_pressed(KEY_ALT) || Input::get_singleton()->is_key_pressed(KEY_CONTROL); + //------- + // Perform smoothing - float orbit_inertia = MAX(0.00001, manipulated ? manip_orbit_inertia : free_orbit_inertia); - float translation_inertia = MAX(0.0001, manipulated ? manip_translation_inertia : free_translation_inertia); + if (is_freelook_active()) { - Cursor old_camera_cursor = camera_cursor; - camera_cursor = cursor; + // Higher inertia should increase "lag" (lerp with factor between 0 and 1) + // Inertia of zero should produce instant movement (lerp with factor of 1) in this case it returns a really high value and gets clamped to 1. + real_t inertia = EDITOR_GET("editors/3d/freelook/freelook_inertia"); + inertia = MAX(0.001, inertia); + real_t factor = (1.0 / inertia) * p_interp_delta; + + // We interpolate a different point here, because in freelook mode the focus point (cursor.pos) orbits around eye_pos + camera_cursor.eye_pos = old_camera_cursor.eye_pos.linear_interpolate(cursor.eye_pos, CLAMP(factor, 0, 1)); + //camera_cursor.pos = camera_cursor.eye_pos + (cursor.pos - cursor.eye_pos); + + float orbit_inertia = EDITOR_GET("editors/3d/navigation_feel/orbit_inertia"); + orbit_inertia = MAX(0.0001, orbit_inertia); + camera_cursor.x_rot = Math::lerp(old_camera_cursor.x_rot, cursor.x_rot, MIN(1.f, p_interp_delta * (1 / orbit_inertia))); + camera_cursor.y_rot = Math::lerp(old_camera_cursor.y_rot, cursor.y_rot, MIN(1.f, p_interp_delta * (1 / orbit_inertia))); + + Vector3 forward = to_camera_transform(camera_cursor).basis.xform(Vector3(0, 0, -1)); + camera_cursor.pos = camera_cursor.eye_pos + forward * camera_cursor.distance; - camera_cursor.x_rot = Math::lerp(old_camera_cursor.x_rot, cursor.x_rot, MIN(1.f, p_interp_delta * (1 / orbit_inertia))); - camera_cursor.y_rot = Math::lerp(old_camera_cursor.y_rot, cursor.y_rot, MIN(1.f, p_interp_delta * (1 / orbit_inertia))); + } else { + + //when not being manipulated, move softly + float free_orbit_inertia = EDITOR_GET("editors/3d/navigation_feel/orbit_inertia"); + float free_translation_inertia = EDITOR_GET("editors/3d/navigation_feel/translation_inertia"); + //when being manipulated, move more quickly + float manip_orbit_inertia = EDITOR_GET("editors/3d/navigation_feel/manipulation_orbit_inertia"); + float manip_translation_inertia = EDITOR_GET("editors/3d/navigation_feel/manipulation_translation_inertia"); + + float zoom_inertia = EDITOR_GET("editors/3d/navigation_feel/zoom_inertia"); + + //determine if being manipulated + bool manipulated = Input::get_singleton()->get_mouse_button_mask() & (2 | 4); + manipulated |= Input::get_singleton()->is_key_pressed(KEY_SHIFT); + manipulated |= Input::get_singleton()->is_key_pressed(KEY_ALT); + manipulated |= Input::get_singleton()->is_key_pressed(KEY_CONTROL); - camera_cursor.pos = old_camera_cursor.pos.linear_interpolate(cursor.pos, MIN(1.f, p_interp_delta * (1 / translation_inertia))); - camera_cursor.distance = Math::lerp(old_camera_cursor.distance, cursor.distance, MIN(1.f, p_interp_delta * (1 / zoom_inertia))); + float orbit_inertia = MAX(0.00001, manipulated ? manip_orbit_inertia : free_orbit_inertia); + float translation_inertia = MAX(0.0001, manipulated ? manip_translation_inertia : free_translation_inertia); + zoom_inertia = MAX(0.0001, zoom_inertia); - if (p_interp_delta == 0 || is_freelook_active()) { - camera_cursor = cursor; + camera_cursor.x_rot = Math::lerp(old_camera_cursor.x_rot, cursor.x_rot, MIN(1.f, p_interp_delta * (1 / orbit_inertia))); + camera_cursor.y_rot = Math::lerp(old_camera_cursor.y_rot, cursor.y_rot, MIN(1.f, p_interp_delta * (1 / orbit_inertia))); + + camera_cursor.pos = old_camera_cursor.pos.linear_interpolate(cursor.pos, MIN(1.f, p_interp_delta * (1 / translation_inertia))); + camera_cursor.distance = Math::lerp(old_camera_cursor.distance, cursor.distance, MIN(1.f, p_interp_delta * (1 / zoom_inertia))); + } } + //------- + // Apply camera transform + float tolerance = 0.001; bool equal = true; if (Math::abs(old_camera_cursor.x_rot - camera_cursor.x_rot) > tolerance || Math::abs(old_camera_cursor.y_rot - camera_cursor.y_rot) > tolerance) { @@ -845,11 +878,17 @@ void SpatialEditorViewport::_sinput(const Ref<InputEvent> &p_event) { switch (b->get_button_index()) { case BUTTON_WHEEL_UP: { - scale_cursor_distance(is_freelook_active() ? zoom_factor : 1.0 / zoom_factor); + if (is_freelook_active()) + scale_freelook_speed(zoom_factor); + else + scale_cursor_distance(1.0 / zoom_factor); } break; case BUTTON_WHEEL_DOWN: { - scale_cursor_distance(is_freelook_active() ? 1.0 / zoom_factor : zoom_factor); + if (is_freelook_active()) + scale_freelook_speed(1.0 / zoom_factor); + else + scale_cursor_distance(zoom_factor); } break; case BUTTON_RIGHT: { @@ -901,10 +940,10 @@ void SpatialEditorViewport::_sinput(const Ref<InputEvent> &p_event) { if (b->is_pressed()) { int mod = _get_key_modifier(b); if (mod == _get_key_modifier_setting("editors/3d/freelook/freelook_activation_modifier")) { - freelook_active = true; + set_freelook_active(true); } } else { - freelook_active = false; + set_freelook_active(false); } if (freelook_active && !surface->has_focus()) { @@ -1645,6 +1684,9 @@ void SpatialEditorViewport::_sinput(const Ref<InputEvent> &p_event) { real_t degrees_per_pixel = EditorSettings::get_singleton()->get("editors/3d/navigation_feel/orbit_sensitivity"); real_t radians_per_pixel = Math::deg2rad(degrees_per_pixel); + // Note: do NOT assume the camera has the "current" transform, because it is interpolated and may have "lag". + Transform prev_camera_transform = to_camera_transform(cursor); + cursor.x_rot += relative.y * radians_per_pixel; cursor.y_rot += relative.x * radians_per_pixel; if (cursor.x_rot > Math_PI / 2.0) @@ -1652,12 +1694,12 @@ void SpatialEditorViewport::_sinput(const Ref<InputEvent> &p_event) { if (cursor.x_rot < -Math_PI / 2.0) cursor.x_rot = -Math_PI / 2.0; - // Look is like Orbit, except the cursor translates, not the camera + // Look is like the opposite of Orbit: the focus point rotates around the camera Transform camera_transform = to_camera_transform(cursor); Vector3 pos = camera_transform.xform(Vector3(0, 0, 0)); - Vector3 diff = camera->get_translation() - pos; + Vector3 prev_pos = prev_camera_transform.xform(Vector3(0, 0, 0)); + Vector3 diff = prev_pos - pos; cursor.pos += diff; - freelook_target_position += diff; name = ""; _update_name(); @@ -1755,23 +1797,57 @@ void SpatialEditorViewport::_sinput(const Ref<InputEvent> &p_event) { } } +void SpatialEditorViewport::set_freelook_active(bool active_now) { + + if (!freelook_active && active_now) { + // Sync camera cursor to cursor to "cut" interpolation jumps due to changing referential + cursor = camera_cursor; + + // Make sure eye_pos is synced, because freelook referential is eye pos rather than orbit pos + Vector3 forward = to_camera_transform(cursor).basis.xform(Vector3(0, 0, -1)); + cursor.eye_pos = cursor.pos - cursor.distance * forward; + // Also sync the camera cursor, otherwise switching to freelook will be trippy if inertia is active + camera_cursor.eye_pos = cursor.eye_pos; + + if (EditorSettings::get_singleton()->get("editors/3d/freelook/freelook_speed_zoom_link")) { + // Re-adjust freelook speed from the current zoom level + real_t base_speed = EditorSettings::get_singleton()->get("editors/3d/freelook/freelook_base_speed"); + freelook_speed = base_speed * cursor.distance; + } + + } else if (freelook_active && !active_now) { + // Sync camera cursor to cursor to "cut" interpolation jumps due to changing referential + cursor = camera_cursor; + } + + freelook_active = active_now; +} + void SpatialEditorViewport::scale_cursor_distance(real_t scale) { // Prevents zero distance which would short-circuit any scaling if (cursor.distance < ZOOM_MIN_DISTANCE) cursor.distance = ZOOM_MIN_DISTANCE; - real_t prev_distance = cursor.distance; cursor.distance *= scale; if (cursor.distance < ZOOM_MIN_DISTANCE) cursor.distance = ZOOM_MIN_DISTANCE; - if (is_freelook_active()) { - // In freelook mode, cursor reference is reversed so it needs to be adjusted - Vector3 forward = camera->get_transform().basis.xform(Vector3(0, 0, -1)); - cursor.pos += (cursor.distance - prev_distance) * forward; - } + zoom_indicator_delay = ZOOM_INDICATOR_DELAY_S; + surface->update(); +} + +void SpatialEditorViewport::scale_freelook_speed(real_t scale) { + + // Prevents zero distance which would short-circuit any scaling + if (freelook_speed < FREELOOK_MIN_SPEED) + freelook_speed = FREELOOK_MIN_SPEED; + + freelook_speed *= scale; + + if (freelook_speed < FREELOOK_MIN_SPEED) + freelook_speed = FREELOOK_MIN_SPEED; zoom_indicator_delay = ZOOM_INDICATOR_DELAY_S; surface->update(); @@ -1790,7 +1866,6 @@ Point2i SpatialEditorViewport::_get_warped_mouse_motion(const Ref<InputEventMous void SpatialEditorViewport::_update_freelook(real_t delta) { if (!is_freelook_active()) { - freelook_target_position = cursor.pos; return; } @@ -1833,21 +1908,15 @@ void SpatialEditorViewport::_update_freelook(real_t delta) { speed_modifier = true; } - real_t inertia = EDITOR_DEF("editors/3d/freelook/freelook_inertia", 0.1); - inertia = MAX(0, inertia); - const real_t base_speed = EDITOR_DEF("editors/3d/freelook/freelook_base_speed", 0.5); - const real_t modifier_speed_factor = EDITOR_DEF("editors/3d/freelook/freelook_modifier_speed_factor", 3); - - real_t speed = base_speed * cursor.distance; - if (speed_modifier) + real_t speed = freelook_speed; + if (speed_modifier) { + real_t modifier_speed_factor = EditorSettings::get_singleton()->get("editors/3d/freelook/freelook_modifier_speed_factor"); speed *= modifier_speed_factor; + } - // Higher inertia should increase "lag" (lerp with factor between 0 and 1) - // Inertia of zero should produce instant movement (lerp with factor of 1) in this case it returns a really high value and gets clamped to 1. - - freelook_target_position += direction * speed; - real_t factor = (1.0 / (inertia + 0.001)) * delta; - cursor.pos = cursor.pos.linear_interpolate(freelook_target_position, CLAMP(factor, 0, 1)); + Vector3 motion = direction * speed * delta; + cursor.pos += motion; + cursor.eye_pos += motion; } void SpatialEditorViewport::set_message(String p_message, float p_time) { @@ -1886,7 +1955,7 @@ void SpatialEditorViewport::_notification(int p_what) { } */ - real_t delta = get_tree()->get_idle_process_time(); + real_t delta = get_process_delta_time(); if (zoom_indicator_delay > 0) { zoom_indicator_delay -= delta; @@ -1897,7 +1966,7 @@ void SpatialEditorViewport::_notification(int p_what) { _update_freelook(delta); - _update_camera(get_process_delta_time()); + _update_camera(delta); Map<Node *, Object *> &selection = editor_selection->get_selection(); @@ -2026,7 +2095,7 @@ void SpatialEditorViewport::_notification(int p_what) { } // TODO That should be part of the drawing API... -static void stroke_rect(CanvasItem *ci, Rect2 rect, Color color, real_t width = 1.0) { +static void stroke_rect(CanvasItem &ci, Rect2 rect, Color color, real_t width = 1.0) { // a---b // | | @@ -2036,10 +2105,31 @@ static void stroke_rect(CanvasItem *ci, Rect2 rect, Color color, real_t width = Vector2 c(rect.position.x, rect.position.y + rect.size.y); Vector2 d(rect.position + rect.size); - ci->draw_line(a, b, color, width); - ci->draw_line(b, d, color, width); - ci->draw_line(d, c, color, width); - ci->draw_line(c, a, color, width); + ci.draw_line(a, b, color, width); + ci.draw_line(b, d, color, width); + ci.draw_line(d, c, color, width); + ci.draw_line(c, a, color, width); +} + +static void draw_indicator_bar(Control &surface, real_t fill, Ref<Texture> icon) { + + // Adjust bar size from control height + Vector2 surface_size = surface.get_size(); + real_t h = surface_size.y / 2.0; + real_t y = (surface_size.y - h) / 2.0; + + Rect2 r(10, y, 6, h); + real_t sy = r.size.y * fill; + + // Note: because this bar appears over the viewport, it has to stay readable for any background color + // Draw both neutral dark and bright colors to account this + surface.draw_rect(r, Color(1, 1, 1, 0.2)); + surface.draw_rect(Rect2(r.position.x, r.position.y + r.size.y - sy, r.size.x, sy), Color(1, 1, 1, 0.6)); + stroke_rect(surface, r.grow(1), Color(0, 0, 0, 0.7)); + + Vector2 icon_size = icon->get_size(); + Vector2 icon_pos = Vector2(r.position.x - (icon_size.x - r.size.x) / 2, r.position.y + r.size.y + 2); + surface.draw_texture(icon, icon_pos); } void SpatialEditorViewport::_draw() { @@ -2098,35 +2188,47 @@ void SpatialEditorViewport::_draw() { draw_rect = Rect2(Vector2(), s).clip(draw_rect); - stroke_rect(surface, draw_rect, Color(0.6, 0.6, 0.1, 0.5), 2.0); + stroke_rect(*surface, draw_rect, Color(0.6, 0.6, 0.1, 0.5), 2.0); } else { if (zoom_indicator_delay > 0.0) { - // Show indicative zoom factor - real_t min_distance = ZOOM_MIN_DISTANCE; // TODO Why not pick znear to limit zoom? - real_t max_distance = camera->get_zfar(); - real_t scale_length = (max_distance - min_distance); + if (is_freelook_active()) { + // Show speed - if (Math::abs(scale_length) > CMP_EPSILON) { - real_t logscale_t = 1.0 - Math::log(1 + cursor.distance - min_distance) / Math::log(1 + scale_length); + real_t min_speed = FREELOOK_MIN_SPEED; + real_t max_speed = camera->get_zfar(); + real_t scale_length = (max_speed - min_speed); - // There is no real maximum distance so that factor can become negative, - // Let's make it look asymptotic instead (will decrease slower and slower). - if (logscale_t < 0.25) - logscale_t = 0.25 * Math::exp(4.0 * logscale_t - 1.0); + if (Math::abs(scale_length) > CMP_EPSILON) { + real_t logscale_t = 1.0 - Math::log(1 + freelook_speed - min_speed) / Math::log(1 + scale_length); - Vector2 surface_size = surface->get_size(); - real_t h = surface_size.y / 2.0; - real_t y = (surface_size.y - h) / 2.0; + // There is no real maximum speed so that factor can become negative, + // Let's make it look asymptotic instead (will decrease slower and slower). + if (logscale_t < 0.25) + logscale_t = 0.25 * Math::exp(4.0 * logscale_t - 1.0); - Rect2 r(10, y, 6, h); - real_t sy = r.size.y * logscale_t; + draw_indicator_bar(*surface, 1.0 - logscale_t, get_icon("ViewportSpeed", "EditorIcons")); + } + + } else { + // Show zoom - surface->draw_rect(r, Color(1, 1, 1, 0.2)); - surface->draw_rect(Rect2(r.position.x, r.position.y + r.size.y - sy, r.size.x, sy), Color(1, 1, 1, 0.6)); - stroke_rect(surface, r.grow(1), Color(0, 0, 0, 0.7)); + real_t min_distance = ZOOM_MIN_DISTANCE; // TODO Why not pick znear to limit zoom? + real_t max_distance = camera->get_zfar(); + real_t scale_length = (max_distance - min_distance); + + if (Math::abs(scale_length) > CMP_EPSILON) { + real_t logscale_t = 1.0 - Math::log(1 + cursor.distance - min_distance) / Math::log(1 + scale_length); + + // There is no real maximum distance so that factor can become negative, + // Let's make it look asymptotic instead (will decrease slower and slower). + if (logscale_t < 0.25) + logscale_t = 0.25 * Math::exp(4.0 * logscale_t - 1.0); + + draw_indicator_bar(*surface, logscale_t, get_icon("ViewportZoom", "EditorIcons")); + } } } } @@ -2576,6 +2678,7 @@ void SpatialEditorViewport::reset() { cursor.y_rot = 0.5; cursor.distance = 4; cursor.region_select = false; + cursor.pos = Vector3(); _update_name(); } @@ -2662,8 +2765,14 @@ Vector3 SpatialEditorViewport::_get_instance_position(const Point2 &p_pos) const normal = hit_normal; } } - Vector3 center = preview_bounds->get_size() * 0.5; - return point + (center * normal); + Vector3 offset = Vector3(); + for (int i = 0; i < 3; i++) { + if (normal[i] > 0.0) + offset[i] = (preview_bounds->get_size()[i] - (preview_bounds->get_size()[i] + preview_bounds->get_position()[i])); + else if (normal[i] < 0.0) + offset[i] = -(preview_bounds->get_size()[i] + preview_bounds->get_position()[i]); + } + return point + offset; } Rect3 SpatialEditorViewport::_calculate_spatial_bounds(const Spatial *p_parent, const Rect3 p_bounds) { @@ -3036,6 +3145,7 @@ SpatialEditorViewport::SpatialEditorViewport(SpatialEditor *p_spatial_editor, Ed accept = NULL; freelook_active = false; + freelook_speed = EditorSettings::get_singleton()->get("editors/3d/freelook/freelook_base_speed"); selection_menu = memnew(PopupMenu); add_child(selection_menu); diff --git a/editor/plugins/spatial_editor_plugin.h b/editor/plugins/spatial_editor_plugin.h index 4f4c540048..a9dd1f1327 100644 --- a/editor/plugins/spatial_editor_plugin.h +++ b/editor/plugins/spatial_editor_plugin.h @@ -131,7 +131,7 @@ private: float gizmo_scale; bool freelook_active; - Vector3 freelook_target_position; + real_t freelook_speed; PanelContainer *info; Label *info_label; @@ -231,6 +231,7 @@ private: Vector3 pos; float x_rot, y_rot, distance; + Vector3 eye_pos; // Used in freelook mode bool region_select; Point2 region_begin, region_end; @@ -239,10 +240,17 @@ private: distance = 4; region_select = false; } - } cursor, camera_cursor; + }; + // Viewport camera supports movement smoothing, + // so one cursor is the real cursor, while the other can be an interpolated version. + Cursor cursor; // Immediate cursor + Cursor camera_cursor; // That one may be interpolated (don't modify this one except for smoothing purposes) void scale_cursor_distance(real_t scale); + void set_freelook_active(bool active_now); + void scale_freelook_speed(real_t scale); + real_t zoom_indicator_delay; RID move_gizmo_instance[3], move_plane_gizmo_instance[3], rotate_gizmo_instance[3], scale_gizmo_instance[3]; diff --git a/editor/plugins/tile_map_editor_plugin.cpp b/editor/plugins/tile_map_editor_plugin.cpp index 2f2ed7bdf0..d12b3f1e0e 100644 --- a/editor/plugins/tile_map_editor_plugin.cpp +++ b/editor/plugins/tile_map_editor_plugin.cpp @@ -229,7 +229,7 @@ struct _PaletteEntry { return name < p_rhs.name; } }; -} +} // namespace void TileMapEditor::_update_palette() { @@ -1152,7 +1152,7 @@ bool TileMapEditor::forward_gui_input(const Ref<InputEvent> &p_event) { return false; } -void TileMapEditor::_canvas_draw() { +void TileMapEditor::forward_draw_over_canvas(Control *p_canvas) { if (!node) return; @@ -1379,8 +1379,6 @@ void TileMapEditor::edit(Node *p_tile_map) { if (p_tile_map) { node = Object::cast_to<TileMap>(p_tile_map); - if (!canvas_item_editor->is_connected("draw", this, "_canvas_draw")) - canvas_item_editor->connect("draw", this, "_canvas_draw"); if (!canvas_item_editor->is_connected("mouse_entered", this, "_canvas_mouse_enter")) canvas_item_editor->connect("mouse_entered", this, "_canvas_mouse_enter"); if (!canvas_item_editor->is_connected("mouse_exited", this, "_canvas_mouse_exit")) @@ -1391,8 +1389,6 @@ void TileMapEditor::edit(Node *p_tile_map) { } else { node = NULL; - if (canvas_item_editor->is_connected("draw", this, "_canvas_draw")) - canvas_item_editor->disconnect("draw", this, "_canvas_draw"); if (canvas_item_editor->is_connected("mouse_entered", this, "_canvas_mouse_enter")) canvas_item_editor->disconnect("mouse_entered", this, "_canvas_mouse_enter"); if (canvas_item_editor->is_connected("mouse_exited", this, "_canvas_mouse_exit")) @@ -1428,7 +1424,6 @@ void TileMapEditor::_bind_methods() { ClassDB::bind_method(D_METHOD("_text_changed"), &TileMapEditor::_text_changed); ClassDB::bind_method(D_METHOD("_sbox_input"), &TileMapEditor::_sbox_input); ClassDB::bind_method(D_METHOD("_menu_option"), &TileMapEditor::_menu_option); - ClassDB::bind_method(D_METHOD("_canvas_draw"), &TileMapEditor::_canvas_draw); ClassDB::bind_method(D_METHOD("_canvas_mouse_enter"), &TileMapEditor::_canvas_mouse_enter); ClassDB::bind_method(D_METHOD("_canvas_mouse_exit"), &TileMapEditor::_canvas_mouse_exit); ClassDB::bind_method(D_METHOD("_tileset_settings_changed"), &TileMapEditor::_tileset_settings_changed); diff --git a/editor/plugins/tile_map_editor_plugin.h b/editor/plugins/tile_map_editor_plugin.h index c8f29dfb7b..5b042e4780 100644 --- a/editor/plugins/tile_map_editor_plugin.h +++ b/editor/plugins/tile_map_editor_plugin.h @@ -163,7 +163,6 @@ class TileMapEditor : public VBoxContainer { void _text_changed(const String &p_text); void _sbox_input(const Ref<InputEvent> &p_ie); void _update_palette(); - void _canvas_draw(); void _menu_option(int p_option); void _set_cell(const Point2i &p_pos, int p_value, bool p_flip_h = false, bool p_flip_v = false, bool p_transpose = false, bool p_with_undo = false); @@ -183,6 +182,8 @@ public: HBoxContainer *get_toolbar() const { return toolbar; } bool forward_gui_input(const Ref<InputEvent> &p_event); + void forward_draw_over_canvas(Control *p_canvas); + void edit(Node *p_tile_map); TileMapEditor(EditorNode *p_editor); @@ -197,6 +198,7 @@ class TileMapEditorPlugin : public EditorPlugin { public: virtual bool forward_canvas_gui_input(const Transform2D &p_canvas_xform, const Ref<InputEvent> &p_event) { return tile_map_editor->forward_gui_input(p_event); } + virtual void forward_draw_over_canvas(Control *p_canvas) { tile_map_editor->forward_draw_over_canvas(p_canvas); } virtual String get_name() const { return "TileMap"; } bool has_main_screen() const { return false; } diff --git a/editor/project_settings_editor.cpp b/editor/project_settings_editor.cpp index 91ef9e36f3..723d7b14ff 100644 --- a/editor/project_settings_editor.cpp +++ b/editor/project_settings_editor.cpp @@ -1189,7 +1189,7 @@ void ProjectSettingsEditor::_translation_res_option_delete(Object *p_item, int p ERR_FAIL_COND(!remaps.has(key)); PoolStringArray r = remaps[key]; - ERR_FAIL_INDEX(idx, remaps.size()); + ERR_FAIL_INDEX(idx, r.size()); r.remove(idx); remaps[key] = r; diff --git a/editor/property_editor.cpp b/editor/property_editor.cpp index 658f67d6a4..b7cc9347f2 100644 --- a/editor/property_editor.cpp +++ b/editor/property_editor.cpp @@ -376,7 +376,7 @@ bool CustomPropertyEditor::edit(Object *p_owner, const String &p_name, Variant:: if (hint == PROPERTY_HINT_RANGE) { int c = hint_text.get_slice_count(","); - float min = 0, max = 100, step = 1; + float min = 0, max = 100, step = type == Variant::REAL ? .01 : 1; if (c >= 1) { if (!hint_text.get_slice(",", 0).empty()) @@ -3032,7 +3032,7 @@ void PropertyEditor::update_tree() { if (p.hint == PROPERTY_HINT_SPRITE_FRAME || p.hint == PROPERTY_HINT_RANGE || p.hint == PROPERTY_HINT_EXP_RANGE) { int c = p.hint_string.get_slice_count(","); - float min = 0, max = 100, step = 1; + float min = 0, max = 100, step = p.type == Variant::REAL ? .01 : 1; if (c >= 1) { min = p.hint_string.get_slice(",", 0).to_double(); diff --git a/editor/script_editor_debugger.h b/editor/script_editor_debugger.h index 64ac2535a9..d0faab5892 100644 --- a/editor/script_editor_debugger.h +++ b/editor/script_editor_debugger.h @@ -166,9 +166,6 @@ class ScriptEditorDebugger : public Control { void _method_changed(Object *p_base, const StringName &p_name, VARIANT_ARG_DECLARE); void _property_changed(Object *p_base, const StringName &p_property, const Variant &p_value); - static void _method_changeds(void *p_ud, Object *p_base, const StringName &p_name, VARIANT_ARG_DECLARE); - static void _property_changeds(void *p_ud, Object *p_base, const StringName &p_property, const Variant &p_value); - void _error_selected(int p_idx); void _error_stack_selected(int p_idx); @@ -196,6 +193,9 @@ public: void set_live_debugging(bool p_enable); + static void _method_changeds(void *p_ud, Object *p_base, const StringName &p_name, VARIANT_ARG_DECLARE); + static void _property_changeds(void *p_ud, Object *p_base, const StringName &p_property, const Variant &p_value); + void live_debug_create_node(const NodePath &p_parent, const String &p_type, const String &p_name); void live_debug_instance_node(const NodePath &p_parent, const String &p_path, const String &p_name); void live_debug_remove_node(const NodePath &p_at); diff --git a/editor/settings_config_dialog.cpp b/editor/settings_config_dialog.cpp index 86979a1174..c052845be9 100644 --- a/editor/settings_config_dialog.cpp +++ b/editor/settings_config_dialog.cpp @@ -35,6 +35,7 @@ #include "os/keyboard.h" #include "project_settings.h" #include "scene/gui/margin_container.h" +#include "script_editor_debugger.h" void EditorSettingsDialog::ok_pressed() { @@ -91,6 +92,7 @@ void EditorSettingsDialog::popup_edit_settings() { search_box->grab_focus(); _update_shortcuts(); + set_process_unhandled_input(true); // Restore valid window bounds or pop up at default size. if (EditorSettings::get_singleton()->has_setting("interface/dialogs/editor_settings_bounds")) { @@ -121,19 +123,62 @@ void EditorSettingsDialog::_filter_shortcuts(const String &p_filter) { _update_shortcuts(); } +void EditorSettingsDialog::_undo_redo_callback(void *p_self, const String &p_name) { + EditorNode::get_log()->add_message(p_name); +} + void EditorSettingsDialog::_notification(int p_what) { switch (p_what) { + case NOTIFICATION_READY: { + ScriptEditorDebugger *sed = ScriptEditor::get_singleton()->get_debugger(); + undo_redo->set_method_notify_callback(sed->_method_changeds, sed); + undo_redo->set_property_notify_callback(sed->_property_changeds, sed); + undo_redo->set_commit_notify_callback(_undo_redo_callback, this); + } break; case NOTIFICATION_ENTER_TREE: { clear_button->set_icon(get_icon("Close", "EditorIcons")); shortcut_clear_button->set_icon(get_icon("Close", "EditorIcons")); } break; case NOTIFICATION_POPUP_HIDE: { EditorSettings::get_singleton()->set("interface/dialogs/editor_settings_bounds", get_rect()); + set_process_unhandled_input(false); } break; } } +void EditorSettingsDialog::_unhandled_input(const Ref<InputEvent> &p_event) { + + Ref<InputEventKey> k = p_event; + + if (k.is_valid() && is_window_modal_on_top()) { + + if (k->is_pressed()) { + + bool handled = false; + + if (ED_IS_SHORTCUT("editor/undo", p_event)) { + String action = undo_redo->get_current_action_name(); + if (action != "") + EditorNode::get_log()->add_message("UNDO: " + action); + undo_redo->undo(); + handled = true; + } + if (ED_IS_SHORTCUT("editor/redo", p_event)) { + undo_redo->redo(); + String action = undo_redo->get_current_action_name(); + if (action != "") + EditorNode::get_log()->add_message("REDO: " + action); + handled = true; + } + + if (handled) { + accept_event(); + } + } + } +} + void EditorSettingsDialog::_update_shortcuts() { shortcuts->clear(); @@ -212,30 +257,28 @@ void EditorSettingsDialog::_shortcut_button_pressed(Object *p_item, int p_column if (!sc.is_valid()) return; //pointless, there is nothing - UndoRedo *ur = EditorNode::get_singleton()->get_undo_redo(); - ur->create_action("Erase Shortcut"); - ur->add_do_method(sc.ptr(), "set_shortcut", Ref<InputEvent>()); - ur->add_undo_method(sc.ptr(), "set_shortcut", sc->get_shortcut()); - ur->add_do_method(this, "_update_shortcuts"); - ur->add_undo_method(this, "_update_shortcuts"); - ur->add_do_method(this, "_settings_changed"); - ur->add_undo_method(this, "_settings_changed"); - ur->commit_action(); + undo_redo->create_action("Erase Shortcut"); + undo_redo->add_do_method(sc.ptr(), "set_shortcut", Ref<InputEvent>()); + undo_redo->add_undo_method(sc.ptr(), "set_shortcut", sc->get_shortcut()); + undo_redo->add_do_method(this, "_update_shortcuts"); + undo_redo->add_undo_method(this, "_update_shortcuts"); + undo_redo->add_do_method(this, "_settings_changed"); + undo_redo->add_undo_method(this, "_settings_changed"); + undo_redo->commit_action(); } else if (p_idx == 2) { //revert to original if (!sc.is_valid()) return; //pointless, there is nothing Ref<InputEvent> original = sc->get_meta("original"); - UndoRedo *ur = EditorNode::get_singleton()->get_undo_redo(); - ur->create_action("Restore Shortcut"); - ur->add_do_method(sc.ptr(), "set_shortcut", original); - ur->add_undo_method(sc.ptr(), "set_shortcut", sc->get_shortcut()); - ur->add_do_method(this, "_update_shortcuts"); - ur->add_undo_method(this, "_update_shortcuts"); - ur->add_do_method(this, "_settings_changed"); - ur->add_undo_method(this, "_settings_changed"); - ur->commit_action(); + undo_redo->create_action("Restore Shortcut"); + undo_redo->add_do_method(sc.ptr(), "set_shortcut", original); + undo_redo->add_undo_method(sc.ptr(), "set_shortcut", sc->get_shortcut()); + undo_redo->add_do_method(this, "_update_shortcuts"); + undo_redo->add_undo_method(this, "_update_shortcuts"); + undo_redo->add_do_method(this, "_settings_changed"); + undo_redo->add_undo_method(this, "_settings_changed"); + undo_redo->commit_action(); } } @@ -276,19 +319,19 @@ void EditorSettingsDialog::_press_a_key_confirm() { Ref<ShortCut> sc = EditorSettings::get_singleton()->get_shortcut(shortcut_configured); - UndoRedo *ur = EditorNode::get_singleton()->get_undo_redo(); - ur->create_action("Change Shortcut '" + shortcut_configured + "'"); - ur->add_do_method(sc.ptr(), "set_shortcut", ie); - ur->add_undo_method(sc.ptr(), "set_shortcut", sc->get_shortcut()); - ur->add_do_method(this, "_update_shortcuts"); - ur->add_undo_method(this, "_update_shortcuts"); - ur->add_do_method(this, "_settings_changed"); - ur->add_undo_method(this, "_settings_changed"); - ur->commit_action(); + undo_redo->create_action("Change Shortcut '" + shortcut_configured + "'"); + undo_redo->add_do_method(sc.ptr(), "set_shortcut", ie); + undo_redo->add_undo_method(sc.ptr(), "set_shortcut", sc->get_shortcut()); + undo_redo->add_do_method(this, "_update_shortcuts"); + undo_redo->add_undo_method(this, "_update_shortcuts"); + undo_redo->add_do_method(this, "_settings_changed"); + undo_redo->add_undo_method(this, "_settings_changed"); + undo_redo->commit_action(); } void EditorSettingsDialog::_bind_methods() { + ClassDB::bind_method(D_METHOD("_unhandled_input"), &EditorSettingsDialog::_unhandled_input); ClassDB::bind_method(D_METHOD("_settings_save"), &EditorSettingsDialog::_settings_save); ClassDB::bind_method(D_METHOD("_settings_changed"), &EditorSettingsDialog::_settings_changed); ClassDB::bind_method(D_METHOD("_settings_property_edited"), &EditorSettingsDialog::_settings_property_edited); @@ -305,6 +348,7 @@ EditorSettingsDialog::EditorSettingsDialog() { set_title(TTR("Editor Settings")); set_resizable(true); + undo_redo = memnew(UndoRedo); tabs = memnew(TabContainer); tabs->set_tab_align(TabContainer::ALIGN_LEFT); @@ -336,7 +380,7 @@ EditorSettingsDialog::EditorSettingsDialog() { property_editor->get_property_editor()->set_use_filter(true); property_editor->register_search_box(search_box); property_editor->set_v_size_flags(Control::SIZE_EXPAND_FILL); - property_editor->get_property_editor()->set_undo_redo(EditorNode::get_singleton()->get_undo_redo()); + property_editor->get_property_editor()->set_undo_redo(undo_redo); vbc->add_child(property_editor); property_editor->get_property_editor()->connect("property_edited", this, "_settings_property_edited"); @@ -400,3 +444,7 @@ EditorSettingsDialog::EditorSettingsDialog() { updating = false; } + +EditorSettingsDialog::~EditorSettingsDialog() { + memdelete(undo_redo); +} diff --git a/editor/settings_config_dialog.h b/editor/settings_config_dialog.h index 8a66d5098c..a03b15c06d 100644 --- a/editor/settings_config_dialog.h +++ b/editor/settings_config_dialog.h @@ -50,6 +50,7 @@ class EditorSettingsDialog : public AcceptDialog { Timer *timer; + UndoRedo *undo_redo; Tree *shortcuts; ConfirmationDialog *press_a_key; @@ -65,6 +66,7 @@ class EditorSettingsDialog : public AcceptDialog { void _settings_property_edited(const String &p_name); void _settings_save(); + void _unhandled_input(const Ref<InputEvent> &p_event); void _notification(int p_what); void _press_a_key_confirm(); @@ -78,6 +80,8 @@ class EditorSettingsDialog : public AcceptDialog { void _update_shortcuts(); void _shortcut_button_pressed(Object *p_item, int p_column, int p_idx); + static void _undo_redo_callback(void *p_self, const String &p_name); + protected: static void _bind_methods(); @@ -85,6 +89,7 @@ public: void popup_edit_settings(); EditorSettingsDialog(); + ~EditorSettingsDialog(); }; #endif // SETTINGS_CONFIG_DIALOG_H diff --git a/main/main.cpp b/main/main.cpp index 68e518ae3d..04ed902c28 100644 --- a/main/main.cpp +++ b/main/main.cpp @@ -1350,7 +1350,7 @@ bool Main::start() { String stretch_mode = GLOBAL_DEF("display/window/stretch/mode", "disabled"); String stretch_aspect = GLOBAL_DEF("display/window/stretch/aspect", "ignore"); Size2i stretch_size = Size2(GLOBAL_DEF("display/window/size/width", 0), GLOBAL_DEF("display/window/size/height", 0)); - int stretch_shrink = GLOBAL_DEF("display/window/stretch/shrink", 1); + real_t stretch_shrink = GLOBAL_DEF("display/window/stretch/shrink", 1.0f); SceneTree::StretchMode sml_sm = SceneTree::STRETCH_MODE_DISABLED; if (stretch_mode == "2d") diff --git a/misc/dist/ios_xcode/godot_ios.xcodeproj/xcshareddata/xcschemes/godot_ios.xcscheme b/misc/dist/ios_xcode/godot_ios.xcodeproj/xcshareddata/xcschemes/godot_ios.xcscheme index 3f0df5c437..b6beeb012f 100644 --- a/misc/dist/ios_xcode/godot_ios.xcodeproj/xcshareddata/xcschemes/godot_ios.xcscheme +++ b/misc/dist/ios_xcode/godot_ios.xcodeproj/xcshareddata/xcschemes/godot_ios.xcscheme @@ -23,7 +23,7 @@ </BuildActionEntries> </BuildAction> <TestAction - buildConfiguration = "Development" + buildConfiguration = "Debug" selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB" selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB" shouldUseLaunchSchemeArgsEnv = "YES"> @@ -42,7 +42,7 @@ </AdditionalOptions> </TestAction> <LaunchAction - buildConfiguration = "Development" + buildConfiguration = "Debug" selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB" selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB" launchStyle = "0" @@ -67,7 +67,7 @@ </AdditionalOptions> </LaunchAction> <ProfileAction - buildConfiguration = "Development" + buildConfiguration = "Debug" shouldUseLaunchSchemeArgsEnv = "YES" savedToolIdentifier = "" useCustomWorkingDirectory = "NO" @@ -84,10 +84,10 @@ </BuildableProductRunnable> </ProfileAction> <AnalyzeAction - buildConfiguration = "Development"> + buildConfiguration = "Debug"> </AnalyzeAction> <ArchiveAction - buildConfiguration = "Development" + buildConfiguration = "Debug" revealArchiveInOrganizer = "YES"> </ArchiveAction> </Scheme> diff --git a/modules/gdnative/SCsub b/modules/gdnative/SCsub index ba4163aab7..a6ae143947 100644 --- a/modules/gdnative/SCsub +++ b/modules/gdnative/SCsub @@ -13,6 +13,7 @@ gdn_env.add_source_files(env.modules_sources, "nativescript/*.cpp") gdn_env.Append(CPPPATH=['#modules/gdnative/include/']) SConscript("nativearvr/SCsub") +SConscript("pluginscript/SCsub") def _spaced(e): return e if e[-1] == '*' else e + ' ' @@ -26,6 +27,7 @@ def _build_gdnative_api_struct_header(api): '#include <gdnative/gdnative.h>', '#include <nativearvr/godot_nativearvr.h>', '#include <nativescript/godot_nativescript.h>', + '#include <pluginscript/godot_pluginscript.h>', '', '#define GDNATIVE_API_INIT(options) do { extern const godot_gdnative_api_struct *_gdnative_wrapper_api_struct; _gdnative_wrapper_api_struct = options->api_struct; } while (0)', '', @@ -98,6 +100,7 @@ def _build_gdnative_wrapper_code(api): '', '#include <gdnative/gdnative.h>', '#include <nativescript/godot_nativescript.h>', + '#include <pluginscript/godot_pluginscript.h>', '', '#include <gdnative_api_struct.gen.h>', '', diff --git a/modules/gdnative/gdnative/string.cpp b/modules/gdnative/gdnative/string.cpp index 9b715ce36a..905c513d9d 100644 --- a/modules/gdnative/gdnative/string.cpp +++ b/modules/gdnative/gdnative/string.cpp @@ -29,9 +29,9 @@ /*************************************************************************/ #include "gdnative/string.h" +#include "core/string_db.h" +#include "core/ustring.h" #include "core/variant.h" -#include "string_db.h" -#include "ustring.h" #include <string.h> diff --git a/modules/gdnative/gdnative_api.json b/modules/gdnative/gdnative_api.json index 459ca12ae9..31b021b751 100644 --- a/modules/gdnative/gdnative_api.json +++ b/modules/gdnative/gdnative_api.json @@ -5234,7 +5234,6 @@ "name": "godot_arvr_register_interface", "return_type": "void", "arguments": [ - ["const char *", "p_name"], ["const godot_arvr_interface_gdnative *", "p_interface"] ] }, diff --git a/modules/gdnative/include/gdnative/array.h b/modules/gdnative/include/gdnative/array.h index edab028cba..d0639589b7 100644 --- a/modules/gdnative/include/gdnative/array.h +++ b/modules/gdnative/include/gdnative/array.h @@ -46,11 +46,20 @@ typedef struct { } godot_array; #endif +// reduce extern "C" nesting for VS2013 +#ifdef __cplusplus +} +#endif + #include <gdnative/pool_arrays.h> #include <gdnative/variant.h> #include <gdnative/gdnative.h> +#ifdef __cplusplus +extern "C" { +#endif + void GDAPI godot_array_new(godot_array *r_dest); void GDAPI godot_array_new_copy(godot_array *r_dest, const godot_array *p_src); void GDAPI godot_array_new_pool_color_array(godot_array *r_dest, const godot_pool_color_array *p_pca); diff --git a/modules/gdnative/include/gdnative/basis.h b/modules/gdnative/include/gdnative/basis.h index 8ff6a6f541..b86b1c17d8 100644 --- a/modules/gdnative/include/gdnative/basis.h +++ b/modules/gdnative/include/gdnative/basis.h @@ -45,10 +45,19 @@ typedef struct { } godot_basis; #endif +// reduce extern "C" nesting for VS2013 +#ifdef __cplusplus +} +#endif + #include <gdnative/gdnative.h> #include <gdnative/quat.h> #include <gdnative/vector3.h> +#ifdef __cplusplus +extern "C" { +#endif + void GDAPI godot_basis_new_with_rows(godot_basis *r_dest, const godot_vector3 *p_x_axis, const godot_vector3 *p_y_axis, const godot_vector3 *p_z_axis); void GDAPI godot_basis_new_with_axis_and_angle(godot_basis *r_dest, const godot_vector3 *p_axis, const godot_real p_phi); void GDAPI godot_basis_new_with_euler(godot_basis *r_dest, const godot_vector3 *p_euler); diff --git a/modules/gdnative/include/gdnative/color.h b/modules/gdnative/include/gdnative/color.h index 14265466b9..857e86a738 100644 --- a/modules/gdnative/include/gdnative/color.h +++ b/modules/gdnative/include/gdnative/color.h @@ -45,9 +45,18 @@ typedef struct { } godot_color; #endif +// reduce extern "C" nesting for VS2013 +#ifdef __cplusplus +} +#endif + #include <gdnative/gdnative.h> #include <gdnative/string.h> +#ifdef __cplusplus +extern "C" { +#endif + void GDAPI godot_color_new_rgba(godot_color *r_dest, const godot_real p_r, const godot_real p_g, const godot_real p_b, const godot_real p_a); void GDAPI godot_color_new_rgb(godot_color *r_dest, const godot_real p_r, const godot_real p_g, const godot_real p_b); diff --git a/modules/gdnative/include/gdnative/dictionary.h b/modules/gdnative/include/gdnative/dictionary.h index c85c3f3830..e68d0fdc29 100644 --- a/modules/gdnative/include/gdnative/dictionary.h +++ b/modules/gdnative/include/gdnative/dictionary.h @@ -45,10 +45,19 @@ typedef struct { } godot_dictionary; #endif +// reduce extern "C" nesting for VS2013 +#ifdef __cplusplus +} +#endif + #include <gdnative/array.h> #include <gdnative/gdnative.h> #include <gdnative/variant.h> +#ifdef __cplusplus +extern "C" { +#endif + void GDAPI godot_dictionary_new(godot_dictionary *r_dest); void GDAPI godot_dictionary_new_copy(godot_dictionary *r_dest, const godot_dictionary *p_src); void GDAPI godot_dictionary_destroy(godot_dictionary *p_self); diff --git a/modules/gdnative/include/gdnative/node_path.h b/modules/gdnative/include/gdnative/node_path.h index 0cfdbc1127..42446175d8 100644 --- a/modules/gdnative/include/gdnative/node_path.h +++ b/modules/gdnative/include/gdnative/node_path.h @@ -45,9 +45,18 @@ typedef struct { } godot_node_path; #endif +// reduce extern "C" nesting for VS2013 +#ifdef __cplusplus +} +#endif + #include <gdnative/gdnative.h> #include <gdnative/string.h> +#ifdef __cplusplus +extern "C" { +#endif + void GDAPI godot_node_path_new(godot_node_path *r_dest, const godot_string *p_from); void GDAPI godot_node_path_new_copy(godot_node_path *r_dest, const godot_node_path *p_src); void GDAPI godot_node_path_destroy(godot_node_path *p_self); diff --git a/modules/gdnative/include/gdnative/plane.h b/modules/gdnative/include/gdnative/plane.h index 6a8915e08b..dddd172122 100644 --- a/modules/gdnative/include/gdnative/plane.h +++ b/modules/gdnative/include/gdnative/plane.h @@ -45,9 +45,18 @@ typedef struct { } godot_plane; #endif +// reduce extern "C" nesting for VS2013 +#ifdef __cplusplus +} +#endif + #include <gdnative/gdnative.h> #include <gdnative/vector3.h> +#ifdef __cplusplus +extern "C" { +#endif + void GDAPI godot_plane_new_with_reals(godot_plane *r_dest, const godot_real p_a, const godot_real p_b, const godot_real p_c, const godot_real p_d); void GDAPI godot_plane_new_with_vectors(godot_plane *r_dest, const godot_vector3 *p_v1, const godot_vector3 *p_v2, const godot_vector3 *p_v3); void GDAPI godot_plane_new_with_normal(godot_plane *r_dest, const godot_vector3 *p_normal, const godot_real p_d); diff --git a/modules/gdnative/include/gdnative/pool_arrays.h b/modules/gdnative/include/gdnative/pool_arrays.h index cb1095ee8c..93181f2a6b 100644 --- a/modules/gdnative/include/gdnative/pool_arrays.h +++ b/modules/gdnative/include/gdnative/pool_arrays.h @@ -113,6 +113,11 @@ typedef struct { } godot_pool_color_array; #endif +// reduce extern "C" nesting for VS2013 +#ifdef __cplusplus +} +#endif + #include <gdnative/array.h> #include <gdnative/color.h> #include <gdnative/vector2.h> @@ -120,6 +125,10 @@ typedef struct { #include <gdnative/gdnative.h> +#ifdef __cplusplus +extern "C" { +#endif + // byte void GDAPI godot_pool_byte_array_new(godot_pool_byte_array *r_dest); diff --git a/modules/gdnative/include/gdnative/quat.h b/modules/gdnative/include/gdnative/quat.h index 4ffb96eb26..acae6e3e90 100644 --- a/modules/gdnative/include/gdnative/quat.h +++ b/modules/gdnative/include/gdnative/quat.h @@ -45,9 +45,18 @@ typedef struct { } godot_quat; #endif +// reduce extern "C" nesting for VS2013 +#ifdef __cplusplus +} +#endif + #include <gdnative/gdnative.h> #include <gdnative/vector3.h> +#ifdef __cplusplus +extern "C" { +#endif + void GDAPI godot_quat_new(godot_quat *r_dest, const godot_real p_x, const godot_real p_y, const godot_real p_z, const godot_real p_w); void GDAPI godot_quat_new_with_axis_angle(godot_quat *r_dest, const godot_vector3 *p_axis, const godot_real p_angle); diff --git a/modules/gdnative/include/gdnative/rect2.h b/modules/gdnative/include/gdnative/rect2.h index 9e6cf60342..1c66443d4f 100644 --- a/modules/gdnative/include/gdnative/rect2.h +++ b/modules/gdnative/include/gdnative/rect2.h @@ -43,9 +43,18 @@ typedef struct godot_rect2 { } godot_rect2; #endif +// reduce extern "C" nesting for VS2013 +#ifdef __cplusplus +} +#endif + #include <gdnative/gdnative.h> #include <gdnative/vector2.h> +#ifdef __cplusplus +extern "C" { +#endif + void GDAPI godot_rect2_new_with_position_and_size(godot_rect2 *r_dest, const godot_vector2 *p_pos, const godot_vector2 *p_size); void GDAPI godot_rect2_new(godot_rect2 *r_dest, const godot_real p_x, const godot_real p_y, const godot_real p_width, const godot_real p_height); diff --git a/modules/gdnative/include/gdnative/rect3.h b/modules/gdnative/include/gdnative/rect3.h index f94b6fea25..f603a9268a 100644 --- a/modules/gdnative/include/gdnative/rect3.h +++ b/modules/gdnative/include/gdnative/rect3.h @@ -45,10 +45,19 @@ typedef struct { } godot_rect3; #endif +// reduce extern "C" nesting for VS2013 +#ifdef __cplusplus +} +#endif + #include <gdnative/gdnative.h> #include <gdnative/plane.h> #include <gdnative/vector3.h> +#ifdef __cplusplus +extern "C" { +#endif + void GDAPI godot_rect3_new(godot_rect3 *r_dest, const godot_vector3 *p_pos, const godot_vector3 *p_size); godot_vector3 GDAPI godot_rect3_get_position(const godot_rect3 *p_self); diff --git a/modules/gdnative/include/gdnative/rid.h b/modules/gdnative/include/gdnative/rid.h index d9b5336fc9..caa1bb967e 100644 --- a/modules/gdnative/include/gdnative/rid.h +++ b/modules/gdnative/include/gdnative/rid.h @@ -45,8 +45,17 @@ typedef struct { } godot_rid; #endif +// reduce extern "C" nesting for VS2013 +#ifdef __cplusplus +} +#endif + #include <gdnative/gdnative.h> +#ifdef __cplusplus +extern "C" { +#endif + void GDAPI godot_rid_new(godot_rid *r_dest); godot_int GDAPI godot_rid_get_id(const godot_rid *p_self); diff --git a/modules/gdnative/include/gdnative/string.h b/modules/gdnative/include/gdnative/string.h index aca23a81d8..f30fdb8dc7 100644 --- a/modules/gdnative/include/gdnative/string.h +++ b/modules/gdnative/include/gdnative/string.h @@ -46,9 +46,18 @@ typedef struct { } godot_string; #endif +// reduce extern "C" nesting for VS2013 +#ifdef __cplusplus +} +#endif + #include <gdnative/gdnative.h> #include <gdnative/variant.h> +#ifdef __cplusplus +extern "C" { +#endif + void GDAPI godot_string_new(godot_string *r_dest); void GDAPI godot_string_new_copy(godot_string *r_dest, const godot_string *p_src); void GDAPI godot_string_new_data(godot_string *r_dest, const char *p_contents, const int p_size); diff --git a/modules/gdnative/include/gdnative/string_name.h b/modules/gdnative/include/gdnative/string_name.h index e217487250..ee9f603d20 100644 --- a/modules/gdnative/include/gdnative/string_name.h +++ b/modules/gdnative/include/gdnative/string_name.h @@ -46,8 +46,17 @@ typedef struct { } godot_string_name; #endif +// reduce extern "C" nesting for VS2013 +#ifdef __cplusplus +} +#endif + #include <gdnative/gdnative.h> +#ifdef __cplusplus +extern "C" { +#endif + void GDAPI godot_string_name_new(godot_string_name *r_dest, const godot_string *p_name); void GDAPI godot_string_name_new_data(godot_string_name *r_dest, const char *p_name); diff --git a/modules/gdnative/include/gdnative/transform.h b/modules/gdnative/include/gdnative/transform.h index 656afae129..8f50b01fb5 100644 --- a/modules/gdnative/include/gdnative/transform.h +++ b/modules/gdnative/include/gdnative/transform.h @@ -45,11 +45,20 @@ typedef struct { } godot_transform; #endif +// reduce extern "C" nesting for VS2013 +#ifdef __cplusplus +} +#endif + #include <gdnative/basis.h> #include <gdnative/gdnative.h> #include <gdnative/variant.h> #include <gdnative/vector3.h> +#ifdef __cplusplus +extern "C" { +#endif + void GDAPI godot_transform_new_with_axis_origin(godot_transform *r_dest, const godot_vector3 *p_x_axis, const godot_vector3 *p_y_axis, const godot_vector3 *p_z_axis, const godot_vector3 *p_origin); void GDAPI godot_transform_new(godot_transform *r_dest, const godot_basis *p_basis, const godot_vector3 *p_origin); diff --git a/modules/gdnative/include/gdnative/transform2d.h b/modules/gdnative/include/gdnative/transform2d.h index a945868b17..c68bd2963f 100644 --- a/modules/gdnative/include/gdnative/transform2d.h +++ b/modules/gdnative/include/gdnative/transform2d.h @@ -45,10 +45,19 @@ typedef struct { } godot_transform2d; #endif +// reduce extern "C" nesting for VS2013 +#ifdef __cplusplus +} +#endif + #include <gdnative/gdnative.h> #include <gdnative/variant.h> #include <gdnative/vector2.h> +#ifdef __cplusplus +extern "C" { +#endif + void GDAPI godot_transform2d_new(godot_transform2d *r_dest, const godot_real p_rot, const godot_vector2 *p_pos); void GDAPI godot_transform2d_new_axis_origin(godot_transform2d *r_dest, const godot_vector2 *p_x_axis, const godot_vector2 *p_y_axis, const godot_vector2 *p_origin); diff --git a/modules/gdnative/include/gdnative/variant.h b/modules/gdnative/include/gdnative/variant.h index 7b804c1eaf..3d744ef1f2 100644 --- a/modules/gdnative/include/gdnative/variant.h +++ b/modules/gdnative/include/gdnative/variant.h @@ -99,6 +99,11 @@ typedef struct godot_variant_call_error { godot_variant_type expected; } godot_variant_call_error; +// reduce extern "C" nesting for VS2013 +#ifdef __cplusplus +} +#endif + #include <gdnative/array.h> #include <gdnative/basis.h> #include <gdnative/color.h> @@ -119,6 +124,10 @@ typedef struct godot_variant_call_error { #include <gdnative/gdnative.h> +#ifdef __cplusplus +extern "C" { +#endif + godot_variant_type GDAPI godot_variant_get_type(const godot_variant *p_v); void GDAPI godot_variant_new_copy(godot_variant *r_dest, const godot_variant *p_src); diff --git a/modules/gdnative/include/gdnative/vector2.h b/modules/gdnative/include/gdnative/vector2.h index 0af4abae27..07105abaf2 100644 --- a/modules/gdnative/include/gdnative/vector2.h +++ b/modules/gdnative/include/gdnative/vector2.h @@ -45,8 +45,17 @@ typedef struct { } godot_vector2; #endif +// reduce extern "C" nesting for VS2013 +#ifdef __cplusplus +} +#endif + #include <gdnative/gdnative.h> +#ifdef __cplusplus +extern "C" { +#endif + void GDAPI godot_vector2_new(godot_vector2 *r_dest, const godot_real p_x, const godot_real p_y); godot_string GDAPI godot_vector2_as_string(const godot_vector2 *p_self); diff --git a/modules/gdnative/include/gdnative/vector3.h b/modules/gdnative/include/gdnative/vector3.h index a27d516ec5..3ed23778ec 100644 --- a/modules/gdnative/include/gdnative/vector3.h +++ b/modules/gdnative/include/gdnative/vector3.h @@ -45,9 +45,18 @@ typedef struct { } godot_vector3; #endif +// reduce extern "C" nesting for VS2013 +#ifdef __cplusplus +} +#endif + #include <gdnative/basis.h> #include <gdnative/gdnative.h> +#ifdef __cplusplus +extern "C" { +#endif + typedef enum { GODOT_VECTOR3_AXIS_X, GODOT_VECTOR3_AXIS_Y, diff --git a/modules/gdnative/include/nativearvr/godot_nativearvr.h b/modules/gdnative/include/nativearvr/godot_nativearvr.h index ee557843c6..1a8970d396 100644 --- a/modules/gdnative/include/nativearvr/godot_nativearvr.h +++ b/modules/gdnative/include/nativearvr/godot_nativearvr.h @@ -54,7 +54,7 @@ typedef struct { void (*process)(void *); } godot_arvr_interface_gdnative; -void GDAPI godot_arvr_register_interface(const char *p_name, const godot_arvr_interface_gdnative *p_interface); +void GDAPI godot_arvr_register_interface(const godot_arvr_interface_gdnative *p_interface); // helper functions to access ARVRServer data godot_real GDAPI godot_arvr_get_worldscale(); diff --git a/modules/gdnative/include/pluginscript/godot_pluginscript.h b/modules/gdnative/include/pluginscript/godot_pluginscript.h new file mode 100644 index 0000000000..ec109bac83 --- /dev/null +++ b/modules/gdnative/include/pluginscript/godot_pluginscript.h @@ -0,0 +1,170 @@ +/*************************************************************************/ +/* godot_nativescript.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ +#ifndef GODOT_PLUGINSCRIPT_H +#define GODOT_PLUGINSCRIPT_H + +#include <gdnative/gdnative.h> +#include <nativescript/godot_nativescript.h> + +#ifdef __cplusplus +extern "C" { +#endif + +typedef void godot_pluginscript_instance_data; +typedef void godot_pluginscript_script_data; +typedef void godot_pluginscript_language_data; + +// --- Instance --- + +// TODO: use godot_string_name for faster lookup ? +typedef struct { + godot_pluginscript_instance_data *(*init)(godot_pluginscript_script_data *p_data, godot_object *p_owner); + void (*finish)(godot_pluginscript_instance_data *p_data); + + godot_bool (*set_prop)(godot_pluginscript_instance_data *p_data, const godot_string *p_name, const godot_variant *p_value); + godot_bool (*get_prop)(godot_pluginscript_instance_data *p_data, const godot_string *p_name, godot_variant *r_ret); + + godot_variant (*call_method)(godot_pluginscript_instance_data *p_data, + const godot_string_name *p_method, const godot_variant **p_args, + int p_argcount, godot_variant_call_error *r_error); + + void (*notification)(godot_pluginscript_instance_data *p_data, int p_notification); + // TODO: could this rpc mode stuff be moved to the godot_pluginscript_script_manifest ? + godot_method_rpc_mode (*get_rpc_mode)(godot_pluginscript_instance_data *p_data, const godot_string *p_method); + godot_method_rpc_mode (*get_rset_mode)(godot_pluginscript_instance_data *p_data, const godot_string *p_variable); + + //this is used by script languages that keep a reference counter of their own + //you can make make Ref<> not die when it reaches zero, so deleting the reference + //depends entirely from the script. + // Note: You can set thoses function pointer to NULL if not needed. + void (*refcount_incremented)(godot_pluginscript_instance_data *p_data); + bool (*refcount_decremented)(godot_pluginscript_instance_data *p_data); // return true if it can die +} godot_pluginscript_instance_desc; + +// --- Script --- + +typedef struct { + godot_pluginscript_script_data *data; + godot_string_name name; + godot_bool is_tool; + godot_string_name base; + + // Member lines format: {<string>: <int>} + godot_dictionary member_lines; + // Method info dictionary format + // { + // name: <string> + // args: [<dict:property>] + // default_args: [<variant>] + // return: <dict:property> + // flags: <int> + // rpc_mode: <int:godot_method_rpc_mode> + // } + godot_array methods; + // Same format than for methods + godot_array signals; + // Property info dictionary format + // { + // name: <string> + // type: <int:godot_variant_type> + // hint: <int:godot_property_hint> + // hint_string: <string> + // usage: <int:godot_property_usage_flags> + // default_value: <variant> + // rset_mode: <int:godot_method_rpc_mode> + // } + godot_array properties; +} godot_pluginscript_script_manifest; + +typedef struct { + godot_pluginscript_script_manifest (*init)(godot_pluginscript_language_data *p_data, const godot_string *p_path, const godot_string *p_source, godot_error *r_error); + void (*finish)(godot_pluginscript_script_data *p_data); + godot_pluginscript_instance_desc instance_desc; +} godot_pluginscript_script_desc; + +// --- Language --- + +typedef struct { + godot_string_name signature; + godot_int call_count; + godot_int total_time; // In microseconds + godot_int self_time; // In microseconds +} godot_pluginscript_profiling_data; + +typedef struct { + const char *name; + const char *type; + const char *extension; + const char **recognized_extensions; // NULL terminated array + godot_pluginscript_language_data *(*init)(); + void (*finish)(godot_pluginscript_language_data *p_data); + const char **reserved_words; // NULL terminated array + const char **comment_delimiters; // NULL terminated array + const char **string_delimiters; // NULL terminated array + godot_bool has_named_classes; + + godot_string (*get_template_source_code)(godot_pluginscript_language_data *p_data, const godot_string *p_class_name, const godot_string *p_base_class_name); + godot_bool (*validate)(godot_pluginscript_language_data *p_data, const godot_string *p_script, int *r_line_error, int *r_col_error, godot_string *r_test_error, const godot_string *p_path, godot_pool_string_array *r_functions); + int (*find_function)(godot_pluginscript_language_data *p_data, const godot_string *p_function, const godot_string *p_code); // Can be NULL + godot_string (*make_function)(godot_pluginscript_language_data *p_data, const godot_string *p_class, const godot_string *p_name, const godot_pool_string_array *p_args); + godot_error (*complete_code)(godot_pluginscript_language_data *p_data, const godot_string *p_code, const godot_string *p_base_path, godot_object *p_owner, godot_array *r_options, godot_bool *r_force, godot_string *r_call_hint); + void (*auto_indent_code)(godot_pluginscript_language_data *p_data, godot_string *p_code, int p_from_line, int p_to_line); + + void (*add_global_constant)(godot_pluginscript_language_data *p_data, const godot_string *p_variable, const godot_variant *p_value); + godot_string (*debug_get_error)(godot_pluginscript_language_data *p_data); + int (*debug_get_stack_level_count)(godot_pluginscript_language_data *p_data); + int (*debug_get_stack_level_line)(godot_pluginscript_language_data *p_data, int p_level); + godot_string (*debug_get_stack_level_function)(godot_pluginscript_language_data *p_data, int p_level); + godot_string (*debug_get_stack_level_source)(godot_pluginscript_language_data *p_data, int p_level); + void (*debug_get_stack_level_locals)(godot_pluginscript_language_data *p_data, int p_level, godot_pool_string_array *p_locals, godot_array *p_values, int p_max_subitems, int p_max_depth); + void (*debug_get_stack_level_members)(godot_pluginscript_language_data *p_data, int p_level, godot_pool_string_array *p_members, godot_array *p_values, int p_max_subitems, int p_max_depth); + void (*debug_get_globals)(godot_pluginscript_language_data *p_data, godot_pool_string_array *p_locals, godot_array *p_values, int p_max_subitems, int p_max_depth); + godot_string (*debug_parse_stack_level_expression)(godot_pluginscript_language_data *p_data, int p_level, const godot_string *p_expression, int p_max_subitems, int p_max_depth); + + // TODO: could this stuff be moved to the godot_pluginscript_language_desc ? + void (*get_public_functions)(godot_pluginscript_language_data *p_data, godot_array *r_functions); + void (*get_public_constants)(godot_pluginscript_language_data *p_data, godot_dictionary *r_constants); + + void (*profiling_start)(godot_pluginscript_language_data *p_data); + void (*profiling_stop)(godot_pluginscript_language_data *p_data); + int (*profiling_get_accumulated_data)(godot_pluginscript_language_data *p_data, godot_pluginscript_profiling_data *r_info, int p_info_max); + int (*profiling_get_frame_data)(godot_pluginscript_language_data *p_data, godot_pluginscript_profiling_data *r_info, int p_info_max); + void (*profiling_frame)(godot_pluginscript_language_data *p_data); + + godot_pluginscript_script_desc script_desc; +} godot_pluginscript_language_desc; + +void GDAPI godot_pluginscript_register_language(const godot_pluginscript_language_desc *language_desc); + +#ifdef __cplusplus +} +#endif + +#endif // GODOT_PLUGINSCRIPT_H diff --git a/modules/gdnative/nativearvr/arvr_interface_gdnative.cpp b/modules/gdnative/nativearvr/arvr_interface_gdnative.cpp index 2f60339afa..ff8bda162f 100644 --- a/modules/gdnative/nativearvr/arvr_interface_gdnative.cpp +++ b/modules/gdnative/nativearvr/arvr_interface_gdnative.cpp @@ -33,10 +33,6 @@ #include "servers/arvr/arvr_positional_tracker.h" #include "servers/visual/visual_server_global.h" -#include "oa_hash_map.h" - -extern OAHashMap<StringName, godot_arvr_interface_gdnative *> *_registered_interfaces; - ARVRInterfaceGDNative::ARVRInterfaceGDNative() { // testing printf("Construct gdnative interface\n"); @@ -66,23 +62,16 @@ void ARVRInterfaceGDNative::cleanup() { } } -void ARVRInterfaceGDNative::set_interface(StringName p_name) { - - godot_arvr_interface_gdnative *new_interface; - - if (!_registered_interfaces->lookup(p_name, &new_interface)) { - ERR_PRINT((String("ARVR interface \"") + p_name + "\" does not exist.").utf8().get_data()); - return; - } - +void ARVRInterfaceGDNative::set_interface(const godot_arvr_interface_gdnative *p_interface) { + // this should only be called once, just being paranoid.. if (interface) { cleanup(); } - interface = new_interface; + // bind to our interface + interface = p_interface; // Now we do our constructing... - data = interface->constructor((godot_object *)this); } @@ -222,20 +211,16 @@ void ARVRInterfaceGDNative::process() { interface->process(data); } -void ARVRInterfaceGDNative::_bind_methods() { - ClassDB::bind_method(D_METHOD("set_interface", "name"), &ARVRInterfaceGDNative::set_interface); -} - ///////////////////////////////////////////////////////////////////////////////////// // some helper callbacks extern "C" { -void GDAPI godot_arvr_register_interface(const char *p_name, const godot_arvr_interface_gdnative *p_interface) { - // this method is supposed to only be called by GDNative singletons - // which are initialized in a thread safe way, so using a global map is fine here - - _registered_interfaces->set(StringName(p_name), (godot_arvr_interface_gdnative * const)p_interface); +void GDAPI godot_arvr_register_interface(const godot_arvr_interface_gdnative *p_interface) { + Ref<ARVRInterfaceGDNative> new_interface; + new_interface.instance(); + new_interface->set_interface((godot_arvr_interface_gdnative * const)p_interface); + ARVRServer::get_singleton()->add_interface(new_interface); } godot_real GDAPI godot_arvr_get_worldscale() { diff --git a/modules/gdnative/nativearvr/arvr_interface_gdnative.h b/modules/gdnative/nativearvr/arvr_interface_gdnative.h index 04730571b7..e45b51e070 100644 --- a/modules/gdnative/nativearvr/arvr_interface_gdnative.h +++ b/modules/gdnative/nativearvr/arvr_interface_gdnative.h @@ -46,17 +46,15 @@ class ARVRInterfaceGDNative : public ARVRInterface { void cleanup(); protected: - godot_arvr_interface_gdnative *interface; + const godot_arvr_interface_gdnative *interface; void *data; - static void _bind_methods(); - public: /** general interface information **/ ARVRInterfaceGDNative(); ~ARVRInterfaceGDNative(); - void set_interface(StringName p_name); + void set_interface(const godot_arvr_interface_gdnative *p_interface); virtual StringName get_name() const; virtual int get_capabilities() const; diff --git a/modules/gdnative/nativearvr/register_types.cpp b/modules/gdnative/nativearvr/register_types.cpp index 09debe2550..c7d7847a21 100644 --- a/modules/gdnative/nativearvr/register_types.cpp +++ b/modules/gdnative/nativearvr/register_types.cpp @@ -29,29 +29,11 @@ /*************************************************************************/ #include "register_types.h" - #include "arvr_interface_gdnative.h" -#include "core/os/os.h" - -#include "oa_hash_map.h" -#include "ustring.h" - -// what is this?? I can't memnew(OAHashMap<String, godot_arvr_interface_gdnative *>) -// but with this typedef it's working just fine... -// C++ grammar can be a joy. -typedef OAHashMap<StringName, godot_arvr_interface_gdnative *> InterfaceMap; - -InterfaceMap *_registered_interfaces; void register_nativearvr_types() { - - _registered_interfaces = memnew(InterfaceMap); - ClassDB::register_class<ARVRInterfaceGDNative>(); } void unregister_nativearvr_types() { - memdelete(_registered_interfaces); - - _registered_interfaces = NULL; } diff --git a/modules/gdnative/nativescript/SCsub b/modules/gdnative/nativescript/SCsub index 178afec64a..ee3b9c351d 100644 --- a/modules/gdnative/nativescript/SCsub +++ b/modules/gdnative/nativescript/SCsub @@ -4,7 +4,6 @@ Import('env') mod_env = env.Clone() mod_env.add_source_files(env.modules_sources, "*.cpp") -mod_env.Append(CPPPATH='#modules/gdnative') mod_env.Append(CPPFLAGS=['-DGDAPI_BUILT_IN']) if "platform" in env and env["platform"] in ["x11", "iphone"]: diff --git a/modules/gdnative/nativescript/api_generator.cpp b/modules/gdnative/nativescript/api_generator.cpp index 9a956ff594..63fb71feb6 100644 --- a/modules/gdnative/nativescript/api_generator.cpp +++ b/modules/gdnative/nativescript/api_generator.cpp @@ -31,7 +31,7 @@ #ifdef TOOLS_ENABLED -#include "class_db.h" +#include "core/class_db.h" #include "core/global_constants.h" #include "core/pair.h" #include "core/project_settings.h" diff --git a/modules/gdnative/nativescript/api_generator.h b/modules/gdnative/nativescript/api_generator.h index 56c2d786e6..a8e2eaf0bf 100644 --- a/modules/gdnative/nativescript/api_generator.h +++ b/modules/gdnative/nativescript/api_generator.h @@ -30,8 +30,8 @@ #ifndef API_GENERATOR_H #define API_GENERATOR_H +#include "core/typedefs.h" #include "core/ustring.h" -#include "typedefs.h" Error generate_c_api(const String &p_path); diff --git a/modules/gdnative/nativescript/nativescript.cpp b/modules/gdnative/nativescript/nativescript.cpp index 7e3a7c8e9e..aa1fdc32da 100644 --- a/modules/gdnative/nativescript/nativescript.cpp +++ b/modules/gdnative/nativescript/nativescript.cpp @@ -31,11 +31,11 @@ #include "gdnative/gdnative.h" -#include "global_constants.h" +#include "core/global_constants.h" +#include "core/project_settings.h" #include "io/file_access_encrypted.h" #include "os/file_access.h" #include "os/os.h" -#include "project_settings.h" #include "scene/main/scene_tree.h" #include "scene/resources/scene_format_text.h" @@ -137,7 +137,6 @@ bool NativeScript::can_instance() const { #endif } -// TODO(karroffel): implement this Ref<Script> NativeScript::get_base_script() const { NativeScriptDesc *script_data = get_script_desc(); @@ -1012,10 +1011,13 @@ void NativeScriptLanguage::init_library(const Ref<GDNativeLibrary> &lib) { void *proc_ptr; - gdn->get_symbol(_init_call_name, proc_ptr); - - ((void (*)(godot_string *))proc_ptr)((godot_string *)&lib_path); + Error err = gdn->get_symbol(_init_call_name, proc_ptr); + if (err != OK) { + ERR_PRINT(String("No " + _init_call_name + " in \"" + lib_path + "\" found").utf8().get_data()); + } else { + ((void (*)(godot_string *))proc_ptr)((godot_string *)&lib_path); + } } else { // already initialized. Nice. } @@ -1052,9 +1054,7 @@ void NativeScriptLanguage::call_libraries_cb(const StringName &name) { void *proc_ptr; Error err = L->get()->get_symbol(name, proc_ptr); - if (err != OK) { - ERR_PRINT((String("No godot_gdnative_init in \"" + L->get()->get_library()->get_active_library_path()) + "\" found").utf8().get_data()); - } else { + if (!err) { ((void (*)())proc_ptr)(); } } @@ -1141,9 +1141,12 @@ void NativeReloadNode::_notification(int p_what) { // here the library registers all the classes and stuff. void *proc_ptr; - L->get()->get_symbol("godot_nativescript_init", proc_ptr); - - ((void (*)(void *))proc_ptr)((void *)&L->key()); + Error err = L->get()->get_symbol("godot_nativescript_init", proc_ptr); + if (err != OK) { + ERR_PRINT(String("No godot_nativescript_init in \"" + L->key() + "\" found").utf8().get_data()); + } else { + ((void (*)(void *))proc_ptr)((void *)&L->key()); + } for (Map<String, Set<NativeScript *> >::Element *U = NSL->library_script_users.front(); U; U = U->next()) { for (Set<NativeScript *>::Element *S = U->get().front(); S; S = S->next()) { diff --git a/modules/gdnative/nativescript/nativescript.h b/modules/gdnative/nativescript/nativescript.h index bc7e850d3e..b5db641179 100644 --- a/modules/gdnative/nativescript/nativescript.h +++ b/modules/gdnative/nativescript/nativescript.h @@ -30,14 +30,14 @@ #ifndef NATIVE_SCRIPT_H #define NATIVE_SCRIPT_H +#include "core/resource.h" +#include "core/script_language.h" +#include "core/self_list.h" #include "io/resource_loader.h" #include "io/resource_saver.h" #include "ordered_hash_map.h" #include "os/thread_safe.h" -#include "resource.h" #include "scene/main/node.h" -#include "script_language.h" -#include "self_list.h" #include "modules/gdnative/gdnative.h" #include <nativescript/godot_nativescript.h> diff --git a/modules/gdnative/pluginscript/SCsub b/modules/gdnative/pluginscript/SCsub new file mode 100644 index 0000000000..2031a4236b --- /dev/null +++ b/modules/gdnative/pluginscript/SCsub @@ -0,0 +1,9 @@ +#!/usr/bin/env python + +Import('env') +Import('env_modules') + +env_pluginscript = env_modules.Clone() + +env_pluginscript.Append(CPPPATH=['#modules/gdnative/include/']) +env_pluginscript.add_source_files(env.modules_sources, '*.cpp') diff --git a/modules/gdnative/pluginscript/pluginscript_instance.cpp b/modules/gdnative/pluginscript/pluginscript_instance.cpp new file mode 100644 index 0000000000..8f01350826 --- /dev/null +++ b/modules/gdnative/pluginscript/pluginscript_instance.cpp @@ -0,0 +1,181 @@ +/*************************************************************************/ +/* pluginscript_instance.cpp */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* http://www.godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +// Godot imports +#include "core/os/os.h" +#include "core/variant.h" +// PluginScript imports +#include "pluginscript_instance.h" +#include "pluginscript_language.h" +#include "pluginscript_script.h" + +bool PluginScriptInstance::set(const StringName &p_name, const Variant &p_value) { + String name = String(p_name); + return _desc->set_prop(_data, (const godot_string *)&name, (const godot_variant *)&p_value); +} + +bool PluginScriptInstance::get(const StringName &p_name, Variant &r_ret) const { + String name = String(p_name); + return _desc->get_prop(_data, (const godot_string *)&name, (godot_variant *)&r_ret); +} + +Ref<Script> PluginScriptInstance::get_script() const { + return _script; +} + +ScriptLanguage *PluginScriptInstance::get_language() { + return _script->get_language(); +} + +Variant::Type PluginScriptInstance::get_property_type(const StringName &p_name, bool *r_is_valid) const { + if (!_script->has_property(p_name)) { + if (r_is_valid) { + *r_is_valid = false; + } + return Variant::NIL; + } + if (r_is_valid) { + *r_is_valid = true; + } + return _script->get_property_info(p_name).type; +} + +void PluginScriptInstance::get_property_list(List<PropertyInfo> *p_properties) const { + _script->get_script_property_list(p_properties); +} + +void PluginScriptInstance::get_method_list(List<MethodInfo> *p_list) const { + _script->get_script_method_list(p_list); +} + +bool PluginScriptInstance::has_method(const StringName &p_method) const { + return _script->has_method(p_method); +} + +Variant PluginScriptInstance::call(const StringName &p_method, const Variant **p_args, int p_argcount, Variant::CallError &r_error) { + // TODO: optimize when calling a Godot method from Godot to avoid param conversion ? + godot_variant ret = _desc->call_method( + _data, (godot_string_name *)&p_method, (const godot_variant **)p_args, + p_argcount, (godot_variant_call_error *)&r_error); + Variant *var_ret = (Variant *)&ret; + return *var_ret; +} + +#if 0 // TODO: Don't rely on default implementations provided by ScriptInstance ? +void PluginScriptInstance::call_multilevel(const StringName& p_method,const Variant** p_args,int p_argcount) { + +#if 0 + PluginScript *sptr=script.ptr(); + Variant::CallError ce; + + while(sptr) { + Map<StringName,GDFunction*>::Element *E = sptr->member_functions.find(p_method); + if (E) { + E->get()->call(this,p_args,p_argcount,ce); + } + sptr = sptr->_base; + } +#endif + +} + +#if 0 +void PluginScriptInstance::_ml_call_reversed(PluginScript *sptr,const StringName& p_method,const Variant** p_args,int p_argcount) { + + if (sptr->_base) + _ml_call_reversed(sptr->_base,p_method,p_args,p_argcount); + + Variant::CallError ce; + + Map<StringName,GDFunction*>::Element *E = sptr->member_functions.find(p_method); + if (E) { + E->get()->call(this,p_args,p_argcount,ce); + } + +} +#endif + + +void PluginScriptInstance::call_multilevel_reversed(const StringName& p_method,const Variant** p_args,int p_argcount) { + +#if 0 + if (script.ptr()) { + _ml_call_reversed(script.ptr(),p_method,p_args,p_argcount); + } +#endif +} +#endif // Multilevel stuff + +void PluginScriptInstance::notification(int p_notification) { + _desc->notification(_data, p_notification); +} + +ScriptInstance::RPCMode PluginScriptInstance::get_rpc_mode(const StringName &p_method) const { + return _script->get_rpc_mode(p_method); +} + +ScriptInstance::RPCMode PluginScriptInstance::get_rset_mode(const StringName &p_variable) const { + return _script->get_rset_mode(p_variable); +} + +void PluginScriptInstance::refcount_incremented() { + if (_desc->refcount_decremented) { + _desc->refcount_incremented(_data); + } +} + +bool PluginScriptInstance::refcount_decremented() { + // Return true if it can die + if (_desc->refcount_decremented) { + return _desc->refcount_decremented(_data); + } + return true; +} + +PluginScriptInstance::PluginScriptInstance() { +} + +bool PluginScriptInstance::init(PluginScript *p_script, Object *p_owner) { + _owner = p_owner; + _owner_variant = Variant(p_owner); + _script = Ref<PluginScript>(p_script); + _desc = &p_script->_desc->instance_desc; + _data = _desc->init(p_script->_data, (godot_object *)p_owner); + ERR_FAIL_COND_V(_data == NULL, false); + p_owner->set_script_instance(this); + return true; +} + +PluginScriptInstance::~PluginScriptInstance() { + _desc->finish(_data); + _script->_language->lock(); + _script->_instances.erase(_owner); + _script->_language->unlock(); +} diff --git a/modules/gdnative/pluginscript/pluginscript_instance.h b/modules/gdnative/pluginscript/pluginscript_instance.h new file mode 100644 index 0000000000..68696b4417 --- /dev/null +++ b/modules/gdnative/pluginscript/pluginscript_instance.h @@ -0,0 +1,90 @@ +/*************************************************************************/ +/* pluginscript_instance.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* http://www.godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#ifndef PLUGINSCRIPT_INSTANCE_H +#define PLUGINSCRIPT_INSTANCE_H + +// Godot imports +#include "core/script_language.h" +// PluginScript imports +#include <pluginscript/godot_pluginscript.h> + +class PluginScript; + +class PluginScriptInstance : public ScriptInstance { + friend class PluginScript; + +private: + Ref<PluginScript> _script; + Object *_owner; + Variant _owner_variant; + godot_pluginscript_instance_data *_data; + const godot_pluginscript_instance_desc *_desc; + +public: + _FORCE_INLINE_ Object *get_owner() { return _owner; } + + virtual bool set(const StringName &p_name, const Variant &p_value); + virtual bool get(const StringName &p_name, Variant &r_ret) const; + virtual void get_property_list(List<PropertyInfo> *p_properties) const; + virtual Variant::Type get_property_type(const StringName &p_name, bool *r_is_valid = NULL) const; + + virtual void get_method_list(List<MethodInfo> *p_list) const; + virtual bool has_method(const StringName &p_method) const; + + virtual Variant call(const StringName &p_method, const Variant **p_args, int p_argcount, Variant::CallError &r_error); +#if 0 + // Rely on default implementations provided by ScriptInstance for the moment. + // Note that multilevel call could be removed in 3.0 release, so stay tunned + // (see https://godotengine.org/qa/9244/can-override-the-_ready-and-_process-functions-child-classes) + virtual void call_multilevel(const StringName& p_method,const Variant** p_args,int p_argcount); + virtual void call_multilevel_reversed(const StringName& p_method,const Variant** p_args,int p_argcount); +#endif + + virtual void notification(int p_notification); + + virtual Ref<Script> get_script() const; + + virtual ScriptLanguage *get_language(); + + void set_path(const String &p_path); + + virtual RPCMode get_rpc_mode(const StringName &p_method) const; + virtual RPCMode get_rset_mode(const StringName &p_variable) const; + + virtual void refcount_incremented(); + virtual bool refcount_decremented(); + + PluginScriptInstance(); + bool init(PluginScript *p_script, Object *p_owner); + virtual ~PluginScriptInstance(); +}; + +#endif // PLUGINSCRIPT_INSTANCE_H diff --git a/modules/gdnative/pluginscript/pluginscript_language.cpp b/modules/gdnative/pluginscript/pluginscript_language.cpp new file mode 100644 index 0000000000..d4b86ae5b4 --- /dev/null +++ b/modules/gdnative/pluginscript/pluginscript_language.cpp @@ -0,0 +1,431 @@ +/*************************************************************************/ +/* pluginscript_language.cpp */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* http://www.godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +// Godot imports +#include "core/os/file_access.h" +#include "core/os/os.h" +#include "core/project_settings.h" +// PluginScript imports +#include "pluginscript_language.h" +#include "pluginscript_script.h" + +String PluginScriptLanguage::get_name() const { + return String(_desc.name); +} + +void PluginScriptLanguage::init() { + _data = _desc.init(); +} + +String PluginScriptLanguage::get_type() const { + return String(_desc.type); +} + +String PluginScriptLanguage::get_extension() const { + return String(_desc.extension); +} + +Error PluginScriptLanguage::execute_file(const String &p_path) { + // TODO: pretty sure this method is totally deprecated and should be removed... + return OK; +} + +void PluginScriptLanguage::finish() { + _desc.finish(_data); +} + +/* EDITOR FUNCTIONS */ + +void PluginScriptLanguage::get_reserved_words(List<String> *p_words) const { + if (_desc.reserved_words) { + const char **w = _desc.reserved_words; + while (*w) { + p_words->push_back(*w); + w++; + } + } +} + +void PluginScriptLanguage::get_comment_delimiters(List<String> *p_delimiters) const { + if (_desc.comment_delimiters) { + const char **w = _desc.comment_delimiters; + while (*w) { + p_delimiters->push_back(*w); + w++; + } + } +} + +void PluginScriptLanguage::get_string_delimiters(List<String> *p_delimiters) const { + if (_desc.string_delimiters) { + const char **w = _desc.string_delimiters; + while (*w) { + p_delimiters->push_back(*w); + w++; + } + } +} + +Ref<Script> PluginScriptLanguage::get_template(const String &p_class_name, const String &p_base_class_name) const { + Script *ns = create_script(); + Ref<Script> script = Ref<Script>(ns); + if (_desc.get_template_source_code) { + godot_string src = _desc.get_template_source_code(_data, (godot_string *)&p_class_name, (godot_string *)&p_base_class_name); + script->set_source_code(*(String *)&src); + } + return script; +} + +bool PluginScriptLanguage::validate(const String &p_script, int &r_line_error, int &r_col_error, String &r_test_error, const String &p_path, List<String> *r_functions) const { + PoolStringArray functions; + if (_desc.validate) { + bool ret = _desc.validate( + _data, + (godot_string *)&p_script, + &r_line_error, + &r_col_error, + (godot_string *)&r_test_error, + (godot_string *)&p_path, + (godot_pool_string_array *)&functions); + for (int i = 0; i < functions.size(); i++) { + r_functions->push_back(functions[i]); + } + return ret; + } + return true; +} + +Script *PluginScriptLanguage::create_script() const { + PluginScript *script = memnew(PluginScript()); + // I'm hurting kittens doing this I guess... + script->init(const_cast<PluginScriptLanguage *>(this)); + return script; +} + +bool PluginScriptLanguage::has_named_classes() const { + return _desc.has_named_classes; +} + +int PluginScriptLanguage::find_function(const String &p_function, const String &p_code) const { + if (_desc.find_function) { + return _desc.find_function(_data, (godot_string *)&p_function, (godot_string *)&p_code); + } + return -1; +} + +String PluginScriptLanguage::make_function(const String &p_class, const String &p_name, const PoolStringArray &p_args) const { + if (_desc.make_function) { + godot_string tmp = _desc.make_function(_data, (godot_string *)&p_class, (godot_string *)&p_name, (godot_pool_string_array *)&p_args); + String ret = *(String *)&tmp; + godot_string_destroy(&tmp); + return ret; + } + return String(); +} + +Error PluginScriptLanguage::complete_code(const String &p_code, const String &p_base_path, Object *p_owner, List<String> *r_options, bool &r_force, String &r_call_hint) { + if (_desc.complete_code) { + Array options; + godot_error tmp = _desc.complete_code( + _data, + (godot_string *)&p_code, + (godot_string *)&p_base_path, + (godot_object *)p_owner, + (godot_array *)&options, + &r_force, + (godot_string *)&r_call_hint); + for (int i = 0; i < options.size(); i++) { + r_options->push_back(String(options[i])); + } + Error err = *(Error *)tmp; + return err; + } + return ERR_UNAVAILABLE; +} + +void PluginScriptLanguage::auto_indent_code(String &p_code, int p_from_line, int p_to_line) const { + if (_desc.auto_indent_code) { + _desc.auto_indent_code(_data, (godot_string *)&p_code, p_from_line, p_to_line); + } + return; +} + +void PluginScriptLanguage::add_global_constant(const StringName &p_variable, const Variant &p_value) { + const String variable = String(p_variable); + _desc.add_global_constant(_data, (godot_string *)&variable, (godot_variant *)&p_value); +} + +/* LOADER FUNCTIONS */ + +void PluginScriptLanguage::get_recognized_extensions(List<String> *p_extensions) const { + for (int i = 0; _desc.recognized_extensions[i]; ++i) { + p_extensions->push_back(String(_desc.recognized_extensions[i])); + } +} + +void PluginScriptLanguage::get_public_functions(List<MethodInfo> *p_functions) const { + // TODO: provid this statically in `godot_pluginscript_language_desc` ? + if (_desc.get_public_functions) { + Array functions; + _desc.get_public_functions(_data, (godot_array *)&functions); + for (int i = 0; i < functions.size(); i++) { + MethodInfo mi = MethodInfo::from_dict(functions[i]); + p_functions->push_back(mi); + } + } +} + +void PluginScriptLanguage::get_public_constants(List<Pair<String, Variant> > *p_constants) const { + // TODO: provid this statically in `godot_pluginscript_language_desc` ? + if (_desc.get_public_constants) { + Dictionary constants; + _desc.get_public_constants(_data, (godot_dictionary *)&constants); + for (const Variant *key = constants.next(); key; key = constants.next(key)) { + Variant value = constants[key]; + p_constants->push_back(Pair<String, Variant>(*key, value)); + } + } +} + +void PluginScriptLanguage::profiling_start() { +#ifdef DEBUG_ENABLED + if (_desc.profiling_start) { + lock(); + _desc.profiling_start(_data); + unlock(); + } +#endif +} + +void PluginScriptLanguage::profiling_stop() { +#ifdef DEBUG_ENABLED + if (_desc.profiling_stop) { + lock(); + _desc.profiling_stop(_data); + unlock(); + } +#endif +} + +int PluginScriptLanguage::profiling_get_accumulated_data(ProfilingInfo *p_info_arr, int p_info_max) { + int info_count = 0; +#ifdef DEBUG_ENABLED + if (_desc.profiling_get_accumulated_data) { + godot_pluginscript_profiling_data *info = (godot_pluginscript_profiling_data *)memalloc( + sizeof(godot_pluginscript_profiling_data) * p_info_max); + info_count = _desc.profiling_get_accumulated_data(_data, info, p_info_max); + for (int i = 0; i < info_count; ++i) { + p_info_arr[i].signature = *(StringName *)&info[i].signature; + p_info_arr[i].call_count = info[i].call_count; + p_info_arr[i].total_time = info[i].total_time; + p_info_arr[i].self_time = info[i].self_time; + godot_string_name_destroy(&info[i].signature); + } + } +#endif + return info_count; +} + +int PluginScriptLanguage::profiling_get_frame_data(ProfilingInfo *p_info_arr, int p_info_max) { + int info_count = 0; +#ifdef DEBUG_ENABLED + if (_desc.profiling_get_frame_data) { + godot_pluginscript_profiling_data *info = (godot_pluginscript_profiling_data *)memalloc( + sizeof(godot_pluginscript_profiling_data) * p_info_max); + info_count = _desc.profiling_get_frame_data(_data, info, p_info_max); + for (int i = 0; i < info_count; ++i) { + p_info_arr[i].signature = *(StringName *)&info[i].signature; + p_info_arr[i].call_count = info[i].call_count; + p_info_arr[i].total_time = info[i].total_time; + p_info_arr[i].self_time = info[i].self_time; + godot_string_name_destroy(&info[i].signature); + } + } +#endif + return info_count; +} + +void PluginScriptLanguage::frame() { +#ifdef DEBUG_ENABLED + if (_desc.profiling_frame) { + _desc.profiling_frame(_data); + } +#endif +} + +/* DEBUGGER FUNCTIONS */ + +String PluginScriptLanguage::debug_get_error() const { + if (_desc.debug_get_error) { + godot_string tmp = _desc.debug_get_error(_data); + String ret = *(String *)&tmp; + godot_string_destroy(&tmp); + return ret; + } + return String("Nothing"); +} + +int PluginScriptLanguage::debug_get_stack_level_count() const { + if (_desc.debug_get_stack_level_count) { + return _desc.debug_get_stack_level_count(_data); + } + return 1; +} + +int PluginScriptLanguage::debug_get_stack_level_line(int p_level) const { + if (_desc.debug_get_stack_level_line) { + return _desc.debug_get_stack_level_line(_data, p_level); + } + return 1; +} + +String PluginScriptLanguage::debug_get_stack_level_function(int p_level) const { + if (_desc.debug_get_stack_level_function) { + godot_string tmp = _desc.debug_get_stack_level_function(_data, p_level); + String ret = *(String *)&tmp; + godot_string_destroy(&tmp); + return ret; + } + return String("Nothing"); +} + +String PluginScriptLanguage::debug_get_stack_level_source(int p_level) const { + if (_desc.debug_get_stack_level_source) { + godot_string tmp = _desc.debug_get_stack_level_source(_data, p_level); + String ret = *(String *)&tmp; + godot_string_destroy(&tmp); + return ret; + } + return String("Nothing"); +} + +void PluginScriptLanguage::debug_get_stack_level_locals(int p_level, List<String> *p_locals, List<Variant> *p_values, int p_max_subitems, int p_max_depth) { + if (_desc.debug_get_stack_level_locals) { + PoolStringArray locals; + Array values; + _desc.debug_get_stack_level_locals(_data, p_level, (godot_pool_string_array *)&locals, (godot_array *)&values, p_max_subitems, p_max_depth); + for (int i = 0; i < locals.size(); i++) { + p_locals->push_back(locals[i]); + } + for (int i = 0; i < values.size(); i++) { + p_values->push_back(values[i]); + } + } +} + +void PluginScriptLanguage::debug_get_stack_level_members(int p_level, List<String> *p_members, List<Variant> *p_values, int p_max_subitems, int p_max_depth) { + if (_desc.debug_get_stack_level_members) { + PoolStringArray members; + Array values; + _desc.debug_get_stack_level_members(_data, p_level, (godot_pool_string_array *)&members, (godot_array *)&values, p_max_subitems, p_max_depth); + for (int i = 0; i < members.size(); i++) { + p_members->push_back(members[i]); + } + for (int i = 0; i < values.size(); i++) { + p_values->push_back(values[i]); + } + } +} + +void PluginScriptLanguage::debug_get_globals(List<String> *p_locals, List<Variant> *p_values, int p_max_subitems, int p_max_depth) { + if (_desc.debug_get_globals) { + PoolStringArray locals; + Array values; + _desc.debug_get_globals(_data, (godot_pool_string_array *)&locals, (godot_array *)&values, p_max_subitems, p_max_depth); + for (int i = 0; i < locals.size(); i++) { + p_locals->push_back(locals[i]); + } + for (int i = 0; i < values.size(); i++) { + p_values->push_back(values[i]); + } + } +} + +String PluginScriptLanguage::debug_parse_stack_level_expression(int p_level, const String &p_expression, int p_max_subitems, int p_max_depth) { + if (_desc.debug_parse_stack_level_expression) { + godot_string tmp = _desc.debug_parse_stack_level_expression(_data, p_level, (godot_string *)&p_expression, p_max_subitems, p_max_depth); + String ret = *(String *)&tmp; + godot_string_destroy(&tmp); + return ret; + } + return String("Nothing"); +} + +void PluginScriptLanguage::reload_all_scripts() { + // TODO +} + +void PluginScriptLanguage::reload_tool_script(const Ref<Script> &p_script, bool p_soft_reload) { +#ifdef DEBUG_ENABLED + lock(); + // TODO + unlock(); +#endif +} + +void PluginScriptLanguage::lock() { +#ifndef NO_THREADS + if (_lock) { + _lock->lock(); + } +#endif +} + +void PluginScriptLanguage::unlock() { +#ifndef NO_THREADS + if (_lock) { + _lock->unlock(); + } +#endif +} + +PluginScriptLanguage::PluginScriptLanguage(const godot_pluginscript_language_desc *desc) + : _desc(*desc) { + _resource_loader = memnew(ResourceFormatLoaderPluginScript(this)); + _resource_saver = memnew(ResourceFormatSaverPluginScript(this)); + +// TODO: totally remove _lock attribute if NO_THREADS is set +#ifdef NO_THREADS + _lock = NULL; +#else + _lock = Mutex::create(); +#endif +} + +PluginScriptLanguage::~PluginScriptLanguage() { + memdelete(_resource_loader); + memdelete(_resource_saver); +#ifndef NO_THREADS + if (_lock) { + memdelete(_lock); + _lock = NULL; + } +#endif +} diff --git a/modules/gdnative/pluginscript/pluginscript_language.h b/modules/gdnative/pluginscript/pluginscript_language.h new file mode 100644 index 0000000000..a48dde97ce --- /dev/null +++ b/modules/gdnative/pluginscript/pluginscript_language.h @@ -0,0 +1,131 @@ +/*************************************************************************/ +/* pluginscript_language.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* http://www.godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#ifndef PLUGINSCRIPT_LANGUAGE_H +#define PLUGINSCRIPT_LANGUAGE_H + +// Godot imports +#include "core/io/resource_loader.h" +#include "core/io/resource_saver.h" +#include "core/map.h" +#include "core/script_language.h" +#include "core/self_list.h" +// PluginScript imports +#include "pluginscript_loader.h" +#include <pluginscript/godot_pluginscript.h> + +class PluginScript; +class PluginScriptInstance; + +class PluginScriptLanguage : public ScriptLanguage { + friend class PluginScript; + friend class PluginScriptInstance; + + ResourceFormatLoaderPluginScript *_resource_loader; + ResourceFormatSaverPluginScript *_resource_saver; + const godot_pluginscript_language_desc _desc; + godot_pluginscript_language_data *_data; + + Mutex *_lock; + SelfList<PluginScript>::List _script_list; + +public: + virtual String get_name() const; + + _FORCE_INLINE_ ResourceFormatLoaderPluginScript *get_resource_loader() { return _resource_loader; }; + _FORCE_INLINE_ ResourceFormatSaverPluginScript *get_resource_saver() { return _resource_saver; }; + + /* LANGUAGE FUNCTIONS */ + virtual void init(); + virtual String get_type() const; + virtual String get_extension() const; + virtual Error execute_file(const String &p_path); + virtual void finish(); + + /* EDITOR FUNCTIONS */ + virtual void get_reserved_words(List<String> *p_words) const; + virtual void get_comment_delimiters(List<String> *p_delimiters) const; + virtual void get_string_delimiters(List<String> *p_delimiters) const; + virtual Ref<Script> get_template(const String &p_class_name, const String &p_base_class_name) const; + virtual bool validate(const String &p_script, int &r_line_error, int &r_col_error, String &r_test_error, const String &p_path = "", List<String> *r_functions = NULL) const; + virtual Script *create_script() const; + virtual bool has_named_classes() const; + virtual bool can_inherit_from_file() { return true; } + virtual int find_function(const String &p_function, const String &p_code) const; + virtual String make_function(const String &p_class, const String &p_name, const PoolStringArray &p_args) const; + virtual Error complete_code(const String &p_code, const String &p_base_path, Object *p_owner, List<String> *r_options, bool &r_force, String &r_call_hint); + virtual void auto_indent_code(String &p_code, int p_from_line, int p_to_line) const; + virtual void add_global_constant(const StringName &p_variable, const Variant &p_value); + + /* MULTITHREAD FUNCTIONS */ + + //some VMs need to be notified of thread creation/exiting to allocate a stack + // void thread_enter() {} + // void thread_exit() {} + + /* DEBUGGER FUNCTIONS */ + + virtual String debug_get_error() const; + virtual int debug_get_stack_level_count() const; + virtual int debug_get_stack_level_line(int p_level) const; + virtual String debug_get_stack_level_function(int p_level) const; + virtual String debug_get_stack_level_source(int p_level) const; + virtual void debug_get_stack_level_locals(int p_level, List<String> *p_locals, List<Variant> *p_values, int p_max_subitems = -1, int p_max_depth = -1); + virtual void debug_get_stack_level_members(int p_level, List<String> *p_members, List<Variant> *p_values, int p_max_subitems = -1, int p_max_depth = -1); + virtual void debug_get_globals(List<String> *p_locals, List<Variant> *p_values, int p_max_subitems = -1, int p_max_depth = -1); + virtual String debug_parse_stack_level_expression(int p_level, const String &p_expression, int p_max_subitems = -1, int p_max_depth = -1); + + // virtual Vector<StackInfo> debug_get_current_stack_info() { return Vector<StackInfo>(); } + + virtual void reload_all_scripts(); + virtual void reload_tool_script(const Ref<Script> &p_script, bool p_soft_reload); + + /* LOADER FUNCTIONS */ + + virtual void get_recognized_extensions(List<String> *p_extensions) const; + virtual void get_public_functions(List<MethodInfo> *p_functions) const; + virtual void get_public_constants(List<Pair<String, Variant> > *p_constants) const; + + virtual void profiling_start(); + virtual void profiling_stop(); + + virtual int profiling_get_accumulated_data(ProfilingInfo *p_info_arr, int p_info_max); + virtual int profiling_get_frame_data(ProfilingInfo *p_info_arr, int p_info_max); + + virtual void frame(); + + void lock(); + void unlock(); + + PluginScriptLanguage(const godot_pluginscript_language_desc *desc); + virtual ~PluginScriptLanguage(); +}; + +#endif // PLUGINSCRIPT_LANGUAGE_H diff --git a/modules/gdnative/pluginscript/pluginscript_loader.cpp b/modules/gdnative/pluginscript/pluginscript_loader.cpp new file mode 100644 index 0000000000..3648e1a5b4 --- /dev/null +++ b/modules/gdnative/pluginscript/pluginscript_loader.cpp @@ -0,0 +1,113 @@ +/*************************************************************************/ +/* pluginscript_loader.cpp */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* http://www.godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +// Godot imports +#include "os/file_access.h" +// Pythonscript imports +#include "pluginscript_language.h" +#include "pluginscript_loader.h" +#include "pluginscript_script.h" + +ResourceFormatLoaderPluginScript::ResourceFormatLoaderPluginScript(PluginScriptLanguage *language) { + _language = language; +} + +RES ResourceFormatLoaderPluginScript::load(const String &p_path, const String &p_original_path, Error *r_error) { + if (r_error) + *r_error = ERR_FILE_CANT_OPEN; + + PluginScript *script = memnew(PluginScript); + script->init(_language); + + Ref<PluginScript> scriptres(script); + + Error err = script->load_source_code(p_path); + ERR_FAIL_COND_V(err != OK, RES()); + + script->set_path(p_original_path); + + script->reload(); + + if (r_error) + *r_error = OK; + + return scriptres; +} + +void ResourceFormatLoaderPluginScript::get_recognized_extensions(List<String> *p_extensions) const { + p_extensions->push_back(_language->get_extension()); +} + +bool ResourceFormatLoaderPluginScript::handles_type(const String &p_type) const { + return p_type == "Script" || p_type == _language->get_type(); +} + +String ResourceFormatLoaderPluginScript::get_resource_type(const String &p_path) const { + String el = p_path.get_extension().to_lower(); + if (el == _language->get_extension()) + return _language->get_type(); + return ""; +} + +ResourceFormatSaverPluginScript::ResourceFormatSaverPluginScript(PluginScriptLanguage *language) { + _language = language; +} + +Error ResourceFormatSaverPluginScript::save(const String &p_path, const RES &p_resource, uint32_t p_flags) { + Ref<PluginScript> sqscr = p_resource; + ERR_FAIL_COND_V(sqscr.is_null(), ERR_INVALID_PARAMETER); + + String source = sqscr->get_source_code(); + + Error err; + FileAccess *file = FileAccess::open(p_path, FileAccess::WRITE, &err); + ERR_FAIL_COND_V(err, err); + + file->store_string(source); + if (file->get_error() != OK && file->get_error() != ERR_FILE_EOF) { + memdelete(file); + return ERR_CANT_CREATE; + } + file->close(); + memdelete(file); + return OK; +} + +void ResourceFormatSaverPluginScript::get_recognized_extensions(const RES &p_resource, List<String> *p_extensions) const { + + if (Object::cast_to<PluginScript>(*p_resource)) { + p_extensions->push_back(_language->get_extension()); + } +} + +bool ResourceFormatSaverPluginScript::recognize(const RES &p_resource) const { + + return Object::cast_to<PluginScript>(*p_resource) != NULL; +} diff --git a/modules/gdnative/pluginscript/pluginscript_loader.h b/modules/gdnative/pluginscript/pluginscript_loader.h new file mode 100644 index 0000000000..b85e7725a1 --- /dev/null +++ b/modules/gdnative/pluginscript/pluginscript_loader.h @@ -0,0 +1,62 @@ +/*************************************************************************/ +/* pluginscript_loader.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* http://www.godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#ifndef PYTHONSCRIPT_PY_LOADER_H +#define PYTHONSCRIPT_PY_LOADER_H + +// Godot imports +#include "core/script_language.h" +#include "io/resource_loader.h" +#include "io/resource_saver.h" + +class PluginScriptLanguage; + +class ResourceFormatLoaderPluginScript : public ResourceFormatLoader { + PluginScriptLanguage *_language; + +public: + ResourceFormatLoaderPluginScript(PluginScriptLanguage *language); + virtual RES load(const String &p_path, const String &p_original_path = "", Error *r_error = NULL); + virtual void get_recognized_extensions(List<String> *p_extensions) const; + virtual bool handles_type(const String &p_type) const; + virtual String get_resource_type(const String &p_path) const; +}; + +class ResourceFormatSaverPluginScript : public ResourceFormatSaver { + PluginScriptLanguage *_language; + +public: + ResourceFormatSaverPluginScript(PluginScriptLanguage *language); + virtual Error save(const String &p_path, const RES &p_resource, uint32_t p_flags = 0); + virtual void get_recognized_extensions(const RES &p_resource, List<String> *p_extensions) const; + virtual bool recognize(const RES &p_resource) const; +}; + +#endif // PYTHONSCRIPT_PY_LOADER_H diff --git a/modules/gdnative/pluginscript/pluginscript_script.cpp b/modules/gdnative/pluginscript/pluginscript_script.cpp new file mode 100644 index 0000000000..7dd10a8bdf --- /dev/null +++ b/modules/gdnative/pluginscript/pluginscript_script.cpp @@ -0,0 +1,454 @@ +/*************************************************************************/ +/* pluginscript_script.cpp */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* http://www.godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +// Godot imports +#include "core/os/file_access.h" +// PluginScript imports +#include "pluginscript_instance.h" +#include "pluginscript_script.h" + +#if DEBUG_ENABLED +#define __ASSERT_SCRIPT_REASON "Cannot retrieve pluginscript class for this script, is you code correct ?" +#define ASSERT_SCRIPT_VALID() \ + { \ + ERR_EXPLAIN(__ASSERT_SCRIPT_REASON); \ + ERR_FAIL_COND(!can_instance()) \ + } +#define ASSERT_SCRIPT_VALID_V(ret) \ + { \ + ERR_EXPLAIN(__ASSERT_SCRIPT_REASON); \ + ERR_FAIL_COND_V(!can_instance(), ret) \ + } +#else +#define ASSERT_SCRIPT_VALID() +#define ASSERT_SCRIPT_VALID_V(ret) +#endif + +void PluginScript::_bind_methods() { +} + +#ifdef TOOLS_ENABLED + +void PluginScript::_placeholder_erased(PlaceHolderScriptInstance *p_placeholder) { + placeholders.erase(p_placeholder); +} + +#endif + +bool PluginScript::can_instance() const { + bool can = _valid || (!_tool && !ScriptServer::is_scripting_enabled()); + return can; +} + +Ref<Script> PluginScript::get_base_script() const { + if (_ref_base_parent.is_valid()) { + return Ref<PluginScript>(_ref_base_parent); + } else { + return Ref<Script>(); + } +} + +StringName PluginScript::get_instance_base_type() const { + if (_native_parent) + return _native_parent; + if (_ref_base_parent.is_valid()) + return _ref_base_parent->get_instance_base_type(); + return StringName(); +} + +void PluginScript::update_exports() { +// TODO +#ifdef TOOLS_ENABLED +#if 0 + ASSERT_SCRIPT_VALID(); + if (/*changed &&*/ placeholders.size()) { //hm :( + + //update placeholders if any + Map<StringName, Variant> propdefvalues; + List<PropertyInfo> propinfos; + const String *props = (const String *)pybind_get_prop_list(_py_exposed_class); + for (int i = 0; props[i] != ""; ++i) { + const String propname = props[i]; + pybind_get_prop_default_value(_py_exposed_class, propname.c_str(), (godot_variant *)&propdefvalues[propname]); + pybind_prop_info raw_info; + pybind_get_prop_info(_py_exposed_class, propname.c_str(), &raw_info); + PropertyInfo info; + info.type = (Variant::Type)raw_info.type; + info.name = propname; + info.hint = (PropertyHint)raw_info.hint; + info.hint_string = *(String *)&raw_info.hint_string; + info.usage = raw_info.usage; + propinfos.push_back(info); + } + for (Set<PlaceHolderScriptInstance *>::Element *E = placeholders.front(); E; E = E->next()) { + E->get()->update(propinfos, propdefvalues); + } + } +#endif +#endif +} + +// TODO: rename p_this "p_owner" ? +ScriptInstance *PluginScript::instance_create(Object *p_this) { + ASSERT_SCRIPT_VALID_V(NULL); + // TODO check script validity ? + if (!_tool && !ScriptServer::is_scripting_enabled()) { +#ifdef TOOLS_ENABLED + // Instance a fake script for editing the values + PlaceHolderScriptInstance *si = memnew(PlaceHolderScriptInstance(get_language(), Ref<Script>(this), p_this)); + placeholders.insert(si); + update_exports(); + return si; +#else + return NULL; +#endif + } + + PluginScript *top = this; + // TODO: can be optimized by storing a PluginScript::_base_parent direct pointer + while (top->_ref_base_parent.is_valid()) + top = top->_ref_base_parent.ptr(); + if (top->_native_parent) { + if (!ClassDB::is_parent_class(p_this->get_class_name(), top->_native_parent)) { + String msg = "Script inherits from native type '" + String(top->_native_parent) + "', so it can't be instanced in object of type: '" + p_this->get_class() + "'"; + // TODO: implement PluginscriptLanguage::debug_break_parse + // if (ScriptDebugger::get_singleton()) { + // _language->debug_break_parse(get_path(), 0, msg); + // } + ERR_EXPLAIN(msg); + ERR_FAIL_V(NULL); + } + } + + PluginScriptInstance *instance = memnew(PluginScriptInstance()); + const bool success = instance->init(this, p_this); + if (success) { + _language->lock(); + _instances.insert(instance->get_owner()); + _language->unlock(); + return instance; + } else { + memdelete(instance); + ERR_FAIL_V(NULL); + } +} + +bool PluginScript::instance_has(const Object *p_this) const { + _language->lock(); + bool hasit = _instances.has((Object *)p_this); + _language->unlock(); + return hasit; +} + +bool PluginScript::has_source_code() const { + bool has = _source != ""; + return has; +} + +String PluginScript::get_source_code() const { + return _source; +} + +void PluginScript::set_source_code(const String &p_code) { + if (_source == p_code) + return; + _source = p_code; +} + +Error PluginScript::reload(bool p_keep_state) { + _language->lock(); + ERR_FAIL_COND_V(!p_keep_state && _instances.size(), ERR_ALREADY_IN_USE); + _language->unlock(); + + _valid = false; + String basedir = _path; + + if (basedir == "") + basedir = get_path(); + + if (basedir != "") + basedir = basedir.get_base_dir(); + + if (_data) { + _desc->finish(_data); + } + + Error err; + godot_pluginscript_script_manifest manifest = _desc->init( + _language->_data, + (godot_string *)&_path, + (godot_string *)&_source, + (godot_error *)&err); + if (err) { + // TODO: GDscript uses `ScriptDebugger` here to jump into the parsing error + return err; + } + _valid = true; + // Use the manifest to configure this script object + _data = manifest.data; + _name = *(StringName *)&manifest.name; + _tool = manifest.is_tool; + // Base name is either another PluginScript or a regular class accessible + // through ClassDB + StringName *base_name = (StringName *)&manifest.base; + for (SelfList<PluginScript> *e = _language->_script_list.first(); e != NULL; e = e->next()) { + if (e->self()->_name == *base_name) { + // Found you, base is a PluginScript ! + _ref_base_parent = Ref<PluginScript>(e->self()); + break; + } + } + if (!_ref_base_parent.is_valid()) { + // Base is a native ClassDB + if (!ClassDB::class_exists(*base_name)) { + ERR_EXPLAIN("Unknown script '" + String(_name) + "' parent '" + String(*base_name) + "'."); + ERR_FAIL_V(ERR_PARSE_ERROR); + } + _native_parent = *base_name; + } + + Dictionary *members = (Dictionary *)&manifest.member_lines; + for (const Variant *key = members->next(); key != NULL; key = members->next(key)) { + _member_lines[*key] = (*members)[key]; + } + Array *methods = (Array *)&manifest.methods; + for (int i = 0; i < methods->size(); ++i) { + Dictionary v = (*methods)[i]; + MethodInfo mi = MethodInfo::from_dict(v); + _methods_info[mi.name] = mi; + // rpc_mode is passed as an optional field and is not part of MethodInfo + Variant var = v["rpc_mode"]; + if (var == Variant()) { + _methods_rpc_mode[mi.name] = ScriptInstance::RPC_MODE_DISABLED; + } else { + _methods_rpc_mode[mi.name] = ScriptInstance::RPCMode(int(var)); + } + } + Array *signals = (Array *)&manifest.signals; + for (int i = 0; i < signals->size(); ++i) { + Variant v = (*signals)[i]; + MethodInfo mi = MethodInfo::from_dict(v); + _signals_info[mi.name] = mi; + } + Array *properties = (Array *)&manifest.properties; + for (int i = 0; i < properties->size(); ++i) { + Dictionary v = (*properties)[i]; + PropertyInfo pi = PropertyInfo::from_dict(v); + _properties_info[pi.name] = pi; + _properties_default_values[pi.name] = v["default_value"]; + // rset_mode is passed as an optional field and is not part of PropertyInfo + Variant var = v["rset_mode"]; + if (var == Variant()) { + _methods_rpc_mode[pi.name] = ScriptInstance::RPC_MODE_DISABLED; + } else { + _methods_rpc_mode[pi.name] = ScriptInstance::RPCMode(int(var)); + } + } + // Manifest's attributes must be explicitly freed + godot_string_name_destroy(&manifest.name); + godot_string_name_destroy(&manifest.base); + godot_dictionary_destroy(&manifest.member_lines); + godot_array_destroy(&manifest.methods); + godot_array_destroy(&manifest.signals); + godot_array_destroy(&manifest.properties); + +#ifdef TOOLS_ENABLED +/*for (Set<PlaceHolderScriptInstance*>::Element *E=placeholders.front();E;E=E->next()) { + + _update_placeholder(E->get()); + }*/ +#endif + return OK; +} + +void PluginScript::get_script_method_list(List<MethodInfo> *r_methods) const { + ASSERT_SCRIPT_VALID(); + for (Map<StringName, MethodInfo>::Element *e = _methods_info.front(); e != NULL; e = e->next()) { + r_methods->push_back(e->get()); + } +} + +void PluginScript::get_script_property_list(List<PropertyInfo> *r_properties) const { + ASSERT_SCRIPT_VALID(); + for (Map<StringName, PropertyInfo>::Element *e = _properties_info.front(); e != NULL; e = e->next()) { + r_properties->push_back(e->get()); + } +} + +bool PluginScript::has_method(const StringName &p_method) const { + ASSERT_SCRIPT_VALID_V(false); + return _methods_info.has(p_method); +} + +MethodInfo PluginScript::get_method_info(const StringName &p_method) const { + ASSERT_SCRIPT_VALID_V(MethodInfo()); + const Map<StringName, MethodInfo>::Element *e = _methods_info.find(p_method); + if (e != NULL) { + return e->get(); + } else { + return MethodInfo(); + } +} + +bool PluginScript::has_property(const StringName &p_method) const { + ASSERT_SCRIPT_VALID_V(false); + return _properties_info.has(p_method); +} + +PropertyInfo PluginScript::get_property_info(const StringName &p_property) const { + ASSERT_SCRIPT_VALID_V(PropertyInfo()); + const Map<StringName, PropertyInfo>::Element *e = _properties_info.find(p_property); + if (e != NULL) { + return e->get(); + } else { + return PropertyInfo(); + } +} + +bool PluginScript::get_property_default_value(const StringName &p_property, Variant &r_value) const { + ASSERT_SCRIPT_VALID_V(false); +#ifdef TOOLS_ENABLED + const Map<StringName, Variant>::Element *e = _properties_default_values.find(p_property); + if (e != NULL) { + r_value = e->get(); + return true; + } else { + return false; + } +#endif + return false; +} + +String PluginScript::get_node_type() const { + // Even GDscript doesn't know what to put here ! + return ""; // ? +} + +ScriptLanguage *PluginScript::get_language() const { + return _language; +} + +Error PluginScript::load_source_code(const String &p_path) { + + PoolVector<uint8_t> sourcef; + Error err; + FileAccess *f = FileAccess::open(p_path, FileAccess::READ, &err); + if (err) { + ERR_FAIL_COND_V(err, err); + } + + int len = f->get_len(); + sourcef.resize(len + 1); + PoolVector<uint8_t>::Write w = sourcef.write(); + int r = f->get_buffer(w.ptr(), len); + f->close(); + memdelete(f); + ERR_FAIL_COND_V(r != len, ERR_CANT_OPEN); + w[len] = 0; + + String s; + if (s.parse_utf8((const char *)w.ptr())) { + ERR_EXPLAIN("Script '" + p_path + "' contains invalid unicode (utf-8), so it was not loaded. Please ensure that scripts are saved in valid utf-8 unicode."); + ERR_FAIL_V(ERR_INVALID_DATA); + } + + _source = s; +#ifdef TOOLS_ENABLED +// source_changed_cache=true; +#endif + _path = p_path; + return OK; +} + +bool PluginScript::has_script_signal(const StringName &p_signal) const { + ASSERT_SCRIPT_VALID_V(false); + return _signals_info.has(p_signal); +} + +void PluginScript::get_script_signal_list(List<MethodInfo> *r_signals) const { + ASSERT_SCRIPT_VALID(); + for (Map<StringName, MethodInfo>::Element *e = _signals_info.front(); e != NULL; e = e->next()) { + r_signals->push_back(e->get()); + } +} + +int PluginScript::get_member_line(const StringName &p_member) const { +#ifdef TOOLS_ENABLED + if (_member_lines.has(p_member)) + return _member_lines[p_member]; + else +#endif + return -1; +} + +ScriptInstance::RPCMode PluginScript::get_rpc_mode(const StringName &p_method) const { + ASSERT_SCRIPT_VALID_V(ScriptInstance::RPC_MODE_DISABLED); + const Map<StringName, ScriptInstance::RPCMode>::Element *e = _methods_rpc_mode.find(p_method); + if (e != NULL) { + return e->get(); + } else { + return ScriptInstance::RPC_MODE_DISABLED; + } +} + +ScriptInstance::RPCMode PluginScript::get_rset_mode(const StringName &p_variable) const { + ASSERT_SCRIPT_VALID_V(ScriptInstance::RPC_MODE_DISABLED); + const Map<StringName, ScriptInstance::RPCMode>::Element *e = _variables_rset_mode.find(p_variable); + if (e != NULL) { + return e->get(); + } else { + return ScriptInstance::RPC_MODE_DISABLED; + } +} + +PluginScript::PluginScript() + : _data(NULL), _tool(false), _valid(false), _script_list(this) { +} + +void PluginScript::init(PluginScriptLanguage *language) { + _desc = &language->_desc.script_desc; + _language = language; + +#ifdef DEBUG_ENABLED + _language->lock(); + _language->_script_list.add(&_script_list); + _language->unlock(); +#endif +} + +PluginScript::~PluginScript() { + _desc->finish(_data); + +#ifdef DEBUG_ENABLED + _language->lock(); + _language->_script_list.remove(&_script_list); + _language->unlock(); +#endif +} diff --git a/modules/gdnative/pluginscript/pluginscript_script.h b/modules/gdnative/pluginscript/pluginscript_script.h new file mode 100644 index 0000000000..e6b8643cd9 --- /dev/null +++ b/modules/gdnative/pluginscript/pluginscript_script.h @@ -0,0 +1,129 @@ +/*************************************************************************/ +/* pluginscript_script.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* http://www.godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#ifndef PLUGINSCRIPT_SCRIPT_H +#define PLUGINSCRIPT_SCRIPT_H + +// Godot imports +#include "core/script_language.h" +// PluginScript imports +#include "pluginscript_language.h" +#include <pluginscript/godot_pluginscript.h> + +class PyInstance; + +class PluginScript : public Script { + + GDCLASS(PluginScript, Script); + + friend class PluginScriptInstance; + friend class PluginScriptLanguage; + +private: + godot_pluginscript_script_data *_data; + const godot_pluginscript_script_desc *_desc; + PluginScriptLanguage *_language; + bool _tool; + bool _valid; + + Ref<PluginScript> _ref_base_parent; + StringName _native_parent; + SelfList<PluginScript> _script_list; + + Map<StringName, int> _member_lines; + Map<StringName, Variant> _properties_default_values; + Map<StringName, PropertyInfo> _properties_info; + Map<StringName, MethodInfo> _signals_info; + Map<StringName, MethodInfo> _methods_info; + Map<StringName, ScriptInstance::RPCMode> _variables_rset_mode; + Map<StringName, ScriptInstance::RPCMode> _methods_rpc_mode; + + Set<Object *> _instances; + //exported members + String _source; + String _path; + StringName _name; + +protected: + static void _bind_methods(); + +#ifdef TOOLS_ENABLED + Set<PlaceHolderScriptInstance *> placeholders; + //void _update_placeholder(PlaceHolderScriptInstance *p_placeholder); + virtual void _placeholder_erased(PlaceHolderScriptInstance *p_placeholder); +#endif +public: + virtual bool can_instance() const; + + virtual Ref<Script> get_base_script() const; //for script inheritance + + virtual StringName get_instance_base_type() const; // this may not work in all scripts, will return empty if so + virtual ScriptInstance *instance_create(Object *p_this); + virtual bool instance_has(const Object *p_this) const; + + virtual bool has_source_code() const; + virtual String get_source_code() const; + virtual void set_source_code(const String &p_code); + virtual Error reload(bool p_keep_state = false); + // TODO: load_source_code only allow utf-8 file, should handle bytecode as well ? + virtual Error load_source_code(const String &p_path); + + virtual bool has_method(const StringName &p_method) const; + virtual MethodInfo get_method_info(const StringName &p_method) const; + + bool has_property(const StringName &p_method) const; + PropertyInfo get_property_info(const StringName &p_property) const; + + bool is_tool() const { return _tool; } + + virtual String get_node_type() const; + + virtual ScriptLanguage *get_language() const; + + virtual bool has_script_signal(const StringName &p_signal) const; + virtual void get_script_signal_list(List<MethodInfo> *r_signals) const; + + virtual bool get_property_default_value(const StringName &p_property, Variant &r_value) const; + + virtual void update_exports(); + virtual void get_script_method_list(List<MethodInfo> *r_methods) const; + virtual void get_script_property_list(List<PropertyInfo> *r_propertieslist) const; + + virtual int get_member_line(const StringName &p_member) const; + + ScriptInstance::RPCMode get_rpc_mode(const StringName &p_method) const; + ScriptInstance::RPCMode get_rset_mode(const StringName &p_variable) const; + + PluginScript(); + void init(PluginScriptLanguage *language); + virtual ~PluginScript(); +}; + +#endif // PLUGINSCRIPT_SCRIPT_H diff --git a/modules/gdnative/pluginscript/register_types.cpp b/modules/gdnative/pluginscript/register_types.cpp new file mode 100644 index 0000000000..5829d08dff --- /dev/null +++ b/modules/gdnative/pluginscript/register_types.cpp @@ -0,0 +1,118 @@ +/*************************************************************************/ +/* register_types.cpp */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* http://www.godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ +#include "register_types.h" + +#include "core/project_settings.h" +#include "io/resource_loader.h" +#include "io/resource_saver.h" +#include "os/dir_access.h" +#include "os/os.h" +#include "scene/main/scene_tree.h" + +#include "pluginscript_language.h" +#include "pluginscript_script.h" +#include <pluginscript/godot_pluginscript.h> + +static List<PluginScriptLanguage *> pluginscript_languages; + +static Error _check_language_desc(const godot_pluginscript_language_desc *desc) { + ERR_FAIL_COND_V(!desc->name || desc->name == String(), ERR_BUG); + ERR_FAIL_COND_V(!desc->type || desc->type == String(), ERR_BUG); + ERR_FAIL_COND_V(!desc->extension || desc->extension == String(), ERR_BUG); + ERR_FAIL_COND_V(!desc->recognized_extensions || !desc->recognized_extensions[0], ERR_BUG); + ERR_FAIL_COND_V(!desc->init, ERR_BUG); + ERR_FAIL_COND_V(!desc->finish, ERR_BUG); + + // desc->reserved_words is not mandatory + // desc->comment_delimiters is not mandatory + // desc->string_delimiters is not mandatory + + // desc->get_template_source_code is not mandatory + // desc->validate is not mandatory + + // desc->get_template_source_code is not mandatory + // desc->validate is not mandatory + // desc->find_function is not mandatory + // desc->make_function is not mandatory + // desc->complete_code is not mandatory + // desc->auto_indent_code is not mandatory + // desc->add_global_constant is not mandatory + // desc->debug_get_error is not mandatory + // desc->debug_get_stack_level_count is not mandatory + // desc->debug_get_stack_level_line is not mandatory + // desc->debug_get_stack_level_function is not mandatory + // desc->debug_get_stack_level_source is not mandatory + // desc->debug_get_stack_level_locals is not mandatory + // desc->debug_get_stack_level_members is not mandatory + // desc->debug_get_globals is not mandatory + // desc->debug_parse_stack_level_expression is not mandatory + // desc->profiling_start is not mandatory + // desc->profiling_stop is not mandatory + // desc->profiling_get_accumulated_data is not mandatory + // desc->profiling_get_frame_data is not mandatory + // desc->frame is not mandatory + + ERR_FAIL_COND_V(!desc->script_desc.init, ERR_BUG); + ERR_FAIL_COND_V(!desc->script_desc.finish, ERR_BUG); + + ERR_FAIL_COND_V(!desc->script_desc.instance_desc.init, ERR_BUG); + ERR_FAIL_COND_V(!desc->script_desc.instance_desc.finish, ERR_BUG); + ERR_FAIL_COND_V(!desc->script_desc.instance_desc.set_prop, ERR_BUG); + ERR_FAIL_COND_V(!desc->script_desc.instance_desc.get_prop, ERR_BUG); + ERR_FAIL_COND_V(!desc->script_desc.instance_desc.call_method, ERR_BUG); + ERR_FAIL_COND_V(!desc->script_desc.instance_desc.notification, ERR_BUG); + // desc->script_desc.instance_desc.refcount_incremented is not mandatory + // desc->script_desc.instance_desc.refcount_decremented is not mandatory + return OK; +} + +void GDAPI godot_pluginscript_register_language(const godot_pluginscript_language_desc *language_desc) { + Error ret = _check_language_desc(language_desc); + if (ret) { + ERR_FAIL(); + } + PluginScriptLanguage *language = memnew(PluginScriptLanguage(language_desc)); + ScriptServer::register_language(language); + ResourceLoader::add_resource_format_loader(language->get_resource_loader()); + ResourceSaver::add_resource_format_saver(language->get_resource_saver()); + pluginscript_languages.push_back(language); +} + +void register_pluginscript_types() { + ClassDB::register_class<PluginScript>(); +} + +void unregister_pluginscript_types() { + for (List<PluginScriptLanguage *>::Element *e = pluginscript_languages.front(); e; e = e->next()) { + PluginScriptLanguage *language = e->get(); + ScriptServer::unregister_language(language); + memdelete(language); + } +} diff --git a/modules/gdnative/pluginscript/register_types.h b/modules/gdnative/pluginscript/register_types.h new file mode 100644 index 0000000000..70bbb16c62 --- /dev/null +++ b/modules/gdnative/pluginscript/register_types.h @@ -0,0 +1,31 @@ +/*************************************************************************/ +/* register_types.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* http://www.godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ +void register_pluginscript_types(); +void unregister_pluginscript_types(); diff --git a/modules/gdnative/register_types.cpp b/modules/gdnative/register_types.cpp index 8e5f58524b..d2a3e29849 100644 --- a/modules/gdnative/register_types.cpp +++ b/modules/gdnative/register_types.cpp @@ -37,6 +37,7 @@ #include "nativearvr/register_types.h" #include "nativescript/register_types.h" +#include "pluginscript/register_types.h" #include "core/engine.h" #include "core/os/os.h" @@ -158,6 +159,7 @@ void register_gdnative_types() { register_nativearvr_types(); register_nativescript_types(); + register_pluginscript_types(); // run singletons @@ -207,8 +209,9 @@ void unregister_gdnative_types() { } singleton_gdnatives.clear(); - unregister_nativearvr_types(); + unregister_pluginscript_types(); unregister_nativescript_types(); + unregister_nativearvr_types(); memdelete(GDNativeCallRegistry::singleton); diff --git a/modules/gridmap/doc_classes/GridMap.xml b/modules/gridmap/doc_classes/GridMap.xml index cd01233ce4..ed8c27e5d0 100644 --- a/modules/gridmap/doc_classes/GridMap.xml +++ b/modules/gridmap/doc_classes/GridMap.xml @@ -1,8 +1,13 @@ <?xml version="1.0" encoding="UTF-8" ?> <class name="GridMap" inherits="Spatial" category="Core" version="3.0.alpha.custom_build"> <brief_description> + Node for 3D tile-based maps. </brief_description> <description> + GridMap lets you place meshes on a grid interactively. It works both from the editor and can help you create in-game level editors. + GridMaps use a [MeshLibrary] which contain a list of tiles: meshes with materials plus optional collisions and extra elements. + A GridMap contains a collection of cells. Each grid cell refers to a [MeshLibrary] item. All cells in the map have the same dimensions. + A GridMap is split into a sparse collection of octants for efficient rendering and physics processing. Every octant has the same dimensions and can contain several cells. </description> <tutorials> </tutorials> @@ -13,6 +18,7 @@ <return type="void"> </return> <description> + Clear all cells. </description> </method> <method name="get_cell_item" qualifiers="const"> @@ -25,6 +31,7 @@ <argument index="2" name="z" type="int"> </argument> <description> + The [MeshLibrary] item index located at the grid-based X, Y and Z coordinates. If the cell is empty, [INVALID_CELL_ITEM] will be returned. </description> </method> <method name="get_cell_item_orientation" qualifiers="const"> @@ -37,54 +44,63 @@ <argument index="2" name="z" type="int"> </argument> <description> + The orientation of the cell at the grid-based X, Y and Z coordinates. -1 is retuned if the cell is empty. </description> </method> <method name="get_cell_size" qualifiers="const"> <return type="Vector3"> </return> <description> + The dimensions of the grid's cells. </description> </method> <method name="get_center_x" qualifiers="const"> <return type="bool"> </return> <description> + Returns whether or not grid items are centered on the X axis. </description> </method> <method name="get_center_y" qualifiers="const"> <return type="bool"> </return> <description> + Returns whether or not grid items are centered on the Y axis. </description> </method> <method name="get_center_z" qualifiers="const"> <return type="bool"> </return> <description> + Returns whether or not grid items are centered on the Z axis. </description> </method> <method name="get_meshes"> <return type="Array"> </return> <description> + Array of [Transform] and [Mesh] references corresponding to the non empty cells in the grid. The transforms are specified in world space. </description> </method> <method name="get_octant_size" qualifiers="const"> <return type="int"> </return> <description> + The size of each octant measured in number of cells. This applies to all three axis. </description> </method> <method name="get_theme" qualifiers="const"> <return type="MeshLibrary"> </return> <description> + The assigned [MeshLibrary]. </description> </method> <method name="get_used_cells" qualifiers="const"> <return type="Array"> </return> <description> + Array of [Vector3] with the non empty cell coordinates in the grid map. </description> </method> <method name="resource_changed"> @@ -109,6 +125,9 @@ <argument index="4" name="orientation" type="int" default="0"> </argument> <description> + Set the mesh index for the cell referenced by its grid-based X, Y and Z coordinates. + A negative item index will clear the cell. + Optionally, the item's orientation can be passed. </description> </method> <method name="set_cell_size"> @@ -117,6 +136,7 @@ <argument index="0" name="size" type="Vector3"> </argument> <description> + Sets the height, width and depth of the grid's cells. </description> </method> <method name="set_center_x"> @@ -125,6 +145,7 @@ <argument index="0" name="enable" type="bool"> </argument> <description> + Set grid items to be centered on the X axis. By default it is enabled. </description> </method> <method name="set_center_y"> @@ -133,6 +154,7 @@ <argument index="0" name="enable" type="bool"> </argument> <description> + Set grid items to be centered on the Y axis. By default it is enabled. </description> </method> <method name="set_center_z"> @@ -141,6 +163,7 @@ <argument index="0" name="enable" type="bool"> </argument> <description> + Set grid items to be centered on the Z axis. By default it is enabled. </description> </method> <method name="set_clip"> @@ -163,6 +186,7 @@ <argument index="0" name="size" type="int"> </argument> <description> + Sets the size for each octant measured in number of cells. This applies to all three axis. </description> </method> <method name="set_theme"> @@ -171,11 +195,13 @@ <argument index="0" name="theme" type="MeshLibrary"> </argument> <description> + Sets the collection of meshes for the map. </description> </method> </methods> <constants> <constant name="INVALID_CELL_ITEM" value="-1" enum=""> + Invalid cell item that can be used in [method set_cell_item] to clear cells (or represent an empty cell in [method get_cell_item]). </constant> </constants> </class> diff --git a/modules/mobile_vr/mobile_interface.h b/modules/mobile_vr/mobile_interface.h index 6a5e01c163..747377ae46 100644 --- a/modules/mobile_vr/mobile_interface.h +++ b/modules/mobile_vr/mobile_interface.h @@ -90,7 +90,7 @@ private: ///@TODO a few support functions for trackers, most are math related and should likely be moved elsewhere float floor_decimals(float p_value, float p_decimals) { - float power_of_10 = pow(10.0, p_decimals); + float power_of_10 = pow(10.0f, p_decimals); return floor(p_value * power_of_10) / power_of_10; }; diff --git a/modules/mono/config.py b/modules/mono/config.py index 9de199bb5a..0833d30ce1 100644 --- a/modules/mono/config.py +++ b/modules/mono/config.py @@ -125,12 +125,16 @@ def configure(env): else: env.Append(LIBS=[mono_lib]) - env.Append(LIBS=['m', 'rt', 'dl', 'pthread']) + if sys.platform == "darwin": + env.Append(LIBS=['iconv', 'pthread']) + elif sys.platform == "linux" or sys.platform == "linux2": + env.Append(LIBS=['m', 'rt', 'dl', 'pthread']) + else: if mono_static: raise RuntimeError('mono-static: Not supported with pkg-config. Specify a mono prefix manually') - env.ParseConfig('pkg-config mono-2 --cflags --libs') + env.ParseConfig('pkg-config monosgen-2 --cflags --libs') env.Append(LINKFLAGS='-rdynamic') diff --git a/modules/mono/csharp_script.cpp b/modules/mono/csharp_script.cpp index b475782729..ba8c7df9cc 100644 --- a/modules/mono/csharp_script.cpp +++ b/modules/mono/csharp_script.cpp @@ -41,6 +41,7 @@ #include "editor/csharp_project.h" #include "editor/editor_node.h" #include "editor/godotsharp_editor.h" +#include "utils/string_utils.h" #endif #include "godotsharp_dirs.h" @@ -48,8 +49,9 @@ #include "mono_gd/gd_mono_marshal.h" #include "signal_awaiter_utils.h" -#define CACHED_STRING_NAME(m_var) (CSharpLanguage::get_singleton()->string_names.m_var) +#define CACHED_STRING_NAME(m_var) (CSharpLanguage::get_singleton()->get_string_names().m_var) +#ifdef TOOLS_ENABLED static bool _create_project_solution_if_needed() { String sln_path = GodotSharpDirs::get_project_sln_path(); @@ -64,6 +66,7 @@ static bool _create_project_solution_if_needed() { return true; } +#endif CSharpLanguage *CSharpLanguage::singleton = NULL; @@ -295,20 +298,88 @@ bool CSharpLanguage::has_named_classes() const { return true; } -String CSharpLanguage::make_function(const String &p_class, const String &p_name, const PoolStringArray &p_args) const { +static String variant_type_to_managed_name(const String &p_var_type_name) { + + if (p_var_type_name.empty()) + return "object"; + + if (!ClassDB::class_exists(p_var_type_name)) { + Variant::Type var_types[] = { + Variant::BOOL, + Variant::INT, + Variant::REAL, + Variant::STRING, + Variant::VECTOR2, + Variant::RECT2, + Variant::VECTOR3, + Variant::TRANSFORM2D, + Variant::PLANE, + Variant::QUAT, + Variant::RECT3, + Variant::BASIS, + Variant::TRANSFORM, + Variant::COLOR, + Variant::NODE_PATH, + Variant::_RID + }; + + for (int i = 0; i < sizeof(var_types) / sizeof(Variant::Type); i++) { + if (p_var_type_name == Variant::get_type_name(var_types[i])) + return p_var_type_name; + } + + if (p_var_type_name == "String") + return "string"; // I prefer this one >:[ + + // TODO these will be rewritten later into custom containers + + if (p_var_type_name == "Array") + return "object[]"; + + if (p_var_type_name == "Dictionary") + return "Dictionary<object, object>"; + if (p_var_type_name == "PoolByteArray") + return "byte[]"; + if (p_var_type_name == "PoolIntArray") + return "int[]"; + if (p_var_type_name == "PoolRealArray") + return "float[]"; + if (p_var_type_name == "PoolStringArray") + return "string[]"; + if (p_var_type_name == "PoolVector2Array") + return "Vector2[]"; + if (p_var_type_name == "PoolVector3Array") + return "Vector3[]"; + if (p_var_type_name == "PoolColorArray") + return "Color[]"; + + return "object"; + } + + return p_var_type_name; +} + +String CSharpLanguage::make_function(const String &p_class, const String &p_name, const PoolStringArray &p_args) const { +#ifdef TOOLS_ENABLED // FIXME - // Due to Godot's API limitation this just appends the function to the end of the file - // Another limitation is that the parameter types are not specified, so we must use System.Object + // - Due to Godot's API limitation this just appends the function to the end of the file + // - Use fully qualified name if there is ambiguity String s = "private void " + p_name + "("; for (int i = 0; i < p_args.size(); i++) { + const String &arg = p_args[i]; + if (i > 0) s += ", "; - s += "object " + p_args[i]; + + s += variant_type_to_managed_name(arg.get_slice(":", 1)) + " " + escape_csharp_keyword(arg.get_slice(":", 0)); } s += ")\n{\n // Replace with function body\n}\n"; return s; +#else + return String(); +#endif } void CSharpLanguage::frame() { @@ -903,46 +974,6 @@ Variant CSharpInstance::call(const StringName &p_method, const Variant **p_args, } else { return Variant(); } - } else if (p_method == CACHED_STRING_NAME(_awaited_signal_callback)) { - // shitty hack.. - // TODO move to its own function, thx - - if (p_argcount < 1) { - r_error.error = Variant::CallError::CALL_ERROR_TOO_FEW_ARGUMENTS; - r_error.argument = 1; - return Variant(); - } - - Ref<SignalAwaiterHandle> awaiter = *p_args[p_argcount - 1]; - - if (awaiter.is_null()) { - r_error.error = Variant::CallError::CALL_ERROR_INVALID_ARGUMENT; - r_error.argument = p_argcount - 1; - r_error.expected = Variant::OBJECT; - return Variant(); - } - - awaiter->set_completed(true); - - int extra_argc = p_argcount - 1; - MonoArray *extra_args = mono_array_new(SCRIPTS_DOMAIN, CACHED_CLASS_RAW(MonoObject), extra_argc); - - for (int i = 0; i < extra_argc; i++) { - MonoObject *boxed = GDMonoMarshal::variant_to_mono_object(*p_args[i]); - mono_array_set(extra_args, MonoObject *, i, boxed); - } - - GDMonoUtils::GodotObject__AwaitedSignalCallback thunk = CACHED_METHOD_THUNK(GodotObject, _AwaitedSignalCallback); - - MonoObject *ex = NULL; - thunk(mono_object, &extra_args, awaiter->get_target(), &ex); - - if (ex) { - mono_print_unhandled_exception(ex); - ERR_FAIL_V(Variant()); - } - - return Variant(); } top = top->get_parent_class(); @@ -1239,8 +1270,11 @@ bool CSharpScript::_update_exports() { for (int i = 0; i < fields.size(); i++) { GDMonoField *field = fields[i]; - if (field->is_static() || field->get_visibility() != GDMono::PUBLIC) + if (field->is_static()) { + if (field->has_attribute(CACHED_CLASS(ExportAttribute))) + ERR_PRINTS("Cannot export field because it is static: " + top->get_full_name() + "." + field->get_name()); continue; + } String name = field->get_name(); StringName cname = name; @@ -1248,17 +1282,39 @@ bool CSharpScript::_update_exports() { if (member_info.has(cname)) continue; - Variant::Type type = GDMonoMarshal::managed_to_variant_type(field->get_type()); + ManagedType field_type = field->get_type(); + Variant::Type type = GDMonoMarshal::managed_to_variant_type(field_type); if (field->has_attribute(CACHED_CLASS(ExportAttribute))) { + // Field has Export attribute MonoObject *attr = field->get_attribute(CACHED_CLASS(ExportAttribute)); - // Field has Export attribute - int hint = CACHED_FIELD(ExportAttribute, hint)->get_int_value(attr); - String hint_string = CACHED_FIELD(ExportAttribute, hint_string)->get_string_value(attr); - int usage = CACHED_FIELD(ExportAttribute, usage)->get_int_value(attr); + PropertyHint hint; + String hint_string; + + if (type == Variant::NIL) { + ERR_PRINTS("Unknown type of exported field: " + top->get_full_name() + "." + field->get_name()); + continue; + } else if (type == Variant::INT && field_type.type_encoding == MONO_TYPE_VALUETYPE && mono_class_is_enum(field_type.type_class->get_raw())) { + type = Variant::INT; + hint = PROPERTY_HINT_ENUM; + + Vector<MonoClassField *> fields = field_type.type_class->get_enum_fields(); + + for (int i = 0; i < fields.size(); i++) { + if (i > 0) + hint_string += ","; + hint_string += mono_field_get_name(fields[i]); + } + } else if (type == Variant::OBJECT && CACHED_CLASS(GodotReference)->is_assignable_from(field_type.type_class)) { + hint = PROPERTY_HINT_RESOURCE_TYPE; + hint_string = NATIVE_GDMONOCLASS_NAME(field_type.type_class); + } else { + hint = PropertyHint(CACHED_FIELD(ExportAttribute, hint)->get_int_value(attr)); + hint_string = CACHED_FIELD(ExportAttribute, hint_string)->get_string_value(attr); + } - PropertyInfo prop_info = PropertyInfo(type, name, PropertyHint(hint), hint_string, PropertyUsageFlags(usage)); + PropertyInfo prop_info = PropertyInfo(type, name, hint, hint_string, PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_SCRIPT_VARIABLE); member_info[cname] = prop_info; exported_members_cache.push_back(prop_info); @@ -1392,12 +1448,15 @@ bool CSharpScript::can_instance() const { #ifdef TOOLS_ENABLED if (Engine::get_singleton()->is_editor_hint()) { - if (_create_project_solution_if_needed()) { - CSharpProject::add_item(GodotSharpDirs::get_project_csproj_path(), - "Compile", - ProjectSettings::get_singleton()->globalize_path(get_path())); - } else { - ERR_PRINTS("Cannot add " + get_path() + " to the C# project because it could not be created."); + + if (get_path().find("::") == -1) { // Ignore if built-in script. Can happen if the file is deleted... + if (_create_project_solution_if_needed()) { + CSharpProject::add_item(GodotSharpDirs::get_project_csproj_path(), + "Compile", + ProjectSettings::get_singleton()->globalize_path(get_path())); + } else { + ERR_PRINTS("Cannot add " + get_path() + " to the C# project because it could not be created."); + } } } #endif @@ -1679,16 +1738,6 @@ void CSharpScript::update_exports() { #ifdef TOOLS_ENABLED _update_exports(); - - if (placeholders.size()) { - Map<StringName, Variant> values; - List<PropertyInfo> propnames; - _update_exports_values(values, propnames); - - for (Set<PlaceHolderScriptInstance *>::Element *E = placeholders.front(); E; E = E->next()) { - E->get()->update(propnames, values); - } - } #endif } @@ -1915,7 +1964,7 @@ bool ResourceFormatSaverCSharpScript::recognize(const RES &p_resource) const { CSharpLanguage::StringNameCache::StringNameCache() { - _awaited_signal_callback = StaticCString::create("_AwaitedSignalCallback"); + _signal_callback = StaticCString::create("_signal_callback"); _set = StaticCString::create("_set"); _get = StaticCString::create("_get"); _notification = StaticCString::create("_notification"); diff --git a/modules/mono/csharp_script.h b/modules/mono/csharp_script.h index 3fcc3bdf04..6b8475fb61 100644 --- a/modules/mono/csharp_script.h +++ b/modules/mono/csharp_script.h @@ -225,7 +225,7 @@ class CSharpLanguage : public ScriptLanguage { struct StringNameCache { - StringName _awaited_signal_callback; + StringName _signal_callback; StringName _set; StringName _get; StringName _notification; @@ -242,6 +242,8 @@ public: _FORCE_INLINE_ int get_language_index() { return lang_idx; } void set_language_index(int p_idx); + _FORCE_INLINE_ const StringNameCache &get_string_names() { return string_names; } + _FORCE_INLINE_ static CSharpLanguage *get_singleton() { return singleton; } bool debug_break(const String &p_error, bool p_allow_continue = true); diff --git a/modules/mono/editor/bindings_generator.cpp b/modules/mono/editor/bindings_generator.cpp index 704910c5b9..95e75f9103 100644 --- a/modules/mono/editor/bindings_generator.cpp +++ b/modules/mono/editor/bindings_generator.cpp @@ -108,36 +108,6 @@ const char *BindingsGenerator::TypeInterface::DEFAULT_VARARG_C_IN = "\t%0 %1_in bool BindingsGenerator::verbose_output = false; -static bool is_csharp_keyword(const String &p_name) { - - // Reserved keywords - - return p_name == "abstract" || p_name == "as" || p_name == "base" || p_name == "bool" || - p_name == "break" || p_name == "byte" || p_name == "case" || p_name == "catch" || - p_name == "char" || p_name == "checked" || p_name == "class" || p_name == "const" || - p_name == "continue" || p_name == "decimal" || p_name == "default" || p_name == "delegate" || - p_name == "do" || p_name == "double" || p_name == "else" || p_name == "enum" || - p_name == "event" || p_name == "explicit" || p_name == "extern" || p_name == "false" || - p_name == "finally" || p_name == "fixed" || p_name == "float" || p_name == "for" || - p_name == "forech" || p_name == "goto" || p_name == "if" || p_name == "implicit" || - p_name == "in" || p_name == "int" || p_name == "interface" || p_name == "internal" || - p_name == "is" || p_name == "lock" || p_name == "long" || p_name == "namespace" || - p_name == "new" || p_name == "null" || p_name == "object" || p_name == "operator" || - p_name == "out" || p_name == "override" || p_name == "params" || p_name == "private" || - p_name == "protected" || p_name == "public" || p_name == "readonly" || p_name == "ref" || - p_name == "return" || p_name == "sbyte" || p_name == "sealed" || p_name == "short" || - p_name == "sizeof" || p_name == "stackalloc" || p_name == "static" || p_name == "string" || - p_name == "struct" || p_name == "switch" || p_name == "this" || p_name == "throw" || - p_name == "true" || p_name == "try" || p_name == "typeof" || p_name == "uint" || p_name == "ulong" || - p_name == "unchecked" || p_name == "unsafe" || p_name == "ushort" || p_name == "using" || - p_name == "virtual" || p_name == "volatile" || p_name == "void" || p_name == "while"; -} - -inline static String escape_csharp_keyword(const String &p_name) { - - return is_csharp_keyword(p_name) ? "@" + p_name : p_name; -} - static String snake_to_pascal_case(const String &p_identifier) { String ret; @@ -904,10 +874,6 @@ Error BindingsGenerator::_generate_cs_type(const TypeInterface &itype, const Str return ERR_BUG; } - cs_file.push_back(MEMBER_BEGIN "private void _AwaitedSignalCallback("); - cs_file.push_back(array_itype->get().cs_type); - cs_file.push_back(" args, SignalAwaiter awaiter)\n" OPEN_BLOCK_L2 "awaiter.SignalCallback(args);\n" CLOSE_BLOCK_L2); - Map<String, TypeInterface>::Element *object_itype = obj_types.find("Object"); if (!object_itype) { diff --git a/modules/mono/glue/cs_files/ExportAttribute.cs b/modules/mono/glue/cs_files/ExportAttribute.cs index af3f603d6d..a4e7d447dd 100644 --- a/modules/mono/glue/cs_files/ExportAttribute.cs +++ b/modules/mono/glue/cs_files/ExportAttribute.cs @@ -7,13 +7,11 @@ namespace Godot { private int hint; private string hint_string; - private int usage; - public ExportAttribute(int hint = GD.PROPERTY_HINT_NONE, string hint_string = "", int usage = GD.PROPERTY_USAGE_DEFAULT) + public ExportAttribute(int hint = GD.PROPERTY_HINT_NONE, string hint_string = "") { this.hint = hint; this.hint_string = hint_string; - this.usage = usage; } } } diff --git a/modules/mono/godotsharp_dirs.cpp b/modules/mono/godotsharp_dirs.cpp index 0a2010e99d..6bcf0e2355 100644 --- a/modules/mono/godotsharp_dirs.cpp +++ b/modules/mono/godotsharp_dirs.cpp @@ -33,6 +33,7 @@ #ifdef TOOLS_ENABLED #include "editor/editor_settings.h" +#include "os/dir_access.h" #include "project_settings.h" #include "version.h" #endif @@ -60,12 +61,20 @@ String _get_mono_user_dir() { } else { String settings_path; - if (OS::get_singleton()->has_environment("APPDATA")) { - String app_data = OS::get_singleton()->get_environment("APPDATA").replace("\\", "/"); - settings_path = app_data.plus_file(String(_MKSTR(VERSION_SHORT_NAME)).capitalize()); - } else if (OS::get_singleton()->has_environment("HOME")) { - String home = OS::get_singleton()->get_environment("HOME"); - settings_path = home.plus_file("." + String(_MKSTR(VERSION_SHORT_NAME)).to_lower()); + String exe_dir = OS::get_singleton()->get_executable_path().get_base_dir(); + DirAccessRef d = DirAccess::create_for_path(exe_dir); + + if (d->file_exists("._sc_") || d->file_exists("_sc_")) { + // contain yourself + settings_path = exe_dir.plus_file("editor_data"); + } else { + if (OS::get_singleton()->has_environment("APPDATA")) { + String app_data = OS::get_singleton()->get_environment("APPDATA").replace("\\", "/"); + settings_path = app_data.plus_file(String(_MKSTR(VERSION_SHORT_NAME)).capitalize()); + } else if (OS::get_singleton()->has_environment("HOME")) { + String home = OS::get_singleton()->get_environment("HOME"); + settings_path = home.plus_file("." + String(_MKSTR(VERSION_SHORT_NAME)).to_lower()); + } } return settings_path.plus_file("mono"); diff --git a/modules/mono/mono_gd/gd_mono_class.cpp b/modules/mono/mono_gd/gd_mono_class.cpp index 0134ace5d7..77ba0ee90e 100644 --- a/modules/mono/mono_gd/gd_mono_class.cpp +++ b/modules/mono/mono_gd/gd_mono_class.cpp @@ -43,6 +43,14 @@ bool GDMonoClass::is_assignable_from(GDMonoClass *p_from) const { return mono_class_is_assignable_from(mono_class, p_from->mono_class); } +String GDMonoClass::get_full_name() const { + + String res = namespace_name; + if (res.length()) + res += "."; + return res + class_name; +} + GDMonoClass *GDMonoClass::get_parent_class() { if (assembly) { @@ -56,6 +64,30 @@ GDMonoClass *GDMonoClass::get_parent_class() { return NULL; } +#ifdef TOOLS_ENABLED +Vector<MonoClassField *> GDMonoClass::get_enum_fields() { + + bool class_is_enum = mono_class_is_enum(mono_class); + ERR_FAIL_COND_V(!class_is_enum, Vector<MonoClassField *>()); + + Vector<MonoClassField *> enum_fields; + + void *iter = NULL; + MonoClassField *raw_field = NULL; + while ((raw_field = mono_class_get_fields(get_raw(), &iter)) != NULL) { + uint32_t field_flags = mono_field_get_flags(raw_field); + + // Enums have an instance field named value__ which holds the value of the enum. + // Enum constants are static, so we will use this to ignore the value__ field. + if (field_flags & MONO_FIELD_ATTR_PUBLIC && field_flags & MONO_FIELD_ATTR_STATIC) { + enum_fields.push_back(raw_field); + } + } + + return enum_fields; +} +#endif + bool GDMonoClass::has_method(const StringName &p_name) { return get_method(p_name) != NULL; diff --git a/modules/mono/mono_gd/gd_mono_class.h b/modules/mono/mono_gd/gd_mono_class.h index 1e72553879..ef1ca425a7 100644 --- a/modules/mono/mono_gd/gd_mono_class.h +++ b/modules/mono/mono_gd/gd_mono_class.h @@ -98,8 +98,14 @@ public: _FORCE_INLINE_ MonoClass *get_raw() const { return mono_class; } _FORCE_INLINE_ const GDMonoAssembly *get_assembly() const { return assembly; } + String get_full_name() const; + GDMonoClass *get_parent_class(); +#ifdef TOOLS_ENABLED + Vector<MonoClassField *> get_enum_fields(); +#endif + bool has_method(const StringName &p_name); bool has_attribute(GDMonoClass *p_attr_class); diff --git a/modules/mono/mono_gd/gd_mono_field.cpp b/modules/mono/mono_gd/gd_mono_field.cpp index c2d8eeaa32..81315ee87a 100644 --- a/modules/mono/mono_gd/gd_mono_field.cpp +++ b/modules/mono/mono_gd/gd_mono_field.cpp @@ -51,6 +51,7 @@ void GDMonoField::set_value(MonoObject *p_object, const Variant &p_value) { { \ m_type val = p_value.operator m_type(); \ mono_field_set_value(p_object, mono_field, &val); \ + break; \ } #define SET_FROM_ARRAY_AND_BREAK(m_type) \ @@ -137,6 +138,9 @@ void GDMonoField::set_value(MonoObject *p_object, const Variant &p_value) { if (tclass == CACHED_CLASS(Plane)) SET_FROM_STRUCT_AND_BREAK(Plane); + if (mono_class_is_enum(tclass->get_raw())) + SET_FROM_PRIMITIVE(signed int); + ERR_EXPLAIN(String() + "Attempted to set the value of a field of unmarshallable type: " + tclass->get_name()); ERR_FAIL(); } break; diff --git a/modules/mono/mono_gd/gd_mono_marshal.cpp b/modules/mono/mono_gd/gd_mono_marshal.cpp index 9a6c8f0cd6..77a1ef3cb0 100644 --- a/modules/mono/mono_gd/gd_mono_marshal.cpp +++ b/modules/mono/mono_gd/gd_mono_marshal.cpp @@ -112,6 +112,9 @@ Variant::Type managed_to_variant_type(const ManagedType &p_type) { if (tclass == CACHED_CLASS(Plane)) return Variant::PLANE; + + if (mono_class_is_enum(tclass->get_raw())) + return Variant::INT; } break; case MONO_TYPE_ARRAY: @@ -165,9 +168,12 @@ Variant::Type managed_to_variant_type(const ManagedType &p_type) { return Variant::DICTIONARY; } } break; + + default: { + } break; } - // No error, the caller will decide what to do in this case + // Unknown return Variant::NIL; } @@ -299,6 +305,11 @@ MonoObject *variant_to_mono_object(const Variant *p_var, const ManagedType &p_ty if (tclass == CACHED_CLASS(Plane)) RETURN_BOXED_STRUCT(Plane, p_var); + + if (mono_class_is_enum(tclass->get_raw())) { + int val = p_var->operator signed int(); + return BOX_ENUM(tclass->get_raw(), val); + } } break; case MONO_TYPE_ARRAY: @@ -515,6 +526,9 @@ Variant mono_object_to_variant(MonoObject *p_obj, const ManagedType &p_type) { if (tclass == CACHED_CLASS(Plane)) RETURN_UNBOXED_STRUCT(Plane, p_obj); + + if (mono_class_is_enum(tclass->get_raw())) + return unbox<int32_t>(p_obj); } break; case MONO_TYPE_ARRAY: diff --git a/modules/mono/mono_gd/gd_mono_marshal.h b/modules/mono/mono_gd/gd_mono_marshal.h index 38dd22357d..9f403b787f 100644 --- a/modules/mono/mono_gd/gd_mono_marshal.h +++ b/modules/mono/mono_gd/gd_mono_marshal.h @@ -53,6 +53,7 @@ T unbox(MonoObject *p_obj) { #define BOX_UINT8(x) mono_value_box(mono_domain_get(), CACHED_CLASS_RAW(uint8_t), &x) #define BOX_BOOLEAN(x) mono_value_box(mono_domain_get(), CACHED_CLASS_RAW(bool), &x) #define BOX_PTR(x) mono_value_box(mono_domain_get(), CACHED_CLASS_RAW(IntPtr), x) +#define BOX_ENUM(m_enum_class, x) mono_value_box(mono_domain_get(), m_enum_class, &x) Variant::Type managed_to_variant_type(const ManagedType &p_type); diff --git a/modules/mono/mono_gd/gd_mono_utils.cpp b/modules/mono/mono_gd/gd_mono_utils.cpp index 5deca8e64d..53e45002c4 100644 --- a/modules/mono/mono_gd/gd_mono_utils.cpp +++ b/modules/mono/mono_gd/gd_mono_utils.cpp @@ -86,6 +86,7 @@ void MonoCache::clear_members() { class_NodePath = NULL; class_RID = NULL; class_GodotObject = NULL; + class_GodotReference = NULL; class_Node = NULL; class_Control = NULL; class_Spatial = NULL; @@ -95,7 +96,6 @@ void MonoCache::clear_members() { class_ExportAttribute = NULL; field_ExportAttribute_hint = NULL; field_ExportAttribute_hint_string = NULL; - field_ExportAttribute_usage = NULL; class_ToolAttribute = NULL; class_RemoteAttribute = NULL; class_SyncAttribute = NULL; @@ -111,7 +111,7 @@ void MonoCache::clear_members() { methodthunk_MarshalUtils_DictionaryToArrays = NULL; methodthunk_MarshalUtils_ArraysToDictionary = NULL; - methodthunk_GodotObject__AwaitedSignalCallback = NULL; + methodthunk_SignalAwaiter_SignalCallback = NULL; methodthunk_SignalAwaiter_FailureCallback = NULL; methodthunk_GodotTaskScheduler_Activate = NULL; @@ -153,6 +153,7 @@ void update_godot_api_cache() { CACHE_CLASS_AND_CHECK(NodePath, GODOT_API_CLASS(NodePath)); CACHE_CLASS_AND_CHECK(RID, GODOT_API_CLASS(NodePath)); CACHE_CLASS_AND_CHECK(GodotObject, GODOT_API_CLASS(Object)); + CACHE_CLASS_AND_CHECK(GodotReference, GODOT_API_CLASS(Reference)); CACHE_CLASS_AND_CHECK(Node, GODOT_API_CLASS(Node)); CACHE_CLASS_AND_CHECK(Control, GODOT_API_CLASS(Control)); CACHE_CLASS_AND_CHECK(Spatial, GODOT_API_CLASS(Spatial)); @@ -163,7 +164,6 @@ void update_godot_api_cache() { CACHE_CLASS_AND_CHECK(ExportAttribute, GODOT_API_CLASS(ExportAttribute)); CACHE_FIELD_AND_CHECK(ExportAttribute, hint, CACHED_CLASS(ExportAttribute)->get_field("hint")); CACHE_FIELD_AND_CHECK(ExportAttribute, hint_string, CACHED_CLASS(ExportAttribute)->get_field("hint_string")); - CACHE_FIELD_AND_CHECK(ExportAttribute, usage, CACHED_CLASS(ExportAttribute)->get_field("usage")); CACHE_CLASS_AND_CHECK(ToolAttribute, GODOT_API_CLASS(ToolAttribute)); CACHE_CLASS_AND_CHECK(RemoteAttribute, GODOT_API_CLASS(RemoteAttribute)); CACHE_CLASS_AND_CHECK(SyncAttribute, GODOT_API_CLASS(SyncAttribute)); @@ -178,7 +178,7 @@ void update_godot_api_cache() { CACHE_METHOD_THUNK_AND_CHECK(MarshalUtils, DictionaryToArrays, (MarshalUtils_DictToArrays)CACHED_CLASS(MarshalUtils)->get_method("DictionaryToArrays", 3)->get_thunk()); CACHE_METHOD_THUNK_AND_CHECK(MarshalUtils, ArraysToDictionary, (MarshalUtils_ArraysToDict)CACHED_CLASS(MarshalUtils)->get_method("ArraysToDictionary", 2)->get_thunk()); - CACHE_METHOD_THUNK_AND_CHECK(GodotObject, _AwaitedSignalCallback, (GodotObject__AwaitedSignalCallback)CACHED_CLASS(GodotObject)->get_method("_AwaitedSignalCallback", 2)->get_thunk()); + CACHE_METHOD_THUNK_AND_CHECK(SignalAwaiter, SignalCallback, (SignalAwaiter_SignalCallback)GODOT_API_CLASS(SignalAwaiter)->get_method("SignalCallback", 1)->get_thunk()); CACHE_METHOD_THUNK_AND_CHECK(SignalAwaiter, FailureCallback, (SignalAwaiter_FailureCallback)GODOT_API_CLASS(SignalAwaiter)->get_method("FailureCallback", 0)->get_thunk()); CACHE_METHOD_THUNK_AND_CHECK(GodotTaskScheduler, Activate, (GodotTaskScheduler_Activate)GODOT_API_CLASS(GodotTaskScheduler)->get_method("Activate", 0)->get_thunk()); diff --git a/modules/mono/mono_gd/gd_mono_utils.h b/modules/mono/mono_gd/gd_mono_utils.h index f97f048aa9..e3af57e78a 100644 --- a/modules/mono/mono_gd/gd_mono_utils.h +++ b/modules/mono/mono_gd/gd_mono_utils.h @@ -42,7 +42,7 @@ namespace GDMonoUtils { typedef MonoObject *(*MarshalUtils_DictToArrays)(MonoObject *, MonoArray **, MonoArray **, MonoObject **); typedef MonoObject *(*MarshalUtils_ArraysToDict)(MonoArray *, MonoArray *, MonoObject **); -typedef MonoObject *(*GodotObject__AwaitedSignalCallback)(MonoObject *, MonoArray **, MonoObject *, MonoObject **); +typedef MonoObject *(*SignalAwaiter_SignalCallback)(MonoObject *, MonoArray **, MonoObject **); typedef MonoObject *(*SignalAwaiter_FailureCallback)(MonoObject *, MonoObject **); typedef MonoObject *(*GodotTaskScheduler_Activate)(MonoObject *, MonoObject **); @@ -88,6 +88,7 @@ struct MonoCache { GDMonoClass *class_NodePath; GDMonoClass *class_RID; GDMonoClass *class_GodotObject; + GDMonoClass *class_GodotReference; GDMonoClass *class_Node; GDMonoClass *class_Control; GDMonoClass *class_Spatial; @@ -97,7 +98,6 @@ struct MonoCache { GDMonoClass *class_ExportAttribute; GDMonoField *field_ExportAttribute_hint; GDMonoField *field_ExportAttribute_hint_string; - GDMonoField *field_ExportAttribute_usage; GDMonoClass *class_ToolAttribute; GDMonoClass *class_RemoteAttribute; GDMonoClass *class_SyncAttribute; @@ -113,7 +113,7 @@ struct MonoCache { MarshalUtils_DictToArrays methodthunk_MarshalUtils_DictionaryToArrays; MarshalUtils_ArraysToDict methodthunk_MarshalUtils_ArraysToDictionary; - GodotObject__AwaitedSignalCallback methodthunk_GodotObject__AwaitedSignalCallback; + SignalAwaiter_SignalCallback methodthunk_SignalAwaiter_SignalCallback; SignalAwaiter_FailureCallback methodthunk_SignalAwaiter_FailureCallback; GodotTaskScheduler_Activate methodthunk_GodotTaskScheduler_Activate; @@ -164,7 +164,7 @@ String get_exception_name_and_message(MonoObject *p_ex); } // GDMonoUtils -#define NATIVE_GDMONOCLASS_NAME(m_class) (GDMonoMarshal::mono_string_to_godot((MonoString *)m_class->get_field("nativeName")->get_value(NULL))) +#define NATIVE_GDMONOCLASS_NAME(m_class) (GDMonoMarshal::mono_string_to_godot((MonoString *)m_class->get_field(BINDINGS_NATIVE_NAME_FIELD)->get_value(NULL))) #define CACHED_CLASS(m_class) (GDMonoUtils::mono_cache.class_##m_class) #define CACHED_CLASS_RAW(m_class) (GDMonoUtils::mono_cache.class_##m_class->get_raw()) diff --git a/modules/mono/signal_awaiter_utils.cpp b/modules/mono/signal_awaiter_utils.cpp index 012dd119b1..7e99df29a1 100644 --- a/modules/mono/signal_awaiter_utils.cpp +++ b/modules/mono/signal_awaiter_utils.cpp @@ -29,6 +29,9 @@ /*************************************************************************/ #include "signal_awaiter_utils.h" +#include "csharp_script.h" +#include "mono_gd/gd_mono_class.h" +#include "mono_gd/gd_mono_marshal.h" #include "mono_gd/gd_mono_utils.h" namespace SignalAwaiterUtils { @@ -40,13 +43,20 @@ Error connect_signal_awaiter(Object *p_source, const String &p_signal, Object *p uint32_t awaiter_handle = MonoGCHandle::make_strong_handle(p_awaiter); Ref<SignalAwaiterHandle> sa_con = memnew(SignalAwaiterHandle(awaiter_handle)); +#ifdef DEBUG_ENABLED + sa_con->set_connection_target(p_target); +#endif + Vector<Variant> binds; binds.push_back(sa_con); - Error err = p_source->connect(p_signal, p_target, "_AwaitedSignalCallback", binds, Object::CONNECT_ONESHOT); + + Error err = p_source->connect(p_signal, sa_con.ptr(), + CSharpLanguage::get_singleton()->get_string_names()._signal_callback, + binds, Object::CONNECT_ONESHOT); if (err != OK) { - // set it as completed to prevent it from calling the failure callback when deleted - // the awaiter will be aware of the failure by checking the returned error + // Set it as completed to prevent it from calling the failure callback when released. + // The awaiter will be aware of the failure by checking the returned error. sa_con->set_completed(true); } @@ -54,11 +64,68 @@ Error connect_signal_awaiter(Object *p_source, const String &p_signal, Object *p } } -SignalAwaiterHandle::SignalAwaiterHandle(uint32_t p_handle) - : MonoGCHandle(p_handle) { +Variant SignalAwaiterHandle::_signal_callback(const Variant **p_args, int p_argcount, Variant::CallError &r_error) { + +#ifdef DEBUG_ENABLED + if (conn_target_id && !ObjectDB::get_instance(conn_target_id)) { + ERR_EXPLAIN("Resumed after await, but class instance is gone"); + ERR_FAIL_V(Variant()); + } +#endif + + if (p_argcount < 1) { + r_error.error = Variant::CallError::CALL_ERROR_TOO_FEW_ARGUMENTS; + r_error.argument = 1; + return Variant(); + } + + Ref<SignalAwaiterHandle> self = *p_args[p_argcount - 1]; + + if (self.is_null()) { + r_error.error = Variant::CallError::CALL_ERROR_INVALID_ARGUMENT; + r_error.argument = p_argcount - 1; + r_error.expected = Variant::OBJECT; + return Variant(); + } + + set_completed(true); + + int signal_argc = p_argcount - 1; + MonoArray *signal_args = mono_array_new(SCRIPTS_DOMAIN, CACHED_CLASS_RAW(MonoObject), signal_argc); + + for (int i = 0; i < signal_argc; i++) { + MonoObject *boxed = GDMonoMarshal::variant_to_mono_object(*p_args[i]); + mono_array_set(signal_args, MonoObject *, i, boxed); + } + + GDMonoUtils::SignalAwaiter_SignalCallback thunk = CACHED_METHOD_THUNK(SignalAwaiter, SignalCallback); + + MonoObject *ex = NULL; + thunk(get_target(), &signal_args, &ex); + + if (ex) { + mono_print_unhandled_exception(ex); + ERR_FAIL_V(Variant()); + } + + return Variant(); +} + +void SignalAwaiterHandle::_bind_methods() { + + ClassDB::bind_vararg_method(METHOD_FLAGS_DEFAULT, "_signal_callback", &SignalAwaiterHandle::_signal_callback, MethodInfo("_signal_callback")); +} + +SignalAwaiterHandle::SignalAwaiterHandle(uint32_t p_managed_handle) + : MonoGCHandle(p_managed_handle) { + +#ifdef DEBUG_ENABLED + conn_target_id = 0; +#endif } SignalAwaiterHandle::~SignalAwaiterHandle() { + if (!completed) { GDMonoUtils::SignalAwaiter_FailureCallback thunk = CACHED_METHOD_THUNK(SignalAwaiter, FailureCallback); diff --git a/modules/mono/signal_awaiter_utils.h b/modules/mono/signal_awaiter_utils.h index 422ed4754f..0d615b5826 100644 --- a/modules/mono/signal_awaiter_utils.h +++ b/modules/mono/signal_awaiter_utils.h @@ -40,13 +40,30 @@ Error connect_signal_awaiter(Object *p_source, const String &p_signal, Object *p class SignalAwaiterHandle : public MonoGCHandle { + GDCLASS(SignalAwaiterHandle, MonoGCHandle) + bool completed; +#ifdef DEBUG_ENABLED + ObjectID conn_target_id; +#endif + + Variant _signal_callback(const Variant **p_args, int p_argcount, Variant::CallError &r_error); + +protected: + static void _bind_methods(); + public: _FORCE_INLINE_ bool is_completed() { return completed; } _FORCE_INLINE_ void set_completed(bool p_completed) { completed = p_completed; } - SignalAwaiterHandle(uint32_t p_handle); +#ifdef DEBUG_ENABLED + _FORCE_INLINE_ void set_connection_target(Object *p_target) { + conn_target_id = p_target->get_instance_id(); + } +#endif + + SignalAwaiterHandle(uint32_t p_managed_handle); ~SignalAwaiterHandle(); }; diff --git a/modules/mono/utils/string_utils.cpp b/modules/mono/utils/string_utils.cpp index de1a60dbd1..f26663ea11 100644 --- a/modules/mono/utils/string_utils.cpp +++ b/modules/mono/utils/string_utils.cpp @@ -126,3 +126,32 @@ String sformat(const String &p_text, const Variant &p1, const Variant &p2, const return new_string; } + +bool is_csharp_keyword(const String &p_name) { + + // Reserved keywords + + return p_name == "abstract" || p_name == "as" || p_name == "base" || p_name == "bool" || + p_name == "break" || p_name == "byte" || p_name == "case" || p_name == "catch" || + p_name == "char" || p_name == "checked" || p_name == "class" || p_name == "const" || + p_name == "continue" || p_name == "decimal" || p_name == "default" || p_name == "delegate" || + p_name == "do" || p_name == "double" || p_name == "else" || p_name == "enum" || + p_name == "event" || p_name == "explicit" || p_name == "extern" || p_name == "false" || + p_name == "finally" || p_name == "fixed" || p_name == "float" || p_name == "for" || + p_name == "forech" || p_name == "goto" || p_name == "if" || p_name == "implicit" || + p_name == "in" || p_name == "int" || p_name == "interface" || p_name == "internal" || + p_name == "is" || p_name == "lock" || p_name == "long" || p_name == "namespace" || + p_name == "new" || p_name == "null" || p_name == "object" || p_name == "operator" || + p_name == "out" || p_name == "override" || p_name == "params" || p_name == "private" || + p_name == "protected" || p_name == "public" || p_name == "readonly" || p_name == "ref" || + p_name == "return" || p_name == "sbyte" || p_name == "sealed" || p_name == "short" || + p_name == "sizeof" || p_name == "stackalloc" || p_name == "static" || p_name == "string" || + p_name == "struct" || p_name == "switch" || p_name == "this" || p_name == "throw" || + p_name == "true" || p_name == "try" || p_name == "typeof" || p_name == "uint" || p_name == "ulong" || + p_name == "unchecked" || p_name == "unsafe" || p_name == "ushort" || p_name == "using" || + p_name == "virtual" || p_name == "volatile" || p_name == "void" || p_name == "while"; +} + +String escape_csharp_keyword(const String &p_name) { + return is_csharp_keyword(p_name) ? "@" + p_name : p_name; +} diff --git a/modules/mono/utils/string_utils.h b/modules/mono/utils/string_utils.h index 2f2c3c2d89..a0d66ebdc3 100644 --- a/modules/mono/utils/string_utils.h +++ b/modules/mono/utils/string_utils.h @@ -35,4 +35,10 @@ String sformat(const String &p_text, const Variant &p1 = Variant(), const Variant &p2 = Variant(), const Variant &p3 = Variant(), const Variant &p4 = Variant(), const Variant &p5 = Variant()); +#ifdef TOOLS_ENABLED +bool is_csharp_keyword(const String &p_name); + +String escape_csharp_keyword(const String &p_name); +#endif + #endif // STRING_FORMAT_H diff --git a/modules/openssl/stream_peer_openssl.cpp b/modules/openssl/stream_peer_openssl.cpp index c19bdc4214..6d1d5485f3 100644 --- a/modules/openssl/stream_peer_openssl.cpp +++ b/modules/openssl/stream_peer_openssl.cpp @@ -30,7 +30,7 @@ #include "stream_peer_openssl.h" // Compatibility with OpenSSL 1.1.0. -#if OPENSSL_VERSION_NUMBER >= 0x10100000L +#if OPENSSL_VERSION_NUMBER >= 0x10100000L && !defined(LIBRESSL_VERSION_NUMBER) #define BIO_set_num(b, n) #else #define BIO_set_num(b, n) ((b)->num = (n)) @@ -269,7 +269,7 @@ int StreamPeerOpenSSL::_bio_puts(BIO *b, const char *str) { return _bio_write(b, str, strlen(str)); } -#if OPENSSL_VERSION_NUMBER >= 0x10100000L +#if OPENSSL_VERSION_NUMBER >= 0x10100000L && !defined(LIBRESSL_VERSION_NUMBER) BIO_METHOD *StreamPeerOpenSSL::_bio_method = NULL; BIO_METHOD *StreamPeerOpenSSL::_get_bio_method() { @@ -568,7 +568,7 @@ void StreamPeerOpenSSL::initialize_ssl() { load_certs_func = _load_certs; _create = _create_func; -#if OPENSSL_VERSION_NUMBER < 0x10100000L +#if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER) CRYPTO_malloc_init(); // Initialize malloc, free, etc for OpenSSL's use #endif SSL_library_init(); // Initialize OpenSSL's SSL libraries diff --git a/modules/openssl/stream_peer_openssl.h b/modules/openssl/stream_peer_openssl.h index 535114058d..ad09564447 100644 --- a/modules/openssl/stream_peer_openssl.h +++ b/modules/openssl/stream_peer_openssl.h @@ -53,7 +53,7 @@ private: static int _bio_gets(BIO *b, char *buf, int len); static int _bio_puts(BIO *b, const char *str); -#if OPENSSL_VERSION_NUMBER >= 0x10100000L +#if OPENSSL_VERSION_NUMBER >= 0x10100000L && !defined(LIBRESSL_VERSION_NUMBER) static BIO_METHOD *_bio_method; #else static BIO_METHOD _bio_method; diff --git a/modules/visual_script/visual_script_builtin_funcs.cpp b/modules/visual_script/visual_script_builtin_funcs.cpp index 972be5f5a4..1980f86114 100644 --- a/modules/visual_script/visual_script_builtin_funcs.cpp +++ b/modules/visual_script/visual_script_builtin_funcs.cpp @@ -65,6 +65,8 @@ const char *VisualScriptBuiltinFunc::func_name[VisualScriptBuiltinFunc::FUNC_MAX "decimals", "stepify", "lerp", + "inverse_lerp", + "range_lerp", "dectime", "randomize", "randi", @@ -194,9 +196,12 @@ int VisualScriptBuiltinFunc::get_func_argument_count(BuiltinFunc p_func) { case COLORN: return 2; case MATH_LERP: + case MATH_INVERSE_LERP: case MATH_DECTIME: case LOGIC_CLAMP: return 3; + case MATH_RANGE_LERP: + return 5; case FUNC_MAX: { } } @@ -297,7 +302,26 @@ PropertyInfo VisualScriptBuiltinFunc::get_input_value_port_info(int p_idx) const return PropertyInfo(Variant::REAL, "to"); else return PropertyInfo(Variant::REAL, "weight"); - + } break; + case MATH_INVERSE_LERP: { + if (p_idx == 0) + return PropertyInfo(Variant::REAL, "from"); + else if (p_idx == 1) + return PropertyInfo(Variant::REAL, "to"); + else + return PropertyInfo(Variant::REAL, "value"); + } break; + case MATH_RANGE_LERP: { + if (p_idx == 0) + return PropertyInfo(Variant::REAL, "value"); + else if (p_idx == 1) + return PropertyInfo(Variant::REAL, "istart"); + else if (p_idx == 2) + return PropertyInfo(Variant::REAL, "istop"); + else if (p_idx == 3) + return PropertyInfo(Variant::REAL, "ostart"); + else + return PropertyInfo(Variant::REAL, "ostop"); } break; case MATH_DECTIME: { if (p_idx == 0) @@ -495,6 +519,8 @@ PropertyInfo VisualScriptBuiltinFunc::get_output_value_port_info(int p_idx) cons } break; case MATH_STEPIFY: case MATH_LERP: + case MATH_INVERSE_LERP: + case MATH_RANGE_LERP: case MATH_DECTIME: { t = Variant::REAL; @@ -795,6 +821,22 @@ void VisualScriptBuiltinFunc::exec_func(BuiltinFunc p_func, const Variant **p_in VALIDATE_ARG_NUM(2); *r_return = Math::lerp((double)*p_inputs[0], (double)*p_inputs[1], (double)*p_inputs[2]); } break; + case VisualScriptBuiltinFunc::MATH_INVERSE_LERP: { + + VALIDATE_ARG_NUM(0); + VALIDATE_ARG_NUM(1); + VALIDATE_ARG_NUM(2); + *r_return = Math::inverse_lerp((double)*p_inputs[0], (double)*p_inputs[1], (double)*p_inputs[2]); + } break; + case VisualScriptBuiltinFunc::MATH_RANGE_LERP: { + + VALIDATE_ARG_NUM(0); + VALIDATE_ARG_NUM(1); + VALIDATE_ARG_NUM(2); + VALIDATE_ARG_NUM(3); + VALIDATE_ARG_NUM(4); + *r_return = Math::range_lerp((double)*p_inputs[0], (double)*p_inputs[1], (double)*p_inputs[2], (double)*p_inputs[3], (double)*p_inputs[4]); + } break; case VisualScriptBuiltinFunc::MATH_DECTIME: { VALIDATE_ARG_NUM(0); @@ -1203,6 +1245,8 @@ void VisualScriptBuiltinFunc::_bind_methods() { BIND_ENUM_CONSTANT(MATH_DECIMALS); BIND_ENUM_CONSTANT(MATH_STEPIFY); BIND_ENUM_CONSTANT(MATH_LERP); + BIND_ENUM_CONSTANT(MATH_INVERSE_LERP); + BIND_ENUM_CONSTANT(MATH_RANGE_LERP); BIND_ENUM_CONSTANT(MATH_DECTIME); BIND_ENUM_CONSTANT(MATH_RANDOMIZE); BIND_ENUM_CONSTANT(MATH_RAND); @@ -1282,6 +1326,8 @@ void register_visual_script_builtin_func_node() { VisualScriptLanguage::singleton->add_register_func("functions/built_in/decimals", create_builtin_func_node<VisualScriptBuiltinFunc::MATH_DECIMALS>); VisualScriptLanguage::singleton->add_register_func("functions/built_in/stepify", create_builtin_func_node<VisualScriptBuiltinFunc::MATH_STEPIFY>); VisualScriptLanguage::singleton->add_register_func("functions/built_in/lerp", create_builtin_func_node<VisualScriptBuiltinFunc::MATH_LERP>); + VisualScriptLanguage::singleton->add_register_func("functions/built_in/inverse_lerp", create_builtin_func_node<VisualScriptBuiltinFunc::MATH_INVERSE_LERP>); + VisualScriptLanguage::singleton->add_register_func("functions/built_in/range_lerp", create_builtin_func_node<VisualScriptBuiltinFunc::MATH_RANGE_LERP>); VisualScriptLanguage::singleton->add_register_func("functions/built_in/dectime", create_builtin_func_node<VisualScriptBuiltinFunc::MATH_DECTIME>); VisualScriptLanguage::singleton->add_register_func("functions/built_in/randomize", create_builtin_func_node<VisualScriptBuiltinFunc::MATH_RANDOMIZE>); VisualScriptLanguage::singleton->add_register_func("functions/built_in/rand", create_builtin_func_node<VisualScriptBuiltinFunc::MATH_RAND>); diff --git a/modules/visual_script/visual_script_builtin_funcs.h b/modules/visual_script/visual_script_builtin_funcs.h index 97ab307039..af24f16a2f 100644 --- a/modules/visual_script/visual_script_builtin_funcs.h +++ b/modules/visual_script/visual_script_builtin_funcs.h @@ -64,6 +64,8 @@ public: MATH_DECIMALS, MATH_STEPIFY, MATH_LERP, + MATH_INVERSE_LERP, + MATH_RANGE_LERP, MATH_DECTIME, MATH_RANDOMIZE, MATH_RAND, diff --git a/modules/visual_script/visual_script_editor.cpp b/modules/visual_script/visual_script_editor.cpp index 47ef0182dc..03015df844 100644 --- a/modules/visual_script/visual_script_editor.cpp +++ b/modules/visual_script/visual_script_editor.cpp @@ -809,7 +809,7 @@ void VisualScriptEditor::_update_members() { ti->set_text(0, E->get()); Variant var = script->get_variable_default_value(E->get()); - ti->set_suffix(0, "=" + String(var)); + ti->set_suffix(0, "= " + String(var)); ti->set_icon(0, type_icons[script->get_variable_info(E->get()).type]); ti->set_selectable(0, true); diff --git a/modules/visual_script/visual_script_nodes.cpp b/modules/visual_script/visual_script_nodes.cpp index 5a34fc3cd9..d3cd839cf3 100644 --- a/modules/visual_script/visual_script_nodes.cpp +++ b/modules/visual_script/visual_script_nodes.cpp @@ -532,6 +532,7 @@ String VisualScriptOperator::get_text() const { L"A or B", //OP_OR, L"A xor B", //OP_XOR, L"not A", //OP_NOT, + L"A in B", //OP_IN, }; return op_names[op]; diff --git a/platform/android/java/src/org/godotengine/godot/Godot.java b/platform/android/java/src/org/godotengine/godot/Godot.java index 053dfa631a..59fefc498f 100644 --- a/platform/android/java/src/org/godotengine/godot/Godot.java +++ b/platform/android/java/src/org/godotengine/godot/Godot.java @@ -191,6 +191,7 @@ public class Godot extends Activity implements SensorEventListener, IDownloaderC protected void onMainPause() {} protected void onMainResume() {} protected void onMainDestroy() {} + protected boolean onMainBackPressed() { return false; } protected void onGLDrawFrame(GL10 gl) {} protected void onGLSurfaceChanged(GL10 gl, int width, int height) {} // singletons will always miss first onGLSurfaceChanged call @@ -767,9 +768,16 @@ public class Godot extends Activity implements SensorEventListener, IDownloaderC */ @Override public void onBackPressed() { + boolean shouldQuit = true; + + for(int i=0;i<singleton_count;i++) { + if (singletons[i].onMainBackPressed()) { + shouldQuit = false; + } + } System.out.printf("** BACK REQUEST!\n"); - if (mView != null) { + if (shouldQuit && mView != null) { mView.queueEvent(new Runnable() { @Override public void run() { diff --git a/platform/android/java/src/org/godotengine/godot/GodotView.java b/platform/android/java/src/org/godotengine/godot/GodotView.java index 3c2ad7cc59..b807b952d4 100644 --- a/platform/android/java/src/org/godotengine/godot/GodotView.java +++ b/platform/android/java/src/org/godotengine/godot/GodotView.java @@ -285,13 +285,7 @@ public class GodotView extends GLSurfaceView implements InputDeviceListener { @Override public boolean onKeyDown(final int keyCode, KeyEvent event) { if (keyCode == KeyEvent.KEYCODE_BACK) { - queueEvent(new Runnable() { - @Override - public void run() { - GodotLib.back(); - } - }); - + activity.onBackPressed(); // press 'back' button should not terminate program //normal handle 'back' event in game logic return true; diff --git a/platform/iphone/export/export.cpp b/platform/iphone/export/export.cpp index c91781ce1d..0507ef19d6 100644 --- a/platform/iphone/export/export.cpp +++ b/platform/iphone/export/export.cpp @@ -397,7 +397,7 @@ Error EditorExportPlatformIOS::_codesign(String p_file, void *p_userdata) { codesign_args.push_back("-s"); codesign_args.push_back(data->preset->get(data->debug ? "application/code_sign_identity_debug" : "application/code_sign_identity_release")); codesign_args.push_back(p_file); - return OS::get_singleton()->execute("/usr/bin/codesign", codesign_args, true); + return OS::get_singleton()->execute("codesign", codesign_args, true); } return OK; } @@ -592,7 +592,15 @@ Error EditorExportPlatformIOS::export_project(const Ref<EditorExportPreset> &p_p return err; #ifdef OSX_ENABLED - ep.step("Making .xcarchive", 2); + ep.step("Code-signing dylibs", 2); + DirAccess *dylibs_dir = DirAccess::open(dest_dir + "dylibs"); + ERR_FAIL_COND_V(!dylibs_dir, ERR_CANT_OPEN); + CodesignData codesign_data(p_preset, p_debug); + err = _walk_dir_recursive(dylibs_dir, _codesign, &codesign_data); + memdelete(dylibs_dir); + ERR_FAIL_COND_V(err, err); + + ep.step("Making .xcarchive", 3); String archive_path = p_path.get_basename() + ".xcarchive"; List<String> archive_args; archive_args.push_back("-project"); @@ -608,15 +616,7 @@ Error EditorExportPlatformIOS::export_project(const Ref<EditorExportPreset> &p_p archive_args.push_back("archive"); archive_args.push_back("-archivePath"); archive_args.push_back(archive_path); - err = OS::get_singleton()->execute("/usr/bin/xcodebuild", archive_args, true); - ERR_FAIL_COND_V(err, err); - - ep.step("Code-signing dylibs", 3); - DirAccess *dylibs_dir = DirAccess::open(archive_path + "/Products/Applications/" + binary_name + ".app/dylibs"); - ERR_FAIL_COND_V(!dylibs_dir, ERR_CANT_OPEN); - CodesignData codesign_data(p_preset, p_debug); - err = _walk_dir_recursive(dylibs_dir, _codesign, &codesign_data); - memdelete(dylibs_dir); + err = OS::get_singleton()->execute("xcodebuild", archive_args, true); ERR_FAIL_COND_V(err, err); ep.step("Making .ipa", 4); @@ -628,7 +628,7 @@ Error EditorExportPlatformIOS::export_project(const Ref<EditorExportPreset> &p_p export_args.push_back(dest_dir + "export_options.plist"); export_args.push_back("-exportPath"); export_args.push_back(dest_dir); - err = OS::get_singleton()->execute("/usr/bin/xcodebuild", export_args, true); + err = OS::get_singleton()->execute("xcodebuild", export_args, true); ERR_FAIL_COND_V(err, err); #else print_line(".ipa can only be built on macOS. Leaving XCode project without building the package."); diff --git a/platform/iphone/game_center.h b/platform/iphone/game_center.h index c0a7830fe9..21f40fa362 100644 --- a/platform/iphone/game_center.h +++ b/platform/iphone/game_center.h @@ -43,11 +43,13 @@ class GameCenter : public Object { List<Variant> pending_events; - bool connected; + bool authenticated; + + void return_connect_error(const char *p_error_description); public: - Error connect(); - bool is_connected(); + void connect(); + bool is_authenticated(); Error post_score(Variant p_score); Error award_achievement(Variant p_params); @@ -55,6 +57,7 @@ public: void request_achievements(); void request_achievement_descriptions(); Error show_game_center(Variant p_params); + Error request_identity_verification_signature(); void game_center_closed(); diff --git a/platform/iphone/game_center.mm b/platform/iphone/game_center.mm index 3955b9f0aa..531b80eee3 100644 --- a/platform/iphone/game_center.mm +++ b/platform/iphone/game_center.mm @@ -49,8 +49,7 @@ extern "C" { GameCenter *GameCenter::instance = NULL; void GameCenter::_bind_methods() { - ClassDB::bind_method(D_METHOD("connect"), &GameCenter::connect); - ClassDB::bind_method(D_METHOD("is_connected"), &GameCenter::is_connected); + ClassDB::bind_method(D_METHOD("is_authenticated"), &GameCenter::is_authenticated); ClassDB::bind_method(D_METHOD("post_score"), &GameCenter::post_score); ClassDB::bind_method(D_METHOD("award_achievement"), &GameCenter::award_achievement); @@ -58,24 +57,41 @@ void GameCenter::_bind_methods() { ClassDB::bind_method(D_METHOD("request_achievements"), &GameCenter::request_achievements); ClassDB::bind_method(D_METHOD("request_achievement_descriptions"), &GameCenter::request_achievement_descriptions); ClassDB::bind_method(D_METHOD("show_game_center"), &GameCenter::show_game_center); + ClassDB::bind_method(D_METHOD("request_identity_verification_signature"), &GameCenter::request_identity_verification_signature); ClassDB::bind_method(D_METHOD("get_pending_event_count"), &GameCenter::get_pending_event_count); ClassDB::bind_method(D_METHOD("pop_pending_event"), &GameCenter::pop_pending_event); }; -Error GameCenter::connect() { +void GameCenter::return_connect_error(const char *p_error_description) { + authenticated = false; + Dictionary ret; + ret["type"] = "authentication"; + ret["result"] = "error"; + ret["error_code"] = 0; + ret["error_description"] = p_error_description; + pending_events.push_back(ret); +} + +void GameCenter::connect() { //if this class isn't available, game center isn't implemented if ((NSClassFromString(@"GKLocalPlayer")) == nil) { - GameCenter::get_singleton()->connected = false; - return ERR_UNAVAILABLE; + return_connect_error("GameCenter not available"); + return; } GKLocalPlayer *player = [GKLocalPlayer localPlayer]; - ERR_FAIL_COND_V(![player respondsToSelector:@selector(authenticateHandler)], ERR_UNAVAILABLE); + if (![player respondsToSelector:@selector(authenticateHandler)]) { + return_connect_error("GameCenter doesn't respond to 'authenticateHandler'"); + return; + } ViewController *root_controller = (ViewController *)((AppDelegate *)[[UIApplication sharedApplication] delegate]).window.rootViewController; - ERR_FAIL_COND_V(!root_controller, FAILED); + if (!root_controller) { + return_connect_error("Window doesn't have root ViewController"); + return; + } // This handler is called several times. First when the view needs to be shown, then again // after the view is cancelled or the user logs in. Or if the user's already logged in, it's @@ -90,23 +106,21 @@ Error GameCenter::connect() { if (player.isAuthenticated) { ret["result"] = "ok"; ret["player_id"] = [player.playerID UTF8String]; - GameCenter::get_singleton()->connected = true; + GameCenter::get_singleton()->authenticated = true; } else { ret["result"] = "error"; ret["error_code"] = error.code; ret["error_description"] = [error.localizedDescription UTF8String]; - GameCenter::get_singleton()->connected = false; + GameCenter::get_singleton()->authenticated = false; }; pending_events.push_back(ret); }; }); - - return OK; }; -bool GameCenter::is_connected() { - return connected; +bool GameCenter::is_authenticated() { + return authenticated; }; Error GameCenter::post_score(Variant p_score) { @@ -117,7 +131,7 @@ Error GameCenter::post_score(Variant p_score) { String category = params["category"]; NSString *cat_str = [[[NSString alloc] initWithUTF8String:category.utf8().get_data()] autorelease]; - GKScore *reporter = [[[GKScore alloc] initWithCategory:cat_str] autorelease]; + GKScore *reporter = [[[GKScore alloc] initWithLeaderboardIdentifier:cat_str] autorelease]; reporter.value = score; ERR_FAIL_COND_V([GKScore respondsToSelector:@selector(reportScores)], ERR_UNAVAILABLE); @@ -326,6 +340,34 @@ Error GameCenter::show_game_center(Variant p_params) { return OK; }; +Error GameCenter::request_identity_verification_signature() { + + ERR_FAIL_COND_V(!is_authenticated(), ERR_UNAUTHORIZED); + + GKLocalPlayer *player = [GKLocalPlayer localPlayer]; + [player generateIdentityVerificationSignatureWithCompletionHandler:^(NSURL *publicKeyUrl, NSData *signature, NSData *salt, uint64_t timestamp, NSError *error) { + + Dictionary ret; + ret["type"] = "identity_verification_signature"; + if (error == nil) { + ret["result"] = "ok"; + ret["public_key_url"] = [publicKeyUrl.absoluteString UTF8String]; + ret["signature"] = [[signature base64EncodedStringWithOptions:0] UTF8String]; + ret["salt"] = [[salt base64EncodedStringWithOptions:0] UTF8String]; + ret["timestamp"] = timestamp; + ret["player_id"] = [player.playerID UTF8String]; + } else { + ret["result"] = "error"; + ret["error_code"] = error.code; + ret["error_description"] = [error.localizedDescription UTF8String]; + }; + + pending_events.push_back(ret); + }]; + + return OK; +}; + void GameCenter::game_center_closed() { Dictionary ret; @@ -354,7 +396,7 @@ GameCenter *GameCenter::get_singleton() { GameCenter::GameCenter() { ERR_FAIL_COND(instance != NULL); instance = this; - connected = false; + authenticated = false; }; GameCenter::~GameCenter(){}; diff --git a/platform/osx/export/export.cpp b/platform/osx/export/export.cpp index 0ba0ddec7d..8a6f1dc04c 100644 --- a/platform/osx/export/export.cpp +++ b/platform/osx/export/export.cpp @@ -244,7 +244,7 @@ Error EditorExportPlatformOSX::_code_sign(const Ref<EditorExportPreset> &p_prese args.push_back(p_path); String str; - Error err = OS::get_singleton()->execute("/usr/bin/codesign", args, true, NULL, &str, NULL, true); + Error err = OS::get_singleton()->execute("codesign", args, true, NULL, &str, NULL, true); ERR_FAIL_COND_V(err != OK, err); print_line("codesign: " + str); @@ -271,7 +271,7 @@ Error EditorExportPlatformOSX::_create_dmg(const String &p_dmg_path, const Strin args.push_back(p_app_path_name); String str; - Error err = OS::get_singleton()->execute("/usr/bin/hdiutil", args, true, NULL, &str, NULL, true); + Error err = OS::get_singleton()->execute("hdiutil", args, true, NULL, &str, NULL, true); ERR_FAIL_COND_V(err != OK, err); print_line("hdiutil returned: " + str); diff --git a/platform/server/detect.py b/platform/server/detect.py index 04b38f280d..ffec2af933 100644 --- a/platform/server/detect.py +++ b/platform/server/detect.py @@ -12,6 +12,9 @@ def get_name(): def can_build(): + # Doesn't build against Godot 3.0 for now, disable to avoid confusing users + return False + if (os.name != "posix" or sys.platform == "darwin"): return False diff --git a/platform/x11/detect.py b/platform/x11/detect.py index 1f7f67fe10..8c68c9ffd1 100644 --- a/platform/x11/detect.py +++ b/platform/x11/detect.py @@ -239,6 +239,9 @@ def configure(env): if (platform.system() == "Linux"): env.Append(LIBS=['dl']) + if (platform.system().find("BSD") >= 0): + env.Append(LIBS=['execinfo']) + ## Cross-compilation if (is64 and env["bits"] == "32"): diff --git a/platform/x11/os_x11.cpp b/platform/x11/os_x11.cpp index e389c6932e..48e2d8f81e 100644 --- a/platform/x11/os_x11.cpp +++ b/platform/x11/os_x11.cpp @@ -35,7 +35,11 @@ #include "servers/physics/physics_server_sw.h" #include "servers/visual/visual_server_raster.h" #include "servers/visual/visual_server_wrap_mt.h" + +#ifdef HAVE_MNTENT #include <mntent.h> +#endif + #include <stdio.h> #include <stdlib.h> #include <string.h> @@ -1939,7 +1943,7 @@ Error OS_X11::shell_open(String p_uri) { Error ok; List<String> args; args.push_back(p_uri); - ok = execute("/usr/bin/xdg-open", args, false); + ok = execute("xdg-open", args, false); if (ok == OK) return OK; ok = execute("gnome-open", args, false); @@ -2003,7 +2007,7 @@ String OS_X11::get_system_dir(SystemDir p_dir) const { String pipe; List<String> arg; arg.push_back(xdgparam); - Error err = const_cast<OS_X11 *>(this)->execute("/usr/bin/xdg-user-dir", arg, true, NULL, &pipe); + Error err = const_cast<OS_X11 *>(this)->execute("xdg-user-dir", arg, true, NULL, &pipe); if (err != OK) return "."; return pipe.strip_edges(); @@ -2053,7 +2057,7 @@ void OS_X11::alert(const String &p_alert, const String &p_title) { args.push_back(p_title); args.push_back(p_alert); - execute("/usr/bin/xmessage", args, true); + execute("xmessage", args, true); } void OS_X11::set_icon(const Ref<Image> &p_icon) { @@ -2182,6 +2186,7 @@ static String get_mountpoint(const String &p_path) { return ""; } +#ifdef HAVE_MNTENT dev_t dev = s.st_dev; FILE *fd = setmntent("/proc/mounts", "r"); if (!fd) { @@ -2199,6 +2204,7 @@ static String get_mountpoint(const String &p_path) { } endmntent(fd); +#endif return ""; } @@ -2236,12 +2242,12 @@ Error OS_X11::move_to_trash(const String &p_path) { List<String> args; args.push_back("-p"); args.push_back(trashcan); - Error err = execute("/bin/mkdir", args, true); + Error err = execute("mkdir", args, true); if (err == OK) { List<String> args2; args2.push_back(p_path); args2.push_back(trashcan); - err = execute("/bin/mv", args2, true); + err = execute("mv", args2, true); } return err; diff --git a/scene/2d/navigation_polygon.cpp b/scene/2d/navigation_polygon.cpp index 352ec3b300..35f94bff59 100644 --- a/scene/2d/navigation_polygon.cpp +++ b/scene/2d/navigation_polygon.cpp @@ -329,7 +329,7 @@ void NavigationPolygonInstance::_notification(int p_what) { break; } - c = Object::cast_to<Node2D>(get_parent()); + c = Object::cast_to<Node2D>(c->get_parent()); } } break; diff --git a/scene/2d/parallax_background.cpp b/scene/2d/parallax_background.cpp index 0ddcb7b51b..a13ce6278e 100644 --- a/scene/2d/parallax_background.cpp +++ b/scene/2d/parallax_background.cpp @@ -49,8 +49,8 @@ void ParallaxBackground::_notification(int p_what) { void ParallaxBackground::_camera_moved(const Transform2D &p_transform) { - set_scroll_offset(p_transform.get_origin()); set_scroll_scale(p_transform.get_scale().dot(Vector2(0.5, 0.5))); + set_scroll_offset(p_transform.get_origin() / p_transform.get_scale()); } void ParallaxBackground::set_scroll_scale(float p_scale) { diff --git a/scene/3d/arvr_nodes.cpp b/scene/3d/arvr_nodes.cpp index c6b6c02129..064a249190 100644 --- a/scene/3d/arvr_nodes.cpp +++ b/scene/3d/arvr_nodes.cpp @@ -204,7 +204,7 @@ void ARVRController::_notification(int p_what) { int mask = 1; // check button states for (int i = 0; i < 16; i++) { - bool was_pressed = (button_states && mask) == mask; + bool was_pressed = (button_states & mask) == mask; bool is_pressed = Input::get_singleton()->is_joy_button_pressed(joy_id, i); if (!was_pressed && is_pressed) { @@ -336,6 +336,7 @@ String ARVRController::get_configuration_warning() const { ARVRController::ARVRController() { controller_id = 0; is_active = true; + button_states = 0; }; ARVRController::~ARVRController(){ diff --git a/scene/animation/animation_player.cpp b/scene/animation/animation_player.cpp index fed3fc1806..2ecb184733 100644 --- a/scene/animation/animation_player.cpp +++ b/scene/animation/animation_player.cpp @@ -533,12 +533,12 @@ void AnimationPlayer::_animation_process_data(PlaybackData &cd, float p_delta, f if (&cd == &playback.current) { - if (!backwards && cd.pos < len && next_pos == len /*&& playback.blend.empty()*/) { + if (!backwards && cd.pos <= len && next_pos == len /*&& playback.blend.empty()*/) { //playback finished end_notify = true; } - if (backwards && cd.pos > 0 && next_pos == 0 /*&& playback.blend.empty()*/) { + if (backwards && cd.pos >= 0 && next_pos == 0 /*&& playback.blend.empty()*/) { //playback finished end_notify = true; } diff --git a/scene/gui/item_list.cpp b/scene/gui/item_list.cpp index a034c7224f..623a110263 100644 --- a/scene/gui/item_list.cpp +++ b/scene/gui/item_list.cpp @@ -489,7 +489,7 @@ void ItemList::_gui_input(const Ref<InputEvent> &p_event) { if (mb->get_button_index() == BUTTON_RIGHT) { - emit_signal("item_rmb_selected", i, pos); + emit_signal("item_rmb_selected", i, get_local_mouse_position()); } } else { @@ -500,7 +500,7 @@ void ItemList::_gui_input(const Ref<InputEvent> &p_event) { if (items[i].selected && mb->get_button_index() == BUTTON_RIGHT) { - emit_signal("item_rmb_selected", i, pos); + emit_signal("item_rmb_selected", i, get_local_mouse_position()); } else { bool selected = !items[i].selected; @@ -515,7 +515,7 @@ void ItemList::_gui_input(const Ref<InputEvent> &p_event) { if (mb->get_button_index() == BUTTON_RIGHT) { - emit_signal("item_rmb_selected", i, pos); + emit_signal("item_rmb_selected", i, get_local_mouse_position()); } else if (/*select_mode==SELECT_SINGLE &&*/ mb->is_doubleclick()) { emit_signal("item_activated", i); diff --git a/scene/gui/rich_text_label.cpp b/scene/gui/rich_text_label.cpp index c2ce2a633e..07b49538d9 100644 --- a/scene/gui/rich_text_label.cpp +++ b/scene/gui/rich_text_label.cpp @@ -354,7 +354,7 @@ int RichTextLabel::_process_line(ItemFrame *p_frame, const Vector2 &p_ofs, int & cw = font->get_char_size(c[i], c[i + 1]).x; draw_rect(Rect2(p_ofs.x + pofs, p_ofs.y + y, cw, lh), selection_bg); if (visible) - font->draw_char(ci, p_ofs + Point2(align_ofs + pofs, y + lh - (fh - ascent)), c[i], c[i + 1], selection_fg); + font->draw_char(ci, p_ofs + Point2(align_ofs + pofs, y + lh - (fh - ascent)), c[i], c[i + 1], override_selected_font_color ? selection_fg : color); } else { if (visible) @@ -1376,6 +1376,16 @@ bool RichTextLabel::is_meta_underlined() const { return underline_meta; } +void RichTextLabel::set_override_selected_font_color(bool p_override_selected_font_color) { + + override_selected_font_color = p_override_selected_font_color; +} + +bool RichTextLabel::is_overriding_selected_font_color() const { + + return override_selected_font_color; +} + void RichTextLabel::set_offset(int p_pixel) { vscroll->set_value(p_pixel); @@ -1906,6 +1916,9 @@ void RichTextLabel::_bind_methods() { ClassDB::bind_method(D_METHOD("set_meta_underline", "enable"), &RichTextLabel::set_meta_underline); ClassDB::bind_method(D_METHOD("is_meta_underlined"), &RichTextLabel::is_meta_underlined); + ClassDB::bind_method(D_METHOD("set_override_selected_font_color", "override"), &RichTextLabel::set_override_selected_font_color); + ClassDB::bind_method(D_METHOD("is_overriding_selected_font_color"), &RichTextLabel::is_overriding_selected_font_color); + ClassDB::bind_method(D_METHOD("set_scroll_active", "active"), &RichTextLabel::set_scroll_active); ClassDB::bind_method(D_METHOD("is_scroll_active"), &RichTextLabel::is_scroll_active); @@ -1948,6 +1961,7 @@ void RichTextLabel::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::INT, "visible_characters", PROPERTY_HINT_RANGE, "-1,128000,1"), "set_visible_characters", "get_visible_characters"); ADD_PROPERTY(PropertyInfo(Variant::REAL, "percent_visible", PROPERTY_HINT_RANGE, "0,1,0.001"), "set_percent_visible", "get_percent_visible"); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "override_selected_font_color"), "set_override_selected_font_color", "is_overriding_selected_font_color"); ADD_SIGNAL(MethodInfo("meta_clicked", PropertyInfo(Variant::NIL, "meta", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NIL_IS_VARIANT))); @@ -2003,6 +2017,7 @@ RichTextLabel::RichTextLabel() { tab_size = 4; default_align = ALIGN_LEFT; underline_meta = true; + override_selected_font_color = false; scroll_visible = false; scroll_follow = false; diff --git a/scene/gui/rich_text_label.h b/scene/gui/rich_text_label.h index 24c1e5eb59..f9e37b1094 100644 --- a/scene/gui/rich_text_label.h +++ b/scene/gui/rich_text_label.h @@ -221,6 +221,7 @@ private: int tab_size; bool underline_meta; + bool override_selected_font_color; Align default_align; @@ -313,6 +314,9 @@ public: void set_meta_underline(bool p_underline); bool is_meta_underlined() const; + void set_override_selected_font_color(bool p_override_selected_font_color); + bool is_overriding_selected_font_color() const; + void set_scroll_active(bool p_active); bool is_scroll_active() const; diff --git a/scene/gui/slider.cpp b/scene/gui/slider.cpp index 116e0ac354..e88742a3e3 100644 --- a/scene/gui/slider.cpp +++ b/scene/gui/slider.cpp @@ -157,6 +157,12 @@ void Slider::_notification(int p_what) { mouse_inside = false; update(); } break; + case NOTIFICATION_VISIBILITY_CHANGED: // fallthrough + case NOTIFICATION_EXIT_TREE: { + + mouse_inside = false; + grab.active = false; + } break; case NOTIFICATION_DRAW: { RID ci = get_canvas_item(); Size2i size = get_size(); diff --git a/scene/gui/tab_container.cpp b/scene/gui/tab_container.cpp index 6e50614e8f..cfe924ecd4 100644 --- a/scene/gui/tab_container.cpp +++ b/scene/gui/tab_container.cpp @@ -94,15 +94,20 @@ void TabContainer::_gui_input(const Ref<InputEvent> &p_event) { // Handle navigation buttons. if (buttons_visible_cache) { + int popup_ofs = 0; + if (popup) { + popup_ofs = menu->get_width(); + } + Ref<Texture> increment = get_icon("increment"); Ref<Texture> decrement = get_icon("decrement"); - if (pos.x > size.width - increment->get_width()) { + if (pos.x > size.width - increment->get_width() - popup_ofs) { if (last_tab_cache < tabs.size() - 1) { first_tab_cache += 1; update(); } return; - } else if (pos.x > size.width - increment->get_width() - decrement->get_width()) { + } else if (pos.x > size.width - increment->get_width() - decrement->get_width() - popup_ofs) { if (first_tab_cache > 0) { first_tab_cache -= 1; update(); diff --git a/scene/gui/text_edit.cpp b/scene/gui/text_edit.cpp index 33c29547be..de69406b37 100644 --- a/scene/gui/text_edit.cpp +++ b/scene/gui/text_edit.cpp @@ -732,10 +732,6 @@ void TextEdit::_notification(int p_what) { VisualServer::get_singleton()->canvas_item_add_rect(ci, Rect2(xmargin_beg, ofs_y, xmargin_end - xmargin_beg, get_row_height()), cache.mark_color); } - if (line == cursor.line) { - VisualServer::get_singleton()->canvas_item_add_rect(ci, Rect2(0, ofs_y, xmargin_end, get_row_height()), cache.current_line_color); - } - if (text.is_breakpoint(line) && !draw_breakpoint_gutter) { #ifdef TOOLS_ENABLED VisualServer::get_singleton()->canvas_item_add_rect(ci, Rect2(xmargin_beg, ofs_y + get_row_height() - EDSCALE, xmargin_end - xmargin_beg, EDSCALE), cache.breakpoint_color); @@ -764,6 +760,7 @@ void TextEdit::_notification(int p_what) { cache.font->draw(ci, Point2(cache.style_normal->get_margin(MARGIN_LEFT) + cache.breakpoint_gutter_width, ofs_y + cache.font->get_ascent()), fc, cache.line_number_color); } + //loop through charcters in one line for (int j = 0; j < str.length(); j++) { //look for keyword @@ -952,10 +949,22 @@ void TextEdit::_notification(int p_what) { } } + //current line highlighting bool in_selection = (selection.active && line >= selection.from_line && line <= selection.to_line && (line > selection.from_line || j >= selection.from_column) && (line < selection.to_line || j < selection.to_column)); + if (line == cursor.line) { + if (j == 0) + //first char + VisualServer::get_singleton()->canvas_item_add_rect(ci, Rect2(0, ofs_y, (char_ofs + char_margin), get_row_height()), cache.current_line_color); + else if (j == str.length() - 1) + //last char + VisualServer::get_singleton()->canvas_item_add_rect(ci, Rect2(char_ofs + char_margin + char_w, ofs_y, xmargin_end - (char_ofs + char_margin + char_w), get_row_height()), cache.current_line_color); + + if (!in_selection) + VisualServer::get_singleton()->canvas_item_add_rect(ci, Rect2(Point2i(char_ofs + char_margin, ofs_y), Size2i(char_w, get_row_height())), cache.current_line_color); + } + if (in_selection) { - //inside selection! VisualServer::get_singleton()->canvas_item_add_rect(ci, Rect2(Point2i(char_ofs + char_margin, ofs_y), Size2i(char_w, get_row_height())), cache.selection_color); } @@ -998,7 +1007,7 @@ void TextEdit::_notification(int p_what) { if (brace_open_mismatch) color = cache.brace_mismatch_color; - cache.font->draw_char(ci, Point2i(char_ofs + char_margin, ofs_y + ascent), '_', str[j + 1], in_selection ? cache.font_selected_color : color); + cache.font->draw_char(ci, Point2i(char_ofs + char_margin, ofs_y + ascent), '_', str[j + 1], in_selection && override_selected_font_color ? cache.font_selected_color : color); } if ( @@ -1007,7 +1016,7 @@ void TextEdit::_notification(int p_what) { if (brace_close_mismatch) color = cache.brace_mismatch_color; - cache.font->draw_char(ci, Point2i(char_ofs + char_margin, ofs_y + ascent), '_', str[j + 1], in_selection ? cache.font_selected_color : color); + cache.font->draw_char(ci, Point2i(char_ofs + char_margin, ofs_y + ascent), '_', str[j + 1], in_selection && override_selected_font_color ? cache.font_selected_color : color); } } @@ -1066,15 +1075,15 @@ void TextEdit::_notification(int p_what) { } if (str[j] >= 32) { - int w = cache.font->draw_char(ci, Point2i(char_ofs + char_margin, ofs_y + ascent), str[j], str[j + 1], in_selection ? cache.font_selected_color : color); + int w = cache.font->draw_char(ci, Point2i(char_ofs + char_margin, ofs_y + ascent), str[j], str[j + 1], in_selection && override_selected_font_color ? cache.font_selected_color : color); if (underlined) { - draw_rect(Rect2(char_ofs + char_margin, ofs_y + ascent + 2, w, 1), in_selection ? cache.font_selected_color : color); + draw_rect(Rect2(char_ofs + char_margin, ofs_y + ascent + 2, w, 1), in_selection && override_selected_font_color ? cache.font_selected_color : color); } } else if (draw_tabs && str[j] == '\t') { int yofs = (get_row_height() - cache.tab_icon->get_height()) / 2; - cache.tab_icon->draw(ci, Point2(char_ofs + char_margin, ofs_y + yofs), in_selection ? cache.font_selected_color : color); + cache.tab_icon->draw(ci, Point2(char_ofs + char_margin, ofs_y + yofs), in_selection && override_selected_font_color ? cache.font_selected_color : color); } char_ofs += char_w; @@ -4256,6 +4265,13 @@ bool TextEdit::is_drawing_tabs() const { return draw_tabs; } +void TextEdit::set_override_selected_font_color(bool p_override_selected_font_color) { + override_selected_font_color = p_override_selected_font_color; +} +bool TextEdit::is_overriding_selected_font_color() const { + return override_selected_font_color; +} + void TextEdit::set_insert_mode(bool p_enabled) { insert_mode = p_enabled; update(); @@ -4821,6 +4837,9 @@ void TextEdit::_bind_methods() { ClassDB::bind_method(D_METHOD("set_highlight_all_occurrences", "enable"), &TextEdit::set_highlight_all_occurrences); ClassDB::bind_method(D_METHOD("is_highlight_all_occurrences_enabled"), &TextEdit::is_highlight_all_occurrences_enabled); + ClassDB::bind_method(D_METHOD("set_override_selected_font_color", "override"), &TextEdit::set_override_selected_font_color); + ClassDB::bind_method(D_METHOD("is_overriding_selected_font_color"), &TextEdit::is_overriding_selected_font_color); + ClassDB::bind_method(D_METHOD("set_syntax_coloring", "enable"), &TextEdit::set_syntax_coloring); ClassDB::bind_method(D_METHOD("is_syntax_coloring_enabled"), &TextEdit::is_syntax_coloring_enabled); @@ -4838,6 +4857,7 @@ void TextEdit::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::BOOL, "syntax_highlighting"), "set_syntax_coloring", "is_syntax_coloring_enabled"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "show_line_numbers"), "set_show_line_numbers", "is_show_line_numbers_enabled"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "highlight_all_occurrences"), "set_highlight_all_occurrences", "is_highlight_all_occurrences_enabled"); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "override_selected_font_color"), "set_override_selected_font_color", "is_overriding_selected_font_color"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "smooth_scrolling"), "set_smooth_scroll_enable", "is_smooth_scroll_enabled"); ADD_PROPERTY(PropertyInfo(Variant::REAL, "v_scroll_speed"), "set_v_scroll_speed", "get_v_scroll_speed"); @@ -4868,6 +4888,7 @@ TextEdit::TextEdit() { readonly = false; setting_row = false; draw_tabs = false; + override_selected_font_color = false; draw_caret = true; max_chars = 0; clear(); diff --git a/scene/gui/text_edit.h b/scene/gui/text_edit.h index 7e61c4e8b1..03f412729d 100644 --- a/scene/gui/text_edit.h +++ b/scene/gui/text_edit.h @@ -238,6 +238,7 @@ class TextEdit : public Control { bool setting_row; bool wrap; bool draw_tabs; + bool override_selected_font_color; bool cursor_changed_dirty; bool text_changed_dirty; bool undo_enabled; @@ -482,6 +483,8 @@ public: void set_indent_size(const int p_size); void set_draw_tabs(bool p_draw); bool is_drawing_tabs() const; + void set_override_selected_font_color(bool p_override_selected_font_color); + bool is_overriding_selected_font_color() const; void set_insert_mode(bool p_enabled); bool is_insert_mode() const; diff --git a/scene/main/node.cpp b/scene/main/node.cpp index c2a31b4a8b..cee25b53a1 100755 --- a/scene/main/node.cpp +++ b/scene/main/node.cpp @@ -212,6 +212,8 @@ void Node::_propagate_enter_tree() { emit_signal(SceneStringNames::get_singleton()->tree_entered); + data.tree->node_added(this); + data.blocked++; //block while adding children diff --git a/scene/main/scene_tree.cpp b/scene/main/scene_tree.cpp index 7a28e2a6f8..d4be683a2b 100644 --- a/scene/main/scene_tree.cpp +++ b/scene/main/scene_tree.cpp @@ -85,6 +85,11 @@ void SceneTree::tree_changed() { emit_signal(tree_changed_name); } +void SceneTree::node_added(Node *p_node) { + + emit_signal(node_added_name, p_node); +} + void SceneTree::node_removed(Node *p_node) { if (current_scene == p_node) { @@ -1172,7 +1177,7 @@ void SceneTree::_update_root_rect() { } } -void SceneTree::set_screen_stretch(StretchMode p_mode, StretchAspect p_aspect, const Size2 p_minsize, int p_shrink) { +void SceneTree::set_screen_stretch(StretchMode p_mode, StretchAspect p_aspect, const Size2 p_minsize, real_t p_shrink) { stretch_mode = p_mode; stretch_aspect = p_aspect; @@ -2189,6 +2194,7 @@ void SceneTree::_bind_methods() { ClassDB::bind_method(D_METHOD("_server_disconnected"), &SceneTree::_server_disconnected); ADD_SIGNAL(MethodInfo("tree_changed")); + ADD_SIGNAL(MethodInfo("node_added", PropertyInfo(Variant::OBJECT, "node"))); ADD_SIGNAL(MethodInfo("node_removed", PropertyInfo(Variant::OBJECT, "node"))); ADD_SIGNAL(MethodInfo("screen_resized")); ADD_SIGNAL(MethodInfo("node_configuration_warning_changed", PropertyInfo(Variant::OBJECT, "node"))); @@ -2260,6 +2266,7 @@ SceneTree::SceneTree() { root = NULL; current_frame = 0; tree_changed_name = "tree_changed"; + node_added_name = "node_added"; node_removed_name = "node_removed"; ugc_locked = false; call_lock = 0; diff --git a/scene/main/scene_tree.h b/scene/main/scene_tree.h index f3e689adab..bc3efdc42f 100644 --- a/scene/main/scene_tree.h +++ b/scene/main/scene_tree.h @@ -124,6 +124,7 @@ private: bool input_handled; Size2 last_screen_size; StringName tree_changed_name; + StringName node_added_name; StringName node_removed_name; int64_t current_frame; @@ -147,7 +148,7 @@ private: StretchMode stretch_mode; StretchAspect stretch_aspect; Size2i stretch_min; - int stretch_shrink; + real_t stretch_shrink; void _update_root_rect(); @@ -233,6 +234,7 @@ private: void _rpc(Node *p_from, int p_to, bool p_unreliable, bool p_set, const StringName &p_name, const Variant **p_arg, int p_argcount); void tree_changed(); + void node_added(Node *p_node); void node_removed(Node *p_node); Group *add_to_group(const StringName &p_group, Node *p_node); @@ -415,7 +417,7 @@ public: void get_nodes_in_group(const StringName &p_group, List<Node *> *p_list); bool has_group(const StringName &p_identifier) const; - void set_screen_stretch(StretchMode p_mode, StretchAspect p_aspect, const Size2 p_minsize, int p_shrink = 1); + void set_screen_stretch(StretchMode p_mode, StretchAspect p_aspect, const Size2 p_minsize, real_t p_shrink = 1); //void change_scene(const String& p_path); //Node *get_loaded_scene(); diff --git a/scene/main/viewport.cpp b/scene/main/viewport.cpp index 37a393b55b..0a02f471c1 100644 --- a/scene/main/viewport.cpp +++ b/scene/main/viewport.cpp @@ -2371,8 +2371,13 @@ void Viewport::input(const Ref<InputEvent> &p_event) { ERR_FAIL_COND(!is_inside_tree()); - get_tree()->_call_input_pause(input_group, "_input", p_event); //not a bug, must happen before GUI, order is _input -> gui input -> _unhandled input - _gui_input_event(p_event); + if (!get_tree()->is_input_handled()) { + get_tree()->_call_input_pause(input_group, "_input", p_event); //not a bug, must happen before GUI, order is _input -> gui input -> _unhandled input + } + + if (!get_tree()->is_input_handled()) { + _gui_input_event(p_event); + } //get_tree()->call_group(SceneTree::GROUP_CALL_REVERSE|SceneTree::GROUP_CALL_REALTIME|SceneTree::GROUP_CALL_MULIILEVEL,gui_input_group,"_gui_input",p_event); //special one for GUI, as controls use their own process check } @@ -2711,7 +2716,7 @@ void Viewport::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::INT, "debug_draw", PROPERTY_HINT_ENUM, "Disabled,Unshaded,Overdraw,Wireframe"), "set_debug_draw", "get_debug_draw"); ADD_GROUP("Render Target", "render_target_"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "render_target_v_flip"), "set_vflip", "get_vflip"); - ADD_PROPERTY(PropertyInfo(Variant::BOOL, "render_target_clear_mode", PROPERTY_HINT_ENUM, "Always,Never,NextFrame"), "set_clear_mode", "get_clear_mode"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "render_target_clear_mode", PROPERTY_HINT_ENUM, "Always,Never,Next Frame"), "set_clear_mode", "get_clear_mode"); ADD_PROPERTY(PropertyInfo(Variant::INT, "render_target_update_mode", PROPERTY_HINT_ENUM, "Disabled,Once,When Visible,Always"), "set_update_mode", "get_update_mode"); ADD_GROUP("Audio Listener", "audio_listener_"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "audio_listener_enable_2d"), "set_as_audio_listener_2d", "is_audio_listener_2d"); diff --git a/servers/physics/joints/pin_joint_sw.h b/servers/physics/joints/pin_joint_sw.h index ee9272ce06..f6c11c49b0 100644 --- a/servers/physics/joints/pin_joint_sw.h +++ b/servers/physics/joints/pin_joint_sw.h @@ -86,8 +86,8 @@ public: void set_pos_a(const Vector3 &p_pos) { m_pivotInA = p_pos; } void set_pos_b(const Vector3 &p_pos) { m_pivotInB = p_pos; } - Vector3 get_position_a() { return m_pivotInB; } - Vector3 get_position_b() { return m_pivotInA; } + Vector3 get_position_a() { return m_pivotInA; } + Vector3 get_position_b() { return m_pivotInB; } PinJointSW(BodySW *p_body_a, const Vector3 &p_pos_a, BodySW *p_body_b, const Vector3 &p_pos_b); ~PinJointSW(); diff --git a/servers/visual/shader_language.cpp b/servers/visual/shader_language.cpp index b2a11deea1..8fee6050a0 100644 --- a/servers/visual/shader_language.cpp +++ b/servers/visual/shader_language.cpp @@ -2586,6 +2586,8 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons } else if (tk.type == TK_BRACKET_OPEN) { Node *index = _parse_and_reduce_expression(p_block, p_builtin_types); + if (!index) + return NULL; if (index->get_datatype() != TYPE_INT && index->get_datatype() != TYPE_UINT) { _set_error("Only integer datatypes are allowed for indexing"); diff --git a/servers/visual_server.cpp b/servers/visual_server.cpp index 979b2ed8ec..64bc978037 100644 --- a/servers/visual_server.cpp +++ b/servers/visual_server.cpp @@ -62,6 +62,31 @@ RID VisualServer::texture_create_from_image(const Ref<Image> &p_image, uint32_t return texture; } +Array VisualServer::_texture_debug_usage_bind() { + + List<TextureInfo> list; + texture_debug_usage(&list); + Array arr; + for (const List<TextureInfo>::Element *E = list.front(); E; E = E->next()) { + + Dictionary dict; + dict["texture"] = E->get().texture; + dict["size"] = E->get().size; + dict["format"] = E->get().format; + dict["bytes"] = E->get().bytes; + dict["path"] = E->get().path; + arr.push_back(dict); + } + return arr; +} + +Array VisualServer::_shader_get_param_list_bind(RID p_shader) const { + + List<PropertyInfo> l; + shader_get_param_list(p_shader, &l); + return convert_property_list(&l); +} + RID VisualServer::get_test_texture() { if (test_texture.is_valid()) { @@ -1443,22 +1468,395 @@ Array VisualServer::mesh_surface_get_blend_shape_arrays(RID p_mesh, int p_surfac } } +Array VisualServer::_mesh_surface_get_skeleton_aabb_bind(RID p_mesh, int p_surface) const { + + Vector<Rect3> vec = VS::get_singleton()->mesh_surface_get_skeleton_aabb(p_mesh, p_surface); + Array arr; + for (int i = 0; i < vec.size(); i++) { + arr[i] = vec[i]; + } + return arr; +} + void VisualServer::_bind_methods() { ClassDB::bind_method(D_METHOD("force_sync"), &VisualServer::sync); ClassDB::bind_method(D_METHOD("force_draw"), &VisualServer::draw); - ClassDB::bind_method(D_METHOD("request_frame_drawn_callback", "where", "method", "userdata"), &VisualServer::request_frame_drawn_callback); + ClassDB::bind_method(D_METHOD("texture_create"), &VisualServer::texture_create); ClassDB::bind_method(D_METHOD("texture_create_from_image", "image", "flags"), &VisualServer::texture_create_from_image, DEFVAL(TEXTURE_FLAGS_DEFAULT)); - //ClassDB::bind_method(D_METHOD("texture_allocate"),&VisualServer::texture_allocate,DEFVAL( TEXTURE_FLAGS_DEFAULT ) ); - //ClassDB::bind_method(D_METHOD("texture_set_data"),&VisualServer::texture_blit_rect,DEFVAL( CUBEMAP_LEFT ) ); - //ClassDB::bind_method(D_METHOD("texture_get_rect"),&VisualServer::texture_get_rect ); + ClassDB::bind_method(D_METHOD("texture_allocate", "texture", "width", "height", "format", "flags"), &VisualServer::texture_allocate, DEFVAL(TEXTURE_FLAGS_DEFAULT)); + ClassDB::bind_method(D_METHOD("texture_set_data", "texture", "image", "cube_side"), &VisualServer::texture_set_data, DEFVAL(CUBEMAP_LEFT)); + ClassDB::bind_method(D_METHOD("texture_get_data", "texture", "cube_side"), &VisualServer::texture_get_data, DEFVAL(CUBEMAP_LEFT)); ClassDB::bind_method(D_METHOD("texture_set_flags", "texture", "flags"), &VisualServer::texture_set_flags); ClassDB::bind_method(D_METHOD("texture_get_flags", "texture"), &VisualServer::texture_get_flags); + ClassDB::bind_method(D_METHOD("texture_get_format", "texture"), &VisualServer::texture_get_format); + ClassDB::bind_method(D_METHOD("texture_get_texid", "texture"), &VisualServer::texture_get_texid); ClassDB::bind_method(D_METHOD("texture_get_width", "texture"), &VisualServer::texture_get_width); ClassDB::bind_method(D_METHOD("texture_get_height", "texture"), &VisualServer::texture_get_height); - + ClassDB::bind_method(D_METHOD("texture_set_size_override", "texture", "width", "height"), &VisualServer::texture_set_size_override); + ClassDB::bind_method(D_METHOD("texture_set_path", "texture", "path"), &VisualServer::texture_set_path); + ClassDB::bind_method(D_METHOD("texture_get_path", "texture"), &VisualServer::texture_get_path); ClassDB::bind_method(D_METHOD("texture_set_shrink_all_x2_on_set_data", "shrink"), &VisualServer::texture_set_shrink_all_x2_on_set_data); + + ClassDB::bind_method(D_METHOD("texture_debug_usage"), &VisualServer::_texture_debug_usage_bind); + ClassDB::bind_method(D_METHOD("textures_keep_original", "enable"), &VisualServer::textures_keep_original); + + ClassDB::bind_method(D_METHOD("sky_create"), &VisualServer::sky_create); + ClassDB::bind_method(D_METHOD("sky_set_texture", "sky", "cube_map", "radiance_size"), &VisualServer::sky_set_texture); + + ClassDB::bind_method(D_METHOD("shader_create"), &VisualServer::shader_create); + ClassDB::bind_method(D_METHOD("shader_set_code", "shader", "code"), &VisualServer::shader_set_code); + ClassDB::bind_method(D_METHOD("shader_get_code", "shader"), &VisualServer::shader_get_code); + ClassDB::bind_method(D_METHOD("shader_get_param_list", "shader"), &VisualServer::_shader_get_param_list_bind); + ClassDB::bind_method(D_METHOD("shader_set_default_texture_param", "shader", "name", "texture"), &VisualServer::shader_set_default_texture_param); + ClassDB::bind_method(D_METHOD("shader_get_default_texture_param", "shader", "name"), &VisualServer::shader_get_default_texture_param); + + ClassDB::bind_method(D_METHOD("material_create"), &VisualServer::material_create); + ClassDB::bind_method(D_METHOD("material_set_shader", "shader_material", "shader"), &VisualServer::material_set_shader); + ClassDB::bind_method(D_METHOD("material_get_shader", "shader_material"), &VisualServer::material_get_shader); + ClassDB::bind_method(D_METHOD("material_set_param", "material", "parameter", "value"), &VisualServer::material_set_param); + ClassDB::bind_method(D_METHOD("material_get_param", "material", "parameter"), &VisualServer::material_get_param); + ClassDB::bind_method(D_METHOD("material_set_render_priority", "material", "priority"), &VisualServer::material_set_render_priority); + ClassDB::bind_method(D_METHOD("material_set_line_width", "material", "width"), &VisualServer::material_set_line_width); + ClassDB::bind_method(D_METHOD("material_set_next_pass", "material", "next_material"), &VisualServer::material_set_next_pass); + + ClassDB::bind_method(D_METHOD("mesh_create"), &VisualServer::mesh_create); + ClassDB::bind_method(D_METHOD("mesh_add_surface_from_arrays", "mesh", "primtive", "arrays", "blend_shapes", "compress_format"), &VisualServer::mesh_add_surface_from_arrays, DEFVAL(Array()), DEFVAL(ARRAY_COMPRESS_DEFAULT)); + ClassDB::bind_method(D_METHOD("mesh_set_blend_shape_count", "mesh", "amount"), &VisualServer::mesh_set_blend_shape_count); + ClassDB::bind_method(D_METHOD("mesh_get_blend_shape_count", "mesh"), &VisualServer::mesh_get_blend_shape_count); + ClassDB::bind_method(D_METHOD("mesh_set_blend_shape_mode", "mesh", "mode"), &VisualServer::mesh_set_blend_shape_mode); + ClassDB::bind_method(D_METHOD("mesh_get_blend_shape_mode", "mesh"), &VisualServer::mesh_get_blend_shape_mode); + ClassDB::bind_method(D_METHOD("mesh_surface_set_material", "mesh", "surface", "material"), &VisualServer::mesh_surface_set_material); + ClassDB::bind_method(D_METHOD("mesh_surface_get_material", "mesh", "surface"), &VisualServer::mesh_surface_get_material); + ClassDB::bind_method(D_METHOD("mesh_surface_get_array_len", "mesh", "surface"), &VisualServer::mesh_surface_get_array_len); + ClassDB::bind_method(D_METHOD("mesh_surface_get_array_index_len", "mesh", "surface"), &VisualServer::mesh_surface_get_array_index_len); + ClassDB::bind_method(D_METHOD("mesh_surface_get_array", "mesh", "surface"), &VisualServer::mesh_surface_get_array); + ClassDB::bind_method(D_METHOD("mesh_surface_get_index_array", "mesh", "surface"), &VisualServer::mesh_surface_get_index_array); + ClassDB::bind_method(D_METHOD("mesh_surface_get_arrays", "mesh", "surface"), &VisualServer::mesh_surface_get_arrays); + ClassDB::bind_method(D_METHOD("mesh_surface_get_blend_shape_arrays", "mesh", "surface"), &VisualServer::mesh_surface_get_blend_shape_arrays); + ClassDB::bind_method(D_METHOD("mesh_surface_get_format", "mesh", "surface"), &VisualServer::mesh_surface_get_format); + ClassDB::bind_method(D_METHOD("mesh_surface_get_primitive_type", "mesh", "surface"), &VisualServer::mesh_surface_get_primitive_type); + ClassDB::bind_method(D_METHOD("mesh_surface_get_aabb", "mesh", "surface"), &VisualServer::mesh_surface_get_aabb); + ClassDB::bind_method(D_METHOD("mesh_surface_get_skeleton_aabb", "mesh", "surface"), &VisualServer::_mesh_surface_get_skeleton_aabb_bind); + ClassDB::bind_method(D_METHOD("mesh_remove_surface", "mesh", "index"), &VisualServer::mesh_remove_surface); + ClassDB::bind_method(D_METHOD("mesh_get_surface_count", "mesh"), &VisualServer::mesh_get_surface_count); + ClassDB::bind_method(D_METHOD("mesh_set_custom_aabb", "mesh", "aabb"), &VisualServer::mesh_set_custom_aabb); + ClassDB::bind_method(D_METHOD("mesh_get_custom_aabb", "mesh"), &VisualServer::mesh_get_custom_aabb); + ClassDB::bind_method(D_METHOD("mesh_clear", "mesh"), &VisualServer::mesh_clear); + + // TODO: multimesh_*, immediate_*, skeleton_*, light_*, reflection_probe_*, gi_probe_*, particles_*, camera_* + + ClassDB::bind_method(D_METHOD("viewport_create"), &VisualServer::viewport_create); + ClassDB::bind_method(D_METHOD("viewport_set_use_arvr", "viewport", "use_arvr"), &VisualServer::viewport_set_use_arvr); + ClassDB::bind_method(D_METHOD("viewport_set_size", "viewport", "width", "height"), &VisualServer::viewport_set_size); + ClassDB::bind_method(D_METHOD("viewport_set_active", "viewport", "active"), &VisualServer::viewport_set_active); + ClassDB::bind_method(D_METHOD("viewport_set_parent_viewport", "viewport", "parent_viewport"), &VisualServer::viewport_set_parent_viewport); + ClassDB::bind_method(D_METHOD("viewport_attach_to_screen", "viewport", "rect", "screen"), &VisualServer::viewport_attach_to_screen, DEFVAL(Rect2()), DEFVAL(0)); + ClassDB::bind_method(D_METHOD("viewport_detach", "viewport"), &VisualServer::viewport_detach); + ClassDB::bind_method(D_METHOD("viewport_set_update_mode", "viewport", "update_mode"), &VisualServer::viewport_set_update_mode); + ClassDB::bind_method(D_METHOD("viewport_set_vflip", "viewport", "enabled"), &VisualServer::viewport_set_vflip); + ClassDB::bind_method(D_METHOD("viewport_set_clear_mode", "viewport", "clear_mode"), &VisualServer::viewport_set_clear_mode); + ClassDB::bind_method(D_METHOD("viewport_get_texture", "viewport"), &VisualServer::viewport_get_texture); + ClassDB::bind_method(D_METHOD("viewport_set_hide_scenario", "viewport", "hidden"), &VisualServer::viewport_set_hide_scenario); + ClassDB::bind_method(D_METHOD("viewport_set_hide_canvas", "viewport", "hidden"), &VisualServer::viewport_set_hide_canvas); + ClassDB::bind_method(D_METHOD("viewport_set_disable_environment", "viewport", "disabled"), &VisualServer::viewport_set_disable_environment); + ClassDB::bind_method(D_METHOD("viewport_set_disable_3d", "viewport", "disabled"), &VisualServer::viewport_set_disable_3d); + ClassDB::bind_method(D_METHOD("viewport_attach_camera", "viewport", "camera"), &VisualServer::viewport_attach_camera); + ClassDB::bind_method(D_METHOD("viewport_set_scenario", "viewport", "scenario"), &VisualServer::viewport_set_scenario); + ClassDB::bind_method(D_METHOD("viewport_attach_canvas", "viewport", "canvas"), &VisualServer::viewport_attach_canvas); + ClassDB::bind_method(D_METHOD("viewport_remove_canvas", "viewport", "canvas"), &VisualServer::viewport_remove_canvas); + ClassDB::bind_method(D_METHOD("viewport_set_canvas_transform", "viewport", "canvas", "offset"), &VisualServer::viewport_set_canvas_transform); + ClassDB::bind_method(D_METHOD("viewport_set_transparent_background", "viewport", "enabled"), &VisualServer::viewport_set_transparent_background); + ClassDB::bind_method(D_METHOD("viewport_set_global_canvas_transform", "viewport", "transform"), &VisualServer::viewport_set_global_canvas_transform); + ClassDB::bind_method(D_METHOD("viewport_set_canvas_layer", "viewport", "canvas", "layer"), &VisualServer::viewport_set_canvas_layer); + ClassDB::bind_method(D_METHOD("viewport_set_shadow_atlas_size", "viewport", "size"), &VisualServer::viewport_set_shadow_atlas_size); + ClassDB::bind_method(D_METHOD("viewport_set_shadow_atlas_quadrant_subdivision", "viewport", "quadrant", "subdivision"), &VisualServer::viewport_set_shadow_atlas_quadrant_subdivision); + ClassDB::bind_method(D_METHOD("viewport_set_msaa", "viewport", "msaa"), &VisualServer::viewport_set_msaa); + ClassDB::bind_method(D_METHOD("viewport_set_hdr", "viewport", "enabled"), &VisualServer::viewport_set_hdr); + ClassDB::bind_method(D_METHOD("viewport_set_usage", "viewport", "usage"), &VisualServer::viewport_set_usage); + ClassDB::bind_method(D_METHOD("viewport_get_render_info", "viewport", "info"), &VisualServer::viewport_get_render_info); + ClassDB::bind_method(D_METHOD("viewport_set_debug_draw", "viewport", "draw"), &VisualServer::viewport_set_debug_draw); + + // TODO: environment_*, scenario_*, instance_* + + ClassDB::bind_method(D_METHOD("canvas_create"), &VisualServer::canvas_create); + ClassDB::bind_method(D_METHOD("canvas_set_item_mirroring", "canvas", "item", "mirroring"), &VisualServer::canvas_set_item_mirroring); + ClassDB::bind_method(D_METHOD("canvas_set_modulate", "canvas", "color"), &VisualServer::canvas_set_modulate); + + ClassDB::bind_method(D_METHOD("canvas_item_create"), &VisualServer::canvas_item_create); + ClassDB::bind_method(D_METHOD("canvas_item_set_parent", "item", "parent"), &VisualServer::canvas_item_set_parent); + ClassDB::bind_method(D_METHOD("canvas_item_set_visible", "item", "visible"), &VisualServer::canvas_item_set_visible); + ClassDB::bind_method(D_METHOD("canvas_item_set_light_mask", "item", "mask"), &VisualServer::canvas_item_set_light_mask); + ClassDB::bind_method(D_METHOD("canvas_item_set_transform", "item", "transform"), &VisualServer::canvas_item_set_transform); + ClassDB::bind_method(D_METHOD("canvas_item_set_clip", "item", "clip"), &VisualServer::canvas_item_set_clip); + ClassDB::bind_method(D_METHOD("canvas_item_set_distance_field_mode", "item", "enabled"), &VisualServer::canvas_item_set_distance_field_mode); + ClassDB::bind_method(D_METHOD("canvas_item_set_custom_rect", "item", "use_custom_rect", "rect"), &VisualServer::canvas_item_set_custom_rect, DEFVAL(Rect2())); + ClassDB::bind_method(D_METHOD("canvas_item_set_modulate", "item", "color"), &VisualServer::canvas_item_set_modulate); + ClassDB::bind_method(D_METHOD("canvas_item_set_self_modulate", "item", "color"), &VisualServer::canvas_item_set_self_modulate); + ClassDB::bind_method(D_METHOD("canvas_item_set_draw_behind_parent", "item", "enabled"), &VisualServer::canvas_item_set_draw_behind_parent); + ClassDB::bind_method(D_METHOD("canvas_item_add_line", "item", "from", "to", "color", "width", "antialiased"), &VisualServer::canvas_item_add_line, DEFVAL(1.0), DEFVAL(false)); + ClassDB::bind_method(D_METHOD("canvas_item_add_polyline", "item", "points", "colors", "width", "antialiased"), &VisualServer::canvas_item_add_polyline, DEFVAL(1.0), DEFVAL(false)); + ClassDB::bind_method(D_METHOD("canvas_item_add_rect", "item", "rect", "color"), &VisualServer::canvas_item_add_rect); + ClassDB::bind_method(D_METHOD("canvas_item_add_circle", "item", "pos", "radius", "color"), &VisualServer::canvas_item_add_circle); + ClassDB::bind_method(D_METHOD("canvas_item_add_texture_rect", "item", "rect", "texture", "tile", "modulate", "transpose", "normal_map"), &VisualServer::canvas_item_add_texture_rect, DEFVAL(false), DEFVAL(Color(1, 1, 1)), DEFVAL(false), DEFVAL(RID())); + ClassDB::bind_method(D_METHOD("canvas_item_add_texture_rect_region", "item", "rect", "texture", "src_rect", "modulate", "transpose", "normal_map", "clip_uv"), &VisualServer::canvas_item_add_texture_rect_region, DEFVAL(Color(1, 1, 1)), DEFVAL(false), DEFVAL(RID()), DEFVAL(true)); + ClassDB::bind_method(D_METHOD("canvas_item_add_nine_patch", "item", "rect", "source", "texture", "topleft", "bottomright", "x_axis_mode", "y_axis_mode", "draw_center", "modulate", "normal_map"), &VisualServer::canvas_item_add_nine_patch, DEFVAL(NINE_PATCH_STRETCH), DEFVAL(NINE_PATCH_STRETCH), DEFVAL(true), DEFVAL(Color(1, 1, 1)), DEFVAL(RID())); + ClassDB::bind_method(D_METHOD("canvas_item_add_primitive", "item", "points", "colors", "uvs", "texture", "width", "normal_map"), &VisualServer::canvas_item_add_primitive, DEFVAL(1.0), DEFVAL(RID())); + ClassDB::bind_method(D_METHOD("canvas_item_add_polygon", "item", "points", "colors", "uvs", "texture", "normal_map", "antialiased"), &VisualServer::canvas_item_add_polygon, DEFVAL(Vector<Point2>()), DEFVAL(RID()), DEFVAL(RID()), DEFVAL(false)); + ClassDB::bind_method(D_METHOD("canvas_item_add_triangle_array", "item", "indices", "points", "colors", "uvs", "texture", "count", "normal_map"), &VisualServer::canvas_item_add_triangle_array, DEFVAL(Vector<Point2>()), DEFVAL(RID()), DEFVAL(-1), DEFVAL(RID())); + ClassDB::bind_method(D_METHOD("canvas_item_add_mesh", "item", "mesh", "skeleton"), &VisualServer::canvas_item_add_mesh, DEFVAL(RID())); + ClassDB::bind_method(D_METHOD("canvas_item_add_multimesh", "item", "mesh", "skeleton"), &VisualServer::canvas_item_add_multimesh, DEFVAL(RID())); + ClassDB::bind_method(D_METHOD("canvas_item_add_particles", "item", "particles", "texture", "normal_map", "h_frames", "v_frames"), &VisualServer::canvas_item_add_particles); + ClassDB::bind_method(D_METHOD("canvas_item_add_set_transform", "item", "transform"), &VisualServer::canvas_item_add_set_transform); + ClassDB::bind_method(D_METHOD("canvas_item_add_clip_ignore", "item", "ignore"), &VisualServer::canvas_item_add_clip_ignore); + ClassDB::bind_method(D_METHOD("canvas_item_set_sort_children_by_y", "item", "enabled"), &VisualServer::canvas_item_set_sort_children_by_y); + ClassDB::bind_method(D_METHOD("canvas_item_set_z", "item", "z"), &VisualServer::canvas_item_set_z); + ClassDB::bind_method(D_METHOD("canvas_item_set_z_as_relative_to_parent", "item", "enabled"), &VisualServer::canvas_item_set_z_as_relative_to_parent); + ClassDB::bind_method(D_METHOD("canvas_item_set_copy_to_backbuffer", "item", "enabled", "rect"), &VisualServer::canvas_item_set_copy_to_backbuffer); + ClassDB::bind_method(D_METHOD("canvas_item_clear", "item"), &VisualServer::canvas_item_clear); + ClassDB::bind_method(D_METHOD("canvas_item_set_draw_index", "item", "index"), &VisualServer::canvas_item_set_draw_index); + ClassDB::bind_method(D_METHOD("canvas_item_set_material", "item", "material"), &VisualServer::canvas_item_set_material); + ClassDB::bind_method(D_METHOD("canvas_item_set_use_parent_material", "item", "enabled"), &VisualServer::canvas_item_set_use_parent_material); + ClassDB::bind_method(D_METHOD("canvas_light_create"), &VisualServer::canvas_light_create); + ClassDB::bind_method(D_METHOD("canvas_light_attach_to_canvas", "light", "canvas"), &VisualServer::canvas_light_attach_to_canvas); + ClassDB::bind_method(D_METHOD("canvas_light_set_enabled", "light", "enabled"), &VisualServer::canvas_light_set_enabled); + ClassDB::bind_method(D_METHOD("canvas_light_set_scale", "light", "scale"), &VisualServer::canvas_light_set_scale); + ClassDB::bind_method(D_METHOD("canvas_light_set_transform", "light", "transform"), &VisualServer::canvas_light_set_transform); + ClassDB::bind_method(D_METHOD("canvas_light_set_texture", "light", "texture"), &VisualServer::canvas_light_set_texture); + ClassDB::bind_method(D_METHOD("canvas_light_set_texture_offset", "light", "offset"), &VisualServer::canvas_light_set_texture_offset); + ClassDB::bind_method(D_METHOD("canvas_light_set_color", "light", "color"), &VisualServer::canvas_light_set_color); + ClassDB::bind_method(D_METHOD("canvas_light_set_height", "light", "height"), &VisualServer::canvas_light_set_height); + ClassDB::bind_method(D_METHOD("canvas_light_set_energy", "light", "energy"), &VisualServer::canvas_light_set_energy); + ClassDB::bind_method(D_METHOD("canvas_light_set_z_range", "light", "min_z", "max_z"), &VisualServer::canvas_light_set_z_range); + ClassDB::bind_method(D_METHOD("canvas_light_set_layer_range", "light", "min_layer", "max_layer"), &VisualServer::canvas_light_set_layer_range); + ClassDB::bind_method(D_METHOD("canvas_light_set_item_cull_mask", "light", "mask"), &VisualServer::canvas_light_set_item_cull_mask); + ClassDB::bind_method(D_METHOD("canvas_light_set_item_shadow_cull_mask", "light", "mask"), &VisualServer::canvas_light_set_item_shadow_cull_mask); + ClassDB::bind_method(D_METHOD("canvas_light_set_mode", "light", "mode"), &VisualServer::canvas_light_set_mode); + ClassDB::bind_method(D_METHOD("canvas_light_set_shadow_enabled", "light", "enabled"), &VisualServer::canvas_light_set_shadow_enabled); + ClassDB::bind_method(D_METHOD("canvas_light_set_shadow_buffer_size", "light", "size"), &VisualServer::canvas_light_set_shadow_buffer_size); + ClassDB::bind_method(D_METHOD("canvas_light_set_shadow_gradient_length", "light", "length"), &VisualServer::canvas_light_set_shadow_gradient_length); + ClassDB::bind_method(D_METHOD("canvas_light_set_shadow_filter", "light", "filter"), &VisualServer::canvas_light_set_shadow_filter); + ClassDB::bind_method(D_METHOD("canvas_light_set_shadow_color", "light", "color"), &VisualServer::canvas_light_set_shadow_color); + ClassDB::bind_method(D_METHOD("canvas_light_set_shadow_smooth", "light", "smooth"), &VisualServer::canvas_light_set_shadow_smooth); + + ClassDB::bind_method(D_METHOD("canvas_light_occluder_create"), &VisualServer::canvas_light_occluder_create); + ClassDB::bind_method(D_METHOD("canvas_light_occluder_attach_to_canvas", "occluder", "canvas"), &VisualServer::canvas_light_occluder_attach_to_canvas); + ClassDB::bind_method(D_METHOD("canvas_light_occluder_set_enabled", "occluder", "enabled"), &VisualServer::canvas_light_occluder_set_enabled); + ClassDB::bind_method(D_METHOD("canvas_light_occluder_set_polygon", "occluder", "polygon"), &VisualServer::canvas_light_occluder_set_polygon); + ClassDB::bind_method(D_METHOD("canvas_light_occluder_set_transform", "occluder", "transform"), &VisualServer::canvas_light_occluder_set_transform); + ClassDB::bind_method(D_METHOD("canvas_light_occluder_set_light_mask", "occluder", "mask"), &VisualServer::canvas_light_occluder_set_light_mask); + + ClassDB::bind_method(D_METHOD("canvas_occluder_polygon_create"), &VisualServer::canvas_occluder_polygon_create); + ClassDB::bind_method(D_METHOD("canvas_occluder_polygon_set_shape", "occluder_polygon", "shape", "closed"), &VisualServer::canvas_occluder_polygon_set_shape); + ClassDB::bind_method(D_METHOD("canvas_occluder_polygon_set_shape_as_lines", "occluder_polygon", "shape"), &VisualServer::canvas_occluder_polygon_set_shape_as_lines); + ClassDB::bind_method(D_METHOD("canvas_occluder_polygon_set_cull_mode", "occluder_polygon", "mode"), &VisualServer::canvas_occluder_polygon_set_cull_mode); + + ClassDB::bind_method(D_METHOD("black_bars_set_margins", "left", "top", "right", "bottom"), &VisualServer::black_bars_set_margins); + ClassDB::bind_method(D_METHOD("black_bars_set_images", "left", "top", "right", "bottom"), &VisualServer::black_bars_set_images); + + ClassDB::bind_method(D_METHOD("free", "rid"), &VisualServer::free); + + ClassDB::bind_method(D_METHOD("request_frame_drawn_callback", "where", "method", "userdata"), &VisualServer::request_frame_drawn_callback); + ClassDB::bind_method(D_METHOD("draw"), &VisualServer::draw); + ClassDB::bind_method(D_METHOD("sync"), &VisualServer::sync); + ClassDB::bind_method(D_METHOD("has_changed"), &VisualServer::has_changed); + ClassDB::bind_method(D_METHOD("init"), &VisualServer::init); + ClassDB::bind_method(D_METHOD("finish"), &VisualServer::finish); + ClassDB::bind_method(D_METHOD("get_render_info", "info"), &VisualServer::get_render_info); + + ClassDB::bind_method(D_METHOD("get_test_cube"), &VisualServer::get_test_cube); + ClassDB::bind_method(D_METHOD("get_test_texture"), &VisualServer::get_test_texture); + ClassDB::bind_method(D_METHOD("get_white_texture"), &VisualServer::get_white_texture); + + ClassDB::bind_method(D_METHOD("make_sphere_mesh", "latitudes", "longitudes", "radius"), &VisualServer::make_sphere_mesh); + + ClassDB::bind_method(D_METHOD("set_boot_image", "image", "color", "scale"), &VisualServer::set_boot_image); + ClassDB::bind_method(D_METHOD("set_default_clear_color", "color"), &VisualServer::set_default_clear_color); + + ClassDB::bind_method(D_METHOD("has_feature", "feature"), &VisualServer::has_feature); + ClassDB::bind_method(D_METHOD("has_os_feature", "feature"), &VisualServer::has_os_feature); + ClassDB::bind_method(D_METHOD("set_debug_generate_wireframes", "generate"), &VisualServer::set_debug_generate_wireframes); + + BIND_CONSTANT(NO_INDEX_ARRAY); + BIND_CONSTANT(ARRAY_WEIGHTS_SIZE); + BIND_CONSTANT(CANVAS_ITEM_Z_MIN); + BIND_CONSTANT(CANVAS_ITEM_Z_MAX); + BIND_CONSTANT(MAX_GLOW_LEVELS); + BIND_CONSTANT(MAX_CURSORS); + BIND_CONSTANT(MATERIAL_RENDER_PRIORITY_MIN); + BIND_CONSTANT(MATERIAL_RENDER_PRIORITY_MAX); + + BIND_ENUM_CONSTANT(CUBEMAP_LEFT); + BIND_ENUM_CONSTANT(CUBEMAP_RIGHT); + BIND_ENUM_CONSTANT(CUBEMAP_BOTTOM); + BIND_ENUM_CONSTANT(CUBEMAP_TOP); + BIND_ENUM_CONSTANT(CUBEMAP_FRONT); + BIND_ENUM_CONSTANT(CUBEMAP_BACK); + + BIND_ENUM_CONSTANT(TEXTURE_FLAG_MIPMAPS); + BIND_ENUM_CONSTANT(TEXTURE_FLAG_REPEAT); + BIND_ENUM_CONSTANT(TEXTURE_FLAG_FILTER); + BIND_ENUM_CONSTANT(TEXTURE_FLAG_ANISOTROPIC_FILTER); + BIND_ENUM_CONSTANT(TEXTURE_FLAG_CONVERT_TO_LINEAR); + BIND_ENUM_CONSTANT(TEXTURE_FLAG_MIRRORED_REPEAT); + BIND_ENUM_CONSTANT(TEXTURE_FLAG_CUBEMAP); + BIND_ENUM_CONSTANT(TEXTURE_FLAG_USED_FOR_STREAMING); + BIND_ENUM_CONSTANT(TEXTURE_FLAGS_DEFAULT); + + BIND_ENUM_CONSTANT(SHADER_SPATIAL); + BIND_ENUM_CONSTANT(SHADER_CANVAS_ITEM); + BIND_ENUM_CONSTANT(SHADER_PARTICLES); + BIND_ENUM_CONSTANT(SHADER_MAX); + + BIND_ENUM_CONSTANT(ARRAY_VERTEX); + BIND_ENUM_CONSTANT(ARRAY_NORMAL); + BIND_ENUM_CONSTANT(ARRAY_TANGENT); + BIND_ENUM_CONSTANT(ARRAY_COLOR); + BIND_ENUM_CONSTANT(ARRAY_TEX_UV); + BIND_ENUM_CONSTANT(ARRAY_TEX_UV2); + BIND_ENUM_CONSTANT(ARRAY_BONES); + BIND_ENUM_CONSTANT(ARRAY_WEIGHTS); + BIND_ENUM_CONSTANT(ARRAY_INDEX); + BIND_ENUM_CONSTANT(ARRAY_MAX); + + BIND_ENUM_CONSTANT(ARRAY_FORMAT_VERTEX); + BIND_ENUM_CONSTANT(ARRAY_FORMAT_NORMAL); + BIND_ENUM_CONSTANT(ARRAY_FORMAT_TANGENT); + BIND_ENUM_CONSTANT(ARRAY_FORMAT_COLOR); + BIND_ENUM_CONSTANT(ARRAY_FORMAT_TEX_UV); + BIND_ENUM_CONSTANT(ARRAY_FORMAT_TEX_UV2); + BIND_ENUM_CONSTANT(ARRAY_FORMAT_BONES); + BIND_ENUM_CONSTANT(ARRAY_FORMAT_WEIGHTS); + BIND_ENUM_CONSTANT(ARRAY_FORMAT_INDEX); + BIND_ENUM_CONSTANT(ARRAY_COMPRESS_BASE); + BIND_ENUM_CONSTANT(ARRAY_COMPRESS_VERTEX); + BIND_ENUM_CONSTANT(ARRAY_COMPRESS_NORMAL); + BIND_ENUM_CONSTANT(ARRAY_COMPRESS_TANGENT); + BIND_ENUM_CONSTANT(ARRAY_COMPRESS_COLOR); + BIND_ENUM_CONSTANT(ARRAY_COMPRESS_TEX_UV); + BIND_ENUM_CONSTANT(ARRAY_COMPRESS_TEX_UV2); + BIND_ENUM_CONSTANT(ARRAY_COMPRESS_BONES); + BIND_ENUM_CONSTANT(ARRAY_COMPRESS_WEIGHTS); + BIND_ENUM_CONSTANT(ARRAY_COMPRESS_INDEX); + BIND_ENUM_CONSTANT(ARRAY_FLAG_USE_2D_VERTICES); + BIND_ENUM_CONSTANT(ARRAY_FLAG_USE_16_BIT_BONES); + BIND_ENUM_CONSTANT(ARRAY_COMPRESS_DEFAULT); + + BIND_ENUM_CONSTANT(PRIMITIVE_POINTS); + BIND_ENUM_CONSTANT(PRIMITIVE_LINES); + BIND_ENUM_CONSTANT(PRIMITIVE_LINE_STRIP); + BIND_ENUM_CONSTANT(PRIMITIVE_LINE_LOOP); + BIND_ENUM_CONSTANT(PRIMITIVE_TRIANGLES); + BIND_ENUM_CONSTANT(PRIMITIVE_TRIANGLE_STRIP); + BIND_ENUM_CONSTANT(PRIMITIVE_TRIANGLE_FAN); + BIND_ENUM_CONSTANT(PRIMITIVE_MAX); + + BIND_ENUM_CONSTANT(BLEND_SHAPE_MODE_NORMALIZED); + BIND_ENUM_CONSTANT(BLEND_SHAPE_MODE_RELATIVE); + + BIND_ENUM_CONSTANT(LIGHT_DIRECTIONAL); + BIND_ENUM_CONSTANT(LIGHT_OMNI); + BIND_ENUM_CONSTANT(LIGHT_SPOT); + + BIND_ENUM_CONSTANT(LIGHT_PARAM_ENERGY); + BIND_ENUM_CONSTANT(LIGHT_PARAM_SPECULAR); + BIND_ENUM_CONSTANT(LIGHT_PARAM_RANGE); + BIND_ENUM_CONSTANT(LIGHT_PARAM_ATTENUATION); + BIND_ENUM_CONSTANT(LIGHT_PARAM_SPOT_ANGLE); + BIND_ENUM_CONSTANT(LIGHT_PARAM_SPOT_ATTENUATION); + BIND_ENUM_CONSTANT(LIGHT_PARAM_CONTACT_SHADOW_SIZE); + BIND_ENUM_CONSTANT(LIGHT_PARAM_SHADOW_MAX_DISTANCE); + BIND_ENUM_CONSTANT(LIGHT_PARAM_SHADOW_SPLIT_1_OFFSET); + BIND_ENUM_CONSTANT(LIGHT_PARAM_SHADOW_SPLIT_2_OFFSET); + BIND_ENUM_CONSTANT(LIGHT_PARAM_SHADOW_SPLIT_3_OFFSET); + BIND_ENUM_CONSTANT(LIGHT_PARAM_SHADOW_NORMAL_BIAS); + BIND_ENUM_CONSTANT(LIGHT_PARAM_SHADOW_BIAS); + BIND_ENUM_CONSTANT(LIGHT_PARAM_SHADOW_BIAS_SPLIT_SCALE); + BIND_ENUM_CONSTANT(LIGHT_PARAM_MAX); + + BIND_ENUM_CONSTANT(VIEWPORT_UPDATE_DISABLED); + BIND_ENUM_CONSTANT(VIEWPORT_UPDATE_ONCE); + BIND_ENUM_CONSTANT(VIEWPORT_UPDATE_WHEN_VISIBLE); + BIND_ENUM_CONSTANT(VIEWPORT_UPDATE_ALWAYS); + + BIND_ENUM_CONSTANT(VIEWPORT_CLEAR_ALWAYS); + BIND_ENUM_CONSTANT(VIEWPORT_CLEAR_NEVER); + BIND_ENUM_CONSTANT(VIEWPORT_CLEAR_ONLY_NEXT_FRAME); + + BIND_ENUM_CONSTANT(VIEWPORT_MSAA_DISABLED); + BIND_ENUM_CONSTANT(VIEWPORT_MSAA_2X); + BIND_ENUM_CONSTANT(VIEWPORT_MSAA_4X); + BIND_ENUM_CONSTANT(VIEWPORT_MSAA_8X); + BIND_ENUM_CONSTANT(VIEWPORT_MSAA_16X); + + BIND_ENUM_CONSTANT(VIEWPORT_USAGE_2D); + BIND_ENUM_CONSTANT(VIEWPORT_USAGE_2D_NO_SAMPLING); + BIND_ENUM_CONSTANT(VIEWPORT_USAGE_3D); + BIND_ENUM_CONSTANT(VIEWPORT_USAGE_3D_NO_EFFECTS); + + BIND_ENUM_CONSTANT(VIEWPORT_RENDER_INFO_OBJECTS_IN_FRAME); + BIND_ENUM_CONSTANT(VIEWPORT_RENDER_INFO_VERTICES_IN_FRAME); + BIND_ENUM_CONSTANT(VIEWPORT_RENDER_INFO_MATERIAL_CHANGES_IN_FRAME); + BIND_ENUM_CONSTANT(VIEWPORT_RENDER_INFO_SHADER_CHANGES_IN_FRAME); + BIND_ENUM_CONSTANT(VIEWPORT_RENDER_INFO_SURFACE_CHANGES_IN_FRAME); + BIND_ENUM_CONSTANT(VIEWPORT_RENDER_INFO_DRAW_CALLS_IN_FRAME); + BIND_ENUM_CONSTANT(VIEWPORT_RENDER_INFO_MAX); + + BIND_ENUM_CONSTANT(VIEWPORT_DEBUG_DRAW_DISABLED); + BIND_ENUM_CONSTANT(VIEWPORT_DEBUG_DRAW_UNSHADED); + BIND_ENUM_CONSTANT(VIEWPORT_DEBUG_DRAW_OVERDRAW); + BIND_ENUM_CONSTANT(VIEWPORT_DEBUG_DRAW_WIREFRAME); + + BIND_ENUM_CONSTANT(SCENARIO_DEBUG_DISABLED); + BIND_ENUM_CONSTANT(SCENARIO_DEBUG_WIREFRAME); + BIND_ENUM_CONSTANT(SCENARIO_DEBUG_OVERDRAW); + BIND_ENUM_CONSTANT(SCENARIO_DEBUG_SHADELESS); + + BIND_ENUM_CONSTANT(INSTANCE_NONE); + BIND_ENUM_CONSTANT(INSTANCE_MESH); + BIND_ENUM_CONSTANT(INSTANCE_MULTIMESH); + BIND_ENUM_CONSTANT(INSTANCE_IMMEDIATE); + BIND_ENUM_CONSTANT(INSTANCE_PARTICLES); + BIND_ENUM_CONSTANT(INSTANCE_LIGHT); + BIND_ENUM_CONSTANT(INSTANCE_REFLECTION_PROBE); + BIND_ENUM_CONSTANT(INSTANCE_GI_PROBE); + BIND_ENUM_CONSTANT(INSTANCE_MAX); + BIND_ENUM_CONSTANT(INSTANCE_GEOMETRY_MASK); + + BIND_ENUM_CONSTANT(NINE_PATCH_STRETCH); + BIND_ENUM_CONSTANT(NINE_PATCH_TILE); + BIND_ENUM_CONSTANT(NINE_PATCH_TILE_FIT); + + BIND_ENUM_CONSTANT(CANVAS_LIGHT_MODE_ADD); + BIND_ENUM_CONSTANT(CANVAS_LIGHT_MODE_SUB); + BIND_ENUM_CONSTANT(CANVAS_LIGHT_MODE_MIX); + BIND_ENUM_CONSTANT(CANVAS_LIGHT_MODE_MASK); + + BIND_ENUM_CONSTANT(CANVAS_LIGHT_FILTER_NONE); + BIND_ENUM_CONSTANT(CANVAS_LIGHT_FILTER_PCF3); + BIND_ENUM_CONSTANT(CANVAS_LIGHT_FILTER_PCF5); + BIND_ENUM_CONSTANT(CANVAS_LIGHT_FILTER_PCF7); + BIND_ENUM_CONSTANT(CANVAS_LIGHT_FILTER_PCF9); + BIND_ENUM_CONSTANT(CANVAS_LIGHT_FILTER_PCF13); + + BIND_ENUM_CONSTANT(CANVAS_OCCLUDER_POLYGON_CULL_DISABLED); + BIND_ENUM_CONSTANT(CANVAS_OCCLUDER_POLYGON_CULL_CLOCKWISE); + BIND_ENUM_CONSTANT(CANVAS_OCCLUDER_POLYGON_CULL_COUNTER_CLOCKWISE); + + BIND_ENUM_CONSTANT(INFO_OBJECTS_IN_FRAME); + BIND_ENUM_CONSTANT(INFO_VERTICES_IN_FRAME); + BIND_ENUM_CONSTANT(INFO_MATERIAL_CHANGES_IN_FRAME); + BIND_ENUM_CONSTANT(INFO_SHADER_CHANGES_IN_FRAME); + BIND_ENUM_CONSTANT(INFO_SURFACE_CHANGES_IN_FRAME); + BIND_ENUM_CONSTANT(INFO_DRAW_CALLS_IN_FRAME); + BIND_ENUM_CONSTANT(INFO_USAGE_VIDEO_MEM_TOTAL); + BIND_ENUM_CONSTANT(INFO_VIDEO_MEM_USED); + BIND_ENUM_CONSTANT(INFO_TEXTURE_MEM_USED); + BIND_ENUM_CONSTANT(INFO_VERTEX_MEM_USED); + + BIND_ENUM_CONSTANT(FEATURE_SHADERS); + BIND_ENUM_CONSTANT(FEATURE_MULTITHREADED); } void VisualServer::_canvas_item_add_style_box(RID p_item, const Rect2 &p_rect, const Rect2 &p_source, RID p_texture, const Vector<float> &p_margins, const Color &p_modulate) { diff --git a/servers/visual_server.h b/servers/visual_server.h index 1cc097f50e..7b83bb929d 100644 --- a/servers/visual_server.h +++ b/servers/visual_server.h @@ -137,6 +137,7 @@ public: }; virtual void texture_debug_usage(List<TextureInfo> *r_info) = 0; + Array _texture_debug_usage_bind(); virtual void textures_keep_original(bool p_enable) = 0; @@ -160,6 +161,7 @@ public: virtual void shader_set_code(RID p_shader, const String &p_code) = 0; virtual String shader_get_code(RID p_shader) const = 0; virtual void shader_get_param_list(RID p_shader, List<PropertyInfo> *p_param_list) const = 0; + Array _shader_get_param_list_bind(RID p_shader) const; virtual void shader_set_default_texture_param(RID p_shader, const StringName &p_name, RID p_texture) = 0; virtual RID shader_get_default_texture_param(RID p_shader, const StringName &p_name) const = 0; @@ -275,6 +277,7 @@ public: virtual Rect3 mesh_surface_get_aabb(RID p_mesh, int p_surface) const = 0; virtual Vector<PoolVector<uint8_t> > mesh_surface_get_blend_shapes(RID p_mesh, int p_surface) const = 0; virtual Vector<Rect3> mesh_surface_get_skeleton_aabb(RID p_mesh, int p_surface) const = 0; + Array _mesh_surface_get_skeleton_aabb_bind(RID p_mesh, int p_surface) const; virtual void mesh_remove_surface(RID p_mesh, int p_index) = 0; virtual int mesh_get_surface_count(RID p_mesh) const = 0; @@ -941,18 +944,29 @@ public: }; // make variant understand the enums - VARIANT_ENUM_CAST(VisualServer::CubeMapSide); VARIANT_ENUM_CAST(VisualServer::TextureFlags); VARIANT_ENUM_CAST(VisualServer::ShaderMode); VARIANT_ENUM_CAST(VisualServer::ArrayType); VARIANT_ENUM_CAST(VisualServer::ArrayFormat); VARIANT_ENUM_CAST(VisualServer::PrimitiveType); +VARIANT_ENUM_CAST(VisualServer::BlendShapeMode); VARIANT_ENUM_CAST(VisualServer::LightType); VARIANT_ENUM_CAST(VisualServer::LightParam); +VARIANT_ENUM_CAST(VisualServer::ViewportUpdateMode); +VARIANT_ENUM_CAST(VisualServer::ViewportClearMode); +VARIANT_ENUM_CAST(VisualServer::ViewportMSAA); +VARIANT_ENUM_CAST(VisualServer::ViewportUsage); +VARIANT_ENUM_CAST(VisualServer::ViewportRenderInfo); +VARIANT_ENUM_CAST(VisualServer::ViewportDebugDraw); VARIANT_ENUM_CAST(VisualServer::ScenarioDebugMode); VARIANT_ENUM_CAST(VisualServer::InstanceType); +VARIANT_ENUM_CAST(VisualServer::NinePatchAxisMode); +VARIANT_ENUM_CAST(VisualServer::CanvasLightMode); +VARIANT_ENUM_CAST(VisualServer::CanvasLightShadowFilter); +VARIANT_ENUM_CAST(VisualServer::CanvasOccluderPolygonCullMode); VARIANT_ENUM_CAST(VisualServer::RenderInfo); +VARIANT_ENUM_CAST(VisualServer::Features); //typedef VisualServer VS; // makes it easier to use #define VS VisualServer diff --git a/thirdparty/enet/enet/enet.h b/thirdparty/enet/enet/enet.h index 8c9ad5463e..246cbb0a62 100644 --- a/thirdparty/enet/enet/enet.h +++ b/thirdparty/enet/enet/enet.h @@ -10,6 +10,7 @@ extern "C" { #endif +#include <stdint.h> #include <stdlib.h> #include "enet/godot.h" |