summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.gitattributes1
-rw-r--r--.gitignore3
-rw-r--r--.travis.yml20
-rw-r--r--doc/classes/CanvasItem.xml2
-rw-r--r--doc/classes/ConfigFile.xml2
-rw-r--r--doc/classes/EditorInterface.xml2
-rw-r--r--doc/classes/PhysicsBody.xml6
-rw-r--r--doc/classes/PhysicsBody2D.xml12
-rw-r--r--doc/classes/SceneState.xml2
-rw-r--r--doc/classes/Shape2D.xml6
-rw-r--r--doc/classes/ShortCut.xml8
-rw-r--r--doc/classes/SoftBody.xml13
-rw-r--r--doc/classes/Timer.xml17
-rw-r--r--modules/bullet/godot_result_callbacks.cpp8
-rw-r--r--modules/gdscript/gdscript_functions.cpp2
-rw-r--r--modules/gdscript/gdscript_parser.cpp2
-rw-r--r--modules/mono/SCsub1
-rw-r--r--modules/mono/config.py26
-rw-r--r--modules/mono/editor/GodotSharpTools/Editor/MonoDevelopInstance.cs105
-rw-r--r--modules/mono/editor/GodotSharpTools/GodotSharpTools.csproj1
-rw-r--r--modules/mono/editor/GodotSharpTools/GodotSharpTools.userprefs14
-rw-r--r--modules/mono/editor/GodotSharpTools/Utils/OS.cs62
-rw-r--r--modules/mono/editor/godotsharp_builds.cpp27
-rw-r--r--modules/mono/editor/godotsharp_builds.h5
-rw-r--r--modules/mono/editor/godotsharp_editor.cpp125
-rw-r--r--modules/mono/editor/godotsharp_editor.h19
-rw-r--r--modules/mono/editor/monodevelop_instance.cpp11
-rw-r--r--modules/mono/editor/monodevelop_instance.h7
-rw-r--r--modules/mono/mono_gd/gd_mono.cpp2
-rw-r--r--modules/mono/utils/osx_utils.cpp62
-rw-r--r--modules/mono/utils/osx_utils.h41
-rw-r--r--modules/visual_script/visual_script_builtin_funcs.cpp7
-rw-r--r--platform/javascript/os_javascript.cpp52
-rw-r--r--platform/javascript/os_javascript.h1
-rw-r--r--platform/osx/os_osx.mm4
-rw-r--r--platform/windows/SCsub1
-rw-r--r--platform/windows/godot.natvis129
-rw-r--r--platform/windows/os_windows.cpp4
-rw-r--r--platform/x11/os_x11.cpp4
39 files changed, 716 insertions, 100 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/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/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/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..81652c3d37 100644
--- a/modules/gdscript/gdscript_parser.cpp
+++ b/modules/gdscript/gdscript_parser.cpp
@@ -4443,7 +4443,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
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/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&lt;*&gt;">
+ <Expand>
+ <Item Name="size">(_cowdata &amp;&amp; _cowdata-&gt;_ptr) ? (((const unsigned int *)(_cowdata-&gt;_ptr))[-1]) : 0</Item>
+ <ArrayItems>
+ <Size>(_cowdata &amp;&amp; _cowdata-&gt;_ptr) ? (((const unsigned int *)(_cowdata-&gt;_ptr))[-1]) : 0</Size>
+ <ValuePointer>(_cowdata) ? (_cowdata-&gt;_ptr) : 0</ValuePointer>
+ </ArrayItems>
+ </Expand>
+ </Type>
+
+ <Type Name="PoolVector&lt;*&gt;">
+ <Expand>
+ <Item Name="size">alloc ? (alloc-&gt;size / sizeof($T1)) : 0</Item>
+ <ArrayItems>
+ <Size>alloc ? (alloc-&gt;size / sizeof($T1)) : 0</Size>
+ <ValuePointer>alloc ? (($T1 *)alloc-&gt;mem) : 0</ValuePointer>
+ </ArrayItems>
+ </Expand>
+ </Type>
+
+ <Type Name="Variant">
+ <DisplayString Condition="this-&gt;type == Variant::NIL">nil</DisplayString>
+ <DisplayString Condition="this-&gt;type == Variant::BOOL">{_data._bool}</DisplayString>
+ <DisplayString Condition="this-&gt;type == Variant::INT">{_data._int}</DisplayString>
+ <DisplayString Condition="this-&gt;type == Variant::REAL">{_data._real}</DisplayString>
+ <DisplayString Condition="this-&gt;type == Variant::TRANSFORM2D">{_data._transform2d}</DisplayString>
+ <DisplayString Condition="this-&gt;type == Variant::AABB">{_data._aabb}</DisplayString>
+ <DisplayString Condition="this-&gt;type == Variant::BASIS">{_data._basis}</DisplayString>
+ <DisplayString Condition="this-&gt;type == Variant::TRANSFORM">{_data._transform}</DisplayString>
+ <DisplayString Condition="this-&gt;type == Variant::ARRAY">{*(Array *)_data._mem}</DisplayString>
+ <DisplayString Condition="this-&gt;type == Variant::STRING &amp;&amp; ((String *)(&amp;_data._mem[0]))-&gt;_cowdata._ptr == 0">""</DisplayString>
+ <DisplayString Condition="this-&gt;type == Variant::STRING &amp;&amp; ((String *)(&amp;_data._mem[0]))-&gt;_cowdata._ptr != 0">{((String *)(&amp;_data._mem[0]))-&gt;_cowdata._ptr,su}</DisplayString>
+ <DisplayString Condition="this-&gt;type == Variant::VECTOR2">{*(Vector2 *)_data._mem}</DisplayString>
+ <DisplayString Condition="this-&gt;type == Variant::RECT2">{*(Rect2 *)_data._mem}</DisplayString>
+ <DisplayString Condition="this-&gt;type == Variant::VECTOR3">{*(Vector3 *)_data._mem}</DisplayString>
+ <DisplayString Condition="this-&gt;type == Variant::PLANE">{*(Plane *)_data._mem}</DisplayString>
+ <DisplayString Condition="this-&gt;type == Variant::QUAT">{*(Quat *)_data._mem}</DisplayString>
+ <DisplayString Condition="this-&gt;type == Variant::COLOR">{*(Color *)_data._mem}</DisplayString>
+ <DisplayString Condition="this-&gt;type == Variant::NODE_PATH">{*(NodePath *)_data._mem}</DisplayString>
+ <DisplayString Condition="this-&gt;type == Variant::_RID">{*(RID *)_data._mem}</DisplayString>
+ <DisplayString Condition="this-&gt;type == Variant::OBJECT">{*(Object *)_data._mem}</DisplayString>
+ <DisplayString Condition="this-&gt;type == Variant::DICTIONARY">{*(Dictionary *)_data._mem}</DisplayString>
+ <DisplayString Condition="this-&gt;type == Variant::ARRAY">{*(Array *)_data._mem}</DisplayString>
+ <DisplayString Condition="this-&gt;type == Variant::POOL_BYTE_ARRAY">{*(PoolByteArray *)_data._mem}</DisplayString>
+ <DisplayString Condition="this-&gt;type == Variant::POOL_INT_ARRAY">{*(PoolIntArray *)_data._mem}</DisplayString>
+ <DisplayString Condition="this-&gt;type == Variant::POOL_REAL_ARRAY">{*(PoolRealArray *)_data._mem}</DisplayString>
+ <DisplayString Condition="this-&gt;type == Variant::POOL_STRING_ARRAY">{*(PoolStringArray *)_data._mem}</DisplayString>
+ <DisplayString Condition="this-&gt;type == Variant::POOL_VECTOR2_ARRAY">{*(PoolVector2Array *)_data._mem}</DisplayString>
+ <DisplayString Condition="this-&gt;type == Variant::POOL_VECTOR3_ARRAY">{*(PoolVector3Array *)_data._mem}</DisplayString>
+ <DisplayString Condition="this-&gt;type == Variant::POOL_COLOR_ARRAY">{*(PoolColorArray *)_data._mem}</DisplayString>
+
+ <StringView Condition="this-&gt;type == Variant::STRING &amp;&amp; ((String *)(&amp;_data._mem[0]))-&gt;_cowdata._ptr != 0">((String *)(&amp;_data._mem[0]))-&gt;_cowdata._ptr,su</StringView>
+
+ <Expand>
+ <Item Name="value" Condition="this-&gt;type == Variant::BOOL">_data._bool</Item>
+ <Item Name="value" Condition="this-&gt;type == Variant::INT">_data._int</Item>
+ <Item Name="value" Condition="this-&gt;type == Variant::REAL">_data._real</Item>
+ <Item Name="value" Condition="this-&gt;type == Variant::TRANSFORM2D">_data._transform2d</Item>
+ <Item Name="value" Condition="this-&gt;type == Variant::AABB">_data._aabb</Item>
+ <Item Name="value" Condition="this-&gt;type == Variant::BASIS">_data._basis</Item>
+ <Item Name="value" Condition="this-&gt;type == Variant::TRANSFORM">_data._transform</Item>
+ <Item Name="value" Condition="this-&gt;type == Variant::ARRAY">*(Array *)_data._mem</Item>
+ <Item Name="value" Condition="this-&gt;type == Variant::STRING">*(String *)_data._mem</Item>
+ <Item Name="value" Condition="this-&gt;type == Variant::VECTOR2">*(Vector2 *)_data._mem</Item>
+ <Item Name="value" Condition="this-&gt;type == Variant::RECT2">*(Rect2 *)_data._mem</Item>
+ <Item Name="value" Condition="this-&gt;type == Variant::VECTOR3">*(Vector3 *)_data._mem</Item>
+ <Item Name="value" Condition="this-&gt;type == Variant::PLANE">*(Plane *)_data._mem</Item>
+ <Item Name="value" Condition="this-&gt;type == Variant::QUAT">*(Quat *)_data._mem</Item>
+ <Item Name="value" Condition="this-&gt;type == Variant::COLOR">*(Color *)_data._mem</Item>
+ <Item Name="value" Condition="this-&gt;type == Variant::NODE_PATH">*(NodePath *)_data._mem</Item>
+ <Item Name="value" Condition="this-&gt;type == Variant::_RID">*(RID *)_data._mem</Item>
+ <Item Name="value" Condition="this-&gt;type == Variant::OBJECT">*(Object *)_data._mem</Item>
+ <Item Name="value" Condition="this-&gt;type == Variant::DICTIONARY">*(Dictionary *)_data._mem</Item>
+ <Item Name="value" Condition="this-&gt;type == Variant::ARRAY">*(Array *)_data._mem</Item>
+ <Item Name="value" Condition="this-&gt;type == Variant::POOL_BYTE_ARRAY">*(PoolByteArray *)_data._mem</Item>
+ <Item Name="value" Condition="this-&gt;type == Variant::POOL_INT_ARRAY">*(PoolIntArray *)_data._mem</Item>
+ <Item Name="value" Condition="this-&gt;type == Variant::POOL_REAL_ARRAY">*(PoolRealArray *)_data._mem</Item>
+ <Item Name="value" Condition="this-&gt;type == Variant::POOL_STRING_ARRAY">*(PoolStringArray *)_data._mem</Item>
+ <Item Name="value" Condition="this-&gt;type == Variant::POOL_VECTOR2_ARRAY">*(PoolVector2Array *)_data._mem</Item>
+ <Item Name="value" Condition="this-&gt;type == Variant::POOL_VECTOR3_ARRAY">*(PoolVector3Array *)_data._mem</Item>
+ <Item Name="value" Condition="this-&gt;type == Variant::POOL_COLOR_ARRAY">*(PoolColorArray *)_data._mem</Item>
+ </Expand>
+ </Type>
+
+ <Type Name="String">
+ <DisplayString Condition="this-&gt;_cowdata._ptr == 0">empty</DisplayString>
+ <DisplayString Condition="this-&gt;_cowdata._ptr != 0">{this->_cowdata._ptr,su}</DisplayString>
+ <StringView Condition="this-&gt;_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..88036c28e3 100644
--- a/platform/x11/os_x11.cpp
+++ b/platform/x11/os_x11.cpp
@@ -2607,7 +2607,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);