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