diff options
72 files changed, 1123 insertions, 372 deletions
diff --git a/.gitattributes b/.gitattributes index 03c6f96f80..47ba2b45bb 100644 --- a/.gitattributes +++ b/.gitattributes @@ -9,3 +9,4 @@ drivers/* linguist-vendored *.py eol=lf *.hpp eol=lf *.xml eol=lf +*.natvis eol=lf diff --git a/.gitignore b/.gitignore index 420a25ac59..52937b8679 100644 --- a/.gitignore +++ b/.gitignore @@ -101,9 +101,6 @@ bld/ # Hints for improving IntelliSense, created together with VS project cpp.hint -# Visualizers for the VS debugger -*.natvis - #NUNIT *.VisualState.xml TestResult.xml diff --git a/.travis.yml b/.travis.yml index ea182027ad..7161a3e029 100644 --- a/.travis.yml +++ b/.travis.yml @@ -29,7 +29,7 @@ matrix: - clang-format-6.0 - libstdc++6 # >= 4.9 needed for clang-format-6.0 - - env: GODOT_TARGET=x11 TOOLS=yes CACHE_NAME=${GODOT_TARGET}-tools-mono-gcc EXTRA_ARGS="module_mono_enabled=yes mono_glue=no" + - env: PLATFORM=x11 TOOLS=yes TARGET=debug CACHE_NAME=${PLATFORM}-tools-mono-gcc EXTRA_ARGS="module_mono_enabled=yes mono_glue=no" os: linux compiler: gcc addons: @@ -49,7 +49,7 @@ matrix: build_command: "scons p=x11 -j2 $OPTIONS" branch_pattern: coverity_scan - - env: GODOT_TARGET=x11 TOOLS=no CACHE_NAME=${GODOT_TARGET}-clang + - env: PLATFORM=x11 TOOLS=no TARGET=release CACHE_NAME=${PLATFORM}-clang os: linux compiler: clang addons: @@ -57,19 +57,19 @@ matrix: packages: - *linux_deps - - env: GODOT_TARGET=android TOOLS=no CACHE_NAME=${GODOT_TARGET}-clang + - env: PLATFORM=android TOOLS=no TARGET=release_debug CACHE_NAME=${PLATFORM}-clang os: linux compiler: clang - - env: GODOT_TARGET=osx TOOLS=yes CACHE_NAME=${GODOT_TARGET}-tools-clang + - env: PLATFORM=osx TOOLS=yes TARGET=debug CACHE_NAME=${PLATFORM}-tools-clang os: osx compiler: clang - - env: GODOT_TARGET=iphone TOOLS=no CACHE_NAME=${GODOT_TARGET}-clang + - env: PLATFORM=iphone TOOLS=no TARGET=debug CACHE_NAME=${PLATFORM}-clang os: osx compiler: clang - - env: GODOT_TARGET=server TOOLS=yes CACHE_NAME=${GODOT_TARGET}-tools-gcc + - env: PLATFORM=server TOOLS=yes TARGET=release_debug CACHE_NAME=${PLATFORM}-tools-gcc os: linux compiler: gcc addons: @@ -83,18 +83,18 @@ before_install: fi install: - - if [ "$TRAVIS_OS_NAME" = "linux" ] && [ "$GODOT_TARGET" = "android" ]; then + - if [ "$TRAVIS_OS_NAME" = "linux" ] && [ "$PLATFORM" = "android" ]; then misc/travis/android-tools-linux.sh; fi - if [ "$TRAVIS_OS_NAME" = "osx" ]; then misc/travis/scons-local-osx.sh; fi - - if [ "$TRAVIS_OS_NAME" = "osx" ] && [ "$GODOT_TARGET" = "android" ]; then + - if [ "$TRAVIS_OS_NAME" = "osx" ] && [ "$PLATFORM" = "android" ]; then misc/travis/android-tools-osx.sh; fi before_script: - - if [ "$GODOT_TARGET" = "android" ]; then + - if [ "$PLATFORM" = "android" ]; then export ANDROID_HOME=$TRAVIS_BUILD_DIR/godot-dev/build-tools/android-sdk; export ANDROID_NDK_ROOT=$TRAVIS_BUILD_DIR/godot-dev/build-tools/android-ndk; fi @@ -103,5 +103,5 @@ script: - if [ "$STATIC_CHECKS" = "yes" ]; then sh ./misc/travis/clang-format.sh; else - scons -j2 CC=$CC CXX=$CXX platform=$GODOT_TARGET TOOLS=$TOOLS $EXTRA_ARGS $OPTIONS; + scons -j2 CC=$CC CXX=$CXX platform=$PLATFORM tools=$TOOLS target=$TARGET $EXTRA_ARGS $OPTIONS; fi diff --git a/core/math/math_funcs.cpp b/core/math/math_funcs.cpp index 5c8512d8bd..0c06d2a2b5 100644 --- a/core/math/math_funcs.cpp +++ b/core/math/math_funcs.cpp @@ -57,7 +57,7 @@ uint32_t Math::rand() { } int Math::step_decimals(double p_step) { - static const int maxn = 9; + static const int maxn = 10; static const double sd[maxn] = { 0.9999, // somehow compensate for floating point error 0.09999, @@ -67,17 +67,19 @@ int Math::step_decimals(double p_step) { 0.000009999, 0.0000009999, 0.00000009999, - 0.000000009999 + 0.000000009999, + 0.0000000009999 }; - double as = Math::abs(p_step); + double abs = Math::abs(p_step); + double decs = abs - (int)abs; // Strip away integer part for (int i = 0; i < maxn; i++) { - if (as >= sd[i]) { + if (decs >= sd[i]) { return i; } } - return maxn; + return 0; } double Math::dectime(double p_value, double p_amount, double p_step) { diff --git a/core/script_debugger_remote.cpp b/core/script_debugger_remote.cpp index 704b4d1fdc..fe1dc2cdd1 100644 --- a/core/script_debugger_remote.cpp +++ b/core/script_debugger_remote.cpp @@ -662,11 +662,14 @@ void ScriptDebuggerRemote::_send_object_id(ObjectID p_id) { prop.push_back(Variant()); } else { prop.push_back(pi.hint); - if (res.is_null() || res->get_path().empty()) - prop.push_back(pi.hint_string); - else - prop.push_back(String("RES:") + res->get_path()); + prop.push_back(pi.hint_string); prop.push_back(pi.usage); + if (!res.is_null()) { + var = String("PATH") + res->get_path(); + } else if (var.get_type() == Variant::STRING) { + var = String("DATA") + var; + } + prop.push_back(var); } send_props.push_back(prop); diff --git a/core/variant_op.cpp b/core/variant_op.cpp index 2edf33ec1c..9afc31a772 100644 --- a/core/variant_op.cpp +++ b/core/variant_op.cpp @@ -1656,13 +1656,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 int(v->r * 255.0); + return int(Math::round(v->r * 255.0)); } else if (p_index == CoreStringNames::singleton->g8) { - return int(v->g * 255.0); + return int(Math::round(v->g * 255.0)); } else if (p_index == CoreStringNames::singleton->b8) { - return int(v->b * 255.0); + return int(Math::round(v->b * 255.0)); } else if (p_index == CoreStringNames::singleton->a8) { - return int(v->a * 255.0); + return int(Math::round(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/CanvasItem.xml b/doc/classes/CanvasItem.xml index 98404478f4..60f097f3f9 100644 --- a/doc/classes/CanvasItem.xml +++ b/doc/classes/CanvasItem.xml @@ -576,7 +576,7 @@ Disable blending mode. Colors including alpha are written as is. Only applicable for render targets with a transparent background. No lighting will be applied. </constant> <constant name="NOTIFICATION_TRANSFORM_CHANGED" value="29"> - Canvas item transform has changed. Only received if requested. + Canvas item transform has changed. Notification is only received if enabled by [method set_notify_transform] or [method set_notify_local_transform]. </constant> <constant name="NOTIFICATION_DRAW" value="30"> CanvasItem is requested to draw. diff --git a/doc/classes/ConfigFile.xml b/doc/classes/ConfigFile.xml index ec0381bda5..a4709c1c86 100644 --- a/doc/classes/ConfigFile.xml +++ b/doc/classes/ConfigFile.xml @@ -18,7 +18,7 @@ var err = config.load("user://settings.cfg") if err == OK: # if not, something went wrong with the file loading # Look for the display/width pair, and default to 1024 if missing - var screen_width = get_value("display", "width", 1024) + var screen_width = config.get_value("display", "width", 1024) # Store a variable if and only if it hasn't been defined yet if not config.has_section_key("audio", "mute"): config.set_value("audio", "mute", false) diff --git a/doc/classes/EditorInterface.xml b/doc/classes/EditorInterface.xml index 19bd7e6d52..d85d021a68 100644 --- a/doc/classes/EditorInterface.xml +++ b/doc/classes/EditorInterface.xml @@ -24,7 +24,7 @@ <return type="Control"> </return> <description> - Returns the base [Control]. + Returns the main container of Godot's editor window. You can use it, for example, to retrieve the size of the container and place your controls accordingly. </description> </method> <method name="get_edited_scene_root"> diff --git a/doc/classes/PhysicsBody.xml b/doc/classes/PhysicsBody.xml index 14053c6a35..af00027ed3 100644 --- a/doc/classes/PhysicsBody.xml +++ b/doc/classes/PhysicsBody.xml @@ -27,6 +27,7 @@ <argument index="0" name="bit" type="int"> </argument> <description> + Returns an individual bit on the collision mask. </description> </method> <method name="get_collision_mask_bit" qualifiers="const"> @@ -35,6 +36,7 @@ <argument index="0" name="bit" type="int"> </argument> <description> + Returns an individual bit on the collision mask. </description> </method> <method name="remove_collision_exception_with"> @@ -54,6 +56,7 @@ <argument index="1" name="value" type="bool"> </argument> <description> + Sets individual bits on the layer mask. Use this if you only need to change one layer's value. </description> </method> <method name="set_collision_mask_bit"> @@ -64,6 +67,7 @@ <argument index="1" name="value" type="bool"> </argument> <description> + Sets individual bits on the collision mask. Use this if you only need to change one layer's value. </description> </method> </methods> @@ -74,7 +78,7 @@ A contact is detected if object A is in any of the layers that object B scans, or object B is in any layer scanned by object A. </member> <member name="collision_mask" type="int" setter="set_collision_mask" getter="get_collision_mask"> - The physics layers this area can scan for collisions. + The physics layers this area scans for collisions. </member> </members> <constants> diff --git a/doc/classes/PhysicsBody2D.xml b/doc/classes/PhysicsBody2D.xml index ccc704c7ec..4278979049 100644 --- a/doc/classes/PhysicsBody2D.xml +++ b/doc/classes/PhysicsBody2D.xml @@ -27,7 +27,7 @@ <argument index="0" name="bit" type="int"> </argument> <description> - Return an individual bit on the collision mask. + Returns an individual bit on the collision mask. </description> </method> <method name="get_collision_mask_bit" qualifiers="const"> @@ -36,7 +36,7 @@ <argument index="0" name="bit" type="int"> </argument> <description> - Return an individual bit on the collision mask. + Returns an individual bit on the collision mask. </description> </method> <method name="remove_collision_exception_with"> @@ -56,7 +56,7 @@ <argument index="1" name="value" type="bool"> </argument> <description> - Set/clear individual bits on the layer mask. This makes getting a body in/out of only one layer easier. + Sets individual bits on the layer mask. Use this if you only need to change one layer's value. </description> </method> <method name="set_collision_mask_bit"> @@ -67,7 +67,7 @@ <argument index="1" name="value" type="bool"> </argument> <description> - Set/clear individual bits on the collision mask. This makes selecting the areas scanned easier. + Sets individual bits on the collision mask. Use this if you only need to change one layer's value. </description> </method> </methods> @@ -78,10 +78,10 @@ A contact is detected if object A is in any of the layers that object B scans, or object B is in any layer scanned by object A. </member> <member name="collision_mask" type="int" setter="set_collision_mask" getter="get_collision_mask"> - The physics layers this area can scan for collisions. + The physics layers this area scans for collisions. </member> <member name="layers" type="int" setter="_set_layers" getter="_get_layers"> - Both collision_layer and collision_mask. Returns collision_layer when accessed. Updates collision_layers and collision_mask when modified. + Both [member collision_layer] and [member collision_mask]. Returns [member collision_layer] when accessed. Updates [member collision_layer] and [member collision_mask] when modified. </member> </members> <constants> diff --git a/doc/classes/SceneState.xml b/doc/classes/SceneState.xml index 36cddf08df..bd2f883cae 100644 --- a/doc/classes/SceneState.xml +++ b/doc/classes/SceneState.xml @@ -4,7 +4,7 @@ A script interface to a scene file's data. </brief_description> <description> - Maintains a list of resources, nodes, exported and overridden properties, and built-in scripts associated with a scene. + Maintains a list of resources, nodes, exported, and overridden properties, and built-in scripts associated with a scene. </description> <tutorials> </tutorials> diff --git a/doc/classes/Shape2D.xml b/doc/classes/Shape2D.xml index 6c13496fc4..2772538cec 100644 --- a/doc/classes/Shape2D.xml +++ b/doc/classes/Shape2D.xml @@ -22,7 +22,7 @@ <argument index="2" name="shape_xform" type="Transform2D"> </argument> <description> - Return whether this shape is colliding with another. + Returns [code]true[/code] if this shape is colliding with another. This method needs the transformation matrix for this shape ([code]local_xform[/code]), the shape to check collisions with ([code]with_shape[/code]), and the transformation matrix of that shape ([code]shape_xform[/code]). </description> </method> @@ -36,7 +36,7 @@ <argument index="2" name="shape_xform" type="Transform2D"> </argument> <description> - Return a list of the points where this shape touches another. If there are no collisions, the list is empty. + Returns a list of the points where this shape touches another. If there are no collisions the list is empty. This method needs the transformation matrix for this shape ([code]local_xform[/code]), the shape to check collisions with ([code]with_shape[/code]), and the transformation matrix of that shape ([code]shape_xform[/code]). </description> </method> @@ -72,7 +72,7 @@ <argument index="4" name="shape_motion" type="Vector2"> </argument> <description> - Return a list of the points where this shape would touch another, if a given movement was applied. If there are no collisions, the list is empty. + Returns a list of the points where this shape would touch another, if a given movement was applied. If there are no collisions the list is empty. This method needs the transformation matrix for this shape ([code]local_xform[/code]), the movement to test on this shape ([code]local_motion[/code]), the shape to check collisions with ([code]with_shape[/code]), the transformation matrix of that shape ([code]shape_xform[/code]), and the movement to test onto the other object ([code]shape_motion[/code]). </description> </method> diff --git a/doc/classes/ShortCut.xml b/doc/classes/ShortCut.xml index 6da9d7c59d..1b5fc035c2 100644 --- a/doc/classes/ShortCut.xml +++ b/doc/classes/ShortCut.xml @@ -16,7 +16,7 @@ <return type="String"> </return> <description> - Returns the Shortcut's [InputEvent] as a [String]. + Returns the shortcut's [InputEvent] as a [String]. </description> </method> <method name="is_shortcut" qualifiers="const"> @@ -25,20 +25,20 @@ <argument index="0" name="event" type="InputEvent"> </argument> <description> - Returns [code]true[/code] if the Shortcut's [InputEvent] equals [code]event[/code]. + Returns [code]true[/code] if the shortcut's [InputEvent] equals [code]event[/code]. </description> </method> <method name="is_valid" qualifiers="const"> <return type="bool"> </return> <description> - If [code]true[/code] this Shortcut is valid. + If [code]true[/code] this shortcut is valid. </description> </method> </methods> <members> <member name="shortcut" type="InputEvent" setter="set_shortcut" getter="get_shortcut"> - The Shortcut's [InputEvent]. + The shortcut's [InputEvent]. Generally the [InputEvent] is a keyboard key, though it can be any [InputEvent]. </member> </members> diff --git a/doc/classes/SoftBody.xml b/doc/classes/SoftBody.xml index c3c789a6de..196d29fc60 100644 --- a/doc/classes/SoftBody.xml +++ b/doc/classes/SoftBody.xml @@ -1,8 +1,10 @@ <?xml version="1.0" encoding="UTF-8" ?> <class name="SoftBody" inherits="MeshInstance" category="Core" version="3.1"> <brief_description> + A soft mesh physics body. </brief_description> <description> + A deformable physics body. Used to create elastic or deformable objects such as cloth, rubber, or other flexible materials. </description> <tutorials> </tutorials> @@ -15,6 +17,7 @@ <argument index="0" name="body" type="Node"> </argument> <description> + Adds a body to the list of bodies that this body can't collide with. </description> </method> <method name="get_collision_layer_bit" qualifiers="const"> @@ -23,6 +26,7 @@ <argument index="0" name="bit" type="int"> </argument> <description> + Returns an individual bit on the collision mask. </description> </method> <method name="get_collision_mask_bit" qualifiers="const"> @@ -31,6 +35,7 @@ <argument index="0" name="bit" type="int"> </argument> <description> + Returns an individual bit on the collision mask. </description> </method> <method name="is_ray_pickable" qualifiers="const"> @@ -45,6 +50,7 @@ <argument index="0" name="body" type="Node"> </argument> <description> + Removes a body from the list of bodies that this body can't collide with. </description> </method> <method name="set_collision_layer_bit"> @@ -55,6 +61,7 @@ <argument index="1" name="value" type="bool"> </argument> <description> + Sets individual bits on the layer mask. Use this if you only need to change one layer's value. </description> </method> <method name="set_collision_mask_bit"> @@ -65,6 +72,7 @@ <argument index="1" name="value" type="bool"> </argument> <description> + Sets individual bits on the collision mask. Use this if you only need to change one layer's value. </description> </method> <method name="set_ray_pickable"> @@ -80,8 +88,12 @@ <member name="areaAngular_stiffness" type="float" setter="set_areaAngular_stiffness" getter="get_areaAngular_stiffness"> </member> <member name="collision_layer" type="int" setter="set_collision_layer" getter="get_collision_layer"> + The physics layers this area is in. + Collidable objects can exist in any of 32 different layers. These layers work like a tagging system, and are not visual. A collidable can use these layers to select with which objects it can collide, using the collision_mask property. + A contact is detected if object A is in any of the layers that object B scans, or object B is in any layer scanned by object A. </member> <member name="collision_mask" type="int" setter="set_collision_mask" getter="get_collision_mask"> + The physics layers this area scans for collisions. </member> <member name="damping_coefficient" type="float" setter="set_damping_coefficient" getter="get_damping_coefficient"> </member> @@ -96,6 +108,7 @@ <member name="pressure_coefficient" type="float" setter="set_pressure_coefficient" getter="get_pressure_coefficient"> </member> <member name="simulation_precision" type="int" setter="set_simulation_precision" getter="get_simulation_precision"> + Increasing this value will improve the resulting simulation, but can affect performance. Use with care. </member> <member name="total_mass" type="float" setter="set_total_mass" getter="get_total_mass"> </member> diff --git a/doc/classes/Timer.xml b/doc/classes/Timer.xml index d1c8722901..65d638c4c0 100644 --- a/doc/classes/Timer.xml +++ b/doc/classes/Timer.xml @@ -32,25 +32,26 @@ <return type="void"> </return> <description> - Stop (cancel) the Timer. + Stops the timer. </description> </method> </methods> <members> <member name="autostart" type="bool" setter="set_autostart" getter="has_autostart"> - If [code]true[/code], Timer will automatically start when entering the scene tree. Default value: [code]false[/code]. + If [code]true[/code] the timer will automatically start when entering the scene tree. Default value: [code]false[/code]. </member> <member name="one_shot" type="bool" setter="set_one_shot" getter="is_one_shot"> - If [code]true[/code], Timer will stop when reaching 0. If [code]false[/code], it will restart. Default value: [code]false[/code]. + If [code]true[/code] the timer will stop when reaching 0. If [code]false[/code] it will restart. Default value: [code]false[/code]. </member> <member name="paused" type="bool" setter="set_paused" getter="is_paused"> - If [code]true[/code], the timer is paused and will not process until it is unpaused again, even if [method start] is called. + If [code]true[/code] the timer is paused and will not process until it is unpaused again, even if [method start] is called. </member> <member name="process_mode" type="int" setter="set_timer_process_mode" getter="get_timer_process_mode" enum="Timer.TimerProcessMode"> - Processing mode. Uses TIMER_PROCESS_* constants as value. + Processing mode. See [enum TimerProcessMode]. </member> <member name="time_left" type="float" setter="" getter="get_time_left"> The timer's remaining time in seconds. Returns 0 if the timer is inactive. + Note: You cannot set this value. To change the timer's remaining time, use [member wait_time]. </member> <member name="wait_time" type="float" setter="set_wait_time" getter="get_wait_time"> Wait time in seconds. @@ -59,16 +60,16 @@ <signals> <signal name="timeout"> <description> - Emitted when the Timer reaches 0. + Emitted when the timer reaches 0. </description> </signal> </signals> <constants> <constant name="TIMER_PROCESS_PHYSICS" value="0" enum="TimerProcessMode"> - Update the Timer during the physics step at each frame (fixed framerate processing). + Update the timer during the physics step at each frame (fixed framerate processing). </constant> <constant name="TIMER_PROCESS_IDLE" value="1" enum="TimerProcessMode"> - Update the Timer during the idle time at each frame. + Update the timer during the idle time at each frame. </constant> </constants> </class> diff --git a/editor/code_editor.cpp b/editor/code_editor.cpp index 80bc73bc12..33d36e5e9c 100644 --- a/editor/code_editor.cpp +++ b/editor/code_editor.cpp @@ -374,7 +374,7 @@ void FindReplaceBar::_hide_bar() { void FindReplaceBar::_show_search() { show(); - search_text->grab_focus(); + search_text->call_deferred("grab_focus"); if (text_edit->is_selection_active() && !selection_only->is_pressed()) { search_text->set_text(text_edit->get_selection_text()); diff --git a/editor/create_dialog.cpp b/editor/create_dialog.cpp index ff34618b04..eb11aea9cc 100644 --- a/editor/create_dialog.cpp +++ b/editor/create_dialog.cpp @@ -55,9 +55,9 @@ void CreateDialog::popup_create(bool p_dont_clear, bool p_replace_mode) { while (!f->eof_reached()) { String l = f->get_line().strip_edges(); + String name = l.split(" ")[0]; - if (l != String()) { - + if (ClassDB::class_exists(name) || ScriptServer::is_global_class(name)) { TreeItem *ti = recent->create_item(root); ti->set_text(0, l); ti->set_icon(0, EditorNode::get_singleton()->get_class_icon(l, base_type)); diff --git a/editor/editor_file_system.cpp b/editor/editor_file_system.cpp index 56358cf5b7..ee20d95f25 100644 --- a/editor/editor_file_system.cpp +++ b/editor/editor_file_system.cpp @@ -1378,7 +1378,6 @@ void EditorFileSystem::update_script_classes() { ScriptServer::save_global_classes(); EditorNode::get_editor_data().script_class_save_icon_paths(); - emit_signal("script_classes_updated"); } void EditorFileSystem::_queue_update_script_classes() { @@ -1721,7 +1720,6 @@ void EditorFileSystem::_bind_methods() { ADD_SIGNAL(MethodInfo("filesystem_changed")); ADD_SIGNAL(MethodInfo("sources_changed", PropertyInfo(Variant::BOOL, "exist"))); ADD_SIGNAL(MethodInfo("resources_reimported", PropertyInfo(Variant::POOL_STRING_ARRAY, "resources"))); - ADD_SIGNAL(MethodInfo("script_classes_updated")); } void EditorFileSystem::_update_extensions() { diff --git a/editor/editor_properties_array_dict.cpp b/editor/editor_properties_array_dict.cpp index 9982a31b7b..808a8ac2f8 100644 --- a/editor/editor_properties_array_dict.cpp +++ b/editor/editor_properties_array_dict.cpp @@ -336,16 +336,16 @@ void EditorPropertyArray::update_property() { } break; case Variant::INT: { - EditorPropertyInteger *ed = memnew(EditorPropertyInteger); - ed->setup(-100000, 100000, true, true); - prop = ed; + EditorPropertyInteger *editor = memnew(EditorPropertyInteger); + editor->setup(-100000, 100000, true, true); + prop = editor; } break; case Variant::REAL: { - EditorPropertyFloat *ed = memnew(EditorPropertyFloat); - ed->setup(-100000, 100000, 0.001, true, false, true, true); - prop = ed; + EditorPropertyFloat *editor = memnew(EditorPropertyFloat); + editor->setup(-100000, 100000, 0.001, true, false, true, true); + prop = editor; } break; case Variant::STRING: { @@ -357,63 +357,63 @@ void EditorPropertyArray::update_property() { case Variant::VECTOR2: { - EditorPropertyVector2 *ed = memnew(EditorPropertyVector2); - ed->setup(-100000, 100000, 0.001, true); - prop = ed; + EditorPropertyVector2 *editor = memnew(EditorPropertyVector2); + editor->setup(-100000, 100000, 0.001, true); + prop = editor; } break; case Variant::RECT2: { - EditorPropertyRect2 *ed = memnew(EditorPropertyRect2); - ed->setup(-100000, 100000, 0.001, true); - prop = ed; + EditorPropertyRect2 *editor = memnew(EditorPropertyRect2); + editor->setup(-100000, 100000, 0.001, true); + prop = editor; } break; case Variant::VECTOR3: { - EditorPropertyVector3 *ed = memnew(EditorPropertyVector3); - ed->setup(-100000, 100000, 0.001, true); - prop = ed; + EditorPropertyVector3 *editor = memnew(EditorPropertyVector3); + editor->setup(-100000, 100000, 0.001, true); + prop = editor; } break; case Variant::TRANSFORM2D: { - EditorPropertyTransform2D *ed = memnew(EditorPropertyTransform2D); - ed->setup(-100000, 100000, 0.001, true); - prop = ed; + EditorPropertyTransform2D *editor = memnew(EditorPropertyTransform2D); + editor->setup(-100000, 100000, 0.001, true); + prop = editor; } break; case Variant::PLANE: { - EditorPropertyPlane *ed = memnew(EditorPropertyPlane); - ed->setup(-100000, 100000, 0.001, true); - prop = ed; + EditorPropertyPlane *editor = memnew(EditorPropertyPlane); + editor->setup(-100000, 100000, 0.001, true); + prop = editor; } break; case Variant::QUAT: { - EditorPropertyQuat *ed = memnew(EditorPropertyQuat); - ed->setup(-100000, 100000, 0.001, true); - prop = ed; + EditorPropertyQuat *editor = memnew(EditorPropertyQuat); + editor->setup(-100000, 100000, 0.001, true); + prop = editor; } break; case Variant::AABB: { - EditorPropertyAABB *ed = memnew(EditorPropertyAABB); - ed->setup(-100000, 100000, 0.001, true); - prop = ed; + EditorPropertyAABB *editor = memnew(EditorPropertyAABB); + editor->setup(-100000, 100000, 0.001, true); + prop = editor; } break; case Variant::BASIS: { - EditorPropertyBasis *ed = memnew(EditorPropertyBasis); - ed->setup(-100000, 100000, 0.001, true); - prop = ed; + EditorPropertyBasis *editor = memnew(EditorPropertyBasis); + editor->setup(-100000, 100000, 0.001, true); + prop = editor; } break; case Variant::TRANSFORM: { - EditorPropertyTransform *ed = memnew(EditorPropertyTransform); - ed->setup(-100000, 100000, 0.001, true); - prop = ed; + EditorPropertyTransform *editor = memnew(EditorPropertyTransform); + editor->setup(-100000, 100000, 0.001, true); + prop = editor; } break; @@ -431,8 +431,9 @@ void EditorPropertyArray::update_property() { } break; case Variant::OBJECT: { - - prop = memnew(EditorPropertyResource); + EditorPropertyResource *editor = memnew(EditorPropertyResource); + editor->setup("Resource"); + prop = editor; } break; case Variant::DICTIONARY: { @@ -798,16 +799,16 @@ void EditorPropertyDictionary::update_property() { } break; case Variant::INT: { - EditorPropertyInteger *ed = memnew(EditorPropertyInteger); - ed->setup(-100000, 100000, true, true); - prop = ed; + EditorPropertyInteger *editor = memnew(EditorPropertyInteger); + editor->setup(-100000, 100000, true, true); + prop = editor; } break; case Variant::REAL: { - EditorPropertyFloat *ed = memnew(EditorPropertyFloat); - ed->setup(-100000, 100000, 0.001, true, false, true, true); - prop = ed; + EditorPropertyFloat *editor = memnew(EditorPropertyFloat); + editor->setup(-100000, 100000, 0.001, true, false, true, true); + prop = editor; } break; case Variant::STRING: { @@ -815,67 +816,66 @@ void EditorPropertyDictionary::update_property() { } break; - // math types - + // math types case Variant::VECTOR2: { - EditorPropertyVector2 *ed = memnew(EditorPropertyVector2); - ed->setup(-100000, 100000, 0.001, true); - prop = ed; + EditorPropertyVector2 *editor = memnew(EditorPropertyVector2); + editor->setup(-100000, 100000, 0.001, true); + prop = editor; } break; case Variant::RECT2: { - EditorPropertyRect2 *ed = memnew(EditorPropertyRect2); - ed->setup(-100000, 100000, 0.001, true); - prop = ed; + EditorPropertyRect2 *editor = memnew(EditorPropertyRect2); + editor->setup(-100000, 100000, 0.001, true); + prop = editor; } break; case Variant::VECTOR3: { - EditorPropertyVector3 *ed = memnew(EditorPropertyVector3); - ed->setup(-100000, 100000, 0.001, true); - prop = ed; + EditorPropertyVector3 *editor = memnew(EditorPropertyVector3); + editor->setup(-100000, 100000, 0.001, true); + prop = editor; } break; case Variant::TRANSFORM2D: { - EditorPropertyTransform2D *ed = memnew(EditorPropertyTransform2D); - ed->setup(-100000, 100000, 0.001, true); - prop = ed; + EditorPropertyTransform2D *editor = memnew(EditorPropertyTransform2D); + editor->setup(-100000, 100000, 0.001, true); + prop = editor; } break; case Variant::PLANE: { - EditorPropertyPlane *ed = memnew(EditorPropertyPlane); - ed->setup(-100000, 100000, 0.001, true); - prop = ed; + EditorPropertyPlane *editor = memnew(EditorPropertyPlane); + editor->setup(-100000, 100000, 0.001, true); + prop = editor; } break; case Variant::QUAT: { - EditorPropertyQuat *ed = memnew(EditorPropertyQuat); - ed->setup(-100000, 100000, 0.001, true); - prop = ed; + EditorPropertyQuat *editor = memnew(EditorPropertyQuat); + editor->setup(-100000, 100000, 0.001, true); + prop = editor; } break; case Variant::AABB: { - EditorPropertyAABB *ed = memnew(EditorPropertyAABB); - ed->setup(-100000, 100000, 0.001, true); - prop = ed; + EditorPropertyAABB *editor = memnew(EditorPropertyAABB); + editor->setup(-100000, 100000, 0.001, true); + prop = editor; } break; case Variant::BASIS: { - EditorPropertyBasis *ed = memnew(EditorPropertyBasis); - ed->setup(-100000, 100000, 0.001, true); - prop = ed; + EditorPropertyBasis *editor = memnew(EditorPropertyBasis); + editor->setup(-100000, 100000, 0.001, true); + prop = editor; } break; case Variant::TRANSFORM: { - EditorPropertyTransform *ed = memnew(EditorPropertyTransform); - ed->setup(-100000, 100000, 0.001, true); - prop = ed; + EditorPropertyTransform *editor = memnew(EditorPropertyTransform); + editor->setup(-100000, 100000, 0.001, true); + prop = editor; } break; @@ -893,8 +893,9 @@ void EditorPropertyDictionary::update_property() { } break; case Variant::OBJECT: { - - prop = memnew(EditorPropertyResource); + EditorPropertyResource *editor = memnew(EditorPropertyResource); + editor->setup("Resource"); + prop = editor; } break; case Variant::DICTIONARY: { @@ -902,39 +903,53 @@ void EditorPropertyDictionary::update_property() { } break; case Variant::ARRAY: { - - prop = memnew(EditorPropertyArray); - + EditorPropertyArray *editor = memnew(EditorPropertyArray); + editor->setup(Variant::ARRAY); + prop = editor; } break; // arrays case Variant::POOL_BYTE_ARRAY: { - prop = memnew(EditorPropertyArray); + EditorPropertyArray *editor = memnew(EditorPropertyArray); + editor->setup(Variant::POOL_BYTE_ARRAY); + prop = editor; } break; case Variant::POOL_INT_ARRAY: { - prop = memnew(EditorPropertyArray); + EditorPropertyArray *editor = memnew(EditorPropertyArray); + editor->setup(Variant::POOL_INT_ARRAY); + prop = editor; } break; case Variant::POOL_REAL_ARRAY: { - prop = memnew(EditorPropertyArray); + EditorPropertyArray *editor = memnew(EditorPropertyArray); + editor->setup(Variant::POOL_REAL_ARRAY); + prop = editor; } break; case Variant::POOL_STRING_ARRAY: { - prop = memnew(EditorPropertyArray); + EditorPropertyArray *editor = memnew(EditorPropertyArray); + editor->setup(Variant::POOL_STRING_ARRAY); + prop = editor; } break; case Variant::POOL_VECTOR2_ARRAY: { - prop = memnew(EditorPropertyArray); + EditorPropertyArray *editor = memnew(EditorPropertyArray); + editor->setup(Variant::POOL_VECTOR2_ARRAY); + prop = editor; } break; case Variant::POOL_VECTOR3_ARRAY: { - prop = memnew(EditorPropertyArray); + EditorPropertyArray *editor = memnew(EditorPropertyArray); + editor->setup(Variant::POOL_VECTOR3_ARRAY); + prop = editor; } break; case Variant::POOL_COLOR_ARRAY: { - prop = memnew(EditorPropertyArray); + EditorPropertyArray *editor = memnew(EditorPropertyArray); + editor->setup(Variant::POOL_COLOR_ARRAY); + prop = editor; } break; default: {} } diff --git a/editor/icons/icon_GUI_checked.svg b/editor/icons/icon_GUI_checked.svg index e5fa67ebf5..8d00eca8d3 100644 --- a/editor/icons/icon_GUI_checked.svg +++ b/editor/icons/icon_GUI_checked.svg @@ -1,3 +1 @@ -<svg width="16" height="16" version="1.1" viewBox="0 0 16 15.999999" xmlns="http://www.w3.org/2000/svg"> -<path d="m4 2c-1.1046 0-2 0.89543-2 2v8c0 1.1046 0.89543 2 2 2h8c1.1046 0 2-0.89543 2-2v-8c0-1.1046-0.89543-2-2-2h-8zm7.293 2.293l1.4141 1.4141-6.707 6.707-2.707-2.707 1.4141-1.4141 1.293 1.293 5.293-5.293z" fill="#e0e0e0" fill-opacity=".78431"/> -</svg> +<svg height="16" viewBox="0 0 16 15.999999" width="16" xmlns="http://www.w3.org/2000/svg"><g fill="#e0e0e0"><path d="m3.3333333 1c-1.2887 0-2.3333333 1.0446683-2.3333333 2.3333333v9.3333337c0 1.2887 1.0446683 2.333333 2.3333333 2.333333h9.3333337c1.2887 0 2.333333-1.044668 2.333333-2.333333v-9.3333337c0-1.2887-1.044668-2.3333333-2.333333-2.3333333z" fill-opacity=".188235" stroke-width="1.166667"/><path d="m11.500773 3.7343508-5.6117507 5.6117502-1.7045017-1.6814543-1.4992276 1.4992276 3.2037293 3.1806817 7.1109777-7.1109775z" stroke-width="1.060227"/></g></svg>
\ No newline at end of file diff --git a/editor/icons/icon_GUI_radio_checked.svg b/editor/icons/icon_GUI_radio_checked.svg index 6a65d49eeb..447b57f8ae 100644 --- a/editor/icons/icon_GUI_radio_checked.svg +++ b/editor/icons/icon_GUI_radio_checked.svg @@ -1,6 +1 @@ -<svg width="16" height="16" version="1.1" viewBox="0 0 16 15.999999" xmlns="http://www.w3.org/2000/svg"> -<g transform="translate(0 -1036.4)"> -<circle cx="8" cy="1044.4" r="5" fill="none" stroke="#e0e0e0" stroke-linecap="round" stroke-linejoin="round" stroke-opacity=".78431" stroke-width="2"/> -<circle cx="8" cy="1044.4" r="3" fill="#e0e0e0" fill-opacity=".78431"/> -</g> -</svg> +<svg height="16" viewBox="0 0 16 15.999999" width="16" xmlns="http://www.w3.org/2000/svg"><g fill="#e0e0e0"><path d="m15 8a7 7 0 0 1 -7 7 7 7 0 0 1 -7-7 7 7 0 0 1 7-7 7 7 0 0 1 7 7" fill-opacity=".188235" stroke-width="2.333333"/><path d="m12 8a4 4 0 0 1 -4 4 4 4 0 0 1 -4-4 4 4 0 0 1 4-4 4 4 0 0 1 4 4" stroke-width="1.333333"/></g></svg>
\ No newline at end of file diff --git a/editor/icons/icon_GUI_radio_unchecked.svg b/editor/icons/icon_GUI_radio_unchecked.svg index 6e52a8af77..1e8117bd10 100644 --- a/editor/icons/icon_GUI_radio_unchecked.svg +++ b/editor/icons/icon_GUI_radio_unchecked.svg @@ -1,5 +1 @@ -<svg width="16" height="16" version="1.1" viewBox="0 0 16 15.999999" xmlns="http://www.w3.org/2000/svg"> -<g transform="translate(0 -1036.4)"> -<circle cx="8" cy="1044.4" r="5" fill="none" stroke="#e0e0e0" stroke-linecap="round" stroke-linejoin="round" stroke-opacity=".78431" stroke-width="2"/> -</g> -</svg> +<svg height="16" viewBox="0 0 16 15.999999" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m15 8a7 7 0 0 1 -7 7 7 7 0 0 1 -7-7 7 7 0 0 1 7-7 7 7 0 0 1 7 7" fill="#e0e0e0" fill-opacity=".188235" stroke-width="2.333333"/></svg>
\ No newline at end of file diff --git a/editor/icons/icon_GUI_unchecked.svg b/editor/icons/icon_GUI_unchecked.svg index 59df40954f..9575422df3 100644 --- a/editor/icons/icon_GUI_unchecked.svg +++ b/editor/icons/icon_GUI_unchecked.svg @@ -1,3 +1 @@ -<svg width="16" height="16" version="1.1" viewBox="0 0 16 15.999999" xmlns="http://www.w3.org/2000/svg"> -<path d="m4 2a2 2 0 0 0 -2 2v8a2 2 0 0 0 2 2h8a2 2 0 0 0 2 -2v-8a2 2 0 0 0 -2 -2h-8zm0.80078 2h6.3984a0.8 0.8 0 0 1 0.80078 0.80078v6.3984a0.8 0.8 0 0 1 -0.80078 0.80078h-6.3984a0.8 0.8 0 0 1 -0.80078 -0.80078v-6.3984a0.8 0.8 0 0 1 0.80078 -0.80078z" fill="#e0e0e0" fill-opacity=".78431"/> -</svg> +<svg height="16" viewBox="0 0 16 15.999999" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m3.3333333 1c-1.2887 0-2.3333333 1.0446683-2.3333333 2.3333333v9.3333337c0 1.2887 1.0446683 2.333333 2.3333333 2.333333h9.3333337c1.2887 0 2.333333-1.044668 2.333333-2.333333v-9.3333337c0-1.2887-1.044668-2.3333333-2.333333-2.3333333z" fill="#e0e0e0" fill-opacity=".188235" stroke-width="1.166667"/></svg>
\ No newline at end of file diff --git a/editor/plugins/abstract_polygon_2d_editor.cpp b/editor/plugins/abstract_polygon_2d_editor.cpp index 2d341cdd93..b51ff8b320 100644 --- a/editor/plugins/abstract_polygon_2d_editor.cpp +++ b/editor/plugins/abstract_polygon_2d_editor.cpp @@ -275,6 +275,10 @@ bool AbstractPolygon2DEditor::forward_gui_input(const Ref<InputEvent> &p_event) return (mb.is_valid() && mb->get_button_index() == 1); } + CanvasItemEditor::Tool tool = CanvasItemEditor::get_singleton()->get_current_tool(); + if (tool != CanvasItemEditor::TOOL_SELECT) + return false; + if (mb.is_valid()) { Transform2D xform = canvas_item_editor->get_canvas_transform() * _get_node()->get_global_transform(); @@ -283,10 +287,10 @@ bool AbstractPolygon2DEditor::forward_gui_input(const Ref<InputEvent> &p_event) 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()))); if (mode == MODE_EDIT || (_is_line() && mode == MODE_CREATE)) { - if (mb->get_button_index() == BUTTON_LEFT) { - if (mb->is_pressed()) { + if (mb->get_control() || mb->get_shift() || mb->get_alt()) + return false; const PosVertex insert = closest_edge_point(gpoint); diff --git a/editor/plugins/canvas_item_editor_plugin.cpp b/editor/plugins/canvas_item_editor_plugin.cpp index 79578989d5..61433bbeec 100644 --- a/editor/plugins/canvas_item_editor_plugin.cpp +++ b/editor/plugins/canvas_item_editor_plugin.cpp @@ -443,8 +443,12 @@ void CanvasItemEditor::_find_canvas_items_at_pos(const Point2 &p_pos, Node *p_no CanvasItem *canvas_item = Object::cast_to<CanvasItem>(p_node); for (int i = p_node->get_child_count() - 1; i >= 0; i--) { - if (canvas_item && !canvas_item->is_set_as_toplevel()) { - _find_canvas_items_at_pos(p_pos, p_node->get_child(i), r_items, p_limit, p_parent_xform * canvas_item->get_transform(), p_canvas_xform); + if (canvas_item) { + if (!canvas_item->is_set_as_toplevel()) { + _find_canvas_items_at_pos(p_pos, p_node->get_child(i), r_items, p_limit, p_parent_xform * canvas_item->get_transform(), p_canvas_xform); + } else { + _find_canvas_items_at_pos(p_pos, p_node->get_child(i), r_items, p_limit, canvas_item->get_transform(), p_canvas_xform); + } } else { CanvasLayer *cl = Object::cast_to<CanvasLayer>(p_node); _find_canvas_items_at_pos(p_pos, p_node->get_child(i), r_items, p_limit, Transform2D(), cl ? cl->get_transform() : p_canvas_xform); @@ -610,8 +614,12 @@ void CanvasItemEditor::_find_canvas_items_in_rect(const Rect2 &p_rect, Node *p_n if (!lock_children || !editable) { for (int i = p_node->get_child_count() - 1; i >= 0; i--) { - if (canvas_item && !canvas_item->is_set_as_toplevel()) { - _find_canvas_items_in_rect(p_rect, p_node->get_child(i), r_items, p_parent_xform * canvas_item->get_transform(), p_canvas_xform); + if (canvas_item) { + if (!canvas_item->is_set_as_toplevel()) { + _find_canvas_items_in_rect(p_rect, p_node->get_child(i), r_items, p_parent_xform * canvas_item->get_transform(), p_canvas_xform); + } else { + _find_canvas_items_in_rect(p_rect, p_node->get_child(i), r_items, canvas_item->get_transform(), p_canvas_xform); + } } else { CanvasLayer *canvas_layer = Object::cast_to<CanvasLayer>(p_node); _find_canvas_items_in_rect(p_rect, p_node->get_child(i), r_items, Transform2D(), canvas_layer ? canvas_layer->get_transform() : p_canvas_xform); @@ -2938,13 +2946,13 @@ void CanvasItemEditor::_draw_locks_and_groups(Node *p_node, const Transform2D &p float offset = 0; Ref<Texture> lock = get_icon("LockViewport", "EditorIcons"); - if (p_node->has_meta("_edit_lock_")) { + if (p_node->has_meta("_edit_lock_") && show_edit_locks) { lock->draw(viewport_canvas_item, (transform * canvas_xform * parent_xform).xform(Point2(0, 0)) + Point2(offset, 0)); offset += lock->get_size().x; } Ref<Texture> group = get_icon("GroupViewport", "EditorIcons"); - if (canvas_item->has_meta("_edit_group_")) { + if (canvas_item->has_meta("_edit_group_") && show_edit_locks) { group->draw(viewport_canvas_item, (transform * canvas_xform * parent_xform).xform(Point2(0, 0)) + Point2(offset, 0)); //offset += group->get_size().x; } @@ -3543,6 +3551,12 @@ void CanvasItemEditor::_popup_callback(int p_op) { view_menu->get_popup()->set_item_checked(idx, show_viewport); viewport->update(); } break; + case SHOW_EDIT_LOCKS: { + show_edit_locks = !show_edit_locks; + int idx = view_menu->get_popup()->get_item_index(SHOW_EDIT_LOCKS); + view_menu->get_popup()->set_item_checked(idx, show_edit_locks); + viewport->update(); + } break; case SNAP_USE_NODE_PARENT: { snap_node_parent = !snap_node_parent; int idx = smartsnap_config_popup->get_item_index(SNAP_USE_NODE_PARENT); @@ -4146,6 +4160,7 @@ Dictionary CanvasItemEditor::get_state() const { state["show_rulers"] = show_rulers; state["show_guides"] = show_guides; state["show_helpers"] = show_helpers; + state["show_edit_locks"] = show_edit_locks; state["snap_rotation"] = snap_rotation; state["snap_relative"] = snap_relative; state["snap_pixel"] = snap_pixel; @@ -4265,6 +4280,12 @@ void CanvasItemEditor::set_state(const Dictionary &p_state) { view_menu->get_popup()->set_item_checked(idx, show_helpers); } + if (state.has("show_edit_locks")) { + show_edit_locks = state["show_edit_locks"]; + int idx = view_menu->get_popup()->get_item_index(SHOW_EDIT_LOCKS); + view_menu->get_popup()->set_item_checked(idx, show_edit_locks); + } + if (state.has("snap_rotation")) { snap_rotation = state["snap_rotation"]; int idx = snap_config_menu->get_popup()->get_item_index(SNAP_USE_ROTATION); @@ -4535,6 +4556,8 @@ CanvasItemEditor::CanvasItemEditor(EditorNode *p_editor) { p->add_check_shortcut(ED_SHORTCUT("canvas_item_editor/show_guides", TTR("Show Guides"), KEY_Y), SHOW_GUIDES); p->add_check_shortcut(ED_SHORTCUT("canvas_item_editor/show_origin", TTR("Show Origin")), SHOW_ORIGIN); p->add_check_shortcut(ED_SHORTCUT("canvas_item_editor/show_viewport", TTR("Show Viewport")), SHOW_VIEWPORT); + p->add_check_shortcut(ED_SHORTCUT("canvas_item_editor/show_edit_locks", TTR("Show Group And Lock Icons")), SHOW_EDIT_LOCKS); + p->add_separator(); p->add_shortcut(ED_SHORTCUT("canvas_item_editor/center_selection", TTR("Center Selection"), KEY_F), VIEW_CENTER_TO_SELECTION); p->add_shortcut(ED_SHORTCUT("canvas_item_editor/frame_selection", TTR("Frame Selection"), KEY_MASK_SHIFT | KEY_F), VIEW_FRAME_TO_SELECTION); @@ -4625,6 +4648,7 @@ CanvasItemEditor::CanvasItemEditor(EditorNode *p_editor) { show_helpers = false; show_rulers = true; show_guides = true; + show_edit_locks = true; zoom = 1; view_offset = Point2(-150 - RULER_WIDTH, -95 - RULER_WIDTH); previous_update_view_offset = view_offset; // Moves the view a little bit to the left so that (0,0) is visible. The values a relative to a 16/10 screen diff --git a/editor/plugins/canvas_item_editor_plugin.h b/editor/plugins/canvas_item_editor_plugin.h index 61d77581d3..61631dee7d 100644 --- a/editor/plugins/canvas_item_editor_plugin.h +++ b/editor/plugins/canvas_item_editor_plugin.h @@ -71,8 +71,7 @@ class CanvasItemEditor : public VBoxContainer { GDCLASS(CanvasItemEditor, VBoxContainer); - EditorNode *editor; - +public: enum Tool { TOOL_SELECT, TOOL_LIST_SELECT, @@ -84,6 +83,9 @@ class CanvasItemEditor : public VBoxContainer { TOOL_MAX }; +private: + EditorNode *editor; + enum MenuOption { SNAP_USE, SNAP_USE_NODE_PARENT, @@ -103,6 +105,7 @@ class CanvasItemEditor : public VBoxContainer { SHOW_GUIDES, SHOW_ORIGIN, SHOW_VIEWPORT, + SHOW_EDIT_LOCKS, LOCK_SELECTED, UNLOCK_SELECTED, GROUP_SELECTED, @@ -223,6 +226,7 @@ class CanvasItemEditor : public VBoxContainer { bool show_origin; bool show_viewport; bool show_helpers; + bool show_edit_locks; float zoom; Point2 view_offset; Point2 previous_update_view_offset; @@ -535,6 +539,8 @@ public: Control *get_viewport_control() { return viewport; } + Tool get_current_tool() { return tool; } + void set_undo_redo(UndoRedo *p_undo_redo) { undo_redo = p_undo_redo; } void edit(CanvasItem *p_canvas_item); diff --git a/editor/plugins/script_text_editor.cpp b/editor/plugins/script_text_editor.cpp index bdeeaa106d..d4ddaf274f 100644 --- a/editor/plugins/script_text_editor.cpp +++ b/editor/plugins/script_text_editor.cpp @@ -317,6 +317,7 @@ void ScriptTextEditor::_notification(int p_what) { switch (p_what) { case NOTIFICATION_READY: _load_theme_settings(); + _change_syntax_highlighter(EditorSettings::get_singleton()->get_project_metadata("script_text_editor", "syntax_highlighter", 0)); break; } } @@ -1058,6 +1059,7 @@ void ScriptTextEditor::_change_syntax_highlighter(int p_idx) { } // highlighter_menu->set_item_checked(p_idx, true); set_syntax_highlighter(highlighters[highlighter_menu->get_item_text(p_idx)]); + EditorSettings::get_singleton()->set_project_metadata("script_text_editor", "syntax_highlighter", p_idx); } void ScriptTextEditor::_bind_methods() { diff --git a/editor/plugins/text_editor.cpp b/editor/plugins/text_editor.cpp index 3bf4140591..4ff7046a35 100644 --- a/editor/plugins/text_editor.cpp +++ b/editor/plugins/text_editor.cpp @@ -66,6 +66,7 @@ void TextEditor::_change_syntax_highlighter(int p_idx) { el = el->next(); } set_syntax_highlighter(highlighters[highlighter_menu->get_item_text(p_idx)]); + EditorSettings::get_singleton()->set_project_metadata("text_editor", "syntax_highlighter", p_idx); } void TextEditor::_load_theme_settings() { @@ -298,7 +299,7 @@ void TextEditor::_notification(int p_what) { switch (p_what) { case NOTIFICATION_READY: _load_theme_settings(); - set_syntax_highlighter(NULL); + _change_syntax_highlighter(EditorSettings::get_singleton()->get_project_metadata("text_editor", "syntax_highlighter", 0)); break; } } diff --git a/editor/plugins/visual_shader_editor_plugin.cpp b/editor/plugins/visual_shader_editor_plugin.cpp index 0d683ea0a0..207078d90f 100644 --- a/editor/plugins/visual_shader_editor_plugin.cpp +++ b/editor/plugins/visual_shader_editor_plugin.cpp @@ -932,7 +932,10 @@ public: class VisualShaderNodePluginDefaultEditor : public VBoxContainer { GDCLASS(VisualShaderNodePluginDefaultEditor, VBoxContainer) public: - void _property_changed(const String &prop, const Variant &p_value) { + void _property_changed(const String &prop, const Variant &p_value, bool p_changing = false) { + + if (p_changing) + return; UndoRedo *undo_redo = EditorNode::get_singleton()->get_undo_redo(); @@ -979,7 +982,7 @@ public: } static void _bind_methods() { - ClassDB::bind_method("_property_changed", &VisualShaderNodePluginDefaultEditor::_property_changed); + ClassDB::bind_method("_property_changed", &VisualShaderNodePluginDefaultEditor::_property_changed, DEFVAL(false)); ClassDB::bind_method("_node_changed", &VisualShaderNodePluginDefaultEditor::_node_changed); ClassDB::bind_method("_refresh_request", &VisualShaderNodePluginDefaultEditor::_refresh_request); } diff --git a/editor/scene_tree_dock.cpp b/editor/scene_tree_dock.cpp index 8637417598..ff6832177e 100644 --- a/editor/scene_tree_dock.cpp +++ b/editor/scene_tree_dock.cpp @@ -830,6 +830,8 @@ void SceneTreeDock::_tool_selected(int p_tool, bool p_confirm_override) { editor_data->get_undo_redo().add_undo_method(editor, "set_edited_scene", (Object *)NULL); editor_data->get_undo_redo().commit_action(); + editor->edit_node(new_node); + } break; default: { @@ -2401,7 +2403,6 @@ SceneTreeDock::SceneTreeDock(EditorNode *p_editor, Node *p_scene_root, EditorSel add_child(create_dialog); create_dialog->connect("create", this, "_create"); create_dialog->connect("favorites_updated", this, "_update_create_root_dialog"); - EditorFileSystem::get_singleton()->connect("script_classes_updated", create_dialog, "_save_and_update_favorite_list"); rename_dialog = memnew(RenameDialog(scene_tree, &editor_data->get_undo_redo())); add_child(rename_dialog); diff --git a/editor/script_editor_debugger.cpp b/editor/script_editor_debugger.cpp index a28a111025..cc477314e9 100644 --- a/editor/script_editor_debugger.cpp +++ b/editor/script_editor_debugger.cpp @@ -492,17 +492,19 @@ void ScriptEditorDebugger::_parse_message(const String &p_msg, const Array &p_da pinfo.usage = PropertyUsageFlags(int(prop[4])); Variant var = prop[5]; - String hint_string = pinfo.hint_string; - if (hint_string.begins_with("RES:") && hint_string != "RES:") { - String path = hint_string.substr(4, hint_string.length()); - var = ResourceLoader::load(path); - } - if (is_new_object) { //don't update.. it's the same, instead refresh debugObj->prop_list.push_back(pinfo); } + if (var.get_type() == Variant::STRING) { + String str = var; + var = str.substr(4, str.length()); + + if (str.begins_with("PATH")) + var = ResourceLoader::load(var); + } + debugObj->prop_values[pinfo.name] = var; } @@ -573,9 +575,7 @@ void ScriptEditorDebugger::_parse_message(const String &p_msg, const Array &p_da PropertyHint h = PROPERTY_HINT_NONE; String hs = String(); - if (n.begins_with("*")) { - - n = n.substr(1, n.length()); + if (v.get_type() == Variant::OBJECT) { h = PROPERTY_HINT_OBJECT_ID; String s = v; s = s.replace("[", ""); @@ -596,9 +596,7 @@ void ScriptEditorDebugger::_parse_message(const String &p_msg, const Array &p_da PropertyHint h = PROPERTY_HINT_NONE; String hs = String(); - if (n.begins_with("*")) { - - n = n.substr(1, n.length()); + if (v.get_type() == Variant::OBJECT) { h = PROPERTY_HINT_OBJECT_ID; String s = v; s = s.replace("[", ""); @@ -619,9 +617,7 @@ void ScriptEditorDebugger::_parse_message(const String &p_msg, const Array &p_da PropertyHint h = PROPERTY_HINT_NONE; String hs = String(); - if (n.begins_with("*")) { - - n = n.substr(1, n.length()); + if (v.get_type() == Variant::OBJECT) { h = PROPERTY_HINT_OBJECT_ID; String s = v; s = s.replace("[", ""); diff --git a/main/input_default.cpp b/main/input_default.cpp index 2efbb3f849..10be291b8d 100644 --- a/main/input_default.cpp +++ b/main/input_default.cpp @@ -598,7 +598,13 @@ Input::CursorShape InputDefault::get_default_cursor_shape() { void InputDefault::set_default_cursor_shape(CursorShape p_shape) { default_shape = p_shape; - OS::get_singleton()->set_cursor_shape((OS::CursorShape)p_shape); + // The default shape is set in Viewport::_gui_input_event. To instantly + // see the shape in the viewport we need to trigger a mouse motion event. + Ref<InputEventMouseMotion> mm; + mm.instance(); + mm->set_position(mouse_pos); + mm->set_global_position(mouse_pos); + parse_input_event(mm); } void InputDefault::set_custom_mouse_cursor(const RES &p_cursor, CursorShape p_shape, const Vector2 &p_hotspot) { diff --git a/modules/bullet/godot_result_callbacks.cpp b/modules/bullet/godot_result_callbacks.cpp index 08d8b8c6f6..3b44ab838e 100644 --- a/modules/bullet/godot_result_callbacks.cpp +++ b/modules/bullet/godot_result_callbacks.cpp @@ -164,9 +164,11 @@ bool GodotClosestConvexResultCallback::needsCollision(btBroadphaseProxy *proxy0) } btScalar GodotClosestConvexResultCallback::addSingleResult(btCollisionWorld::LocalConvexResult &convexResult, bool normalInWorldSpace) { - btScalar res = btCollisionWorld::ClosestConvexResultCallback::addSingleResult(convexResult, normalInWorldSpace); - m_shapeId = convexResult.m_localShapeInfo->m_triangleIndex; // "m_triangleIndex" Is a odd name but contains the compound shape ID - return res; + if (convexResult.m_localShapeInfo) + m_shapeId = convexResult.m_localShapeInfo->m_triangleIndex; // "m_triangleIndex" Is a odd name but contains the compound shape ID + else + m_shapeId = 0; + return btCollisionWorld::ClosestConvexResultCallback::addSingleResult(convexResult, normalInWorldSpace); } bool GodotAllContactResultCallback::needsCollision(btBroadphaseProxy *proxy0) const { diff --git a/modules/bullet/rigid_body_bullet.cpp b/modules/bullet/rigid_body_bullet.cpp index f81cfe84fb..f24c8670a3 100644 --- a/modules/bullet/rigid_body_bullet.cpp +++ b/modules/bullet/rigid_body_bullet.cpp @@ -351,7 +351,7 @@ void RigidBodyBullet::set_space(SpaceBullet *p_space) { void RigidBodyBullet::dispatch_callbacks() { /// The check isTransformChanged is necessary in order to call integrated forces only when the first transform is sent - if ((btBody->isActive() || previousActiveState != btBody->isActive()) && force_integration_callback && isTransformChanged) { + if ((btBody->isKinematicObject() || btBody->isActive() || previousActiveState != btBody->isActive()) && force_integration_callback && isTransformChanged) { if (omit_forces_integration) btBody->clearForces(); @@ -774,10 +774,13 @@ Vector3 RigidBodyBullet::get_angular_velocity() const { void RigidBodyBullet::set_transform__bullet(const btTransform &p_global_transform) { if (mode == PhysicsServer::BODY_MODE_KINEMATIC) { + if (space) + btBody->setLinearVelocity((p_global_transform.getOrigin() - btBody->getWorldTransform().getOrigin()) / space->get_delta_time()); // The kinematic use MotionState class godotMotionState->moveBody(p_global_transform); } btBody->setWorldTransform(p_global_transform); + scratch(); } const btTransform &RigidBodyBullet::get_transform__bullet() const { diff --git a/modules/bullet/space_bullet.cpp b/modules/bullet/space_bullet.cpp index 5b220e1039..404cb8e37b 100644 --- a/modules/bullet/space_bullet.cpp +++ b/modules/bullet/space_bullet.cpp @@ -786,30 +786,32 @@ void SpaceBullet::check_body_collision() { if (numContacts) { btManifoldPoint &pt = contactManifold->getContactPoint(0); #endif - Vector3 collisionWorldPosition; - Vector3 collisionLocalPosition; - Vector3 normalOnB; - float appliedImpulse = pt.m_appliedImpulse; - B_TO_G(pt.m_normalWorldOnB, normalOnB); - - if (bodyA->can_add_collision()) { - B_TO_G(pt.getPositionWorldOnB(), collisionWorldPosition); - /// pt.m_localPointB Doesn't report the exact point in local space - B_TO_G(pt.getPositionWorldOnB() - contactManifold->getBody1()->getWorldTransform().getOrigin(), collisionLocalPosition); - bodyA->add_collision_object(bodyB, collisionWorldPosition, collisionLocalPosition, normalOnB, appliedImpulse, pt.m_index1, pt.m_index0); - } - if (bodyB->can_add_collision()) { - B_TO_G(pt.getPositionWorldOnA(), collisionWorldPosition); - /// pt.m_localPointA Doesn't report the exact point in local space - B_TO_G(pt.getPositionWorldOnA() - contactManifold->getBody0()->getWorldTransform().getOrigin(), collisionLocalPosition); - bodyB->add_collision_object(bodyA, collisionWorldPosition, collisionLocalPosition, normalOnB * -1, appliedImpulse * -1, pt.m_index0, pt.m_index1); - } + if (pt.getDistance() <= 0.0) { + Vector3 collisionWorldPosition; + Vector3 collisionLocalPosition; + Vector3 normalOnB; + float appliedImpulse = pt.m_appliedImpulse; + B_TO_G(pt.m_normalWorldOnB, normalOnB); + + if (bodyA->can_add_collision()) { + B_TO_G(pt.getPositionWorldOnB(), collisionWorldPosition); + /// pt.m_localPointB Doesn't report the exact point in local space + B_TO_G(pt.getPositionWorldOnB() - contactManifold->getBody1()->getWorldTransform().getOrigin(), collisionLocalPosition); + bodyA->add_collision_object(bodyB, collisionWorldPosition, collisionLocalPosition, normalOnB, appliedImpulse, pt.m_index1, pt.m_index0); + } + if (bodyB->can_add_collision()) { + B_TO_G(pt.getPositionWorldOnA(), collisionWorldPosition); + /// pt.m_localPointA Doesn't report the exact point in local space + B_TO_G(pt.getPositionWorldOnA() - contactManifold->getBody0()->getWorldTransform().getOrigin(), collisionLocalPosition); + bodyB->add_collision_object(bodyA, collisionWorldPosition, collisionLocalPosition, normalOnB * -1, appliedImpulse * -1, pt.m_index0, pt.m_index1); + } #ifdef DEBUG_ENABLED - if (is_debugging_contacts()) { - add_debug_contact(collisionWorldPosition); - } + if (is_debugging_contacts()) { + add_debug_contact(collisionWorldPosition); + } #endif + } } } } diff --git a/modules/gdnative/arvr/config.py b/modules/gdnative/arvr/config.py index 4d1bdfe4d1..53bc827027 100644 --- a/modules/gdnative/arvr/config.py +++ b/modules/gdnative/arvr/config.py @@ -1,4 +1,4 @@ -def can_build(platform): +def can_build(env, platform): return True def configure(env): diff --git a/modules/gdscript/gdscript.cpp b/modules/gdscript/gdscript.cpp index d12c1f555c..b0d5422afe 100644 --- a/modules/gdscript/gdscript.cpp +++ b/modules/gdscript/gdscript.cpp @@ -126,10 +126,7 @@ GDScriptInstance *GDScript::_create_instance(const Variant **p_args, int p_argco GDScriptLanguage::singleton->lock->unlock(); #endif - if (r_error.error != Variant::CallError::CALL_OK) { - memdelete(instance); - ERR_FAIL_COND_V(r_error.error != Variant::CallError::CALL_OK, NULL); //error constructing - } + ERR_FAIL_COND_V(r_error.error != Variant::CallError::CALL_OK, NULL); //error constructing } //@TODO make thread safe diff --git a/modules/gdscript/gdscript_compiler.cpp b/modules/gdscript/gdscript_compiler.cpp index 741b837b05..310c4e21f2 100644 --- a/modules/gdscript/gdscript_compiler.cpp +++ b/modules/gdscript/gdscript_compiler.cpp @@ -388,7 +388,7 @@ int GDScriptCompiler::_parse_expression(CodeGen &codegen, const GDScriptParser:: int ret = _parse_expression(codegen, an->elements[i], slevel); if (ret < 0) return ret; - if (ret & GDScriptFunction::ADDR_TYPE_STACK << GDScriptFunction::ADDR_BITS) { + if ((ret >> GDScriptFunction::ADDR_BITS & GDScriptFunction::ADDR_TYPE_STACK) == GDScriptFunction::ADDR_TYPE_STACK) { slevel++; codegen.alloc_stack(slevel); } @@ -419,7 +419,7 @@ int GDScriptCompiler::_parse_expression(CodeGen &codegen, const GDScriptParser:: int ret = _parse_expression(codegen, dn->elements[i].key, slevel); if (ret < 0) return ret; - if (ret & GDScriptFunction::ADDR_TYPE_STACK << GDScriptFunction::ADDR_BITS) { + if ((ret >> GDScriptFunction::ADDR_BITS & GDScriptFunction::ADDR_TYPE_STACK) == GDScriptFunction::ADDR_TYPE_STACK) { slevel++; codegen.alloc_stack(slevel); } @@ -429,7 +429,7 @@ int GDScriptCompiler::_parse_expression(CodeGen &codegen, const GDScriptParser:: ret = _parse_expression(codegen, dn->elements[i].value, slevel); if (ret < 0) return ret; - if (ret & GDScriptFunction::ADDR_TYPE_STACK << GDScriptFunction::ADDR_BITS) { + if ((ret >> GDScriptFunction::ADDR_BITS & GDScriptFunction::ADDR_TYPE_STACK) == GDScriptFunction::ADDR_TYPE_STACK) { slevel++; codegen.alloc_stack(slevel); } @@ -545,7 +545,7 @@ int GDScriptCompiler::_parse_expression(CodeGen &codegen, const GDScriptParser:: int ret = _parse_expression(codegen, on->arguments[i], slevel); if (ret < 0) return ret; - if (ret & GDScriptFunction::ADDR_TYPE_STACK << GDScriptFunction::ADDR_BITS) { + if ((ret >> GDScriptFunction::ADDR_BITS & GDScriptFunction::ADDR_TYPE_STACK) == GDScriptFunction::ADDR_TYPE_STACK) { slevel++; codegen.alloc_stack(slevel); } @@ -578,7 +578,7 @@ int GDScriptCompiler::_parse_expression(CodeGen &codegen, const GDScriptParser:: int ret = _parse_expression(codegen, on->arguments[i], slevel); if (ret < 0) return ret; - if (ret & GDScriptFunction::ADDR_TYPE_STACK << GDScriptFunction::ADDR_BITS) { + if ((ret >> GDScriptFunction::ADDR_BITS & GDScriptFunction::ADDR_TYPE_STACK) == GDScriptFunction::ADDR_TYPE_STACK) { slevel++; codegen.alloc_stack(slevel); } @@ -606,7 +606,7 @@ int GDScriptCompiler::_parse_expression(CodeGen &codegen, const GDScriptParser:: if (ret < 0) return ret; - if (ret & GDScriptFunction::ADDR_TYPE_STACK << GDScriptFunction::ADDR_BITS) { + if ((ret >> GDScriptFunction::ADDR_BITS & GDScriptFunction::ADDR_TYPE_STACK) == GDScriptFunction::ADDR_TYPE_STACK) { slevel++; codegen.alloc_stack(slevel); } @@ -655,7 +655,7 @@ int GDScriptCompiler::_parse_expression(CodeGen &codegen, const GDScriptParser:: ret = _parse_expression(codegen, on->arguments[i], slevel); if (ret < 0) return ret; - if (ret & GDScriptFunction::ADDR_TYPE_STACK << GDScriptFunction::ADDR_BITS) { + if ((ret >> GDScriptFunction::ADDR_BITS & GDScriptFunction::ADDR_TYPE_STACK) == GDScriptFunction::ADDR_TYPE_STACK) { slevel++; codegen.alloc_stack(slevel); } @@ -681,7 +681,7 @@ int GDScriptCompiler::_parse_expression(CodeGen &codegen, const GDScriptParser:: int ret = _parse_expression(codegen, on->arguments[i], slevel); if (ret < 0) return ret; - if (ret & (GDScriptFunction::ADDR_TYPE_STACK << GDScriptFunction::ADDR_BITS)) { + if ((ret >> GDScriptFunction::ADDR_BITS & GDScriptFunction::ADDR_TYPE_STACK) == GDScriptFunction::ADDR_TYPE_STACK) { slevel++; codegen.alloc_stack(slevel); } diff --git a/modules/gdscript/gdscript_editor.cpp b/modules/gdscript/gdscript_editor.cpp index 32a7668760..a9b641de50 100644 --- a/modules/gdscript/gdscript_editor.cpp +++ b/modules/gdscript/gdscript_editor.cpp @@ -1189,6 +1189,7 @@ static bool _guess_identifier_type(const GDScriptCompletionContext &p_context, c c.line = op->line; c.block = blk; if (_guess_expression_type(p_context, op->arguments[1], r_type)) { + r_type.type.is_meta_type = false; return true; } } @@ -1221,7 +1222,7 @@ static bool _guess_identifier_type(const GDScriptCompletionContext &p_context, c int def_from = p_context.function->arguments.size() - p_context.function->default_values.size(); if (i >= def_from) { - int def_idx = def_from - i; + int def_idx = i - def_from; if (p_context.function->default_values[def_idx]->type == GDScriptParser::Node::TYPE_OPERATOR) { const GDScriptParser::OperatorNode *op = static_cast<const GDScriptParser::OperatorNode *>(p_context.function->default_values[def_idx]); if (op->arguments.size() < 2) { @@ -1376,11 +1377,11 @@ static bool _guess_identifier_type_from_base(const GDScriptCompletionContext &p_ for (int i = 0; i < base_type.class_type->variables.size(); i++) { GDScriptParser::ClassNode::Member m = base_type.class_type->variables[i]; if (m.identifier == p_identifier) { - if (m.data_type.has_type) { - r_type.type = m.data_type; - return true; - } if (m.expression) { + if (p_context.line == m.expression->line) { + // Variable used in the same expression + return false; + } if (_guess_expression_type(p_context, m.expression, r_type)) { return true; } @@ -1389,6 +1390,10 @@ static bool _guess_identifier_type_from_base(const GDScriptCompletionContext &p_ return true; } } + if (m.data_type.has_type) { + r_type.type = m.data_type; + return true; + } return false; } } diff --git a/modules/gdscript/gdscript_functions.cpp b/modules/gdscript/gdscript_functions.cpp index c469defb01..5af9bbc05f 100644 --- a/modules/gdscript/gdscript_functions.cpp +++ b/modules/gdscript/gdscript_functions.cpp @@ -1458,7 +1458,7 @@ MethodInfo GDScriptFunctions::get_info(Function p_func) { return mi; } break; case MATH_ATAN2: { - MethodInfo mi("atan2", PropertyInfo(Variant::REAL, "x"), PropertyInfo(Variant::REAL, "y")); + MethodInfo mi("atan2", PropertyInfo(Variant::REAL, "y"), PropertyInfo(Variant::REAL, "x")); mi.return_val.type = Variant::REAL; return mi; } break; diff --git a/modules/gdscript/gdscript_parser.cpp b/modules/gdscript/gdscript_parser.cpp index 89e102a858..ea1287374b 100644 --- a/modules/gdscript/gdscript_parser.cpp +++ b/modules/gdscript/gdscript_parser.cpp @@ -81,8 +81,11 @@ bool GDScriptParser::_enter_indent_block(BlockNode *p_block) { } tokenizer->advance(); - if (tokenizer->get_token() != GDScriptTokenizer::TK_NEWLINE) { + if (tokenizer->get_token() == GDScriptTokenizer::TK_EOF) { + return false; + } + if (tokenizer->get_token() != GDScriptTokenizer::TK_NEWLINE) { // be more python-like int current = tab_level.back()->get(); tab_level.push_back(current); @@ -92,10 +95,11 @@ bool GDScriptParser::_enter_indent_block(BlockNode *p_block) { } while (true) { - if (tokenizer->get_token() != GDScriptTokenizer::TK_NEWLINE) { return false; //wtf + } else if (tokenizer->get_token(1) == GDScriptTokenizer::TK_EOF) { + return false; } else if (tokenizer->get_token(1) != GDScriptTokenizer::TK_NEWLINE) { int indent = tokenizer->get_token_line_indent(); @@ -637,9 +641,21 @@ GDScriptParser::Node *GDScriptParser::_parse_expression(Node *p_parent, bool p_s expr = op; } else { - - _set_error("Static constant '" + identifier.operator String() + "' not present in built-in type " + Variant::get_type_name(bi_type) + "."); - return NULL; + // Object is a special case + bool valid = false; + if (bi_type == Variant::OBJECT) { + int object_constant = ClassDB::get_integer_constant("Object", identifier, &valid); + if (valid) { + ConstantNode *cn = alloc_node<ConstantNode>(); + cn->value = object_constant; + cn->datatype = _type_from_variant(cn->value); + expr = cn; + } + } + if (!valid) { + _set_error("Static constant '" + identifier.operator String() + "' not present in built-in type " + Variant::get_type_name(bi_type) + "."); + return NULL; + } } } else { @@ -4443,7 +4459,9 @@ void GDScriptParser::_parse_class(ClassNode *p_class) { continue; } break; case GDScriptTokenizer::TK_PR_SLAVE: +#ifdef DEBUG_ENABLED _add_warning(GDScriptWarning::DEPRECATED_KEYWORD, tokenizer->get_token_line(), "slave", "puppet"); +#endif case GDScriptTokenizer::TK_PR_PUPPET: { //may be fallthrough from export, ignore if so @@ -4849,6 +4867,20 @@ void GDScriptParser::_parse_class(ClassNode *p_class) { StringName const_id = tokenizer->get_token_literal(); + if (current_class->constant_expressions.has(const_id)) { + _set_error("A constant named '" + String(const_id) + "' already exists in this class (at line: " + + itos(current_class->constant_expressions[const_id].expression->line) + ")."); + return; + } + + for (int i = 0; i < current_class->variables.size(); i++) { + if (current_class->variables[i].identifier == const_id) { + _set_error("A variable named '" + String(const_id) + "' already exists in this class (at line: " + + itos(current_class->variables[i].line) + ")."); + return; + } + } + tokenizer->advance(); if (tokenizer->get_token() == GDScriptTokenizer::TK_OP_ASSIGN) { @@ -7202,6 +7234,12 @@ void GDScriptParser::_check_class_level_types(ClassNode *p_class) { expr.is_constant = true; c.type = expr; c.expression->set_datatype(expr); + + DataType tmp; + if (_get_member_type(p_class->base_type, E->key(), tmp)) { + _set_error("Member '" + String(E->key()) + "' already exists in parent class.", c.expression->line); + return; + } } // Function declarations diff --git a/modules/gridmap/grid_map_editor_plugin.cpp b/modules/gridmap/grid_map_editor_plugin.cpp index e6eaabd9ce..5fdb6a5196 100644 --- a/modules/gridmap/grid_map_editor_plugin.cpp +++ b/modules/gridmap/grid_map_editor_plugin.cpp @@ -645,7 +645,7 @@ bool GridMapEditor::forward_spatial_input_event(Camera *p_camera, const Ref<Inpu } set_items.clear(); input_action = INPUT_NONE; - return true; + return set_items.size() > 0; } if (mb->get_button_index() == BUTTON_LEFT && input_action != INPUT_NONE) { diff --git a/modules/mono/SCsub b/modules/mono/SCsub index b3a2d26e4a..1d5c145027 100644 --- a/modules/mono/SCsub +++ b/modules/mono/SCsub @@ -134,6 +134,7 @@ def find_msbuild_unix(filename): def find_msbuild_windows(): import mono_reg_utils as monoreg + mono_root = '' bits = env['bits'] if bits == '32': diff --git a/modules/mono/config.py b/modules/mono/config.py index 70fd1a35f1..01649a972e 100644 --- a/modules/mono/config.py +++ b/modules/mono/config.py @@ -99,6 +99,8 @@ def configure(env): if not mono_root: raise RuntimeError('Mono installation directory not found') + print('Found Mono root directory: ' + mono_root) + mono_version = mono_root_try_find_mono_version(mono_root) configure_for_mono_version(env, mono_version) @@ -164,6 +166,14 @@ def configure(env): if os.getenv('MONO64_PREFIX'): mono_root = os.getenv('MONO64_PREFIX') + if not mono_root and sys.platform == 'darwin': + # Try with some known directories under OSX + hint_dirs = ['/Library/Frameworks/Mono.framework/Versions/Current', '/usr/local/var/homebrew/linked/mono'] + for hint_dir in hint_dirs: + if os.path.isdir(hint_dir): + mono_root = hint_dir + break + # We can't use pkg-config to link mono statically, # but we can still use it to find the mono root directory if not mono_root and mono_static: @@ -172,6 +182,8 @@ def configure(env): raise RuntimeError('Building with mono_static=yes, but failed to find the mono prefix with pkg-config. Specify one manually') if mono_root: + print('Found Mono root directory: ' + mono_root) + mono_version = mono_root_try_find_mono_version(mono_root) configure_for_mono_version(env, mono_version) @@ -216,6 +228,9 @@ def configure(env): else: assert not mono_static + # TODO: Add option to force using pkg-config + print('Mono root directory not found. Using pkg-config instead') + mono_version = pkgconfig_try_find_mono_version() configure_for_mono_version(env, mono_version) @@ -248,7 +263,7 @@ def configure(env): def configure_for_mono_version(env, mono_version): if mono_version is None: raise RuntimeError('Mono JIT compiler version not found') - print('Mono JIT compiler version: ' + str(mono_version)) + print('Found Mono JIT compiler version: ' + str(mono_version)) if mono_version >= LooseVersion("5.12.0"): env.Append(CPPFLAGS=['-DHAS_PENDING_EXCEPTIONS']) @@ -282,7 +297,14 @@ def pkgconfig_try_find_mono_version(): def mono_root_try_find_mono_version(mono_root): from compat import decode_utf8 - output = subprocess.check_output([os.path.join(mono_root, 'bin', 'mono'), '--version']) + mono_bin = os.path.join(mono_root, 'bin') + if os.path.isfile(os.path.join(mono_bin, 'mono')): + mono_binary = os.path.join(mono_bin, 'mono') + elif os.path.isfile(os.path.join(mono_bin, 'mono.exe')): + mono_binary = os.path.join(mono_bin, 'mono.exe') + else: + return None + output = subprocess.check_output([mono_binary, '--version']) first_line = decode_utf8(output.splitlines()[0]) try: return LooseVersion(first_line.split()[len('Mono JIT compiler version'.split())]) diff --git a/modules/mono/editor/GodotSharpTools/Editor/MonoDevelopInstance.cs b/modules/mono/editor/GodotSharpTools/Editor/MonoDevelopInstance.cs index 303be3b732..fba4a8f65c 100644 --- a/modules/mono/editor/GodotSharpTools/Editor/MonoDevelopInstance.cs +++ b/modules/mono/editor/GodotSharpTools/Editor/MonoDevelopInstance.cs @@ -2,13 +2,23 @@ using System; using System.IO; using System.Collections.Generic; using System.Diagnostics; +using System.Runtime.InteropServices; +using System.Runtime.CompilerServices; namespace GodotSharpTools.Editor { public class MonoDevelopInstance { - private Process process; - private string solutionFile; + public enum EditorId + { + MonoDevelop = 0, + VisualStudioForMac = 1 + } + + readonly string solutionFile; + readonly EditorId editorId; + + Process process; public void Execute(string[] files) { @@ -16,6 +26,35 @@ namespace GodotSharpTools.Editor List<string> args = new List<string>(); + string command; + + if (Utils.OS.IsOSX()) + { + string bundleId = codeEditorBundleIds[editorId]; + + if (IsApplicationBundleInstalled(bundleId)) + { + command = "open"; + + args.Add("-b"); + args.Add(bundleId); + + // The 'open' process must wait until the application finishes + if (newWindow) + args.Add("--wait-apps"); + + args.Add("--args"); + } + else + { + command = codeEditorPaths[editorId]; + } + } + else + { + command = codeEditorPaths[editorId]; + } + args.Add("--ipc-tcp"); if (newWindow) @@ -33,25 +72,73 @@ namespace GodotSharpTools.Editor if (newWindow) { - ProcessStartInfo startInfo = new ProcessStartInfo(MonoDevelopFile, string.Join(" ", args)); - process = Process.Start(startInfo); + process = Process.Start(new ProcessStartInfo() + { + FileName = command, + Arguments = string.Join(" ", args), + UseShellExecute = false + }); } else { - Process.Start(MonoDevelopFile, string.Join(" ", args)); + Process.Start(new ProcessStartInfo() + { + FileName = command, + Arguments = string.Join(" ", args), + UseShellExecute = false + }); } } - public MonoDevelopInstance(string solutionFile) + public MonoDevelopInstance(string solutionFile, EditorId editorId) { + if (editorId == EditorId.VisualStudioForMac && !Utils.OS.IsOSX()) + throw new InvalidOperationException($"{nameof(EditorId.VisualStudioForMac)} not supported on this platform"); + this.solutionFile = solutionFile; + this.editorId = editorId; } - private static string MonoDevelopFile + [MethodImpl(MethodImplOptions.InternalCall)] + private extern static bool IsApplicationBundleInstalled(string bundleId); + + static readonly IReadOnlyDictionary<EditorId, string> codeEditorPaths; + static readonly IReadOnlyDictionary<EditorId, string> codeEditorBundleIds; + + static MonoDevelopInstance() { - get + if (Utils.OS.IsOSX()) + { + codeEditorPaths = new Dictionary<EditorId, string> + { + // Rely on PATH + { EditorId.MonoDevelop, "monodevelop" }, + { EditorId.VisualStudioForMac, "VisualStudio" } + }; + codeEditorBundleIds = new Dictionary<EditorId, string> + { + // TODO EditorId.MonoDevelop + { EditorId.VisualStudioForMac, "com.microsoft.visual-studio" } + }; + } + else if (Utils.OS.IsWindows()) + { + codeEditorPaths = new Dictionary<EditorId, string> + { + // XamarinStudio is no longer a thing, and the latest version is quite old + // MonoDevelop is available from source only on Windows. The recommendation + // is to use Visual Studio instead. Since there are no official builds, we + // will rely on custom MonoDevelop builds being added to PATH. + { EditorId.MonoDevelop, "MonoDevelop.exe" } + }; + } + else if (Utils.OS.IsUnix()) { - return "monodevelop"; + codeEditorPaths = new Dictionary<EditorId, string> + { + // Rely on PATH + { EditorId.MonoDevelop, "monodevelop" } + }; } } } diff --git a/modules/mono/editor/GodotSharpTools/GodotSharpTools.csproj b/modules/mono/editor/GodotSharpTools/GodotSharpTools.csproj index 1c8714e31d..773e8196f7 100644 --- a/modules/mono/editor/GodotSharpTools/GodotSharpTools.csproj +++ b/modules/mono/editor/GodotSharpTools/GodotSharpTools.csproj @@ -40,6 +40,7 @@ <Compile Include="Project\ProjectGenerator.cs" /> <Compile Include="Project\ProjectUtils.cs" /> <Compile Include="Properties\AssemblyInfo.cs" /> + <Compile Include="Utils\OS.cs" /> </ItemGroup> <Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" /> </Project>
\ No newline at end of file diff --git a/modules/mono/editor/GodotSharpTools/GodotSharpTools.userprefs b/modules/mono/editor/GodotSharpTools/GodotSharpTools.userprefs deleted file mode 100644 index 0cbafdc20d..0000000000 --- a/modules/mono/editor/GodotSharpTools/GodotSharpTools.userprefs +++ /dev/null @@ -1,14 +0,0 @@ -<Properties StartupItem="GodotSharpTools.csproj"> - <MonoDevelop.Ide.Workspace ActiveConfiguration="Debug" /> - <MonoDevelop.Ide.Workbench ActiveDocument="Build/BuildSystem.cs"> - <Files> - <File FileName="Build/ProjectExtensions.cs" Line="1" Column="1" /> - <File FileName="Build/ProjectGenerator.cs" Line="1" Column="1" /> - <File FileName="Build/BuildSystem.cs" Line="37" Column="14" /> - </Files> - </MonoDevelop.Ide.Workbench> - <MonoDevelop.Ide.DebuggingService.Breakpoints> - <BreakpointStore /> - </MonoDevelop.Ide.DebuggingService.Breakpoints> - <MonoDevelop.Ide.DebuggingService.PinnedWatches /> -</Properties>
\ No newline at end of file diff --git a/modules/mono/editor/GodotSharpTools/Utils/OS.cs b/modules/mono/editor/GodotSharpTools/Utils/OS.cs new file mode 100644 index 0000000000..148e954e77 --- /dev/null +++ b/modules/mono/editor/GodotSharpTools/Utils/OS.cs @@ -0,0 +1,62 @@ +using System; +using System.Linq; +using System.Runtime.CompilerServices; + +namespace GodotSharpTools.Utils +{ + public static class OS + { + [MethodImpl(MethodImplOptions.InternalCall)] + extern static string GetPlatformName(); + + const string HaikuName = "Haiku"; + const string OSXName = "OSX"; + const string ServerName = "Server"; + const string UWPName = "UWP"; + const string WindowsName = "Windows"; + const string X11Name = "X11"; + + public static bool IsHaiku() + { + return HaikuName.Equals(GetPlatformName(), StringComparison.OrdinalIgnoreCase); + } + + public static bool IsOSX() + { + return OSXName.Equals(GetPlatformName(), StringComparison.OrdinalIgnoreCase); + } + + public static bool IsServer() + { + return ServerName.Equals(GetPlatformName(), StringComparison.OrdinalIgnoreCase); + } + + public static bool IsUWP() + { + return UWPName.Equals(GetPlatformName(), StringComparison.OrdinalIgnoreCase); + } + + public static bool IsWindows() + { + return WindowsName.Equals(GetPlatformName(), StringComparison.OrdinalIgnoreCase); + } + + public static bool IsX11() + { + return X11Name.Equals(GetPlatformName(), StringComparison.OrdinalIgnoreCase); + } + + static bool? IsUnixCache = null; + static readonly string[] UnixPlatforms = new string[] { HaikuName, OSXName, ServerName, X11Name }; + + public static bool IsUnix() + { + if (IsUnixCache.HasValue) + return IsUnixCache.Value; + + string osName = GetPlatformName(); + IsUnixCache = UnixPlatforms.Any(p => p.Equals(osName, StringComparison.OrdinalIgnoreCase)); + return IsUnixCache.Value; + } + } +} diff --git a/modules/mono/editor/godotsharp_builds.cpp b/modules/mono/editor/godotsharp_builds.cpp index b01f8e66c3..d397814fa7 100644 --- a/modules/mono/editor/godotsharp_builds.cpp +++ b/modules/mono/editor/godotsharp_builds.cpp @@ -94,7 +94,12 @@ MonoString *godot_icall_BuildInstance_get_MSBuildPath() { #if defined(WINDOWS_ENABLED) switch (build_tool) { case GodotSharpBuilds::MSBUILD_VS: { - static String msbuild_tools_path = MonoRegUtils::find_msbuild_tools_path(); + static String msbuild_tools_path; + + if (msbuild_tools_path.empty() || !FileAccess::exists(msbuild_tools_path)) { + // Try to search it again if it wasn't found last time or if it was removed from its location + msbuild_tools_path = MonoRegUtils::find_msbuild_tools_path(); + } if (msbuild_tools_path.length()) { if (!msbuild_tools_path.ends_with("\\")) @@ -128,15 +133,25 @@ MonoString *godot_icall_BuildInstance_get_MSBuildPath() { CRASH_NOW(); } #elif defined(UNIX_ENABLED) - static String msbuild_path = _find_build_engine_on_unix("msbuild"); - static String xbuild_path = _find_build_engine_on_unix("xbuild"); + static String msbuild_path; + static String xbuild_path; if (build_tool == GodotSharpBuilds::XBUILD) { + if (xbuild_path.empty() || !FileAccess::exists(xbuild_path)) { + // Try to search it again if it wasn't found last time or if it was removed from its location + xbuild_path = _find_build_engine_on_unix("msbuild"); + } + if (xbuild_path.empty()) { WARN_PRINT("Cannot find binary for '" PROP_NAME_XBUILD "'"); return NULL; } } else { + if (msbuild_path.empty() || !FileAccess::exists(msbuild_path)) { + // Try to search it again if it wasn't found last time or if it was removed from its location + msbuild_path = _find_build_engine_on_unix("msbuild"); + } + if (msbuild_path.empty()) { WARN_PRINT("Cannot find binary for '" PROP_NAME_MSBUILD_MONO "'"); return NULL; @@ -192,7 +207,11 @@ MonoBoolean godot_icall_BuildInstance_get_UsingMonoMSBuildOnWindows() { #endif } -void GodotSharpBuilds::_register_internal_calls() { +void GodotSharpBuilds::register_internal_calls() { + + static bool registered = false; + ERR_FAIL_COND(registered); + registered = true; mono_add_internal_call("GodotSharpTools.Build.BuildSystem::godot_icall_BuildInstance_ExitCallback", (void *)godot_icall_BuildInstance_ExitCallback); mono_add_internal_call("GodotSharpTools.Build.BuildInstance::godot_icall_BuildInstance_get_MSBuildPath", (void *)godot_icall_BuildInstance_get_MSBuildPath); diff --git a/modules/mono/editor/godotsharp_builds.h b/modules/mono/editor/godotsharp_builds.h index 4afc284d45..c6dc6b6236 100644 --- a/modules/mono/editor/godotsharp_builds.h +++ b/modules/mono/editor/godotsharp_builds.h @@ -61,9 +61,6 @@ private: static GodotSharpBuilds *singleton; - friend class GDMono; - static void _register_internal_calls(); - public: enum BuildTool { MSBUILD_MONO, @@ -75,6 +72,8 @@ public: _FORCE_INLINE_ static GodotSharpBuilds *get_singleton() { return singleton; } + static void register_internal_calls(); + static void show_build_error_dialog(const String &p_message); void build_exit_callback(const MonoBuildInfo &p_build_info, int p_exit_code); diff --git a/modules/mono/editor/godotsharp_editor.cpp b/modules/mono/editor/godotsharp_editor.cpp index faeb58e5a7..3ee38515bf 100644 --- a/modules/mono/editor/godotsharp_editor.cpp +++ b/modules/mono/editor/godotsharp_editor.cpp @@ -38,12 +38,17 @@ #include "../csharp_script.h" #include "../godotsharp_dirs.h" #include "../mono_gd/gd_mono.h" +#include "../mono_gd/gd_mono_marshal.h" #include "../utils/path_utils.h" #include "bindings_generator.h" #include "csharp_project.h" #include "godotsharp_export.h" #include "net_solution.h" +#ifdef OSX_ENABLED +#include "../utils/osx_utils.h" +#endif + #ifdef WINDOWS_ENABLED #include "../utils/mono_reg_utils.h" #endif @@ -169,6 +174,31 @@ void GodotSharpEditor::_bind_methods() { ClassDB::bind_method(D_METHOD("_menu_option_pressed", "id"), &GodotSharpEditor::_menu_option_pressed); } +MonoBoolean godot_icall_MonoDevelopInstance_IsApplicationBundleInstalled(MonoString *p_bundle_id) { +#ifdef OSX_ENABLED + return (MonoBoolean)osx_is_app_bundle_installed(GDMonoMarshal::mono_string_to_godot(p_bundle_id)); +#else + (void)p_bundle_id; // UNUSED + ERR_FAIL_V(false); +#endif +} + +MonoString *godot_icall_Utils_OS_GetPlatformName() { + return GDMonoMarshal::mono_string_from_godot(OS::get_singleton()->get_name()); +} + +void GodotSharpEditor::register_internal_calls() { + + static bool registered = false; + ERR_FAIL_COND(registered); + registered = true; + + mono_add_internal_call("GodotSharpTools.Editor.MonoDevelopInstance::IsApplicationBundleInstalled", (void *)godot_icall_MonoDevelopInstance_IsApplicationBundleInstalled); + mono_add_internal_call("GodotSharpTools.Utils.OS::GetPlatformName", (void *)godot_icall_Utils_OS_GetPlatformName); + + GodotSharpBuilds::register_internal_calls(); +} + void GodotSharpEditor::show_error_dialog(const String &p_message, const String &p_title) { error_dialog->set_title(p_title); @@ -181,8 +211,36 @@ Error GodotSharpEditor::open_in_external_editor(const Ref<Script> &p_script, int ExternalEditor editor = ExternalEditor(int(EditorSettings::get_singleton()->get("mono/editor/external_editor"))); switch (editor) { - case EDITOR_CODE: { + case EDITOR_VSCODE: { + static String vscode_path; + + if (vscode_path.empty() || !FileAccess::exists(vscode_path)) { + // Try to search it again if it wasn't found last time or if it was removed from its location + vscode_path = path_which("code"); + } + List<String> args; + +#ifdef OSX_ENABLED + // The package path is '/Applications/Visual Studio Code.app' + static const String vscode_bundle_id = "com.microsoft.VSCode"; + static bool osx_app_bundle_installed = osx_is_app_bundle_installed(vscode_bundle_id); + + if (osx_app_bundle_installed) { + args.push_back("-b"); + args.push_back(vscode_bundle_id); + + // The reusing of existing windows made by the 'open' command might not choose a wubdiw that is + // editing our folder. It's better to ask for a new window and let VSCode do the window management. + args.push_back("-n"); + + // The open process must wait until the application finishes (which is instant in VSCode's case) + args.push_back("--wait-apps"); + + args.push_back("--args"); + } +#endif + args.push_back(ProjectSettings::get_singleton()->get_resource_path()); String script_path = ProjectSettings::get_singleton()->globalize_path(p_script->get_path()); @@ -194,18 +252,47 @@ Error GodotSharpEditor::open_in_external_editor(const Ref<Script> &p_script, int args.push_back(script_path); } - static String program = path_which("code"); +#ifdef OSX_ENABLED + ERR_EXPLAIN("Cannot find code editor: VSCode"); + ERR_FAIL_COND_V(!osx_app_bundle_installed && vscode_path.empty(), ERR_FILE_NOT_FOUND); - Error err = OS::get_singleton()->execute(program.length() ? program : "code", args, false); + String command = osx_app_bundle_installed ? "/usr/bin/open" : vscode_path; +#else + ERR_EXPLAIN("Cannot find code editor: VSCode"); + ERR_FAIL_COND_V(vscode_path.empty(), ERR_FILE_NOT_FOUND); + + String command = vscode_path; +#endif + + Error err = OS::get_singleton()->execute(command, args, false); if (err != OK) { - ERR_PRINT("GodotSharp: Could not execute external editor"); + ERR_PRINT("Error when trying to execute code editor: VSCode"); return err; } } break; +#ifdef OSX_ENABLED + case EDITOR_VISUALSTUDIO_MAC: + // [[fallthrough]]; +#endif case EDITOR_MONODEVELOP: { - if (!monodevel_instance) - monodevel_instance = memnew(MonoDevelopInstance(GodotSharpDirs::get_project_sln_path())); +#ifdef OSX_ENABLED + bool is_visualstudio = editor == EDITOR_VISUALSTUDIO_MAC; + + MonoDevelopInstance **instance = is_visualstudio ? + &visualstudio_mac_instance : + &monodevelop_instance; + + MonoDevelopInstance::EditorId editor_id = is_visualstudio ? + MonoDevelopInstance::VISUALSTUDIO_FOR_MAC : + MonoDevelopInstance::MONODEVELOP; +#else + MonoDevelopInstance **instance = &monodevelop_instance; + MonoDevelopInstance::EditorId editor_id = MonoDevelopInstance::MONODEVELOP; +#endif + + if (!*instance) + *instance = memnew(MonoDevelopInstance(GodotSharpDirs::get_project_sln_path(), editor_id)); String script_path = ProjectSettings::get_singleton()->globalize_path(p_script->get_path()); @@ -213,7 +300,7 @@ Error GodotSharpEditor::open_in_external_editor(const Ref<Script> &p_script, int script_path += ";" + itos(p_line + 1) + ";" + itos(p_col); } - monodevel_instance->execute(script_path); + (*instance)->execute(script_path); } break; default: return ERR_UNAVAILABLE; @@ -231,7 +318,10 @@ GodotSharpEditor::GodotSharpEditor(EditorNode *p_editor) { singleton = this; - monodevel_instance = NULL; + monodevelop_instance = NULL; +#ifdef OSX_ENABLED + visualstudio_mac_instance = NULL; +#endif editor = p_editor; @@ -314,7 +404,18 @@ GodotSharpEditor::GodotSharpEditor(EditorNode *p_editor) { // External editor settings EditorSettings *ed_settings = EditorSettings::get_singleton(); EDITOR_DEF("mono/editor/external_editor", EDITOR_NONE); - ed_settings->add_property_hint(PropertyInfo(Variant::INT, "mono/editor/external_editor", PROPERTY_HINT_ENUM, "None,MonoDevelop,Visual Studio Code")); + + String settings_hint_str = "None"; + +#ifdef WINDOWS_ENABLED + settings_hint_str += ",MonoDevelop,Visual Studio Code"; +#elif OSX_ENABLED + settings_hint_str += ",Visual Studio,MonoDevelop,Visual Studio Code"; +#elif UNIX_ENABLED + settings_hint_str += ",MonoDevelop,Visual Studio Code"; +#endif + + ed_settings->add_property_hint(PropertyInfo(Variant::INT, "mono/editor/external_editor", PROPERTY_HINT_ENUM, settings_hint_str)); // Export plugin Ref<GodotSharpExport> godotsharp_export; @@ -328,9 +429,9 @@ GodotSharpEditor::~GodotSharpEditor() { memdelete(godotsharp_builds); - if (monodevel_instance) { - memdelete(monodevel_instance); - monodevel_instance = NULL; + if (monodevelop_instance) { + memdelete(monodevelop_instance); + monodevelop_instance = NULL; } } diff --git a/modules/mono/editor/godotsharp_editor.h b/modules/mono/editor/godotsharp_editor.h index 66da814c8b..46b6bd5ebf 100644 --- a/modules/mono/editor/godotsharp_editor.h +++ b/modules/mono/editor/godotsharp_editor.h @@ -50,7 +50,10 @@ class GodotSharpEditor : public Node { GodotSharpBuilds *godotsharp_builds; - MonoDevelopInstance *monodevel_instance; + MonoDevelopInstance *monodevelop_instance; +#ifdef OSX_ENABLED + MonoDevelopInstance *visualstudio_mac_instance; +#endif bool _create_project_solution(); @@ -74,12 +77,24 @@ public: enum ExternalEditor { EDITOR_NONE, +#ifdef WINDOWS_ENABLED + //EDITOR_VISUALSTUDIO, // TODO EDITOR_MONODEVELOP, - EDITOR_CODE, + EDITOR_VSCODE +#elif OSX_ENABLED + EDITOR_VISUALSTUDIO_MAC, + EDITOR_MONODEVELOP, + EDITOR_VSCODE +#elif UNIX_ENABLED + EDITOR_MONODEVELOP, + EDITOR_VSCODE +#endif }; _FORCE_INLINE_ static GodotSharpEditor *get_singleton() { return singleton; } + static void register_internal_calls(); + void show_error_dialog(const String &p_message, const String &p_title = "Error"); Error open_in_external_editor(const Ref<Script> &p_script, int p_line, int p_col); diff --git a/modules/mono/editor/monodevelop_instance.cpp b/modules/mono/editor/monodevelop_instance.cpp index 9f05711fd6..1d858d80bf 100644 --- a/modules/mono/editor/monodevelop_instance.cpp +++ b/modules/mono/editor/monodevelop_instance.cpp @@ -47,7 +47,7 @@ void MonoDevelopInstance::execute(const Vector<String> &p_files) { execute_method->invoke(gc_handle->get_target(), args, &exc); if (exc) { - GDMonoUtils::debug_unhandled_exception(exc); + GDMonoUtils::debug_print_unhandled_exception(exc); ERR_FAIL(); } } @@ -59,7 +59,7 @@ void MonoDevelopInstance::execute(const String &p_file) { execute(files); } -MonoDevelopInstance::MonoDevelopInstance(const String &p_solution) { +MonoDevelopInstance::MonoDevelopInstance(const String &p_solution, EditorId p_editor_id) { _GDMONO_SCOPE_DOMAIN_(TOOLS_DOMAIN) @@ -67,15 +67,16 @@ MonoDevelopInstance::MonoDevelopInstance(const String &p_solution) { MonoObject *obj = mono_object_new(TOOLS_DOMAIN, klass->get_mono_ptr()); - GDMonoMethod *ctor = klass->get_method(".ctor", 1); + GDMonoMethod *ctor = klass->get_method(".ctor", 2); MonoException *exc = NULL; Variant solution = p_solution; - const Variant *args[1] = { &solution }; + Variant editor_id = p_editor_id; + const Variant *args[2] = { &solution, &editor_id }; ctor->invoke(obj, args, &exc); if (exc) { - GDMonoUtils::debug_unhandled_exception(exc); + GDMonoUtils::debug_print_unhandled_exception(exc); ERR_FAIL(); } diff --git a/modules/mono/editor/monodevelop_instance.h b/modules/mono/editor/monodevelop_instance.h index 73cf0f54cc..29de4a4735 100644 --- a/modules/mono/editor/monodevelop_instance.h +++ b/modules/mono/editor/monodevelop_instance.h @@ -42,10 +42,15 @@ class MonoDevelopInstance { GDMonoMethod *execute_method; public: + enum EditorId { + MONODEVELOP = 0, + VISUALSTUDIO_FOR_MAC = 1 + }; + void execute(const Vector<String> &p_files); void execute(const String &p_file); - MonoDevelopInstance(const String &p_solution); + MonoDevelopInstance(const String &p_solution, EditorId p_editor_id); }; #endif // MONODEVELOP_INSTANCE_H diff --git a/modules/mono/mono_gd/gd_mono.cpp b/modules/mono/mono_gd/gd_mono.cpp index 03418a02ea..2fed6064b7 100644 --- a/modules/mono/mono_gd/gd_mono.cpp +++ b/modules/mono/mono_gd/gd_mono.cpp @@ -319,7 +319,7 @@ void GDMono::_register_internal_calls() { #endif #ifdef TOOLS_ENABLED - GodotSharpBuilds::_register_internal_calls(); + GodotSharpEditor::register_internal_calls(); #endif } diff --git a/modules/mono/utils/osx_utils.cpp b/modules/mono/utils/osx_utils.cpp new file mode 100644 index 0000000000..f520706a0c --- /dev/null +++ b/modules/mono/utils/osx_utils.cpp @@ -0,0 +1,62 @@ +/*************************************************************************/ +/* osx_utils.cpp */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#include "osx_utils.h" + +#include "core/print_string.h" + +#ifdef OSX_ENABLED + +#include <CoreFoundation/CoreFoundation.h> +#include <CoreServices/CoreServices.h> + +bool osx_is_app_bundle_installed(const String &p_bundle_id) { + + CFURLRef app_url = NULL; + CFStringRef bundle_id = CFStringCreateWithCString(NULL, p_bundle_id.utf8(), kCFStringEncodingUTF8); + OSStatus result = LSFindApplicationForInfo(kLSUnknownCreator, bundle_id, NULL, NULL, &app_url); + CFRelease(bundle_id); + + if (app_url) + CFRelease(app_url); + + switch (result) { + case noErr: + return true; + case kLSApplicationNotFoundErr: + break; + default: + break; + } + + return false; +} + +#endif diff --git a/modules/mono/utils/osx_utils.h b/modules/mono/utils/osx_utils.h new file mode 100644 index 0000000000..68479b4f44 --- /dev/null +++ b/modules/mono/utils/osx_utils.h @@ -0,0 +1,41 @@ +/*************************************************************************/ +/* osx_utils.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#include "core/ustring.h" + +#ifndef OSX_UTILS_H + +#ifdef OSX_ENABLED + +bool osx_is_app_bundle_installed(const String &p_bundle_id); + +#endif + +#endif // OSX_UTILS_H diff --git a/modules/opensimplex/doc_classes/SimplexNoise.xml b/modules/opensimplex/doc_classes/SimplexNoise.xml index a5a01d88a7..de29ff874c 100644 --- a/modules/opensimplex/doc_classes/SimplexNoise.xml +++ b/modules/opensimplex/doc_classes/SimplexNoise.xml @@ -15,12 +15,12 @@ noise.octaves = 4 noise.period = 20.0 noise.persistance = 0.8 - - #Sample + + # Sample print("Values:") - print(noise.get_noise_2d(1.0,1.0)) - print(noise.get_noise_3d(0.5,3.0,15.0)) - print(noise.get_noise_3d(0.5,1.9,4.7,0.0)) + print(noise.get_noise_2d(1.0, 1.0)) + print(noise.get_noise_3d(0.5, 3.0, 15.0)) + print(noise.get_noise_4d(0.5, 1.9, 4.7, 0.0)) [/codeblock] </description> <tutorials> @@ -47,7 +47,7 @@ <argument index="1" name="y" type="float"> </argument> <description> - 2D noise value [-1,1] at position [code]x[/code],[code]y[/code]. + Returns the 2D noise value [code][-1,1][/code] at the given position. </description> </method> <method name="get_noise_2dv"> @@ -56,7 +56,7 @@ <argument index="0" name="pos" type="Vector2"> </argument> <description> - 2D noise value [-1,1] at position [code]pos.x[/code],[code]pos.y[/code]. + Returns the 2D noise value [code][-1,1][/code] at the given position. </description> </method> <method name="get_noise_3d"> @@ -69,7 +69,7 @@ <argument index="2" name="z" type="float"> </argument> <description> - 3D noise value [-1,1] at position [code]x[/code],[code]y[/code],[code]z[/code]. + Returns the 3D noise value [code][-1,1][/code] at the given position. </description> </method> <method name="get_noise_3dv"> @@ -78,7 +78,7 @@ <argument index="0" name="pos" type="Vector3"> </argument> <description> - 3D noise value [-1,1] at position [code]pos.x[/code],[code]pos.y[/code],[code]pos.z[/code]. + Returns the 3D noise value [code][-1,1][/code] at the given position. </description> </method> <method name="get_noise_4d"> @@ -93,7 +93,7 @@ <argument index="3" name="w" type="float"> </argument> <description> - 4D noise value [-1,1] at position [code]x[/code],[code]y[/code],[code]z[/code],[code]w[/code]. + Returns the 4D noise value [code][-1,1][/code] at the given position. </description> </method> <method name="get_seamless_image"> @@ -102,8 +102,8 @@ <argument index="0" name="size" type="int"> </argument> <description> - Generate a tileable noise image, based on the current noise parameters. - Generated seamless images are always square ([code]size[/code]x[code]size[/code]). + Generate a tileable noise image, based on the current noise parameters. + Generated seamless images are always square ([code]size[/code] x [code]size[/code]). </description> </method> </methods> @@ -112,14 +112,14 @@ Difference in period between [member octaves]. </member> <member name="octaves" type="int" setter="set_octaves" getter="get_octaves"> - Number of Simplex Noise layers that are sampled to get the fractal noise. + Number of Simplex noise layers that are sampled to get the fractal noise. </member> <member name="period" type="float" setter="set_period" getter="get_period"> - Period of the base octave. - A lower period results in a higher frequancy noise (more value changes across the same distance). + Period of the base octave. + A lower period results in a higher-frequency noise (more value changes across the same distance). </member> <member name="persistance" type="float" setter="set_persistance" getter="get_persistance"> - Contribuiton factor of the different octaves. + Contribution factor of the different octaves. A [code]persistance[/code] value of 1 means all the octaves have the same contribution, a value of 0.5 means each octave contributes half as much as the previous one. </member> <member name="seed" type="int" setter="set_seed" getter="get_seed"> diff --git a/modules/opensimplex/simplex_noise.cpp b/modules/opensimplex/simplex_noise.cpp index 6d66c7110e..e489b7f6f0 100644 --- a/modules/opensimplex/simplex_noise.cpp +++ b/modules/opensimplex/simplex_noise.cpp @@ -35,7 +35,7 @@ SimplexNoise::SimplexNoise() { seed = 0; - persistance = 0.5; + persistence = 0.5; octaves = 3; period = 64; lacunarity = 2.0; @@ -81,9 +81,9 @@ void SimplexNoise::set_period(float p_period) { emit_changed(); } -void SimplexNoise::set_persistance(float p_persistance) { - if (p_persistance == persistance) return; - persistance = p_persistance; +void SimplexNoise::set_persistence(float p_persistence) { + if (p_persistence == persistence) return; + persistence = p_persistence; emit_changed(); } @@ -164,8 +164,8 @@ void SimplexNoise::_bind_methods() { ClassDB::bind_method(D_METHOD("set_period", "period"), &SimplexNoise::set_period); ClassDB::bind_method(D_METHOD("get_period"), &SimplexNoise::get_period); - ClassDB::bind_method(D_METHOD("set_persistance", "persistance"), &SimplexNoise::set_persistance); - ClassDB::bind_method(D_METHOD("get_persistance"), &SimplexNoise::get_persistance); + ClassDB::bind_method(D_METHOD("set_persistence", "persistence"), &SimplexNoise::set_persistence); + ClassDB::bind_method(D_METHOD("get_persistence"), &SimplexNoise::get_persistence); ClassDB::bind_method(D_METHOD("set_lacunarity", "lacunarity"), &SimplexNoise::set_lacunarity); ClassDB::bind_method(D_METHOD("get_lacunarity"), &SimplexNoise::get_lacunarity); @@ -183,7 +183,7 @@ void SimplexNoise::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::INT, "seed"), "set_seed", "get_seed"); ADD_PROPERTY(PropertyInfo(Variant::INT, "octaves", PROPERTY_HINT_RANGE, "1,6,1"), "set_octaves", "get_octaves"); ADD_PROPERTY(PropertyInfo(Variant::REAL, "period", PROPERTY_HINT_RANGE, "0.1,256.0,0.1"), "set_period", "get_period"); - ADD_PROPERTY(PropertyInfo(Variant::REAL, "persistance", PROPERTY_HINT_RANGE, "0.0,1.0,0.001"), "set_persistance", "get_persistance"); + ADD_PROPERTY(PropertyInfo(Variant::REAL, "persistence", PROPERTY_HINT_RANGE, "0.0,1.0,0.001"), "set_persistence", "get_persistence"); ADD_PROPERTY(PropertyInfo(Variant::REAL, "lacunarity", PROPERTY_HINT_RANGE, "0.1,4.0,0.01"), "set_lacunarity", "get_lacunarity"); } @@ -200,7 +200,7 @@ float SimplexNoise::get_noise_2d(float x, float y) { while (++i < octaves) { x *= lacunarity; y *= lacunarity; - amp *= persistance; + amp *= persistence; max += amp; sum += _get_octave_noise_2d(i, x, y) * amp; } @@ -223,7 +223,7 @@ float SimplexNoise::get_noise_3d(float x, float y, float z) { x *= lacunarity; y *= lacunarity; z *= lacunarity; - amp *= persistance; + amp *= persistence; max += amp; sum += _get_octave_noise_3d(i, x, y, z) * amp; } @@ -248,7 +248,7 @@ float SimplexNoise::get_noise_4d(float x, float y, float z, float w) { y *= lacunarity; z *= lacunarity; w *= lacunarity; - amp *= persistance; + amp *= persistence; max += amp; sum += _get_octave_noise_4d(i, x, y, z, w) * amp; } diff --git a/modules/opensimplex/simplex_noise.h b/modules/opensimplex/simplex_noise.h index 59390c6172..9a48dbf809 100644 --- a/modules/opensimplex/simplex_noise.h +++ b/modules/opensimplex/simplex_noise.h @@ -44,7 +44,7 @@ class SimplexNoise : public Resource { osn_context contexts[6]; int seed; - float persistance; // Controls details, value in [0,1]. Higher increases grain, lower increases smoothness. + float persistence; // Controls details, value in [0,1]. Higher increases grain, lower increases smoothness. int octaves; // Number of noise layers float period; // Distance above which we start to see similarities. The higher, the longer "hills" will be on a terrain. float lacunarity; // Controls period change across octaves. 2 is usually a good value to address all detail levels. @@ -64,8 +64,8 @@ public: void set_period(float p_period); float get_period() const { return period; } - void set_persistance(float p_persistance); - float get_persistance() const { return persistance; } + void set_persistence(float p_persistence); + float get_persistence() const { return persistence; } void set_lacunarity(float p_lacunarity); float get_lacunarity() const { return lacunarity; } diff --git a/modules/visual_script/visual_script_builtin_funcs.cpp b/modules/visual_script/visual_script_builtin_funcs.cpp index e7a4e0c31f..60bc54afe4 100644 --- a/modules/visual_script/visual_script_builtin_funcs.cpp +++ b/modules/visual_script/visual_script_builtin_funcs.cpp @@ -260,7 +260,12 @@ PropertyInfo VisualScriptBuiltinFunc::get_input_value_port_info(int p_idx) const case MATH_SQRT: { return PropertyInfo(Variant::REAL, "s"); } break; - case MATH_ATAN2: + case MATH_ATAN2: { + if (p_idx == 0) + return PropertyInfo(Variant::REAL, "y"); + else + return PropertyInfo(Variant::REAL, "x"); + } break; case MATH_FMOD: case MATH_FPOSMOD: { if (p_idx == 0) diff --git a/platform/javascript/os_javascript.cpp b/platform/javascript/os_javascript.cpp index 3515eeeb60..b0ec3c4245 100644 --- a/platform/javascript/os_javascript.cpp +++ b/platform/javascript/os_javascript.cpp @@ -39,6 +39,7 @@ #include "unix/file_access_unix.h" #include <emscripten.h> +#include <png.h> #include <stdlib.h> #include "dom_keys.inc" @@ -912,6 +913,57 @@ void OS_JavaScript::set_window_title(const String &p_title) { /* clang-format on */ } +void OS_JavaScript::set_icon(const Ref<Image> &p_icon) { + + ERR_FAIL_COND(p_icon.is_null()); + Ref<Image> icon = p_icon; + if (icon->is_compressed()) { + icon = icon->duplicate(); + ERR_FAIL_COND(icon->decompress() != OK) + } + if (icon->get_format() != Image::FORMAT_RGBA8) { + if (icon == p_icon) + icon = icon->duplicate(); + icon->convert(Image::FORMAT_RGBA8); + } + + png_image png_meta; + memset(&png_meta, 0, sizeof png_meta); + png_meta.version = PNG_IMAGE_VERSION; + png_meta.width = icon->get_width(); + png_meta.height = icon->get_height(); + png_meta.format = PNG_FORMAT_RGBA; + + PoolByteArray png; + size_t len; + PoolByteArray::Read r = icon->get_data().read(); + ERR_FAIL_COND(!png_image_write_get_memory_size(png_meta, len, 0, r.ptr(), 0, NULL)); + + png.resize(len); + PoolByteArray::Write w = png.write(); + ERR_FAIL_COND(!png_image_write_to_memory(&png_meta, w.ptr(), &len, 0, r.ptr(), 0, NULL)); + w = PoolByteArray::Write(); + + r = png.read(); + /* clang-format off */ + EM_ASM_ARGS({ + var PNG_PTR = $0; + var PNG_LEN = $1; + + var png = new Blob([HEAPU8.slice(PNG_PTR, PNG_PTR + PNG_LEN)], { type: "image/png" }); + var url = URL.createObjectURL(png); + var link = document.getElementById('-gd-engine-icon'); + if (link === null) { + link = document.createElement('link'); + link.rel = 'icon'; + link.id = '-gd-engine-icon'; + document.head.appendChild(link); + } + link.href = url; + }, r.ptr(), len); + /* clang-format on */ +} + String OS_JavaScript::get_executable_path() const { return OS::get_executable_path(); diff --git a/platform/javascript/os_javascript.h b/platform/javascript/os_javascript.h index f40fb8fc7e..ddcbf8c7c9 100644 --- a/platform/javascript/os_javascript.h +++ b/platform/javascript/os_javascript.h @@ -135,6 +135,7 @@ public: virtual void alert(const String &p_alert, const String &p_title = "ALERT!"); virtual void set_window_title(const String &p_title); + virtual void set_icon(const Ref<Image> &p_icon); String get_executable_path() const; virtual Error shell_open(String p_uri); virtual String get_name(); diff --git a/platform/osx/os_osx.mm b/platform/osx/os_osx.mm index b98113baeb..886ff4b332 100644 --- a/platform/osx/os_osx.mm +++ b/platform/osx/os_osx.mm @@ -1663,7 +1663,9 @@ void OS_OSX::set_custom_mouse_cursor(const RES &p_cursor, CursorShape p_shape, c cursors[p_shape] = cursor; if (p_shape == cursor_shape) { - [cursor set]; + if (mouse_mode == MOUSE_MODE_VISIBLE || mouse_mode == MOUSE_MODE_CONFINED) { + [cursor set]; + } } [imgrep release]; diff --git a/platform/windows/SCsub b/platform/windows/SCsub index 586533e817..5dfb1592e0 100644 --- a/platform/windows/SCsub +++ b/platform/windows/SCsub @@ -29,6 +29,7 @@ prog = env.add_program('#bin/godot', common_win + res_obj, PROGSUFFIX=env["PROGS # Microsoft Visual Studio Project Generation if env['vsproj']: env.vs_srcs = env.vs_srcs + ["platform/windows/" + res_file] + env.vs_srcs = env.vs_srcs + ["platform/windows/godot.natvis"] for x in common_win: env.vs_srcs = env.vs_srcs + ["platform/windows/" + str(x)] diff --git a/platform/windows/godot.natvis b/platform/windows/godot.natvis new file mode 100644 index 0000000000..01963035a1 --- /dev/null +++ b/platform/windows/godot.natvis @@ -0,0 +1,129 @@ +<?xml version="1.0" encoding="utf-8"?> +<AutoVisualizer xmlns="http://schemas.microsoft.com/vstudio/debugger/natvis/2010"> + <Type Name="Vector<*>"> + <Expand> + <Item Name="size">(_cowdata && _cowdata->_ptr) ? (((const unsigned int *)(_cowdata->_ptr))[-1]) : 0</Item> + <ArrayItems> + <Size>(_cowdata && _cowdata->_ptr) ? (((const unsigned int *)(_cowdata->_ptr))[-1]) : 0</Size> + <ValuePointer>(_cowdata) ? (_cowdata->_ptr) : 0</ValuePointer> + </ArrayItems> + </Expand> + </Type> + + <Type Name="PoolVector<*>"> + <Expand> + <Item Name="size">alloc ? (alloc->size / sizeof($T1)) : 0</Item> + <ArrayItems> + <Size>alloc ? (alloc->size / sizeof($T1)) : 0</Size> + <ValuePointer>alloc ? (($T1 *)alloc->mem) : 0</ValuePointer> + </ArrayItems> + </Expand> + </Type> + + <Type Name="Variant"> + <DisplayString Condition="this->type == Variant::NIL">nil</DisplayString> + <DisplayString Condition="this->type == Variant::BOOL">{_data._bool}</DisplayString> + <DisplayString Condition="this->type == Variant::INT">{_data._int}</DisplayString> + <DisplayString Condition="this->type == Variant::REAL">{_data._real}</DisplayString> + <DisplayString Condition="this->type == Variant::TRANSFORM2D">{_data._transform2d}</DisplayString> + <DisplayString Condition="this->type == Variant::AABB">{_data._aabb}</DisplayString> + <DisplayString Condition="this->type == Variant::BASIS">{_data._basis}</DisplayString> + <DisplayString Condition="this->type == Variant::TRANSFORM">{_data._transform}</DisplayString> + <DisplayString Condition="this->type == Variant::ARRAY">{*(Array *)_data._mem}</DisplayString> + <DisplayString Condition="this->type == Variant::STRING && ((String *)(&_data._mem[0]))->_cowdata._ptr == 0">""</DisplayString> + <DisplayString Condition="this->type == Variant::STRING && ((String *)(&_data._mem[0]))->_cowdata._ptr != 0">{((String *)(&_data._mem[0]))->_cowdata._ptr,su}</DisplayString> + <DisplayString Condition="this->type == Variant::VECTOR2">{*(Vector2 *)_data._mem}</DisplayString> + <DisplayString Condition="this->type == Variant::RECT2">{*(Rect2 *)_data._mem}</DisplayString> + <DisplayString Condition="this->type == Variant::VECTOR3">{*(Vector3 *)_data._mem}</DisplayString> + <DisplayString Condition="this->type == Variant::PLANE">{*(Plane *)_data._mem}</DisplayString> + <DisplayString Condition="this->type == Variant::QUAT">{*(Quat *)_data._mem}</DisplayString> + <DisplayString Condition="this->type == Variant::COLOR">{*(Color *)_data._mem}</DisplayString> + <DisplayString Condition="this->type == Variant::NODE_PATH">{*(NodePath *)_data._mem}</DisplayString> + <DisplayString Condition="this->type == Variant::_RID">{*(RID *)_data._mem}</DisplayString> + <DisplayString Condition="this->type == Variant::OBJECT">{*(Object *)_data._mem}</DisplayString> + <DisplayString Condition="this->type == Variant::DICTIONARY">{*(Dictionary *)_data._mem}</DisplayString> + <DisplayString Condition="this->type == Variant::ARRAY">{*(Array *)_data._mem}</DisplayString> + <DisplayString Condition="this->type == Variant::POOL_BYTE_ARRAY">{*(PoolByteArray *)_data._mem}</DisplayString> + <DisplayString Condition="this->type == Variant::POOL_INT_ARRAY">{*(PoolIntArray *)_data._mem}</DisplayString> + <DisplayString Condition="this->type == Variant::POOL_REAL_ARRAY">{*(PoolRealArray *)_data._mem}</DisplayString> + <DisplayString Condition="this->type == Variant::POOL_STRING_ARRAY">{*(PoolStringArray *)_data._mem}</DisplayString> + <DisplayString Condition="this->type == Variant::POOL_VECTOR2_ARRAY">{*(PoolVector2Array *)_data._mem}</DisplayString> + <DisplayString Condition="this->type == Variant::POOL_VECTOR3_ARRAY">{*(PoolVector3Array *)_data._mem}</DisplayString> + <DisplayString Condition="this->type == Variant::POOL_COLOR_ARRAY">{*(PoolColorArray *)_data._mem}</DisplayString> + + <StringView Condition="this->type == Variant::STRING && ((String *)(&_data._mem[0]))->_cowdata._ptr != 0">((String *)(&_data._mem[0]))->_cowdata._ptr,su</StringView> + + <Expand> + <Item Name="value" Condition="this->type == Variant::BOOL">_data._bool</Item> + <Item Name="value" Condition="this->type == Variant::INT">_data._int</Item> + <Item Name="value" Condition="this->type == Variant::REAL">_data._real</Item> + <Item Name="value" Condition="this->type == Variant::TRANSFORM2D">_data._transform2d</Item> + <Item Name="value" Condition="this->type == Variant::AABB">_data._aabb</Item> + <Item Name="value" Condition="this->type == Variant::BASIS">_data._basis</Item> + <Item Name="value" Condition="this->type == Variant::TRANSFORM">_data._transform</Item> + <Item Name="value" Condition="this->type == Variant::ARRAY">*(Array *)_data._mem</Item> + <Item Name="value" Condition="this->type == Variant::STRING">*(String *)_data._mem</Item> + <Item Name="value" Condition="this->type == Variant::VECTOR2">*(Vector2 *)_data._mem</Item> + <Item Name="value" Condition="this->type == Variant::RECT2">*(Rect2 *)_data._mem</Item> + <Item Name="value" Condition="this->type == Variant::VECTOR3">*(Vector3 *)_data._mem</Item> + <Item Name="value" Condition="this->type == Variant::PLANE">*(Plane *)_data._mem</Item> + <Item Name="value" Condition="this->type == Variant::QUAT">*(Quat *)_data._mem</Item> + <Item Name="value" Condition="this->type == Variant::COLOR">*(Color *)_data._mem</Item> + <Item Name="value" Condition="this->type == Variant::NODE_PATH">*(NodePath *)_data._mem</Item> + <Item Name="value" Condition="this->type == Variant::_RID">*(RID *)_data._mem</Item> + <Item Name="value" Condition="this->type == Variant::OBJECT">*(Object *)_data._mem</Item> + <Item Name="value" Condition="this->type == Variant::DICTIONARY">*(Dictionary *)_data._mem</Item> + <Item Name="value" Condition="this->type == Variant::ARRAY">*(Array *)_data._mem</Item> + <Item Name="value" Condition="this->type == Variant::POOL_BYTE_ARRAY">*(PoolByteArray *)_data._mem</Item> + <Item Name="value" Condition="this->type == Variant::POOL_INT_ARRAY">*(PoolIntArray *)_data._mem</Item> + <Item Name="value" Condition="this->type == Variant::POOL_REAL_ARRAY">*(PoolRealArray *)_data._mem</Item> + <Item Name="value" Condition="this->type == Variant::POOL_STRING_ARRAY">*(PoolStringArray *)_data._mem</Item> + <Item Name="value" Condition="this->type == Variant::POOL_VECTOR2_ARRAY">*(PoolVector2Array *)_data._mem</Item> + <Item Name="value" Condition="this->type == Variant::POOL_VECTOR3_ARRAY">*(PoolVector3Array *)_data._mem</Item> + <Item Name="value" Condition="this->type == Variant::POOL_COLOR_ARRAY">*(PoolColorArray *)_data._mem</Item> + </Expand> + </Type> + + <Type Name="String"> + <DisplayString Condition="this->_cowdata._ptr == 0">empty</DisplayString> + <DisplayString Condition="this->_cowdata._ptr != 0">{this->_cowdata._ptr,su}</DisplayString> + <StringView Condition="this->_cowdata._ptr != 0">this->_cowdata._ptr,su</StringView> + </Type> + + <Type Name="Vector2"> + <DisplayString>{{{x},{y}}}</DisplayString> + <Expand> + <Item Name="x">x</Item> + <Item Name="y">y</Item> + </Expand> + </Type> + + <Type Name="Vector3"> + <DisplayString>{{{x},{y},{z}}}</DisplayString> + <Expand> + <Item Name="x">x</Item> + <Item Name="y">y</Item> + <Item Name="z">z</Item> + </Expand> + </Type> + + <Type Name="Quat"> + <DisplayString>Quat {{{x},{y},{z},{w}}}</DisplayString> + <Expand> + <Item Name="x">x</Item> + <Item Name="y">y</Item> + <Item Name="z">z</Item> + <Item Name="w">w</Item> + </Expand> + </Type> + + <Type Name="Color"> + <DisplayString>Color {{{r},{g},{b},{a}}}</DisplayString> + <Expand> + <Item Name="red">r</Item> + <Item Name="green">g</Item> + <Item Name="blue">b</Item> + <Item Name="alpha">a</Item> + </Expand> + </Type> +</AutoVisualizer> diff --git a/platform/windows/os_windows.cpp b/platform/windows/os_windows.cpp index f63aebbbd3..d575525f93 100644 --- a/platform/windows/os_windows.cpp +++ b/platform/windows/os_windows.cpp @@ -2312,7 +2312,9 @@ void OS_Windows::set_custom_mouse_cursor(const RES &p_cursor, CursorShape p_shap cursors[p_shape] = CreateIconIndirect(&iconinfo); if (p_shape == cursor_shape) { - SetCursor(cursors[p_shape]); + if (mouse_mode == MOUSE_MODE_VISIBLE || mouse_mode == MOUSE_MODE_CONFINED) { + SetCursor(cursors[p_shape]); + } } if (hAndMask != NULL) { diff --git a/platform/x11/os_x11.cpp b/platform/x11/os_x11.cpp index 24dfe541f9..3d05a650da 100644 --- a/platform/x11/os_x11.cpp +++ b/platform/x11/os_x11.cpp @@ -2524,13 +2524,16 @@ void OS_X11::set_cursor_shape(CursorShape p_shape) { ERR_FAIL_INDEX(p_shape, CURSOR_MAX); - if (p_shape == current_cursor) + if (p_shape == current_cursor) { return; - if (mouse_mode == MOUSE_MODE_VISIBLE && mouse_mode != MOUSE_MODE_CONFINED) { - if (cursors[p_shape] != None) + } + + if (mouse_mode == MOUSE_MODE_VISIBLE || mouse_mode == MOUSE_MODE_CONFINED) { + if (cursors[p_shape] != None) { XDefineCursor(x11_display, x11_window, cursors[p_shape]); - else if (cursors[CURSOR_ARROW] != None) + } else if (cursors[CURSOR_ARROW] != None) { XDefineCursor(x11_display, x11_window, cursors[CURSOR_ARROW]); + } } current_cursor = p_shape; @@ -2607,7 +2610,9 @@ void OS_X11::set_custom_mouse_cursor(const RES &p_cursor, CursorShape p_shape, c cursors[p_shape] = XcursorImageLoadCursor(x11_display, cursor_image); if (p_shape == current_cursor) { - XDefineCursor(x11_display, x11_window, cursors[p_shape]); + if (mouse_mode == MOUSE_MODE_VISIBLE || mouse_mode == MOUSE_MODE_CONFINED) { + XDefineCursor(x11_display, x11_window, cursors[p_shape]); + } } memfree(cursor_image->pixels); diff --git a/scene/gui/label.cpp b/scene/gui/label.cpp index ce8de38b74..91dab27930 100644 --- a/scene/gui/label.cpp +++ b/scene/gui/label.cpp @@ -295,14 +295,13 @@ Size2 Label::get_minimum_size() const { Size2 min_style = get_stylebox("normal")->get_minimum_size(); + // don't want to mutable everything + if (word_cache_dirty) + const_cast<Label *>(this)->regenerate_word_cache(); + if (autowrap) return Size2(1, clip ? 1 : minsize.height) + min_style; else { - - // don't want to mutable everything - if (word_cache_dirty) - const_cast<Label *>(this)->regenerate_word_cache(); - Size2 ms = minsize; if (clip) ms.width = 1; diff --git a/servers/visual/shader_language.cpp b/servers/visual/shader_language.cpp index 35236b23f1..4718eb14a5 100644 --- a/servers/visual/shader_language.cpp +++ b/servers/visual/shader_language.cpp @@ -3437,8 +3437,9 @@ ShaderLanguage::Node *ShaderLanguage::_reduce_expression(BlockNode *p_block, Sha } } } else { + ConstantNode::Value value = values[0]; for (int i = 1; i < cardinality; i++) { - values.push_back(values[0]); + values.push_back(value); } } } else if (values.size() != cardinality) { diff --git a/thirdparty/miniupnpc/minissdpc.c b/thirdparty/miniupnpc/minissdpc.c index d76b242ad0..1d29b4ba5b 100644 --- a/thirdparty/miniupnpc/minissdpc.c +++ b/thirdparty/miniupnpc/minissdpc.c @@ -494,7 +494,6 @@ ssdpDiscoverDevices(const char * const deviceTypes[], struct addrinfo hints, *servinfo, *p; #endif #ifdef _WIN32 - MIB_IPFORWARDROW ip_forward; unsigned long _ttl = (unsigned long)ttl; #endif int linklocal = 1; @@ -538,61 +537,103 @@ ssdpDiscoverDevices(const char * const deviceTypes[], * SSDP multicast traffic */ /* Get IP associated with the index given in the ip_forward struct * in order to give this ip to setsockopt(sudp, IPPROTO_IP, IP_MULTICAST_IF) */ - if(!ipv6 - && (GetBestRoute(inet_addr("223.255.255.255"), 0, &ip_forward) == NO_ERROR)) { - DWORD dwRetVal = 0; - PMIB_IPADDRTABLE pIPAddrTable; - DWORD dwSize = 0; -#ifdef DEBUG - IN_ADDR IPAddr; -#endif - int i; -#ifdef DEBUG - printf("ifIndex=%lu nextHop=%lx \n", ip_forward.dwForwardIfIndex, ip_forward.dwForwardNextHop); -#endif - pIPAddrTable = (MIB_IPADDRTABLE *) malloc(sizeof (MIB_IPADDRTABLE)); - if(pIPAddrTable) { - if (GetIpAddrTable(pIPAddrTable, &dwSize, 0) == ERROR_INSUFFICIENT_BUFFER) { - free(pIPAddrTable); - pIPAddrTable = (MIB_IPADDRTABLE *) malloc(dwSize); - } - } - if(pIPAddrTable) { - dwRetVal = GetIpAddrTable( pIPAddrTable, &dwSize, 0 ); + if(!ipv6) { + DWORD ifbestidx; + SOCKADDR_IN destAddr; + memset(&destAddr, 0, sizeof(destAddr)); + destAddr.sin_family = AF_INET; + destAddr.sin_addr.s_addr = inet_addr("223.255.255.255"); + destAddr.sin_port = 0; + if (GetBestInterfaceEx((struct sockaddr *)&destAddr, &ifbestidx) == NO_ERROR) { + DWORD dwSize = 0; + DWORD dwRetVal = 0; + unsigned int i = 0; + ULONG flags = GAA_FLAG_INCLUDE_PREFIX; + ULONG family = AF_INET; + LPVOID lpMsgBuf = NULL; + PIP_ADAPTER_ADDRESSES pAddresses = NULL; + ULONG outBufLen = 0; + ULONG Iterations = 0; + PIP_ADAPTER_ADDRESSES pCurrAddresses = NULL; + PIP_ADAPTER_UNICAST_ADDRESS pUnicast = NULL; + PIP_ADAPTER_ANYCAST_ADDRESS pAnycast = NULL; + PIP_ADAPTER_MULTICAST_ADDRESS pMulticast = NULL; + IP_ADAPTER_DNS_SERVER_ADDRESS *pDnServer = NULL; + IP_ADAPTER_PREFIX *pPrefix = NULL; + + outBufLen = 15360; + do { + pAddresses = (IP_ADAPTER_ADDRESSES *) HeapAlloc(GetProcessHeap(), 0, outBufLen); + if (pAddresses == NULL) { + break; + } + + dwRetVal = GetAdaptersAddresses(family, flags, NULL, pAddresses, &outBufLen); + + if (dwRetVal == ERROR_BUFFER_OVERFLOW) { + HeapFree(GetProcessHeap(), 0, pAddresses); + pAddresses = NULL; + } else { + break; + } + Iterations++; + } while ((dwRetVal == ERROR_BUFFER_OVERFLOW) && (Iterations < 3)); + if (dwRetVal == NO_ERROR) { + pCurrAddresses = pAddresses; + while (pCurrAddresses) { #ifdef DEBUG - printf("\tNum Entries: %ld\n", pIPAddrTable->dwNumEntries); -#endif - for (i=0; i < (int) pIPAddrTable->dwNumEntries; i++) { -#ifdef DEBUG - printf("\n\tInterface Index[%d]:\t%ld\n", i, pIPAddrTable->table[i].dwIndex); - IPAddr.S_un.S_addr = (u_long) pIPAddrTable->table[i].dwAddr; - printf("\tIP Address[%d]: \t%s\n", i, inet_ntoa(IPAddr) ); - IPAddr.S_un.S_addr = (u_long) pIPAddrTable->table[i].dwMask; - printf("\tSubnet Mask[%d]: \t%s\n", i, inet_ntoa(IPAddr) ); - IPAddr.S_un.S_addr = (u_long) pIPAddrTable->table[i].dwBCastAddr; - printf("\tBroadCast[%d]: \t%s (%ld)\n", i, inet_ntoa(IPAddr), pIPAddrTable->table[i].dwBCastAddr); - printf("\tReassembly size[%d]:\t%ld\n", i, pIPAddrTable->table[i].dwReasmSize); - printf("\tType and State[%d]:", i); + printf("\tIfIndex (IPv4 interface): %u\n", pCurrAddresses->IfIndex); + printf("\tAdapter name: %s\n", pCurrAddresses->AdapterName); + pUnicast = pCurrAddresses->FirstUnicastAddress; + if (pUnicast != NULL) { + for (i = 0; pUnicast != NULL; i++) { + IPAddr.S_un.S_addr = (u_long) pUnicast->Address; + printf("\tIP Address[%d]: \t%s\n", i, inet_ntoa(IPAddr) ); + pUnicast = pUnicast->Next; + } + printf("\tNumber of Unicast Addresses: %d\n", i); + } + pAnycast = pCurrAddresses->FirstAnycastAddress; + if (pAnycast) { + for (i = 0; pAnycast != NULL; i++) { + IPAddr.S_un.S_addr = (u_long) pAnyCast->Address; + printf("\tAnycast Address[%d]: \t%s\n", i, inet_ntoa(IPAddr) ); + pAnycast = pAnycast->Next; + } + printf("\tNumber of Anycast Addresses: %d\n", i); + } + pMulticast = pCurrAddresses->FirstMulticastAddress; + if (pMulticast) { + for (i = 0; pMulticast != NULL; i++) { + IPAddr.S_un.S_addr = (u_long) pMultiCast->Address; + printf("\tMulticast Address[%d]: \t%s\n", i, inet_ntoa(IPAddr) ); + } + } printf("\n"); #endif - if (pIPAddrTable->table[i].dwIndex == ip_forward.dwForwardIfIndex) { + pUnicast = pCurrAddresses->FirstUnicastAddress; + if (pCurrAddresses->IfIndex == ifbestidx && pUnicast != NULL) { + SOCKADDR_IN *ipv4 = (SOCKADDR_IN *)(pUnicast->Address.lpSockaddr); /* Set the address of this interface to be used */ struct in_addr mc_if; memset(&mc_if, 0, sizeof(mc_if)); - mc_if.s_addr = pIPAddrTable->table[i].dwAddr; + mc_if.s_addr = ipv4->sin_addr.s_addr; if(setsockopt(sudp, IPPROTO_IP, IP_MULTICAST_IF, (const char *)&mc_if, sizeof(mc_if)) < 0) { PRINT_SOCKET_ERROR("setsockopt"); } - ((struct sockaddr_in *)&sockudp_r)->sin_addr.s_addr = pIPAddrTable->table[i].dwAddr; + ((struct sockaddr_in *)&sockudp_r)->sin_addr.s_addr = ipv4->sin_addr.s_addr; #ifndef DEBUG break; #endif } + pCurrAddresses = pCurrAddresses->Next; } } - free(pIPAddrTable); - pIPAddrTable = NULL; + if (pAddresses != NULL) { + HeapFree(GetProcessHeap(), 0, pAddresses); + pAddresses = NULL; + } } } #endif /* _WIN32 */ |