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/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_parser.cpp2
-rw-r--r--platform/javascript/os_javascript.cpp52
-rw-r--r--platform/javascript/os_javascript.h1
-rw-r--r--platform/windows/SCsub1
-rw-r--r--platform/windows/godot.natvis129
17 files changed, 243 insertions, 40 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/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_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/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/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>