summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--CONTRIBUTING.md18
-rw-r--r--SConstruct9
-rw-r--r--core/bind/core_bind.cpp12
-rw-r--r--core/bind/core_bind.h4
-rw-r--r--core/class_db.cpp3
-rw-r--r--core/dictionary.cpp9
-rw-r--r--core/dictionary.h1
-rw-r--r--core/image.cpp9
-rw-r--r--core/image.h1
-rw-r--r--core/io/image_loader.h2
-rw-r--r--core/io/ip_address.cpp2
-rw-r--r--core/math/math_defs.h4
-rw-r--r--core/object.cpp32
-rw-r--r--core/object.h1
-rw-r--r--core/os/file_access.cpp28
-rw-r--r--core/os/file_access.h3
-rw-r--r--core/os/input.cpp2
-rw-r--r--core/script_debugger_remote.cpp2
-rw-r--r--core/undo_redo.cpp7
-rw-r--r--core/undo_redo.h2
-rw-r--r--core/variant_call.cpp4
-rw-r--r--core/vmap.h21
-rw-r--r--doc/Doxyfile126
-rw-r--r--doc/classes/ARVRInterface.xml4
-rw-r--r--doc/classes/Animation.xml2
-rw-r--r--doc/classes/AudioEffectReverb.xml4
-rw-r--r--doc/classes/ConfigFile.xml1
-rw-r--r--doc/classes/Dictionary.xml11
-rw-r--r--doc/classes/DynamicFontData.xml3
-rw-r--r--doc/classes/Environment.xml3
-rw-r--r--doc/classes/File.xml13
-rw-r--r--doc/classes/Generic6DOFJoint.xml78
-rw-r--r--doc/classes/Input.xml5
-rw-r--r--doc/classes/Object.xml10
-rw-r--r--doc/classes/OrientedPathFollow.xml2
-rw-r--r--doc/classes/PHashTranslation.xml1
-rw-r--r--doc/classes/PhysicsServer.xml22
-rw-r--r--doc/classes/SpatialMaterial.xml4
-rw-r--r--doc/classes/StyleBoxFlat.xml33
-rw-r--r--doc/classes/Translation.xml12
-rw-r--r--doc/classes/TranslationServer.xml12
-rw-r--r--doc/classes/Tree.xml2
-rw-r--r--doc/classes/UndoRedo.xml3
-rw-r--r--doc/classes/Viewport.xml14
-rw-r--r--doc/classes/VisualServer.xml8
-rw-r--r--drivers/dummy/rasterizer_dummy.h2
-rw-r--r--drivers/gles2/rasterizer_scene_gles2.cpp11
-rw-r--r--drivers/gles2/rasterizer_storage_gles2.cpp9
-rw-r--r--drivers/gles2/rasterizer_storage_gles2.h2
-rw-r--r--drivers/gles2/shader_compiler_gles2.cpp9
-rw-r--r--drivers/gles2/shaders/scene.glsl5
-rw-r--r--drivers/gles3/rasterizer_canvas_gles3.cpp23
-rw-r--r--drivers/gles3/rasterizer_scene_gles3.cpp19
-rw-r--r--drivers/gles3/rasterizer_storage_gles3.cpp28
-rw-r--r--drivers/gles3/rasterizer_storage_gles3.h2
-rw-r--r--drivers/gles3/shader_compiler_gles3.cpp14
-rw-r--r--drivers/gles3/shader_gles3.cpp6
-rw-r--r--drivers/gles3/shaders/scene.glsl29
-rw-r--r--drivers/pulseaudio/audio_driver_pulseaudio.cpp6
-rw-r--r--drivers/unix/net_socket_posix.cpp3
-rw-r--r--editor/array_property_edit.cpp11
-rw-r--r--editor/code_editor.cpp33
-rw-r--r--editor/code_editor.h7
-rw-r--r--editor/create_dialog.cpp2
-rw-r--r--editor/editor_about.cpp2
-rw-r--r--editor/editor_data.cpp18
-rw-r--r--editor/editor_file_system.cpp33
-rw-r--r--editor/editor_file_system.h3
-rw-r--r--editor/editor_folding.cpp2
-rw-r--r--editor/editor_fonts.cpp16
-rw-r--r--editor/editor_help.cpp2
-rw-r--r--editor/editor_inspector.cpp5
-rw-r--r--editor/editor_node.cpp96
-rw-r--r--editor/editor_node.h3
-rw-r--r--editor/editor_properties.cpp57
-rw-r--r--editor/editor_properties.h12
-rw-r--r--editor/editor_properties_array_dict.cpp54
-rw-r--r--editor/editor_properties_array_dict.h3
-rw-r--r--editor/editor_settings.cpp4
-rw-r--r--editor/import/editor_import_collada.cpp2
-rw-r--r--editor/import/editor_scene_importer_gltf.cpp11
-rw-r--r--editor/import/resource_importer_texture.cpp2
-rw-r--r--editor/multi_node_edit.cpp2
-rw-r--r--editor/plugins/animation_blend_space_2d_editor.cpp15
-rw-r--r--editor/plugins/animation_blend_space_2d_editor.h1
-rw-r--r--editor/plugins/canvas_item_editor_plugin.cpp28
-rw-r--r--editor/plugins/canvas_item_editor_plugin.h4
-rw-r--r--editor/plugins/script_text_editor.cpp1
-rw-r--r--editor/plugins/shader_editor_plugin.cpp1
-rw-r--r--editor/plugins/spatial_editor_plugin.cpp16
-rw-r--r--editor/plugins/spatial_editor_plugin.h6
-rw-r--r--editor/scene_tree_editor.cpp5
-rw-r--r--editor/script_editor_debugger.cpp6
-rw-r--r--gles_builders.py4
-rw-r--r--methods.py26
-rw-r--r--modules/bullet/bullet_physics_server.h2
-rw-r--r--modules/bullet/collision_object_bullet.cpp9
-rw-r--r--modules/bullet/generic_6dof_joint_bullet.cpp40
-rw-r--r--modules/bullet/rigid_body_bullet.cpp26
-rw-r--r--modules/bullet/rigid_body_bullet.h15
-rw-r--r--modules/bullet/space_bullet.cpp10
-rw-r--r--modules/csg/csg_shape.cpp162
-rw-r--r--modules/csg/csg_shape.h18
-rw-r--r--modules/csg/doc_classes/CSGShape.xml3
-rw-r--r--modules/gdnative/gdnative_builders.py24
-rw-r--r--modules/gdscript/gdscript_function.cpp57
-rw-r--r--modules/gdscript/gdscript_parser.cpp20
-rw-r--r--modules/gridmap/grid_map_editor_plugin.cpp4
-rw-r--r--modules/mono/glue/Managed/Files/AABB.cs4
-rw-r--r--modules/mono/glue/Managed/Files/Basis.cs45
-rw-r--r--modules/mono/glue/Managed/Files/Color.cs4
-rw-r--r--modules/mono/glue/Managed/Files/Mathf.cs4
-rw-r--r--modules/mono/glue/Managed/Files/MathfEx.cs2
-rw-r--r--modules/mono/glue/Managed/Files/Plane.cs6
-rw-r--r--modules/mono/glue/Managed/Files/Quat.cs2
-rw-r--r--modules/mono/glue/Managed/Files/Rect2.cs4
-rw-r--r--modules/mono/glue/Managed/Files/StringExtensions.cs8
-rw-r--r--modules/mono/glue/Managed/Files/Transform.cs8
-rw-r--r--modules/mono/glue/Managed/Files/Transform2D.cs6
-rw-r--r--modules/mono/glue/Managed/Files/Vector2.cs4
-rw-r--r--modules/mono/glue/Managed/Files/Vector3.cs12
-rw-r--r--modules/mono/glue/Managed/Properties/AssemblyInfo.cs4
-rw-r--r--modules/squish/image_compress_squish.cpp7
-rw-r--r--modules/visual_script/doc_classes/VisualScriptCustomNode.xml2
-rw-r--r--modules/visual_script/visual_script_editor.cpp2
-rw-r--r--modules/visual_script/visual_script_editor.h2
-rw-r--r--platform/android/detect.py6
-rw-r--r--platform/android/java/res/layout/status_bar_ongoing_event_progress_bar.xml4
-rw-r--r--platform/android/java/src/org/godotengine/godot/utils/CustomSSLSocketFactory.java2
-rw-r--r--platform/android/java/src/org/godotengine/godot/utils/HttpRequester.java2
-rw-r--r--platform/android/java/src/org/godotengine/godot/utils/RequestParams.java2
-rw-r--r--platform/android/java_glue.cpp6
-rw-r--r--platform/android/power_android.cpp2
-rw-r--r--platform/iphone/detect.py9
-rw-r--r--platform/osx/detect.py6
-rw-r--r--platform/osx/os_osx.mm23
-rw-r--r--platform/windows/detect.py4
-rw-r--r--platform/x11/os_x11.cpp2
-rw-r--r--scene/2d/area_2d.cpp8
-rw-r--r--scene/2d/audio_stream_player_2d.cpp1
-rw-r--r--scene/2d/canvas_item.cpp3
-rw-r--r--scene/2d/cpu_particles_2d.cpp2
-rw-r--r--scene/2d/physics_body_2d.cpp4
-rw-r--r--scene/2d/skeleton_2d.cpp1
-rw-r--r--scene/2d/visibility_notifier_2d.cpp2
-rw-r--r--scene/3d/area.cpp8
-rw-r--r--scene/3d/audio_stream_player_3d.cpp1
-rw-r--r--scene/3d/cpu_particles.cpp2
-rw-r--r--scene/3d/physics_body.cpp72
-rw-r--r--scene/3d/physics_body.h18
-rw-r--r--scene/3d/physics_joint.cpp51
-rw-r--r--scene/3d/physics_joint.h8
-rw-r--r--scene/3d/sprite_3d.cpp16
-rw-r--r--scene/3d/visibility_notifier.cpp2
-rw-r--r--scene/animation/animation_blend_space_2d.cpp185
-rw-r--r--scene/animation/animation_blend_space_2d.h15
-rw-r--r--scene/animation/animation_blend_tree.cpp2
-rw-r--r--scene/animation/animation_player.cpp3
-rw-r--r--scene/animation/skeleton_ik.cpp22
-rw-r--r--scene/animation/skeleton_ik.h6
-rw-r--r--scene/gui/scroll_container.cpp2
-rw-r--r--scene/gui/split_container.cpp50
-rw-r--r--scene/gui/split_container.h4
-rw-r--r--scene/gui/tree.cpp5
-rw-r--r--scene/gui/tree.h1
-rw-r--r--scene/main/canvas_layer.cpp4
-rw-r--r--scene/main/node.cpp111
-rw-r--r--scene/main/viewport.cpp15
-rw-r--r--scene/resources/default_theme/default_theme.cpp1
-rw-r--r--scene/resources/dynamic_font.cpp18
-rw-r--r--scene/resources/dynamic_font.h3
-rw-r--r--scene/resources/material.cpp4
-rw-r--r--scene/resources/mesh.cpp1
-rw-r--r--scene/resources/particles_material.cpp2
-rw-r--r--scene/resources/primitive_meshes.cpp44
-rw-r--r--scene/resources/sky_box.cpp6
-rw-r--r--servers/audio/audio_rb_resampler.cpp32
-rw-r--r--servers/audio/effects/audio_effect_filter.h13
-rw-r--r--servers/physics/joints/generic_6dof_joint_sw.cpp48
-rw-r--r--servers/physics/physics_server_sw.cpp17
-rw-r--r--servers/physics/physics_server_sw.h4
-rw-r--r--servers/physics_2d/physics_2d_server_sw.cpp19
-rw-r--r--servers/physics_2d/physics_2d_server_sw.h4
-rw-r--r--servers/physics_2d/physics_2d_server_wrap_mt.h4
-rw-r--r--servers/physics_2d_server.h2
-rw-r--r--servers/physics_server.h10
-rw-r--r--servers/visual/rasterizer.h2
-rw-r--r--servers/visual/shader_language.cpp13
-rw-r--r--servers/visual/shader_language.h4
-rw-r--r--servers/visual/visual_server_canvas.cpp22
-rw-r--r--servers/visual/visual_server_scene.cpp11
-rw-r--r--servers/visual_server.cpp2
-rw-r--r--servers/visual_server.h2
-rw-r--r--thirdparty/enet/godot.cpp64
194 files changed, 2010 insertions, 760 deletions
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index a8e4650710..04e42d14b6 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -59,7 +59,8 @@ by drag and dropping the file in the GitHub edition field.
If you want to add new engine functionalities, please make sure that:
-* This functionality is desired.
+* This functionality is desired, which means that it solves a common use case
+ that several users will need in their real-life projects.
* You talked to other developers on how to implement it best (on either
communication channel, and maybe in a GitHub issue first before making your
PR).
@@ -70,10 +71,18 @@ Similar rules can be applied when contributing bug fixes - it's always best to
discuss the implementation in the bug report first if you are not 100% about
what would be the best fix.
+[This blog post](https://godotengine.org/article/will-your-contribution-be-merged-heres-how-tell)
+outlines the process used by core developers when assessing PRs. We strongly
+recommend that you have a look at it to know what's important to take into
+account for a PR to be considered for merging.
+
In addition to the following tips, also take a look at the
[Engine development guide](https://docs.godotengine.org/en/latest/development/cpp/)
for an introduction to developing on Godot.
+The [Contributing docs](http://docs.godotengine.org/en/latest/community/contributing/index.html)
+also have important information on the PR workflow and the code style we use.
+
#### Be nice to the git history
Try to make simple PRs that handle one specific topic. Just like for reporting
@@ -93,6 +102,9 @@ Internet).
This git style guide has some good practices to have in mind:
[Git Style Guide](https://github.com/agis-/git-style-guide)
+See our [PR workflow](http://docs.godotengine.org/en/latest/community/contributing/pr_workflow.html)
+documentation for tips on using Git, amending commits and rebasing branches.
+
#### Format your commit logs with readability in mind
The way you format your commit logs is quite important to ensure that the
@@ -138,6 +150,10 @@ Weblate](https://hosted.weblate.org/projects/godot-engine/godot), an open
source and web-based translation platform. Please refer to the [translation
readme](editor/translations/README.md) for more information.
+You can also help translate [Godot's
+documentation](https://hosted.weblate.org/projects/godot-engine/godot-docs/)
+on Weblate.
+
## Communicating with developers
The Godot Engine community has [many communication
diff --git a/SConstruct b/SConstruct
index 628aac42af..8b7b95a600 100644
--- a/SConstruct
+++ b/SConstruct
@@ -425,8 +425,13 @@ if selected_platform in platform_list:
# (SH)LIBSUFFIX will be used for our own built libraries
# LIBSUFFIXES contains LIBSUFFIX and SHLIBSUFFIX by default,
# so we need to append the default suffixes to keep the ability
- # to link against thirdparty libraries (.a, .so, .dll, etc.).
- env["LIBSUFFIXES"] += [env["LIBSUFFIX"], env["SHLIBSUFFIX"]]
+ # to link against thirdparty libraries (.a, .so, .lib, etc.).
+ if os.name == "nt":
+ # On Windows, only static libraries and import libraries can be
+ # statically linked - both using .lib extension
+ env["LIBSUFFIXES"] += [env["LIBSUFFIX"]]
+ else:
+ env["LIBSUFFIXES"] += [env["LIBSUFFIX"], env["SHLIBSUFFIX"]]
env["LIBSUFFIX"] = suffix + env["LIBSUFFIX"]
env["SHLIBSUFFIX"] = suffix + env["SHLIBSUFFIX"]
diff --git a/core/bind/core_bind.cpp b/core/bind/core_bind.cpp
index cd28081f76..0032c43179 100644
--- a/core/bind/core_bind.cpp
+++ b/core/bind/core_bind.cpp
@@ -1754,9 +1754,9 @@ String _File::get_line() const {
return f->get_line();
}
-Vector<String> _File::get_csv_line(String delim) const {
+Vector<String> _File::get_csv_line(const String &p_delim) const {
ERR_FAIL_COND_V(!f, Vector<String>());
- return f->get_csv_line(delim);
+ return f->get_csv_line(p_delim);
}
/**< use this for files WRITTEN in _big_ endian machines (ie, amiga/mac)
@@ -1853,6 +1853,11 @@ void _File::store_line(const String &p_string) {
f->store_line(p_string);
}
+void _File::store_csv_line(const Vector<String> &p_values, const String &p_delim) {
+ ERR_FAIL_COND(!f);
+ f->store_csv_line(p_values, p_delim);
+}
+
void _File::store_buffer(const PoolVector<uint8_t> &p_buffer) {
ERR_FAIL_COND(!f);
@@ -1936,6 +1941,7 @@ void _File::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_real"), &_File::get_real);
ClassDB::bind_method(D_METHOD("get_buffer", "len"), &_File::get_buffer);
ClassDB::bind_method(D_METHOD("get_line"), &_File::get_line);
+ ClassDB::bind_method(D_METHOD("get_csv_line", "delim"), &_File::get_csv_line, DEFVAL(","));
ClassDB::bind_method(D_METHOD("get_as_text"), &_File::get_as_text);
ClassDB::bind_method(D_METHOD("get_md5", "path"), &_File::get_md5);
ClassDB::bind_method(D_METHOD("get_sha256", "path"), &_File::get_sha256);
@@ -1943,7 +1949,6 @@ void _File::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_endian_swap", "enable"), &_File::set_endian_swap);
ClassDB::bind_method(D_METHOD("get_error"), &_File::get_error);
ClassDB::bind_method(D_METHOD("get_var"), &_File::get_var);
- ClassDB::bind_method(D_METHOD("get_csv_line", "delim"), &_File::get_csv_line, DEFVAL(","));
ClassDB::bind_method(D_METHOD("store_8", "value"), &_File::store_8);
ClassDB::bind_method(D_METHOD("store_16", "value"), &_File::store_16);
@@ -1954,6 +1959,7 @@ void _File::_bind_methods() {
ClassDB::bind_method(D_METHOD("store_real", "value"), &_File::store_real);
ClassDB::bind_method(D_METHOD("store_buffer", "buffer"), &_File::store_buffer);
ClassDB::bind_method(D_METHOD("store_line", "line"), &_File::store_line);
+ ClassDB::bind_method(D_METHOD("store_csv_line", "values", "delim"), &_File::store_csv_line, DEFVAL(","));
ClassDB::bind_method(D_METHOD("store_string", "string"), &_File::store_string);
ClassDB::bind_method(D_METHOD("store_var", "value"), &_File::store_var);
diff --git a/core/bind/core_bind.h b/core/bind/core_bind.h
index 437d7515c6..720b14bf56 100644
--- a/core/bind/core_bind.h
+++ b/core/bind/core_bind.h
@@ -455,6 +455,7 @@ public:
PoolVector<uint8_t> get_buffer(int p_length) const; ///< get an array of bytes
String get_line() const;
+ Vector<String> get_csv_line(const String &p_delim = ",") const;
String get_as_text() const;
String get_md5(const String &p_path) const;
String get_sha256(const String &p_path) const;
@@ -480,12 +481,11 @@ public:
void store_string(const String &p_string);
void store_line(const String &p_string);
+ void store_csv_line(const Vector<String> &p_values, const String &p_delim = ",");
virtual void store_pascal_string(const String &p_string);
virtual String get_pascal_string();
- Vector<String> get_csv_line(String delim = ",") const;
-
void store_buffer(const PoolVector<uint8_t> &p_buffer); ///< store an array of bytes
void store_var(const Variant &p_var);
diff --git a/core/class_db.cpp b/core/class_db.cpp
index 6565d242a2..052a4586fe 100644
--- a/core/class_db.cpp
+++ b/core/class_db.cpp
@@ -936,9 +936,8 @@ void ClassDB::add_property(StringName p_class, const PropertyInfo &p_pinfo, cons
}
#ifdef DEBUG_METHODS_ENABLED
-
if (type->property_setget.has(p_pinfo.name)) {
- ERR_EXPLAIN("Object already has property: " + p_class);
+ ERR_EXPLAIN("Object " + p_class + " already has property: " + p_pinfo.name);
ERR_FAIL();
}
#endif
diff --git a/core/dictionary.cpp b/core/dictionary.cpp
index ccbdff3816..6a3ab82879 100644
--- a/core/dictionary.cpp
+++ b/core/dictionary.cpp
@@ -112,6 +112,15 @@ Variant Dictionary::get_valid(const Variant &p_key) const {
return E.get();
}
+Variant Dictionary::get(const Variant &p_key, const Variant &p_default) const {
+ const Variant *result = getptr(p_key);
+ if (!result) {
+ return p_default;
+ }
+
+ return *result;
+}
+
int Dictionary::size() const {
return _p->variant_map.size();
diff --git a/core/dictionary.h b/core/dictionary.h
index d3b98c2f63..b77cc55254 100644
--- a/core/dictionary.h
+++ b/core/dictionary.h
@@ -58,6 +58,7 @@ public:
Variant *getptr(const Variant &p_key);
Variant get_valid(const Variant &p_key) const;
+ Variant get(const Variant &p_key, const Variant &p_default) const;
int size() const;
bool empty() const;
diff --git a/core/image.cpp b/core/image.cpp
index 172f5e517a..698a0b0b98 100644
--- a/core/image.cpp
+++ b/core/image.cpp
@@ -1766,6 +1766,15 @@ int Image::get_image_required_mipmaps(int p_width, int p_height, Format p_format
return mm;
}
+int Image::get_image_mipmap_offset(int p_width, int p_height, Format p_format, int p_mipmap) {
+
+ if (p_mipmap <= 0) {
+ return 0;
+ }
+ int mm;
+ return _get_dst_image_size(p_width, p_height, p_format, mm, p_mipmap - 1);
+}
+
bool Image::is_compressed() const {
return format > FORMAT_RGBE9995;
}
diff --git a/core/image.h b/core/image.h
index 11f9380c3c..0770eb953e 100644
--- a/core/image.h
+++ b/core/image.h
@@ -286,6 +286,7 @@ public:
static int get_image_data_size(int p_width, int p_height, Format p_format, bool p_mipmaps = false);
static int get_image_required_mipmaps(int p_width, int p_height, Format p_format);
+ static int get_image_mipmap_offset(int p_width, int p_height, Format p_format, int p_mipmap);
enum CompressMode {
COMPRESS_S3TC,
diff --git a/core/io/image_loader.h b/core/io/image_loader.h
index 561f275e0c..d95a483c0d 100644
--- a/core/io/image_loader.h
+++ b/core/io/image_loader.h
@@ -71,7 +71,7 @@ public:
class ImageLoader {
enum {
- MAX_LOADERS = 8
+ MAX_LOADERS = 32
};
friend class ResourceFormatLoaderImage;
static ImageFormatLoader *loader[MAX_LOADERS];
diff --git a/core/io/ip_address.cpp b/core/io/ip_address.cpp
index 6d979d10eb..194d1af6bf 100644
--- a/core/io/ip_address.cpp
+++ b/core/io/ip_address.cpp
@@ -184,7 +184,7 @@ bool IP_Address::is_ipv4() const {
}
const uint8_t *IP_Address::get_ipv4() const {
- ERR_FAIL_COND_V(!is_ipv4(), 0);
+ ERR_FAIL_COND_V(!is_ipv4(), &(field8[12])); // Not the correct IPv4 (it's an IPv6), but we don't want to return a null pointer risking an engine crash.
return &(field8[12]);
}
diff --git a/core/math/math_defs.h b/core/math/math_defs.h
index a5feee6eb5..db9055cee2 100644
--- a/core/math/math_defs.h
+++ b/core/math/math_defs.h
@@ -93,9 +93,9 @@ enum Corner {
};
/**
- * The "Real" type is an abstract type used for real numbers, such as 1.5,
+ * The "Real" type is an abstract type used for real numbers, such as 1.5,
* in contrast to integer numbers. Precision can be controlled with the
- * presence or absence of the REAL_T_IS_DOUBLE define.
+ * presence or absence of the REAL_T_IS_DOUBLE define.
*/
#ifdef REAL_T_IS_DOUBLE
typedef double real_t;
diff --git a/core/object.cpp b/core/object.cpp
index 6a6749f3b8..ea77090a45 100644
--- a/core/object.cpp
+++ b/core/object.cpp
@@ -1715,6 +1715,8 @@ void Object::_bind_methods() {
ClassDB::bind_vararg_method(METHOD_FLAGS_DEFAULT, "call_deferred", &Object::_call_deferred_bind, mi);
}
+ ClassDB::bind_method(D_METHOD("set_deferred", "property", "value"), &Object::set_deferred);
+
ClassDB::bind_method(D_METHOD("callv", "method", "arg_array"), &Object::callv);
ClassDB::bind_method(D_METHOD("has_method", "method"), &Object::has_method);
@@ -1771,6 +1773,10 @@ void Object::call_deferred(const StringName &p_method, VARIANT_ARG_DECLARE) {
MessageQueue::get_singleton()->push_call(this, p_method, VARIANT_ARG_PASS);
}
+void Object::set_deferred(const StringName &p_property, const Variant &p_value) {
+ MessageQueue::get_singleton()->push_set(this, p_property, p_value);
+}
+
void Object::set_block_signals(bool p_block) {
_block_signals = p_block;
@@ -1935,30 +1941,30 @@ Object::~Object() {
memdelete(script_instance);
script_instance = NULL;
- List<Connection> sconnections;
const StringName *S = NULL;
- while ((S = signal_map.next(S))) {
+ while ((S = signal_map.next(NULL))) {
Signal *s = &signal_map[*S];
- ERR_EXPLAIN("Attempt to delete an object in the middle of a signal emission from it");
- ERR_CONTINUE(s->lock > 0);
-
- for (int i = 0; i < s->slot_map.size(); i++) {
-
- sconnections.push_back(s->slot_map.getv(i).conn);
+ if (s->lock) {
+ ERR_EXPLAIN("Attempt to delete an object in the middle of a signal emission from it");
+ ERR_CONTINUE(s->lock > 0);
}
- }
- for (List<Connection>::Element *E = sconnections.front(); E; E = E->next()) {
+ //brute force disconnect for performance
+ int slot_count = s->slot_map.size();
+ const VMap<Signal::Target, Signal::Slot>::Pair *slot_list = s->slot_map.get_array();
- Connection &c = E->get();
- ERR_CONTINUE(c.source != this); //bug?
+ for (int i = 0; i < slot_count; i++) {
+
+ slot_list[i].value.conn.target->connections.erase(slot_list[i].value.cE);
+ }
- this->_disconnect(c.signal, c.target, c.method, true);
+ signal_map.erase(*S);
}
+ //signals from nodes that connect to this node
while (connections.size()) {
Connection c = connections.front()->get();
diff --git a/core/object.h b/core/object.h
index 25d41140aa..88a98dacbe 100644
--- a/core/object.h
+++ b/core/object.h
@@ -698,6 +698,7 @@ public:
bool is_connected(const StringName &p_signal, Object *p_to_object, const StringName &p_to_method) const;
void call_deferred(const StringName &p_method, VARIANT_ARG_LIST);
+ void set_deferred(const StringName &p_property, const Variant &p_value);
void set_block_signals(bool p_block);
bool is_blocking_signals() const;
diff --git a/core/os/file_access.cpp b/core/os/file_access.cpp
index e09e5e16ad..679b1c9054 100644
--- a/core/os/file_access.cpp
+++ b/core/os/file_access.cpp
@@ -346,9 +346,9 @@ String FileAccess::get_line() const {
return String::utf8(line.get_data());
}
-Vector<String> FileAccess::get_csv_line(String delim) const {
+Vector<String> FileAccess::get_csv_line(const String &p_delim) const {
- ERR_FAIL_COND_V(delim.length() != 1, Vector<String>());
+ ERR_FAIL_COND_V(p_delim.length() != 1, Vector<String>());
String l;
int qc = 0;
@@ -376,7 +376,7 @@ Vector<String> FileAccess::get_csv_line(String delim) const {
CharType c = l[i];
CharType s[2] = { 0, 0 };
- if (!in_quote && c == delim[0]) {
+ if (!in_quote && c == p_delim[0]) {
strings.push_back(current);
current = String();
} else if (c == '"') {
@@ -525,6 +525,28 @@ void FileAccess::store_line(const String &p_line) {
store_8('\n');
}
+void FileAccess::store_csv_line(const Vector<String> &p_values, const String &p_delim) {
+
+ ERR_FAIL_COND(p_delim.length() != 1);
+
+ String line = "";
+ int size = p_values.size();
+ for (int i = 0; i < size; ++i) {
+ String value = p_values[i];
+
+ if (value.find("\"") != -1 || value.find(p_delim) != -1 || value.find("\n") != -1) {
+ value = "\"" + value.replace("\"", "\"\"") + "\"";
+ }
+ if (i < size - 1) {
+ value += p_delim;
+ }
+
+ line += value;
+ }
+
+ store_line(line);
+}
+
void FileAccess::store_buffer(const uint8_t *p_src, int p_length) {
for (int i = 0; i < p_length; i++)
diff --git a/core/os/file_access.h b/core/os/file_access.h
index b7d93e9f5d..f1f3005dd9 100644
--- a/core/os/file_access.h
+++ b/core/os/file_access.h
@@ -112,7 +112,7 @@ public:
virtual int get_buffer(uint8_t *p_dst, int p_length) const; ///< get an array of bytes
virtual String get_line() const;
virtual String get_token() const;
- virtual Vector<String> get_csv_line(String delim = ",") const;
+ virtual Vector<String> get_csv_line(const String &p_delim = ",") const;
/**< use this for files WRITTEN in _big_ endian machines (ie, amiga/mac)
* It's not about the current CPU type but file formats.
@@ -136,6 +136,7 @@ public:
virtual void store_string(const String &p_string);
virtual void store_line(const String &p_line);
+ virtual void store_csv_line(const Vector<String> &p_values, const String &p_delim = ",");
virtual void store_pascal_string(const String &p_string);
virtual String get_pascal_string();
diff --git a/core/os/input.cpp b/core/os/input.cpp
index 1a24258a10..3b895b16b4 100644
--- a/core/os/input.cpp
+++ b/core/os/input.cpp
@@ -86,7 +86,7 @@ void Input::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_mouse_mode", "mode"), &Input::set_mouse_mode);
ClassDB::bind_method(D_METHOD("get_mouse_mode"), &Input::get_mouse_mode);
ClassDB::bind_method(D_METHOD("warp_mouse_position", "to"), &Input::warp_mouse_position);
- ClassDB::bind_method(D_METHOD("action_press", "action", "strength"), &Input::action_press);
+ ClassDB::bind_method(D_METHOD("action_press", "action", "strength"), &Input::action_press, DEFVAL(1.f));
ClassDB::bind_method(D_METHOD("action_release", "action"), &Input::action_release);
ClassDB::bind_method(D_METHOD("set_default_cursor_shape", "shape"), &Input::set_default_cursor_shape, DEFVAL(CURSOR_ARROW));
ClassDB::bind_method(D_METHOD("set_custom_mouse_cursor", "image", "shape", "hotspot"), &Input::set_custom_mouse_cursor, DEFVAL(CURSOR_ARROW), DEFVAL(Vector2()));
diff --git a/core/script_debugger_remote.cpp b/core/script_debugger_remote.cpp
index 621a94ab1a..a03ddd0983 100644
--- a/core/script_debugger_remote.cpp
+++ b/core/script_debugger_remote.cpp
@@ -108,7 +108,7 @@ void ScriptDebuggerRemote::_put_variable(const String &p_name, const Variant &p_
}
int len = 0;
- Error err = encode_variant(var, NULL, len);
+ Error err = encode_variant(var, NULL, len, true);
if (err != OK)
ERR_PRINT("Failed to encode variant");
diff --git a/core/undo_redo.cpp b/core/undo_redo.cpp
index 7d67076df5..3d41c374ea 100644
--- a/core/undo_redo.cpp
+++ b/core/undo_redo.cpp
@@ -325,7 +325,7 @@ bool UndoRedo::undo() {
return true;
}
-void UndoRedo::clear_history() {
+void UndoRedo::clear_history(bool p_increase_version) {
ERR_FAIL_COND(action_level > 0);
_discard_redo();
@@ -333,7 +333,8 @@ void UndoRedo::clear_history() {
while (actions.size())
_pop_history_tail();
- //version++;
+ if (p_increase_version)
+ version++;
}
String UndoRedo::get_current_action_name() const {
@@ -493,7 +494,7 @@ void UndoRedo::_bind_methods() {
ClassDB::bind_method(D_METHOD("add_undo_property", "object", "property", "value"), &UndoRedo::add_undo_property);
ClassDB::bind_method(D_METHOD("add_do_reference", "object"), &UndoRedo::add_do_reference);
ClassDB::bind_method(D_METHOD("add_undo_reference", "object"), &UndoRedo::add_undo_reference);
- ClassDB::bind_method(D_METHOD("clear_history"), &UndoRedo::clear_history);
+ ClassDB::bind_method(D_METHOD("clear_history", "increase_version"), &UndoRedo::clear_history, DEFVAL(true));
ClassDB::bind_method(D_METHOD("get_current_action_name"), &UndoRedo::get_current_action_name);
ClassDB::bind_method(D_METHOD("get_version"), &UndoRedo::get_version);
ClassDB::bind_method(D_METHOD("redo"), &UndoRedo::redo);
diff --git a/core/undo_redo.h b/core/undo_redo.h
index 22dcd60472..f09fca9a78 100644
--- a/core/undo_redo.h
+++ b/core/undo_redo.h
@@ -112,7 +112,7 @@ public:
bool redo();
bool undo();
String get_current_action_name() const;
- void clear_history();
+ void clear_history(bool p_increase_version = true);
uint64_t get_version() const;
diff --git a/core/variant_call.cpp b/core/variant_call.cpp
index 8693a584f2..0c6e43fe36 100644
--- a/core/variant_call.cpp
+++ b/core/variant_call.cpp
@@ -155,9 +155,7 @@ struct _VariantCall {
funcdata.default_args = p_defaultarg;
funcdata._const = p_const;
funcdata.returns = p_has_return;
-#ifdef DEBUG_ENABLED
funcdata.return_type = p_return;
-#endif
if (p_argtype1.name) {
funcdata.arg_types.push_back(p_argtype1.type);
@@ -486,6 +484,7 @@ struct _VariantCall {
VCALL_LOCALMEM0R(Dictionary, keys);
VCALL_LOCALMEM0R(Dictionary, values);
VCALL_LOCALMEM1R(Dictionary, duplicate);
+ VCALL_LOCALMEM2R(Dictionary, get);
VCALL_LOCALMEM2(Array, set);
VCALL_LOCALMEM1R(Array, get);
@@ -1679,6 +1678,7 @@ void register_variant_methods() {
ADDFUNC0R(DICTIONARY, ARRAY, Dictionary, keys, varray());
ADDFUNC0R(DICTIONARY, ARRAY, Dictionary, values, varray());
ADDFUNC1R(DICTIONARY, DICTIONARY, Dictionary, duplicate, BOOL, "deep", varray(false));
+ ADDFUNC2R(DICTIONARY, NIL, Dictionary, get, NIL, "key", NIL, "default", varray(Variant()));
ADDFUNC0R(ARRAY, INT, Array, size, varray());
ADDFUNC0R(ARRAY, BOOL, Array, empty, varray());
diff --git a/core/vmap.h b/core/vmap.h
index 9fc99e636d..5f6d8190c6 100644
--- a/core/vmap.h
+++ b/core/vmap.h
@@ -36,22 +36,23 @@
template <class T, class V>
class VMap {
-
- struct _Pair {
+public:
+ struct Pair {
T key;
V value;
- _FORCE_INLINE_ _Pair() {}
+ _FORCE_INLINE_ Pair() {}
- _FORCE_INLINE_ _Pair(const T &p_key, const V &p_value) {
+ _FORCE_INLINE_ Pair(const T &p_key, const V &p_value) {
key = p_key;
value = p_value;
}
};
- CowData<_Pair> _cowdata;
+private:
+ CowData<Pair> _cowdata;
_FORCE_INLINE_ int _find(const T &p_val, bool &r_exact) const {
@@ -61,7 +62,7 @@ class VMap {
int low = 0;
int high = _cowdata.size() - 1;
- const _Pair *a = _cowdata.ptr();
+ const Pair *a = _cowdata.ptr();
int middle = 0;
#if DEBUG_ENABLED
@@ -95,7 +96,7 @@ class VMap {
int low = 0;
int high = _cowdata.size() - 1;
int middle;
- const _Pair *a = _cowdata.ptr();
+ const Pair *a = _cowdata.ptr();
while (low <= high) {
middle = (low + high) / 2;
@@ -121,7 +122,7 @@ public:
_cowdata.get_m(pos).value = p_val;
return pos;
}
- _cowdata.insert(pos, _Pair(p_key, p_val));
+ _cowdata.insert(pos, Pair(p_key, p_val));
return pos;
}
@@ -152,12 +153,12 @@ public:
_FORCE_INLINE_ int size() const { return _cowdata.size(); }
_FORCE_INLINE_ bool empty() const { return _cowdata.empty(); }
- const _Pair *get_array() const {
+ const Pair *get_array() const {
return _cowdata.ptr();
}
- _Pair *get_array() {
+ Pair *get_array() {
return _cowdata.ptrw();
}
diff --git a/doc/Doxyfile b/doc/Doxyfile
index c1904f17c9..a7aa204741 100644
--- a/doc/Doxyfile
+++ b/doc/Doxyfile
@@ -38,7 +38,7 @@ PROJECT_NAME = Godot
# could be handy for archiving the generated documentation or if some version
# control system is used.
-PROJECT_NUMBER =
+PROJECT_NUMBER =
# Using the PROJECT_BRIEF tag one can provide an optional one line description
# for a project that appears at the top of each page and should give viewer a
@@ -162,7 +162,7 @@ FULL_PATH_NAMES = YES
# will be relative from the directory where doxygen is started.
# This tag requires that the tag FULL_PATH_NAMES is set to YES.
-STRIP_FROM_PATH =
+STRIP_FROM_PATH =
# The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of the
# path mentioned in the documentation of a class, which tells the reader which
@@ -171,7 +171,7 @@ STRIP_FROM_PATH =
# specify the list of include paths that are normally passed to the compiler
# using the -I flag.
-STRIP_FROM_INC_PATH =
+STRIP_FROM_INC_PATH =
# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter (but
# less readable) file names. This can be useful is your file systems doesn't
@@ -238,13 +238,13 @@ TAB_SIZE = 4
# "Side Effects:". You can put \n's in the value part of an alias to insert
# newlines.
-ALIASES =
+ALIASES =
# This tag can be used to specify a number of word-keyword mappings (TCL only).
# A mapping has the form "name=value". For example adding "class=itcl::class"
# will allow you to use the command class in the itcl::class meaning.
-TCL_SUBST =
+TCL_SUBST =
# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C sources
# only. Doxygen will then generate output that is more tailored for C. For
@@ -291,7 +291,7 @@ OPTIMIZE_OUTPUT_VHDL = NO
# Note that for custom extensions you also need to set FILE_PATTERNS otherwise
# the files are not read by doxygen.
-EXTENSION_MAPPING =
+EXTENSION_MAPPING =
# If the MARKDOWN_SUPPORT tag is enabled then doxygen pre-processes all comments
# according to the Markdown format, which allows for more readable
@@ -632,7 +632,7 @@ GENERATE_DEPRECATEDLIST= YES
# sections, marked by \if <section_label> ... \endif and \cond <section_label>
# ... \endcond blocks.
-ENABLED_SECTIONS =
+ENABLED_SECTIONS =
# The MAX_INITIALIZER_LINES tag determines the maximum number of lines that the
# initial value of a variable or macro / define can have for it to appear in the
@@ -674,7 +674,7 @@ SHOW_NAMESPACES = YES
# by doxygen. Whatever the program writes to standard output is used as the file
# version. For an example see the documentation.
-FILE_VERSION_FILTER =
+FILE_VERSION_FILTER =
# The LAYOUT_FILE tag can be used to specify a layout file which will be parsed
# by doxygen. The layout file controls the global structure of the generated
@@ -687,7 +687,7 @@ FILE_VERSION_FILTER =
# DoxygenLayout.xml, doxygen will parse it automatically even if the LAYOUT_FILE
# tag is left empty.
-LAYOUT_FILE =
+LAYOUT_FILE =
# The CITE_BIB_FILES tag can be used to specify one or more bib files containing
# the reference definitions. This must be a list of .bib files. The .bib
@@ -697,7 +697,7 @@ LAYOUT_FILE =
# LATEX_BIB_STYLE. To use this feature you need bibtex and perl available in the
# search path. See also \cite for info how to create references.
-CITE_BIB_FILES =
+CITE_BIB_FILES =
#---------------------------------------------------------------------------
# Configuration options related to warning and progress messages
@@ -756,7 +756,7 @@ WARN_FORMAT = "$file:$line: $text"
# messages should be written. If left blank the output is written to standard
# error (stderr).
-WARN_LOGFILE =
+WARN_LOGFILE =
#---------------------------------------------------------------------------
# Configuration options related to the input files
@@ -844,7 +844,7 @@ RECURSIVE = YES
# Note that relative paths are relative to the directory from which doxygen is
# run.
-EXCLUDE =
+EXCLUDE =
# The EXCLUDE_SYMLINKS tag can be used to select whether or not files or
# directories that are symbolic links (a Unix file system feature) are excluded
@@ -860,7 +860,7 @@ EXCLUDE_SYMLINKS = NO
# Note that the wildcards are matched against the file with absolute path, so to
# exclude all test directories for example use the pattern */test/*
-EXCLUDE_PATTERNS =
+EXCLUDE_PATTERNS =
# The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names
# (namespaces, classes, functions, etc.) that should be excluded from the
@@ -871,13 +871,13 @@ EXCLUDE_PATTERNS =
# Note that the wildcards are matched against the file with absolute path, so to
# exclude all test directories use the pattern */test/*
-EXCLUDE_SYMBOLS =
+EXCLUDE_SYMBOLS =
# The EXAMPLE_PATH tag can be used to specify one or more files or directories
# that contain example code fragments that are included (see the \include
# command).
-EXAMPLE_PATH =
+EXAMPLE_PATH =
# If the value of the EXAMPLE_PATH tag contains directories, you can use the
# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp and
@@ -897,7 +897,7 @@ EXAMPLE_RECURSIVE = NO
# that contain images that are to be included in the documentation (see the
# \image command).
-IMAGE_PATH =
+IMAGE_PATH =
# The INPUT_FILTER tag can be used to specify a program that doxygen should
# invoke to filter for each input file. Doxygen will invoke the filter program
@@ -914,7 +914,7 @@ IMAGE_PATH =
# code is scanned, but not when the output code is generated. If lines are added
# or removed, the anchors will not be placed correctly.
-INPUT_FILTER =
+INPUT_FILTER =
# The FILTER_PATTERNS tag can be used to specify filters on a per file pattern
# basis. Doxygen will compare the file name with each pattern and apply the
@@ -923,7 +923,7 @@ INPUT_FILTER =
# filters are used. If the FILTER_PATTERNS tag is empty or if none of the
# patterns match the file name, INPUT_FILTER is applied.
-FILTER_PATTERNS =
+FILTER_PATTERNS =
# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using
# INPUT_FILTER) will also be used to filter the input files that are used for
@@ -938,7 +938,7 @@ FILTER_SOURCE_FILES = NO
# *.ext= (so without naming a filter).
# This tag requires that the tag FILTER_SOURCE_FILES is set to YES.
-FILTER_SOURCE_PATTERNS =
+FILTER_SOURCE_PATTERNS =
# If the USE_MDFILE_AS_MAINPAGE tag refers to the name of a markdown file that
# is part of the input, its contents will be placed on the main page
@@ -1050,7 +1050,7 @@ CLANG_ASSISTED_PARSING = NO
# specified with INPUT and INCLUDE_PATH.
# This tag requires that the tag CLANG_ASSISTED_PARSING is set to YES.
-CLANG_OPTIONS =
+CLANG_OPTIONS =
#---------------------------------------------------------------------------
# Configuration options related to the alphabetical class index
@@ -1076,7 +1076,7 @@ COLS_IN_ALPHA_INDEX = 5
# while generating the index headers.
# This tag requires that the tag ALPHABETICAL_INDEX is set to YES.
-IGNORE_PREFIX =
+IGNORE_PREFIX =
#---------------------------------------------------------------------------
# Configuration options related to the HTML output
@@ -1120,7 +1120,7 @@ HTML_FILE_EXTENSION = .html
# of the possible markers and block names see the documentation.
# This tag requires that the tag GENERATE_HTML is set to YES.
-HTML_HEADER =
+HTML_HEADER =
# The HTML_FOOTER tag can be used to specify a user-defined HTML footer for each
# generated HTML page. If the tag is left blank doxygen will generate a standard
@@ -1130,7 +1130,7 @@ HTML_HEADER =
# that doxygen normally uses.
# This tag requires that the tag GENERATE_HTML is set to YES.
-HTML_FOOTER =
+HTML_FOOTER =
# The HTML_STYLESHEET tag can be used to specify a user-defined cascading style
# sheet that is used by each HTML page. It can be used to fine-tune the look of
@@ -1142,7 +1142,7 @@ HTML_FOOTER =
# obsolete.
# This tag requires that the tag GENERATE_HTML is set to YES.
-HTML_STYLESHEET =
+HTML_STYLESHEET =
# The HTML_EXTRA_STYLESHEET tag can be used to specify additional user-defined
# cascading style sheets that are included after the standard style sheets
@@ -1155,7 +1155,7 @@ HTML_STYLESHEET =
# list). For an example see the documentation.
# This tag requires that the tag GENERATE_HTML is set to YES.
-HTML_EXTRA_STYLESHEET =
+HTML_EXTRA_STYLESHEET =
# The HTML_EXTRA_FILES tag can be used to specify one or more extra images or
# other source files which should be copied to the HTML output directory. Note
@@ -1165,7 +1165,7 @@ HTML_EXTRA_STYLESHEET =
# files will be copied as-is; there are no commands or markers available.
# This tag requires that the tag GENERATE_HTML is set to YES.
-HTML_EXTRA_FILES =
+HTML_EXTRA_FILES =
# The HTML_COLORSTYLE_HUE tag controls the color of the HTML output. Doxygen
# will adjust the colors in the style sheet and background images according to
@@ -1293,7 +1293,7 @@ GENERATE_HTMLHELP = NO
# written to the html output directory.
# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
-CHM_FILE =
+CHM_FILE =
# The HHC_LOCATION tag can be used to specify the location (absolute path
# including file name) of the HTML help compiler (hhc.exe). If non-empty,
@@ -1301,7 +1301,7 @@ CHM_FILE =
# The file has to be specified with full path.
# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
-HHC_LOCATION =
+HHC_LOCATION =
# The GENERATE_CHI flag controls if a separate .chi index file is generated
# (YES) or that it should be included in the master .chm file (NO).
@@ -1314,7 +1314,7 @@ GENERATE_CHI = NO
# and project file content.
# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
-CHM_INDEX_ENCODING =
+CHM_INDEX_ENCODING =
# The BINARY_TOC flag controls whether a binary table of contents is generated
# (YES) or a normal table of contents (NO) in the .chm file. Furthermore it
@@ -1345,7 +1345,7 @@ GENERATE_QHP = NO
# the HTML output folder.
# This tag requires that the tag GENERATE_QHP is set to YES.
-QCH_FILE =
+QCH_FILE =
# The QHP_NAMESPACE tag specifies the namespace to use when generating Qt Help
# Project output. For more information please see Qt Help Project / Namespace
@@ -1370,7 +1370,7 @@ QHP_VIRTUAL_FOLDER = doc
# filters).
# This tag requires that the tag GENERATE_QHP is set to YES.
-QHP_CUST_FILTER_NAME =
+QHP_CUST_FILTER_NAME =
# The QHP_CUST_FILTER_ATTRS tag specifies the list of the attributes of the
# custom filter to add. For more information please see Qt Help Project / Custom
@@ -1378,21 +1378,21 @@ QHP_CUST_FILTER_NAME =
# filters).
# This tag requires that the tag GENERATE_QHP is set to YES.
-QHP_CUST_FILTER_ATTRS =
+QHP_CUST_FILTER_ATTRS =
# The QHP_SECT_FILTER_ATTRS tag specifies the list of the attributes this
# project's filter section matches. Qt Help Project / Filter Attributes (see:
# http://qt-project.org/doc/qt-4.8/qthelpproject.html#filter-attributes).
# This tag requires that the tag GENERATE_QHP is set to YES.
-QHP_SECT_FILTER_ATTRS =
+QHP_SECT_FILTER_ATTRS =
# The QHG_LOCATION tag can be used to specify the location of Qt's
# qhelpgenerator. If non-empty doxygen will try to run qhelpgenerator on the
# generated .qhp file.
# This tag requires that the tag GENERATE_QHP is set to YES.
-QHG_LOCATION =
+QHG_LOCATION =
# If the GENERATE_ECLIPSEHELP tag is set to YES, additional index files will be
# generated, together with the HTML files, they form an Eclipse help plugin. To
@@ -1525,7 +1525,7 @@ MATHJAX_RELPATH = http://cdn.mathjax.org/mathjax/latest
# MATHJAX_EXTENSIONS = TeX/AMSmath TeX/AMSsymbols
# This tag requires that the tag USE_MATHJAX is set to YES.
-MATHJAX_EXTENSIONS =
+MATHJAX_EXTENSIONS =
# The MATHJAX_CODEFILE tag can be used to specify a file with javascript pieces
# of code that will be used on startup of the MathJax code. See the MathJax site
@@ -1533,7 +1533,7 @@ MATHJAX_EXTENSIONS =
# example see the documentation.
# This tag requires that the tag USE_MATHJAX is set to YES.
-MATHJAX_CODEFILE =
+MATHJAX_CODEFILE =
# When the SEARCHENGINE tag is enabled doxygen will generate a search box for
# the HTML output. The underlying search engine uses javascript and DHTML and
@@ -1593,7 +1593,7 @@ EXTERNAL_SEARCH = NO
# Searching" for details.
# This tag requires that the tag SEARCHENGINE is set to YES.
-SEARCHENGINE_URL =
+SEARCHENGINE_URL =
# When SERVER_BASED_SEARCH and EXTERNAL_SEARCH are both enabled the unindexed
# search data is written to a file for indexing by an external tool. With the
@@ -1609,7 +1609,7 @@ SEARCHDATA_FILE = searchdata.xml
# projects and redirect the results back to the right project.
# This tag requires that the tag SEARCHENGINE is set to YES.
-EXTERNAL_SEARCH_ID =
+EXTERNAL_SEARCH_ID =
# The EXTRA_SEARCH_MAPPINGS tag can be used to enable searching through doxygen
# projects other than the one defined by this configuration file, but that are
@@ -1619,7 +1619,7 @@ EXTERNAL_SEARCH_ID =
# EXTRA_SEARCH_MAPPINGS = tagname1=loc1 tagname2=loc2 ...
# This tag requires that the tag SEARCHENGINE is set to YES.
-EXTRA_SEARCH_MAPPINGS =
+EXTRA_SEARCH_MAPPINGS =
#---------------------------------------------------------------------------
# Configuration options related to the LaTeX output
@@ -1680,7 +1680,7 @@ PAPER_TYPE = a4
# If left blank no extra packages will be included.
# This tag requires that the tag GENERATE_LATEX is set to YES.
-EXTRA_PACKAGES =
+EXTRA_PACKAGES =
# The LATEX_HEADER tag can be used to specify a personal LaTeX header for the
# generated LaTeX document. The header should contain everything until the first
@@ -1696,7 +1696,7 @@ EXTRA_PACKAGES =
# to HTML_HEADER.
# This tag requires that the tag GENERATE_LATEX is set to YES.
-LATEX_HEADER =
+LATEX_HEADER =
# The LATEX_FOOTER tag can be used to specify a personal LaTeX footer for the
# generated LaTeX document. The footer should contain everything after the last
@@ -1707,7 +1707,7 @@ LATEX_HEADER =
# Note: Only use a user-defined footer if you know what you are doing!
# This tag requires that the tag GENERATE_LATEX is set to YES.
-LATEX_FOOTER =
+LATEX_FOOTER =
# The LATEX_EXTRA_STYLESHEET tag can be used to specify additional user-defined
# LaTeX style sheets that are included after the standard style sheets created
@@ -1718,7 +1718,7 @@ LATEX_FOOTER =
# list).
# This tag requires that the tag GENERATE_LATEX is set to YES.
-LATEX_EXTRA_STYLESHEET =
+LATEX_EXTRA_STYLESHEET =
# The LATEX_EXTRA_FILES tag can be used to specify one or more extra images or
# other source files which should be copied to the LATEX_OUTPUT output
@@ -1726,7 +1726,7 @@ LATEX_EXTRA_STYLESHEET =
# markers available.
# This tag requires that the tag GENERATE_LATEX is set to YES.
-LATEX_EXTRA_FILES =
+LATEX_EXTRA_FILES =
# If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated is
# prepared for conversion to PDF (using ps2pdf or pdflatex). The PDF file will
@@ -1826,14 +1826,14 @@ RTF_HYPERLINKS = NO
# default style sheet that doxygen normally uses.
# This tag requires that the tag GENERATE_RTF is set to YES.
-RTF_STYLESHEET_FILE =
+RTF_STYLESHEET_FILE =
# Set optional variables used in the generation of an RTF document. Syntax is
# similar to doxygen's config file. A template extensions file can be generated
# using doxygen -e rtf extensionFile.
# This tag requires that the tag GENERATE_RTF is set to YES.
-RTF_EXTENSIONS_FILE =
+RTF_EXTENSIONS_FILE =
# If the RTF_SOURCE_CODE tag is set to YES then doxygen will include source code
# with syntax highlighting in the RTF output.
@@ -1878,7 +1878,7 @@ MAN_EXTENSION = .3
# MAN_EXTENSION with the initial . removed.
# This tag requires that the tag GENERATE_MAN is set to YES.
-MAN_SUBDIR =
+MAN_SUBDIR =
# If the MAN_LINKS tag is set to YES and doxygen generates man output, then it
# will generate one additional man file for each entity documented in the real
@@ -1991,7 +1991,7 @@ PERLMOD_PRETTY = YES
# overwrite each other's variables.
# This tag requires that the tag GENERATE_PERLMOD is set to YES.
-PERLMOD_MAKEVAR_PREFIX =
+PERLMOD_MAKEVAR_PREFIX =
#---------------------------------------------------------------------------
# Configuration options related to the preprocessor
@@ -2032,7 +2032,7 @@ SEARCH_INCLUDES = YES
# preprocessor.
# This tag requires that the tag SEARCH_INCLUDES is set to YES.
-INCLUDE_PATH =
+INCLUDE_PATH =
# You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard
# patterns (like *.h and *.hpp) to filter out the header-files in the
@@ -2040,7 +2040,7 @@ INCLUDE_PATH =
# used.
# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
-INCLUDE_FILE_PATTERNS =
+INCLUDE_FILE_PATTERNS =
# The PREDEFINED tag can be used to specify one or more macro names that are
# defined before the preprocessor is started (similar to the -D option of e.g.
@@ -2050,7 +2050,7 @@ INCLUDE_FILE_PATTERNS =
# recursively expanded use the := operator instead of the = operator.
# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
-PREDEFINED =
+PREDEFINED =
# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then this
# tag can be used to specify a list of macro names that should be expanded. The
@@ -2059,7 +2059,7 @@ PREDEFINED =
# definition found in the source code.
# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
-EXPAND_AS_DEFINED =
+EXPAND_AS_DEFINED =
# If the SKIP_FUNCTION_MACROS tag is set to YES then doxygen's preprocessor will
# remove all references to function-like macros that are alone on a line, have
@@ -2088,13 +2088,13 @@ SKIP_FUNCTION_MACROS = YES
# the path). If a tag file is not located in the directory in which doxygen is
# run, you must also specify the path to the tagfile here.
-TAGFILES =
+TAGFILES =
# When a file name is specified after GENERATE_TAGFILE, doxygen will create a
# tag file that is based on the input files it reads. See section "Linking to
# external documentation" for more information about the usage of tag files.
-GENERATE_TAGFILE =
+GENERATE_TAGFILE =
# If the ALLEXTERNALS tag is set to YES, all external class will be listed in
# the class index. If set to NO, only the inherited external classes will be
@@ -2143,14 +2143,14 @@ CLASS_DIAGRAMS = YES
# the mscgen tool resides. If left empty the tool is assumed to be found in the
# default search path.
-MSCGEN_PATH =
+MSCGEN_PATH =
# You can include diagrams made with dia in doxygen documentation. Doxygen will
# then run dia to produce the diagram and insert it in the documentation. The
# DIA_PATH tag allows you to specify the directory where the dia binary resides.
# If left empty dia is assumed to be found in the default search path.
-DIA_PATH =
+DIA_PATH =
# If set to YES the inheritance and collaboration graphs will hide inheritance
# and usage relations if the target is undocumented or is not a class.
@@ -2199,7 +2199,7 @@ DOT_FONTSIZE = 10
# the path where dot can find it using this tag.
# This tag requires that the tag HAVE_DOT is set to YES.
-DOT_FONTPATH =
+DOT_FONTPATH =
# If the CLASS_GRAPH tag is set to YES then doxygen will generate a graph for
# each documented class showing the direct and indirect inheritance relations.
@@ -2337,26 +2337,26 @@ INTERACTIVE_SVG = NO
# found. If left blank, it is assumed the dot tool can be found in the path.
# This tag requires that the tag HAVE_DOT is set to YES.
-DOT_PATH =
+DOT_PATH =
# The DOTFILE_DIRS tag can be used to specify one or more directories that
# contain dot files that are included in the documentation (see the \dotfile
# command).
# This tag requires that the tag HAVE_DOT is set to YES.
-DOTFILE_DIRS =
+DOTFILE_DIRS =
# The MSCFILE_DIRS tag can be used to specify one or more directories that
# contain msc files that are included in the documentation (see the \mscfile
# command).
-MSCFILE_DIRS =
+MSCFILE_DIRS =
# The DIAFILE_DIRS tag can be used to specify one or more directories that
# contain dia files that are included in the documentation (see the \diafile
# command).
-DIAFILE_DIRS =
+DIAFILE_DIRS =
# When using plantuml, the PLANTUML_JAR_PATH tag should be used to specify the
# path where java can find the plantuml.jar file. If left blank, it is assumed
@@ -2364,12 +2364,12 @@ DIAFILE_DIRS =
# generate a warning when it encounters a \startuml command in this case and
# will not generate output for the diagram.
-PLANTUML_JAR_PATH =
+PLANTUML_JAR_PATH =
# When using plantuml, the specified paths are searched for files specified by
# the !include statement in a plantuml block.
-PLANTUML_INCLUDE_PATH =
+PLANTUML_INCLUDE_PATH =
# The DOT_GRAPH_MAX_NODES tag can be used to set the maximum number of nodes
# that will be shown in the graph. If the number of nodes in a graph becomes
diff --git a/doc/classes/ARVRInterface.xml b/doc/classes/ARVRInterface.xml
index 413370ed0b..bf72902410 100644
--- a/doc/classes/ARVRInterface.xml
+++ b/doc/classes/ARVRInterface.xml
@@ -45,8 +45,8 @@
</return>
<description>
Call this to initialize this interface. The first interface that is initialized is identified as the primary interface and it will be used for rendering output.
- After initializing the interface you want to use you then need to enable the AR/VR mode of a viewport and rendering should commence.
- Note that you must enable the AR/VR mode on the main viewport for any device that uses the main output of Godot such as for mobile VR.
+ After initializing the interface you want to use you then need to enable the AR/VR mode of a viewport and rendering should commence.
+ Note that you must enable the AR/VR mode on the main viewport for any device that uses the main output of Godot such as for mobile VR.
If you do this for a platform that handles its own output (such as OpenVR) Godot will show just one eye without distortion on screen. Alternatively you can add a separate viewport node to your scene and enable AR/VR on that viewport and it will be used to output to the HMD leaving you free to do anything you like in the main window such as using a separate camera as a spectator camera or render out something completely different.
While currently not used you can activate additional interfaces, you may wish to do this if you want to track controllers from other platforms. However at this point in time only one interface can render to an HMD.
</description>
diff --git a/doc/classes/Animation.xml b/doc/classes/Animation.xml
index f189e6451d..169fbcd5a8 100644
--- a/doc/classes/Animation.xml
+++ b/doc/classes/Animation.xml
@@ -7,7 +7,7 @@
An Animation resource contains data used to animate everything in the engine. Animations are divided into tracks, and each track must be linked to a node. The state of that node can be changed through time, by adding timed keys (events) to the track.
[codeblock]
# This creates an animation that makes the node "Enemy" move to the right by
- # 100 pixels in 1 second.
+ # 100 pixels in 1 second.
var animation = Animation.new()
var track_index = animation.add_track(Animation.TYPE_VALUE)
animation.track_set_path(track_index, "Enemy:position.x")
diff --git a/doc/classes/AudioEffectReverb.xml b/doc/classes/AudioEffectReverb.xml
index fb2009105d..008c644466 100644
--- a/doc/classes/AudioEffectReverb.xml
+++ b/doc/classes/AudioEffectReverb.xml
@@ -15,7 +15,7 @@
</methods>
<members>
<member name="damping" type="float" setter="set_damping" getter="get_damping">
- Widens or narrows the stereo image of the reverb tail. 1 means fully widens. Value can range from 0 to 1. Default value: [code]1[/code].
+ Defines how reflective the imaginary room's walls are. Value can range from 0 to 1. Default value: [code]1[/code].
</member>
<member name="dry" type="float" setter="set_dry" getter="get_dry">
Output percent of original sound. At 0, only modified sound is outputted. Value can range from 0 to 1. Default value: [code]1[/code].
@@ -33,7 +33,7 @@
Dimensions of simulated room. Bigger means more echoes. Value can range from 0 to 1. Default value: [code]0.8[/code].
</member>
<member name="spread" type="float" setter="set_spread" getter="get_spread">
- Defines how reflective the imaginary room's walls are. Value can range from 0 to 1. Default value: [code]1[/code].
+ Widens or narrows the stereo image of the reverb tail. 1 means fully widens. Value can range from 0 to 1. Default value: [code]1[/code].
</member>
<member name="wet" type="float" setter="set_wet" getter="get_wet">
Output percent of modified sound. At 0, only original sound is outputted. Value can range from 0 to 1. Default value: [code]0.5[/code].
diff --git a/doc/classes/ConfigFile.xml b/doc/classes/ConfigFile.xml
index a4709c1c86..703043294b 100644
--- a/doc/classes/ConfigFile.xml
+++ b/doc/classes/ConfigFile.xml
@@ -25,6 +25,7 @@
# Save the changes by overwriting the previous file
config.save("user://settings.cfg")
[/codeblock]
+ Keep in mind that section and property names can't contain spaces. Anything after a space will be ignored on save and on load.
</description>
<tutorials>
</tutorials>
diff --git a/doc/classes/Dictionary.xml b/doc/classes/Dictionary.xml
index 06c996e13e..a9e2a38dcf 100644
--- a/doc/classes/Dictionary.xml
+++ b/doc/classes/Dictionary.xml
@@ -41,6 +41,17 @@
Erase a dictionary key/value pair by key.
</description>
</method>
+ <method name="get">
+ <return type="Variant">
+ </return>
+ <argument index="0" name="key" type="Variant">
+ </argument>
+ <argument index="1" name="default" type="Variant" default="Null">
+ </argument>
+ <description>
+ Returns the current value for the specified key in the [code]Dictionary[/code]. If the key does not exist, the method returns the value of the optional default argument, or Null if it is omitted.
+ </description>
+ </method>
<method name="has">
<return type="bool">
</return>
diff --git a/doc/classes/DynamicFontData.xml b/doc/classes/DynamicFontData.xml
index 7b34d02316..5fcccf7db9 100644
--- a/doc/classes/DynamicFontData.xml
+++ b/doc/classes/DynamicFontData.xml
@@ -13,6 +13,9 @@
<methods>
</methods>
<members>
+ <member name="antialiased" type="bool" setter="set_antialiased" getter="is_antialiased">
+ Controls whether the font should be rendered with anti-aliasing.
+ </member>
<member name="font_path" type="String" setter="set_font_path" getter="get_font_path">
The path to the vector font file.
</member>
diff --git a/doc/classes/Environment.xml b/doc/classes/Environment.xml
index 4c2c83e55f..949c93761e 100644
--- a/doc/classes/Environment.xml
+++ b/doc/classes/Environment.xml
@@ -5,7 +5,6 @@
</brief_description>
<description>
Resource for environment nodes (like [WorldEnvironment]) that define multiple environment operations (such as background [Sky] or [Color], ambient light, fog, depth-of-field...). These parameters affect the final render of the scene. The order of these operations is:
-
- DOF Blur
- Motion Blur
- Bloom
@@ -120,6 +119,8 @@
<member name="fog_depth_enabled" type="bool" setter="set_fog_depth_enabled" getter="is_fog_depth_enabled">
Enables the fog depth.
</member>
+ <member name="fog_depth_end" type="float" setter="set_fog_depth_end" getter="get_fog_depth_end">
+ </member>
<member name="fog_enabled" type="bool" setter="set_fog_enabled" getter="is_fog_enabled">
Enables the fog. Needs fog_height_enabled and/or for_depth_enabled to actually display fog.
</member>
diff --git a/doc/classes/File.xml b/doc/classes/File.xml
index 6c900385f7..058bb09090 100644
--- a/doc/classes/File.xml
+++ b/doc/classes/File.xml
@@ -100,7 +100,7 @@
<argument index="0" name="delim" type="String" default="&quot;,&quot;">
</argument>
<description>
- Returns the next value of the file in CSV (Comma Separated Values) format. You can pass a different delimiter to use other than the default "," (comma).
+ Returns the next value of the file in CSV (Comma Separated Values) format. You can pass a different delimiter to use other than the default "," (comma), it should be one character long.
</description>
</method>
<method name="get_double" qualifiers="const">
@@ -327,6 +327,17 @@
Stores the given array of bytes in the file.
</description>
</method>
+ <method name="store_csv_line">
+ <return type="void">
+ </return>
+ <argument index="0" name="values" type="PoolStringArray">
+ </argument>
+ <argument index="1" name="delim" type="String" default="&quot;,&quot;">
+ </argument>
+ <description>
+ Store the given [PoolStringArray] in the file as a line formatted in the CSV (Comma Separated Values) format. You can pass a different delimiter to use other than the default "," (comma), it should be one character long.
+ </description>
+ </method>
<method name="store_double">
<return type="void">
</return>
diff --git a/doc/classes/Generic6DOFJoint.xml b/doc/classes/Generic6DOFJoint.xml
index 0863ead4ec..e1046e282a 100644
--- a/doc/classes/Generic6DOFJoint.xml
+++ b/doc/classes/Generic6DOFJoint.xml
@@ -113,6 +113,30 @@
<member name="angular_motor_z/target_velocity" type="float" setter="set_param_z" getter="get_param_z">
Target speed for the motor at the z-axis.
</member>
+ <member name="angular_spring_x/damping" type="float" setter="set_param_x" getter="get_param_x">
+ </member>
+ <member name="angular_spring_x/enabled" type="bool" setter="set_flag_x" getter="get_flag_x">
+ </member>
+ <member name="angular_spring_x/equilibrium_point" type="float" setter="set_param_x" getter="get_param_x">
+ </member>
+ <member name="angular_spring_x/stiffness" type="float" setter="set_param_x" getter="get_param_x">
+ </member>
+ <member name="angular_spring_y/damping" type="float" setter="set_param_y" getter="get_param_y">
+ </member>
+ <member name="angular_spring_y/enabled" type="bool" setter="set_flag_y" getter="get_flag_y">
+ </member>
+ <member name="angular_spring_y/equilibrium_point" type="float" setter="set_param_y" getter="get_param_y">
+ </member>
+ <member name="angular_spring_y/stiffness" type="float" setter="set_param_y" getter="get_param_y">
+ </member>
+ <member name="angular_spring_z/damping" type="float" setter="set_param_z" getter="get_param_z">
+ </member>
+ <member name="angular_spring_z/enabled" type="bool" setter="set_flag_z" getter="get_flag_z">
+ </member>
+ <member name="angular_spring_z/equilibrium_point" type="float" setter="set_param_z" getter="get_param_z">
+ </member>
+ <member name="angular_spring_z/stiffness" type="float" setter="set_param_z" getter="get_param_z">
+ </member>
<member name="linear_limit_x/damping" type="float" setter="set_param_x" getter="get_param_x">
The amount of damping that happens at the x-motion.
</member>
@@ -194,6 +218,30 @@
<member name="linear_motor_z/target_velocity" type="float" setter="set_param_z" getter="get_param_z">
The speed that the linear motor will attempt to reach on the z-axis.
</member>
+ <member name="linear_spring_x/damping" type="float" setter="set_param_x" getter="get_param_x">
+ </member>
+ <member name="linear_spring_x/enabled" type="bool" setter="set_flag_x" getter="get_flag_x">
+ </member>
+ <member name="linear_spring_x/equilibrium_point" type="float" setter="set_param_x" getter="get_param_x">
+ </member>
+ <member name="linear_spring_x/stiffness" type="float" setter="set_param_x" getter="get_param_x">
+ </member>
+ <member name="linear_spring_y/damping" type="float" setter="set_param_y" getter="get_param_y">
+ </member>
+ <member name="linear_spring_y/enabled" type="bool" setter="set_flag_y" getter="get_flag_y">
+ </member>
+ <member name="linear_spring_y/equilibrium_point" type="float" setter="set_param_y" getter="get_param_y">
+ </member>
+ <member name="linear_spring_y/stiffness" type="float" setter="set_param_y" getter="get_param_y">
+ </member>
+ <member name="linear_spring_z/damping" type="float" setter="set_param_z" getter="get_param_z">
+ </member>
+ <member name="linear_spring_z/enabled" type="bool" setter="set_flag_z" getter="get_flag_z">
+ </member>
+ <member name="linear_spring_z/equilibrium_point" type="float" setter="set_param_z" getter="get_param_z">
+ </member>
+ <member name="linear_spring_z/stiffness" type="float" setter="set_param_z" getter="get_param_z">
+ </member>
</members>
<constants>
<constant name="PARAM_LINEAR_LOWER_LIMIT" value="0" enum="Param">
@@ -217,34 +265,34 @@
<constant name="PARAM_LINEAR_MOTOR_FORCE_LIMIT" value="6" enum="Param">
The maximum force the linear motor will apply while trying to reach the velocity target.
</constant>
- <constant name="PARAM_ANGULAR_LOWER_LIMIT" value="7" enum="Param">
+ <constant name="PARAM_ANGULAR_LOWER_LIMIT" value="10" enum="Param">
The minimum rotation in negative direction to break loose and rotate around the axes.
</constant>
- <constant name="PARAM_ANGULAR_UPPER_LIMIT" value="8" enum="Param">
+ <constant name="PARAM_ANGULAR_UPPER_LIMIT" value="11" enum="Param">
The minimum rotation in positive direction to break loose and rotate around the axes.
</constant>
- <constant name="PARAM_ANGULAR_LIMIT_SOFTNESS" value="9" enum="Param">
+ <constant name="PARAM_ANGULAR_LIMIT_SOFTNESS" value="12" enum="Param">
The speed of all rotations across the axes.
</constant>
- <constant name="PARAM_ANGULAR_DAMPING" value="10" enum="Param">
+ <constant name="PARAM_ANGULAR_DAMPING" value="13" enum="Param">
The amount of rotational damping across the axes. The lower, the more dampening occurs.
</constant>
- <constant name="PARAM_ANGULAR_RESTITUTION" value="11" enum="Param">
+ <constant name="PARAM_ANGULAR_RESTITUTION" value="14" enum="Param">
The amount of rotational restitution across the axes. The lower, the more restitution occurs.
</constant>
- <constant name="PARAM_ANGULAR_FORCE_LIMIT" value="12" enum="Param">
+ <constant name="PARAM_ANGULAR_FORCE_LIMIT" value="15" enum="Param">
The maximum amount of force that can occur, when rotating around the axes.
</constant>
- <constant name="PARAM_ANGULAR_ERP" value="13" enum="Param">
+ <constant name="PARAM_ANGULAR_ERP" value="16" enum="Param">
When rotating across the axes, this error tolerance factor defines how much the correction gets slowed down. The lower, the slower.
</constant>
- <constant name="PARAM_ANGULAR_MOTOR_TARGET_VELOCITY" value="14" enum="Param">
+ <constant name="PARAM_ANGULAR_MOTOR_TARGET_VELOCITY" value="17" enum="Param">
Target speed for the motor at the axes.
</constant>
- <constant name="PARAM_ANGULAR_MOTOR_FORCE_LIMIT" value="15" enum="Param">
+ <constant name="PARAM_ANGULAR_MOTOR_FORCE_LIMIT" value="18" enum="Param">
Maximum acceleration for the motor at the axes.
</constant>
- <constant name="PARAM_MAX" value="16" enum="Param">
+ <constant name="PARAM_MAX" value="22" enum="Param">
End flag of PARAM_* constants, used internally.
</constant>
<constant name="FLAG_ENABLE_LINEAR_LIMIT" value="0" enum="Flag">
@@ -253,12 +301,16 @@
<constant name="FLAG_ENABLE_ANGULAR_LIMIT" value="1" enum="Flag">
If [code]set[/code] there is rotational motion possible.
</constant>
- <constant name="FLAG_ENABLE_MOTOR" value="2" enum="Flag">
+ <constant name="FLAG_ENABLE_LINEAR_SPRING" value="3" enum="Flag">
+ </constant>
+ <constant name="FLAG_ENABLE_ANGULAR_SPRING" value="2" enum="Flag">
+ </constant>
+ <constant name="FLAG_ENABLE_MOTOR" value="4" enum="Flag">
If [code]set[/code] there is a rotational motor across these axes.
</constant>
- <constant name="FLAG_ENABLE_LINEAR_MOTOR" value="3" enum="Flag">
+ <constant name="FLAG_ENABLE_LINEAR_MOTOR" value="5" enum="Flag">
</constant>
- <constant name="FLAG_MAX" value="4" enum="Flag">
+ <constant name="FLAG_MAX" value="6" enum="Flag">
End flag of FLAG_* constants, used internally.
</constant>
</constants>
diff --git a/doc/classes/Input.xml b/doc/classes/Input.xml
index bf395ee513..724e6a078d 100644
--- a/doc/classes/Input.xml
+++ b/doc/classes/Input.xml
@@ -17,10 +17,11 @@
</return>
<argument index="0" name="action" type="String">
</argument>
- <argument index="1" name="strength" type="float">
+ <argument index="1" name="strength" type="float" default="1.0">
</argument>
<description>
- This will simulate pressing the specified action. The strength can be used for non-boolean actions.
+ This will simulate pressing the specified action.
+ The strength can be used for non-boolean actions, it's ranged between 0 and 1 representing the intensity of the given action.
</description>
</method>
<method name="action_release">
diff --git a/doc/classes/Object.xml b/doc/classes/Object.xml
index fcd105d66b..86de830d56 100644
--- a/doc/classes/Object.xml
+++ b/doc/classes/Object.xml
@@ -348,6 +348,16 @@
If set to true, signal emission is blocked.
</description>
</method>
+ <method name="set_deferred">
+ <return type="void">
+ </return>
+ <argument index="0" name="property" type="String">
+ </argument>
+ <argument index="1" name="value" type="Variant">
+ </argument>
+ <description>
+ </description>
+ </method>
<method name="set_indexed">
<return type="void">
</return>
diff --git a/doc/classes/OrientedPathFollow.xml b/doc/classes/OrientedPathFollow.xml
index 85d60936ad..bc6af4711b 100644
--- a/doc/classes/OrientedPathFollow.xml
+++ b/doc/classes/OrientedPathFollow.xml
@@ -4,7 +4,7 @@
Oriented point sampler for a [Path].
</brief_description>
<description>
- This node behaves like [PathFollow], except it uses its parent [Path] up vector information to enforce orientation.
+ This node behaves like [PathFollow], except it uses its parent [Path] up vector information to enforce orientation.
Make sure to check if the curve of this node's parent [Path] has up vectors enabled. See [PathFollow] and [Curve3D] for further information.
</description>
<tutorials>
diff --git a/doc/classes/PHashTranslation.xml b/doc/classes/PHashTranslation.xml
index 18c72a0576..e5745375b0 100644
--- a/doc/classes/PHashTranslation.xml
+++ b/doc/classes/PHashTranslation.xml
@@ -17,6 +17,7 @@
<argument index="0" name="from" type="Translation">
</argument>
<description>
+ Generates and sets an optimized translation from the given [Translation] resource.
</description>
</method>
</methods>
diff --git a/doc/classes/PhysicsServer.xml b/doc/classes/PhysicsServer.xml
index c836414dd2..7dfc8e66d4 100644
--- a/doc/classes/PhysicsServer.xml
+++ b/doc/classes/PhysicsServer.xml
@@ -1401,31 +1401,31 @@
<constant name="G6DOF_JOINT_LINEAR_MOTOR_FORCE_LIMIT" value="6" enum="G6DOFJointAxisParam">
The maximum force that the linear motor can apply while trying to reach the target velocity.
</constant>
- <constant name="G6DOF_JOINT_ANGULAR_LOWER_LIMIT" value="7" enum="G6DOFJointAxisParam">
+ <constant name="G6DOF_JOINT_ANGULAR_LOWER_LIMIT" value="10" enum="G6DOFJointAxisParam">
The minimum rotation in negative direction to break loose and rotate around the axes.
</constant>
- <constant name="G6DOF_JOINT_ANGULAR_UPPER_LIMIT" value="8" enum="G6DOFJointAxisParam">
+ <constant name="G6DOF_JOINT_ANGULAR_UPPER_LIMIT" value="11" enum="G6DOFJointAxisParam">
The minimum rotation in positive direction to break loose and rotate around the axes.
</constant>
- <constant name="G6DOF_JOINT_ANGULAR_LIMIT_SOFTNESS" value="9" enum="G6DOFJointAxisParam">
+ <constant name="G6DOF_JOINT_ANGULAR_LIMIT_SOFTNESS" value="12" enum="G6DOFJointAxisParam">
A factor that gets multiplied onto all rotations across the axes.
</constant>
- <constant name="G6DOF_JOINT_ANGULAR_DAMPING" value="10" enum="G6DOFJointAxisParam">
+ <constant name="G6DOF_JOINT_ANGULAR_DAMPING" value="13" enum="G6DOFJointAxisParam">
The amount of rotational damping across the axes. The lower, the more dampening occurs.
</constant>
- <constant name="G6DOF_JOINT_ANGULAR_RESTITUTION" value="11" enum="G6DOFJointAxisParam">
+ <constant name="G6DOF_JOINT_ANGULAR_RESTITUTION" value="14" enum="G6DOFJointAxisParam">
The amount of rotational restitution across the axes. The lower, the more restitution occurs.
</constant>
- <constant name="G6DOF_JOINT_ANGULAR_FORCE_LIMIT" value="12" enum="G6DOFJointAxisParam">
+ <constant name="G6DOF_JOINT_ANGULAR_FORCE_LIMIT" value="15" enum="G6DOFJointAxisParam">
The maximum amount of force that can occur, when rotating around the axes.
</constant>
- <constant name="G6DOF_JOINT_ANGULAR_ERP" value="13" enum="G6DOFJointAxisParam">
+ <constant name="G6DOF_JOINT_ANGULAR_ERP" value="16" enum="G6DOFJointAxisParam">
When correcting the crossing of limits in rotation across the axes, this error tolerance factor defines how much the correction gets slowed down. The lower, the slower.
</constant>
- <constant name="G6DOF_JOINT_ANGULAR_MOTOR_TARGET_VELOCITY" value="14" enum="G6DOFJointAxisParam">
+ <constant name="G6DOF_JOINT_ANGULAR_MOTOR_TARGET_VELOCITY" value="17" enum="G6DOFJointAxisParam">
Target speed for the motor at the axes.
</constant>
- <constant name="G6DOF_JOINT_ANGULAR_MOTOR_FORCE_LIMIT" value="15" enum="G6DOFJointAxisParam">
+ <constant name="G6DOF_JOINT_ANGULAR_MOTOR_FORCE_LIMIT" value="18" enum="G6DOFJointAxisParam">
Maximum acceleration for the motor at the axes.
</constant>
<constant name="G6DOF_JOINT_FLAG_ENABLE_LINEAR_LIMIT" value="0" enum="G6DOFJointAxisFlag">
@@ -1434,10 +1434,10 @@
<constant name="G6DOF_JOINT_FLAG_ENABLE_ANGULAR_LIMIT" value="1" enum="G6DOFJointAxisFlag">
If [code]set[/code] there is rotational motion possible.
</constant>
- <constant name="G6DOF_JOINT_FLAG_ENABLE_MOTOR" value="2" enum="G6DOFJointAxisFlag">
+ <constant name="G6DOF_JOINT_FLAG_ENABLE_MOTOR" value="4" enum="G6DOFJointAxisFlag">
If [code]set[/code] there is a rotational motor across these axes.
</constant>
- <constant name="G6DOF_JOINT_FLAG_ENABLE_LINEAR_MOTOR" value="3" enum="G6DOFJointAxisFlag">
+ <constant name="G6DOF_JOINT_FLAG_ENABLE_LINEAR_MOTOR" value="5" enum="G6DOFJointAxisFlag">
If [code]set[/code] there is a linear motor on this axis that targets a specific velocity.
</constant>
<constant name="SHAPE_PLANE" value="0" enum="ShapeType">
diff --git a/doc/classes/SpatialMaterial.xml b/doc/classes/SpatialMaterial.xml
index 392a550ee4..3503505999 100644
--- a/doc/classes/SpatialMaterial.xml
+++ b/doc/classes/SpatialMaterial.xml
@@ -52,6 +52,10 @@
<member name="depth_enabled" type="bool" setter="set_feature" getter="get_feature">
If [code]true[/code] Depth mapping is enabled. See also [member normal_enabled].
</member>
+ <member name="depth_flip_binormal" type="bool" setter="set_depth_deep_parallax_flip_binormal" getter="get_depth_deep_parallax_flip_binormal">
+ </member>
+ <member name="depth_flip_tangent" type="bool" setter="set_depth_deep_parallax_flip_tangent" getter="get_depth_deep_parallax_flip_tangent">
+ </member>
<member name="depth_max_layers" type="int" setter="set_depth_deep_parallax_max_layers" getter="get_depth_deep_parallax_max_layers">
</member>
<member name="depth_min_layers" type="int" setter="set_depth_deep_parallax_min_layers" getter="get_depth_deep_parallax_min_layers">
diff --git a/doc/classes/StyleBoxFlat.xml b/doc/classes/StyleBoxFlat.xml
index 641d6214a4..bf544d2b78 100644
--- a/doc/classes/StyleBoxFlat.xml
+++ b/doc/classes/StyleBoxFlat.xml
@@ -5,22 +5,21 @@
</brief_description>
<description>
This stylebox can be used to achieve all kinds of looks without the need of a texture. Those properties are customizable:
- - Color
- - Border width (individual width for each border)
- - Rounded corners (individual radius for each corner)
- - Shadow
- About corner radius:
- Setting corner radius to high values is allowed. As soon as corners would overlap the stylebox will switch to a relative system. Example:
- [codeblock]
- height = 30
- corner_radius_top_left = 50
- corner_radius_bottom_left = 100
- [/codeblock]
- The relative system now would take the 1:2 ratio of the two left corners to calculate the actual corner width. Both corners added will [b]never[/b] be more than the height. Result:
- [codeblock]
- corner_radius_top_left: 10
- corner_radius_bottom_left: 20
- [/codeblock]
+ - Color
+ - Border width (individual width for each border)
+ - Rounded corners (individual radius for each corner)
+ - Shadow
+ Setting corner radius to high values is allowed. As soon as corners would overlap the stylebox will switch to a relative system. Example:
+ [codeblock]
+ height = 30
+ corner_radius_top_left = 50
+ corner_radius_bottom_left = 100
+ [/codeblock]
+ The relative system now would take the 1:2 ratio of the two left corners to calculate the actual corner width. Both corners added will [b]never[/b] be more than the height. Result:
+ [codeblock]
+ corner_radius_top_left: 10
+ corner_radius_bottom_left: 20
+ [/codeblock]
</description>
<tutorials>
</tutorials>
@@ -117,7 +116,7 @@
<member name="corner_detail" type="int" setter="set_corner_detail" getter="get_corner_detail">
This sets the amount of vertices used for each corner. Higher values result in rounder corners but take more processing power to compute. When choosing a value you should take the corner radius ([method set_corner_radius]) into account.
For corner radius smaller than 10: 4-5 should be enough
- For corner radius smaller than 30: 8-12 should be enough ...
+ For corner radius smaller than 30: 8-12 should be enough
</member>
<member name="corner_radius_bottom_left" type="int" setter="set_corner_radius" getter="get_corner_radius">
The corner radius of the bottom left corner. When set to 0 the corner is not rounded.
diff --git a/doc/classes/Translation.xml b/doc/classes/Translation.xml
index c4e9dbfb70..b57f8f3556 100644
--- a/doc/classes/Translation.xml
+++ b/doc/classes/Translation.xml
@@ -7,6 +7,8 @@
Translations are resources that can be loaded/unloaded on demand. They map a string to another string.
</description>
<tutorials>
+ <link>https://docs.godotengine.org/en/stable/tutorials/i18n/internationalizing_games.html</link>
+ <link>https://docs.godotengine.org/en/stable/tutorials/i18n/locales.html</link>
</tutorials>
<demos>
</demos>
@@ -19,7 +21,7 @@
<argument index="1" name="xlated_message" type="String">
</argument>
<description>
- Add a message for translation.
+ Adds a message if nonexistent, followed by its translation.
</description>
</method>
<method name="erase_message">
@@ -28,7 +30,7 @@
<argument index="0" name="src_message" type="String">
</argument>
<description>
- Erase a message.
+ Erases a message.
</description>
</method>
<method name="get_message" qualifiers="const">
@@ -37,25 +39,27 @@
<argument index="0" name="src_message" type="String">
</argument>
<description>
- Return a message for translation.
+ Returns a message's translation.
</description>
</method>
<method name="get_message_count" qualifiers="const">
<return type="int">
</return>
<description>
+ Returns the number of existing messages.
</description>
</method>
<method name="get_message_list" qualifiers="const">
<return type="PoolStringArray">
</return>
<description>
- Return all the messages (keys).
+ Returns all the messages (keys).
</description>
</method>
</methods>
<members>
<member name="locale" type="String" setter="set_locale" getter="get_locale">
+ The locale of the translation.
</member>
</members>
<constants>
diff --git a/doc/classes/TranslationServer.xml b/doc/classes/TranslationServer.xml
index 52d2b2cc47..c2c400ccd5 100644
--- a/doc/classes/TranslationServer.xml
+++ b/doc/classes/TranslationServer.xml
@@ -1,11 +1,14 @@
<?xml version="1.0" encoding="UTF-8" ?>
<class name="TranslationServer" inherits="Object" category="Core" version="3.1">
<brief_description>
- Server that manages all translations. Translations can be set to it and removed from it.
+ Server that manages all translations.
</brief_description>
<description>
+ Server that manages all translations. Translations can be set to it and removed from it.
</description>
<tutorials>
+ <link>https://docs.godotengine.org/en/stable/tutorials/i18n/internationalizing_games.html</link>
+ <link>https://docs.godotengine.org/en/stable/tutorials/i18n/locales.html</link>
</tutorials>
<demos>
</demos>
@@ -16,18 +19,21 @@
<argument index="0" name="translation" type="Translation">
</argument>
<description>
+ Adds a [Translation] resource.
</description>
</method>
<method name="clear">
<return type="void">
</return>
<description>
+ Clears the server from all translations.
</description>
</method>
<method name="get_locale" qualifiers="const">
<return type="String">
</return>
<description>
+ Returns the current locale of the game.
</description>
</method>
<method name="get_locale_name" qualifiers="const">
@@ -36,6 +42,7 @@
<argument index="0" name="locale" type="String">
</argument>
<description>
+ Returns a locale's language and its variant (e.g. "en_US" would return "English (United States)").
</description>
</method>
<method name="remove_translation">
@@ -44,6 +51,7 @@
<argument index="0" name="translation" type="Translation">
</argument>
<description>
+ Removes the given translation from the server.
</description>
</method>
<method name="set_locale">
@@ -52,6 +60,7 @@
<argument index="0" name="locale" type="String">
</argument>
<description>
+ Sets the locale of the game.
</description>
</method>
<method name="translate" qualifiers="const">
@@ -60,6 +69,7 @@
<argument index="0" name="message" type="String">
</argument>
<description>
+ Returns the current locale's translation for the given message (key).
</description>
</method>
</methods>
diff --git a/doc/classes/Tree.xml b/doc/classes/Tree.xml
index 8051062fc4..14be256d85 100644
--- a/doc/classes/Tree.xml
+++ b/doc/classes/Tree.xml
@@ -384,6 +384,8 @@
</theme_item>
<theme_item name="custom_button_pressed" type="StyleBox">
</theme_item>
+ <theme_item name="draw_guides" type="int">
+ </theme_item>
<theme_item name="draw_relationship_lines" type="int">
</theme_item>
<theme_item name="drop_position_color" type="Color">
diff --git a/doc/classes/UndoRedo.xml b/doc/classes/UndoRedo.xml
index 0ea5c6e005..93806ac326 100644
--- a/doc/classes/UndoRedo.xml
+++ b/doc/classes/UndoRedo.xml
@@ -102,8 +102,11 @@
<method name="clear_history">
<return type="void">
</return>
+ <argument index="0" name="increase_version" type="bool" default="true">
+ </argument>
<description>
Clear the undo/redo history and associated references.
+ Passing [code]false[/code] to [code]increase_version[/code] will prevent the version number to be increased from this.
</description>
</method>
<method name="commit_action">
diff --git a/doc/classes/Viewport.xml b/doc/classes/Viewport.xml
index 2cdd8c407f..4706651c6e 100644
--- a/doc/classes/Viewport.xml
+++ b/doc/classes/Viewport.xml
@@ -125,6 +125,12 @@
<description>
</description>
</method>
+ <method name="is_input_handled" qualifiers="const">
+ <return type="bool">
+ </return>
+ <description>
+ </description>
+ </method>
<method name="is_size_override_enabled" qualifiers="const">
<return type="bool">
</return>
@@ -147,6 +153,12 @@
<description>
</description>
</method>
+ <method name="set_input_as_handled">
+ <return type="void">
+ </return>
+ <description>
+ </description>
+ </method>
<method name="set_size_override">
<return type="void">
</return>
@@ -222,6 +234,8 @@
<member name="gui_snap_controls_to_pixels" type="bool" setter="set_snap_controls_to_pixels" getter="is_snap_controls_to_pixels_enabled">
If [code]true[/code] the GUI controls on the viewport will lay pixel perfectly. Default value: [code]true[/code].
</member>
+ <member name="handle_input_locally" type="bool" setter="set_handle_input_locally" getter="is_handling_input_locally">
+ </member>
<member name="hdr" type="bool" setter="set_hdr" getter="get_hdr">
If [code]true[/code] the viewport rendering will receive benefits from High Dynamic Range algorithm. Default value: [code]true[/code].
</member>
diff --git a/doc/classes/VisualServer.xml b/doc/classes/VisualServer.xml
index 46a06d63d4..b24eeaa112 100644
--- a/doc/classes/VisualServer.xml
+++ b/doc/classes/VisualServer.xml
@@ -1113,11 +1113,13 @@
</argument>
<argument index="2" name="depth_begin" type="float">
</argument>
- <argument index="3" name="depth_curve" type="float">
+ <argument index="3" name="depth_end" type="float">
</argument>
- <argument index="4" name="transmit" type="bool">
+ <argument index="4" name="depth_curve" type="float">
</argument>
- <argument index="5" name="transmit_curve" type="float">
+ <argument index="5" name="transmit" type="bool">
+ </argument>
+ <argument index="6" name="transmit_curve" type="float">
</argument>
<description>
</description>
diff --git a/drivers/dummy/rasterizer_dummy.h b/drivers/dummy/rasterizer_dummy.h
index bd3a36feef..7c095e3798 100644
--- a/drivers/dummy/rasterizer_dummy.h
+++ b/drivers/dummy/rasterizer_dummy.h
@@ -681,6 +681,8 @@ public:
int particles_get_draw_passes(RID p_particles) const { return 0; }
RID particles_get_draw_pass_mesh(RID p_particles, int p_pass) const { return RID(); }
+ virtual bool particles_is_inactive(RID p_particles) const { return false; }
+
/* RENDER TARGET */
RID render_target_create() { return RID(); }
diff --git a/drivers/gles2/rasterizer_scene_gles2.cpp b/drivers/gles2/rasterizer_scene_gles2.cpp
index 64fe385889..6eafdb0e1c 100644
--- a/drivers/gles2/rasterizer_scene_gles2.cpp
+++ b/drivers/gles2/rasterizer_scene_gles2.cpp
@@ -605,7 +605,6 @@ bool RasterizerSceneGLES2::reflection_probe_instance_postprocess_step(RID p_inst
size >>= 1;
int mipmaps = 6;
- int mm_level = mipmaps - 1;
storage->shaders.cubemap_filter.set_conditional(CubemapFilterShaderGLES2::USE_SOURCE_PANORAMA, false);
storage->shaders.cubemap_filter.bind();
@@ -628,8 +627,6 @@ bool RasterizerSceneGLES2::reflection_probe_instance_postprocess_step(RID p_inst
size >>= 1;
- mm_level--;
-
lod++;
}
@@ -2339,7 +2336,6 @@ void RasterizerSceneGLES2::_render_render_list(RenderList::Element **p_elements,
state.scene_shader.set_uniform(SceneShaderGLES2::TIME, storage->frame.time[0]);
state.scene_shader.set_uniform(SceneShaderGLES2::SCREEN_PIXEL_SIZE, screen_pixel_size);
- state.scene_shader.set_uniform(SceneShaderGLES2::NORMAL_MULT, 1.0); // TODO mirror?
}
if (rebind_light && light) {
@@ -2498,6 +2494,7 @@ void RasterizerSceneGLES2::render_scene(const Transform &p_cam_transform, const
Environment *env = NULL;
int viewport_width, viewport_height;
+ bool probe_interior = false;
if (p_reflection_probe.is_valid()) {
ReflectionProbeInstance *probe = reflection_probe_instance_owner.getornull(p_reflection_probe);
@@ -2515,6 +2512,8 @@ void RasterizerSceneGLES2::render_scene(const Transform &p_cam_transform, const
viewport_width = probe->probe_ptr->resolution;
viewport_height = probe->probe_ptr->resolution;
+ probe_interior = probe->probe_ptr->interior;
+
} else {
state.render_no_shadows = false;
current_fb = storage->frame.current_rt->fbo;
@@ -2625,6 +2624,10 @@ void RasterizerSceneGLES2::render_scene(const Transform &p_cam_transform, const
}
}
+ if (probe_interior) {
+ env_radiance_tex = 0; //do not use radiance texture on interiors
+ }
+
// render opaque things first
render_list.sort_by_key(false);
_render_render_list(render_list.elements, render_list.element_count, p_cam_transform, p_cam_projection, p_shadow_atlas, env, env_radiance_tex, 0.0, 0.0, false, false, false);
diff --git a/drivers/gles2/rasterizer_storage_gles2.cpp b/drivers/gles2/rasterizer_storage_gles2.cpp
index 060988fbea..3beb8eac33 100644
--- a/drivers/gles2/rasterizer_storage_gles2.cpp
+++ b/drivers/gles2/rasterizer_storage_gles2.cpp
@@ -1497,8 +1497,9 @@ Variant RasterizerStorageGLES2::material_get_param_default(RID p_material, const
if (material->shader) {
if (material->shader->uniforms.has(p_param)) {
- Vector<ShaderLanguage::ConstantNode::Value> default_value = material->shader->uniforms[p_param].default_value;
- return ShaderLanguage::constant_value_to_variant(default_value, material->shader->uniforms[p_param].type);
+ ShaderLanguage::ShaderNode::Uniform uniform = material->shader->uniforms[p_param];
+ Vector<ShaderLanguage::ConstantNode::Value> default_value = uniform.default_value;
+ return ShaderLanguage::constant_value_to_variant(default_value, uniform.type, uniform.hint);
}
}
return Variant();
@@ -3841,6 +3842,10 @@ RID RasterizerStorageGLES2::particles_get_draw_pass_mesh(RID p_particles, int p_
void RasterizerStorageGLES2::update_particles() {
}
+bool RasterizerStorageGLES2::particles_is_inactive(RID p_particles) const {
+ return true;
+}
+
////////
void RasterizerStorageGLES2::instance_add_skeleton(RID p_skeleton, RasterizerScene::InstanceBase *p_instance) {
diff --git a/drivers/gles2/rasterizer_storage_gles2.h b/drivers/gles2/rasterizer_storage_gles2.h
index 59f911e880..5bdc65a0b5 100644
--- a/drivers/gles2/rasterizer_storage_gles2.h
+++ b/drivers/gles2/rasterizer_storage_gles2.h
@@ -1090,6 +1090,8 @@ public:
virtual int particles_get_draw_passes(RID p_particles) const;
virtual RID particles_get_draw_pass_mesh(RID p_particles, int p_pass) const;
+ virtual bool particles_is_inactive(RID p_particles) const;
+
/* INSTANCE */
virtual void instance_add_skeleton(RID p_skeleton, RasterizerScene::InstanceBase *p_instance);
diff --git a/drivers/gles2/shader_compiler_gles2.cpp b/drivers/gles2/shader_compiler_gles2.cpp
index 28c0274afa..d52be09cac 100644
--- a/drivers/gles2/shader_compiler_gles2.cpp
+++ b/drivers/gles2/shader_compiler_gles2.cpp
@@ -86,10 +86,11 @@ static String _mkid(const String &p_id) {
static String f2sp0(float p_float) {
- if (int(p_float) == p_float)
- return itos(p_float) + ".0";
- else
- return rtoss(p_float);
+ String num = rtoss(p_float);
+ if (num.find(".") == -1 && num.find("e") == -1) {
+ num += ".0";
+ }
+ return num;
}
static String get_constant_text(SL::DataType p_type, const Vector<SL::ConstantNode::Value> &p_values) {
diff --git a/drivers/gles2/shaders/scene.glsl b/drivers/gles2/shaders/scene.glsl
index 4c652cd9e9..bc83b69b49 100644
--- a/drivers/gles2/shaders/scene.glsl
+++ b/drivers/gles2/shaders/scene.glsl
@@ -84,7 +84,7 @@ uniform highp mat4 world_transform;
uniform highp float time;
-uniform float normal_mult;
+
#ifdef RENDER_DEPTH
uniform float light_bias;
@@ -330,11 +330,10 @@ void main() {
#endif
- vec3 normal = normal_attrib * normal_mult;
+ vec3 normal = normal_attrib;
#if defined(ENABLE_TANGENT_INTERP) || defined(ENABLE_NORMALMAP)
vec3 tangent = tangent_attrib.xyz;
- tangent *= normal_mult;
float binormalf = tangent_attrib.a;
vec3 binormal = normalize(cross(normal, tangent) * binormalf);
#endif
diff --git a/drivers/gles3/rasterizer_canvas_gles3.cpp b/drivers/gles3/rasterizer_canvas_gles3.cpp
index 6e7ecee007..4166cb8361 100644
--- a/drivers/gles3/rasterizer_canvas_gles3.cpp
+++ b/drivers/gles3/rasterizer_canvas_gles3.cpp
@@ -213,12 +213,12 @@ RasterizerStorageGLES3::Texture *RasterizerCanvasGLES3::_bind_canvas_texture(con
} else {
+ texture = texture->get_ptr();
+
if (texture->redraw_if_visible) { //check before proxy, because this is usually used with proxies
VisualServerRaster::redraw_request();
}
- texture = texture->get_ptr();
-
if (texture->render_target)
texture->render_target->used_in_frame = true;
@@ -254,11 +254,12 @@ RasterizerStorageGLES3::Texture *RasterizerCanvasGLES3::_bind_canvas_texture(con
} else {
+ normal_map = normal_map->get_ptr();
+
if (normal_map->redraw_if_visible) { //check before proxy, because this is usually used with proxies
VisualServerRaster::redraw_request();
}
- normal_map = normal_map->get_ptr();
glActiveTexture(GL_TEXTURE1);
glBindTexture(GL_TEXTURE_2D, normal_map->tex_id);
state.current_normal = p_normal_map;
@@ -1220,8 +1221,6 @@ void RasterizerCanvasGLES3::canvas_render_items(Item *p_item_list, int p_z, cons
bool rebind_shader = true;
- state.canvas_shader.set_conditional(CanvasShaderGLES3::USE_DISTANCE_FIELD, false);
-
glBindBuffer(GL_UNIFORM_BUFFER, state.canvas_item_ubo);
glBufferData(GL_UNIFORM_BUFFER, sizeof(CanvasItemUBO), &state.canvas_item_ubo_data, GL_DYNAMIC_DRAW);
glBindBuffer(GL_UNIFORM_BUFFER, 0);
@@ -1339,7 +1338,7 @@ void RasterizerCanvasGLES3::canvas_render_items(Item *p_item_list, int p_z, cons
last_blend_mode = last_blend_mode != RasterizerStorageGLES3::Shader::CanvasItem::BLEND_MODE_DISABLED ? last_blend_mode : -1;
}
- if (shader_ptr != shader_cache) {
+ if (shader_ptr != shader_cache || rebind_shader) {
if (shader_ptr->canvas_item.uses_time) {
VisualServerRaster::redraw_request();
@@ -1385,12 +1384,12 @@ void RasterizerCanvasGLES3::canvas_render_items(Item *p_item_list, int p_z, cons
continue;
}
+ t = t->get_ptr();
+
if (t->redraw_if_visible) { //check before proxy, because this is usually used with proxies
VisualServerRaster::redraw_request();
}
- t = t->get_ptr();
-
if (storage->config.srgb_decode_supported && t->using_srgb) {
//no srgb in 2D
glTexParameteri(t->target, _TEXTURE_SRGB_DECODE_EXT, _SKIP_DECODE_EXT);
@@ -1656,6 +1655,14 @@ void RasterizerCanvasGLES3::canvas_render_items(Item *p_item_list, int p_z, cons
if (current_clip) {
glDisable(GL_SCISSOR_TEST);
}
+ //disable states that may have been used
+ state.canvas_shader.set_conditional(CanvasShaderGLES3::USE_DISTANCE_FIELD, false);
+ state.canvas_shader.set_conditional(CanvasShaderGLES3::USE_SKELETON, false);
+ state.canvas_shader.set_conditional(CanvasShaderGLES3::USE_INSTANCE_CUSTOM, false);
+ state.canvas_shader.set_conditional(CanvasShaderGLES3::USE_PARTICLES, false);
+ state.canvas_shader.set_conditional(CanvasShaderGLES3::USE_INSTANCING, false);
+ state.canvas_shader.set_conditional(CanvasShaderGLES3::USE_LIGHTING, false);
+ state.canvas_shader.set_conditional(CanvasShaderGLES3::USE_SHADOWS, false);
}
void RasterizerCanvasGLES3::canvas_debug_viewport_shadows(Light *p_lights_with_shadow) {
diff --git a/drivers/gles3/rasterizer_scene_gles3.cpp b/drivers/gles3/rasterizer_scene_gles3.cpp
index 8d0e438ec5..e0c8d3af52 100644
--- a/drivers/gles3/rasterizer_scene_gles3.cpp
+++ b/drivers/gles3/rasterizer_scene_gles3.cpp
@@ -1190,11 +1190,12 @@ bool RasterizerSceneGLES3::_setup_material(RasterizerStorageGLES3::Material *p_m
if (t) {
+ t = t->get_ptr(); //resolve for proxies
+
if (t->redraw_if_visible) { //must check before proxy because this is often used with proxies
VisualServerRaster::redraw_request();
}
- t = t->get_ptr(); //resolve for proxies
#ifdef TOOLS_ENABLED
if (t->detect_3d) {
t->detect_3d(t->detect_3d_ud);
@@ -2222,7 +2223,6 @@ void RasterizerSceneGLES3::_render_list(RenderList::Element **p_elements, int p_
_set_cull(e->sort_key & RenderList::SORT_KEY_MIRROR_FLAG, e->sort_key & RenderList::SORT_KEY_CULL_DISABLED_FLAG, p_reverse_cull);
- state.scene_shader.set_uniform(SceneShaderGLES3::NORMAL_MULT, e->instance->mirror ? -1.0 : 1.0);
state.scene_shader.set_uniform(SceneShaderGLES3::WORLD_TRANSFORM, e->instance->transform);
_render_geometry(e);
@@ -3039,20 +3039,17 @@ void RasterizerSceneGLES3::_setup_reflections(RID *p_reflection_probe_cull_resul
reflection_ubo.ambient[3] = rpi->probe_ptr->interior_ambient_probe_contrib;
} else {
Color ambient_linear;
- // FIXME: contrib was retrieved but never used, is it meant to be set as ambient[3]? (GH-20361)
- //float contrib = 0;
if (p_env) {
ambient_linear = p_env->ambient_color.to_linear();
ambient_linear.r *= p_env->ambient_energy;
ambient_linear.g *= p_env->ambient_energy;
ambient_linear.b *= p_env->ambient_energy;
- //contrib = p_env->ambient_sky_contribution;
}
reflection_ubo.ambient[0] = ambient_linear.r;
reflection_ubo.ambient[1] = ambient_linear.g;
reflection_ubo.ambient[2] = ambient_linear.b;
- reflection_ubo.ambient[3] = 0;
+ reflection_ubo.ambient[3] = 0; //not used in exterior mode, since it just blends with regular ambient light
}
int cell_size = reflection_atlas->size / reflection_atlas->subdiv;
@@ -3599,7 +3596,7 @@ void RasterizerSceneGLES3::_post_process(Environment *env, const CameraMatrix &p
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
}
- if (!env || storage->frame.current_rt->flags[RasterizerStorage::RENDER_TARGET_TRANSPARENT]) {
+ if (!env || storage->frame.current_rt->flags[RasterizerStorage::RENDER_TARGET_TRANSPARENT] || storage->frame.current_rt->width < 4 || storage->frame.current_rt->height < 4) { //no post process on small render targets
//no environment or transparent render, simply return and convert to SRGB
glBindFramebuffer(GL_FRAMEBUFFER, storage->frame.current_rt->fbo);
glActiveTexture(GL_TEXTURE0);
@@ -4297,8 +4294,10 @@ void RasterizerSceneGLES3::render_scene(const Transform &p_cam_transform, const
glClearBufferfv(GL_COLOR, 0, clear_color.components); // specular
}
+ VS::EnvironmentBG bg_mode = (!env || (probe && env->bg_mode == VS::ENV_BG_CANVAS)) ? VS::ENV_BG_CLEAR_COLOR : env->bg_mode; //if no environment, or canvas while rendering a probe (invalid use case), use color.
+
if (env) {
- switch (env->bg_mode) {
+ switch (bg_mode) {
case VS::ENV_BG_COLOR_SKY:
case VS::ENV_BG_SKY:
@@ -4341,6 +4340,10 @@ void RasterizerSceneGLES3::render_scene(const Transform &p_cam_transform, const
}
}
+ if (probe && probe->probe_ptr->interior) {
+ env_radiance_tex = 0; //for rendering probe interiors, radiance must not be used.
+ }
+
state.texscreen_copied = false;
glBlendEquation(GL_FUNC_ADD);
diff --git a/drivers/gles3/rasterizer_storage_gles3.cpp b/drivers/gles3/rasterizer_storage_gles3.cpp
index 7ca7d8a471..235c799a55 100644
--- a/drivers/gles3/rasterizer_storage_gles3.cpp
+++ b/drivers/gles3/rasterizer_storage_gles3.cpp
@@ -874,8 +874,6 @@ void RasterizerStorageGLES3::texture_set_data(RID p_texture, const Ref<Image> &p
int size, ofs;
img->get_mipmap_offset_and_size(i, ofs, size);
- //print_line("mipmap: "+itos(i)+" size: "+itos(size)+" w: "+itos(mm_w)+", h: "+itos(mm_h));
-
if (texture->type == VS::TEXTURE_TYPE_2D || texture->type == VS::TEXTURE_TYPE_CUBEMAP) {
if (texture->compressed) {
@@ -1062,8 +1060,6 @@ Ref<Image> RasterizerStorageGLES3::texture_get_data(RID p_texture, int p_layer)
glBindBuffer(GL_PIXEL_PACK_BUFFER, 0);
- //print_line("GET FORMAT: " + Image::get_format_name(texture->format) + " mipmaps: " + itos(texture->mipmaps));
-
for (int i = 0; i < texture->mipmaps; i++) {
int ofs = 0;
@@ -1142,8 +1138,6 @@ Ref<Image> RasterizerStorageGLES3::texture_get_data(RID p_texture, int p_layer)
glBindTexture(GL_TEXTURE_2D, temp_color_texture);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, texture->alloc_width, texture->alloc_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
- print_line(itos(texture->alloc_width) + " xx " + itos(texture->alloc_height) + " -> " + itos(real_format));
-
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, temp_color_texture, 0);
@@ -2253,8 +2247,9 @@ Variant RasterizerStorageGLES3::material_get_param_default(RID p_material, const
if (material->shader) {
if (material->shader->uniforms.has(p_param)) {
- Vector<ShaderLanguage::ConstantNode::Value> default_value = material->shader->uniforms[p_param].default_value;
- return ShaderLanguage::constant_value_to_variant(default_value, material->shader->uniforms[p_param].type);
+ ShaderLanguage::ShaderNode::Uniform uniform = material->shader->uniforms[p_param];
+ Vector<ShaderLanguage::ConstantNode::Value> default_value = uniform.default_value;
+ return ShaderLanguage::constant_value_to_variant(default_value, uniform.type, uniform.hint);
}
}
return Variant();
@@ -2891,9 +2886,6 @@ void RasterizerStorageGLES3::_update_material(Material *material) {
if (E->get().order < 0)
continue; // texture, does not go here
- //if (material->shader->mode == VS::SHADER_PARTICLES) {
- // print_line("uniform " + String(E->key()) + " order " + itos(E->get().order) + " offset " + itos(material->shader->ubo_offsets[E->get().order]));
- //}
//regular uniform
uint8_t *data = &local_ubo[material->shader->ubo_offsets[E->get().order]];
@@ -3786,12 +3778,14 @@ AABB RasterizerStorageGLES3::mesh_get_aabb(RID p_mesh, RID p_skeleton) const {
Mesh *mesh = mesh_owner.get(p_mesh);
ERR_FAIL_COND_V(!mesh, AABB());
- if (mesh->custom_aabb != AABB())
+ if (mesh->custom_aabb != AABB()) {
return mesh->custom_aabb;
+ }
Skeleton *sk = NULL;
- if (p_skeleton.is_valid())
+ if (p_skeleton.is_valid()) {
sk = skeleton_owner.get(p_skeleton);
+ }
AABB aabb;
@@ -3830,6 +3824,7 @@ AABB RasterizerStorageGLES3::mesh_get_aabb(RID p_mesh, RID p_skeleton) const {
mtx.origin.y = texture[base_ofs + 3];
AABB baabb = mtx.xform(skbones[j]);
+
if (first) {
laabb = baabb;
first = false;
@@ -6449,6 +6444,13 @@ void RasterizerStorageGLES3::update_particles() {
glDisable(GL_RASTERIZER_DISCARD);
}
+bool RasterizerStorageGLES3::particles_is_inactive(RID p_particles) const {
+
+ const Particles *particles = particles_owner.getornull(p_particles);
+ ERR_FAIL_COND_V(!particles, false);
+ return !particles->emitting && particles->inactive;
+}
+
////////
void RasterizerStorageGLES3::instance_add_skeleton(RID p_skeleton, RasterizerScene::InstanceBase *p_instance) {
diff --git a/drivers/gles3/rasterizer_storage_gles3.h b/drivers/gles3/rasterizer_storage_gles3.h
index 8c843e4d96..398ffdeb82 100644
--- a/drivers/gles3/rasterizer_storage_gles3.h
+++ b/drivers/gles3/rasterizer_storage_gles3.h
@@ -1261,6 +1261,8 @@ public:
virtual int particles_get_draw_passes(RID p_particles) const;
virtual RID particles_get_draw_pass_mesh(RID p_particles, int p_pass) const;
+ virtual bool particles_is_inactive(RID p_particles) const;
+
/* INSTANCE */
virtual void instance_add_skeleton(RID p_skeleton, RasterizerScene::InstanceBase *p_instance);
diff --git a/drivers/gles3/shader_compiler_gles3.cpp b/drivers/gles3/shader_compiler_gles3.cpp
index fb6e168327..2372dfb17e 100644
--- a/drivers/gles3/shader_compiler_gles3.cpp
+++ b/drivers/gles3/shader_compiler_gles3.cpp
@@ -133,8 +133,7 @@ static String _interpstr(SL::DataInterpolation p_interp) {
switch (p_interp) {
case SL::INTERPOLATION_FLAT: return "flat ";
- case SL::INTERPOLATION_NO_PERSPECTIVE: return "noperspective ";
- case SL::INTERPOLATION_SMOOTH: return "smooth ";
+ case SL::INTERPOLATION_SMOOTH: return "";
}
return "";
}
@@ -173,10 +172,11 @@ static String _mkid(const String &p_id) {
static String f2sp0(float p_float) {
- if (int(p_float) == p_float)
- return itos(p_float) + ".0";
- else
- return rtoss(p_float);
+ String num = rtoss(p_float);
+ if (num.find(".") == -1 && num.find("e") == -1) {
+ num += ".0";
+ }
+ return num;
}
static String get_constant_text(SL::DataType p_type, const Vector<SL::ConstantNode::Value> &p_values) {
@@ -229,7 +229,7 @@ static String get_constant_text(SL::DataType p_type, const Vector<SL::ConstantNo
text += ")";
return text;
} break;
- case SL::TYPE_FLOAT: return f2sp0(p_values[0].real) + "f";
+ case SL::TYPE_FLOAT: return f2sp0(p_values[0].real);
case SL::TYPE_VEC2:
case SL::TYPE_VEC3:
case SL::TYPE_VEC4: {
diff --git a/drivers/gles3/shader_gles3.cpp b/drivers/gles3/shader_gles3.cpp
index 799179e8d4..404a9107ab 100644
--- a/drivers/gles3/shader_gles3.cpp
+++ b/drivers/gles3/shader_gles3.cpp
@@ -219,20 +219,15 @@ ShaderGLES3::Version *ShaderGLES3::get_current_version() {
strings.push_back("#version 300 es\n");
#endif
- int define_line_ofs = 1;
-
for (int i = 0; i < custom_defines.size(); i++) {
strings.push_back(custom_defines[i].get_data());
- define_line_ofs++;
}
for (int j = 0; j < conditional_count; j++) {
bool enable = ((1 << j) & conditional_version.version);
strings.push_back(enable ? conditional_defines[j] : "");
- if (enable)
- define_line_ofs++;
if (enable) {
DEBUG_PRINT(conditional_defines[j]);
@@ -253,7 +248,6 @@ ShaderGLES3::Version *ShaderGLES3::get_current_version() {
ERR_FAIL_COND_V(!custom_code_map.has(conditional_version.code_version), NULL);
cc = &custom_code_map[conditional_version.code_version];
v.code_version = cc->version;
- define_line_ofs += 2;
}
/* CREATE PROGRAM */
diff --git a/drivers/gles3/shaders/scene.glsl b/drivers/gles3/shaders/scene.glsl
index 2288c17334..45802ad3b5 100644
--- a/drivers/gles3/shaders/scene.glsl
+++ b/drivers/gles3/shaders/scene.glsl
@@ -42,8 +42,6 @@ layout(location = 4) in vec2 uv_attrib;
layout(location = 5) in vec2 uv2_attrib;
#endif
-uniform float normal_mult;
-
#ifdef USE_SKELETON
layout(location = 6) in uvec4 bone_indices; // attrib:6
layout(location = 7) in vec4 bone_weights; // attrib:7
@@ -280,11 +278,10 @@ void main() {
}
#endif
- vec3 normal = normal_attrib * normal_mult;
+ vec3 normal = normal_attrib;
#if defined(ENABLE_TANGENT_INTERP) || defined(ENABLE_NORMALMAP) || defined(LIGHT_USE_ANISOTROPY)
vec3 tangent = tangent_attrib.xyz;
- tangent *= normal_mult;
float binormalf = tangent_attrib.a;
#endif
@@ -1106,9 +1103,9 @@ LIGHT_SHADER_CODE
float Fr = mix(.04, 1.0, cLdotH5);
float Gr = G_GGX_2cos(cNdotL, .25) * G_GGX_2cos(cNdotV, .25);
- float specular_brdf_NL = 0.25 * clearcoat * Gr * Fr * Dr * cNdotL;
+ float clearcoat_specular_brdf_NL = 0.25 * clearcoat * Gr * Fr * Dr * cNdotL;
- specular_light += specular_brdf_NL * light_color * specular_blob_intensity * attenuation;
+ specular_light += clearcoat_specular_brdf_NL * light_color * specular_blob_intensity * attenuation;
#endif
}
@@ -1588,24 +1585,24 @@ void main() {
float alpha = 1.0;
-#if defined(DO_SIDE_CHECK)
- float side = gl_FrontFacing ? 1.0 : -1.0;
-#else
- float side = 1.0;
-#endif
-
#if defined(ALPHA_SCISSOR_USED)
float alpha_scissor = 0.5;
#endif
#if defined(ENABLE_TANGENT_INTERP) || defined(ENABLE_NORMALMAP) || defined(LIGHT_USE_ANISOTROPY)
- vec3 binormal = normalize(binormal_interp) * side;
- vec3 tangent = normalize(tangent_interp) * side;
+ vec3 binormal = normalize(binormal_interp);// * side;
+ vec3 tangent = normalize(tangent_interp);// * side;
#else
vec3 binormal = vec3(0.0);
vec3 tangent = vec3(0.0);
#endif
- vec3 normal = normalize(normal_interp) * side;
+ vec3 normal = normalize(normal_interp);
+
+#if defined(DO_SIDE_CHECK)
+ if (!gl_FrontFacing) {
+ normal = -normal;
+ }
+#endif
#if defined(ENABLE_UV_INTERP)
vec2 uv = uv_interp;
@@ -1661,7 +1658,7 @@ FRAGMENT_SHADER_CODE
normalmap.xy = normalmap.xy * 2.0 - 1.0;
normalmap.z = sqrt(max(0.0, 1.0 - dot(normalmap.xy, normalmap.xy))); //always ignore Z, as it can be RG packed, Z may be pos/neg, etc.
- normal = normalize(mix(normal_interp, tangent * normalmap.x + binormal * normalmap.y + normal * normalmap.z, normaldepth)) * side;
+ normal = normalize(mix(normal, tangent * normalmap.x + binormal * normalmap.y + normal * normalmap.z, normaldepth));
#endif
diff --git a/drivers/pulseaudio/audio_driver_pulseaudio.cpp b/drivers/pulseaudio/audio_driver_pulseaudio.cpp
index d78316945f..010f7bdb0a 100644
--- a/drivers/pulseaudio/audio_driver_pulseaudio.cpp
+++ b/drivers/pulseaudio/audio_driver_pulseaudio.cpp
@@ -346,9 +346,9 @@ void AudioDriverPulseAudio::thread_func(void *p_udata) {
for (int j = 0; j < ad->pa_map.channels - 1; j++) {
ad->samples_out.write[out_idx++] = ad->samples_in[in_idx++] >> 16;
}
- uint32_t l = ad->samples_in[in_idx++];
- uint32_t r = ad->samples_in[in_idx++];
- ad->samples_out.write[out_idx++] = ((l >> 1) + (r >> 1)) >> 16;
+ uint32_t l = ad->samples_in[in_idx++] >> 16;
+ uint32_t r = ad->samples_in[in_idx++] >> 16;
+ ad->samples_out.write[out_idx++] = (l + r) / 2;
}
}
}
diff --git a/drivers/unix/net_socket_posix.cpp b/drivers/unix/net_socket_posix.cpp
index f981be66ce..833b17f122 100644
--- a/drivers/unix/net_socket_posix.cpp
+++ b/drivers/unix/net_socket_posix.cpp
@@ -110,7 +110,7 @@ size_t NetSocketPosix::_set_addr_storage(struct sockaddr_storage *p_addr, const
} else { // IPv4 socket
// IPv4 socket with IPv6 address
- ERR_FAIL_COND_V(!p_ip.is_ipv4(), 0);
+ ERR_FAIL_COND_V(!p_ip.is_wildcard() && !p_ip.is_ipv4(), 0);
struct sockaddr_in *addr4 = (struct sockaddr_in *)p_addr;
addr4->sin_family = AF_INET;
@@ -122,7 +122,6 @@ size_t NetSocketPosix::_set_addr_storage(struct sockaddr_storage *p_addr, const
addr4->sin_addr.s_addr = INADDR_ANY;
}
- copymem(&addr4->sin_addr.s_addr, p_ip.get_ipv4(), 4);
return sizeof(sockaddr_in);
}
}
diff --git a/editor/array_property_edit.cpp b/editor/array_property_edit.cpp
index a32a71262f..245c9273ff 100644
--- a/editor/array_property_edit.cpp
+++ b/editor/array_property_edit.cpp
@@ -30,6 +30,7 @@
#include "array_property_edit.h"
+#include "core/io/marshalls.h"
#include "editor_node.h"
#define ITEMS_PER_PAGE 100
@@ -202,6 +203,11 @@ bool ArrayPropertyEdit::_get(const StringName &p_name, Variant &r_ret) const {
int idx = pn.get_slicec('/', 1).to_int();
bool valid;
r_ret = arr.get(idx, &valid);
+
+ if (r_ret.get_type() == Variant::OBJECT && Object::cast_to<EncodedObjectAsID>(r_ret)) {
+ r_ret = Object::cast_to<EncodedObjectAsID>(r_ret)->get_object_id();
+ }
+
return valid;
}
}
@@ -232,6 +238,11 @@ void ArrayPropertyEdit::_get_property_list(List<PropertyInfo> *p_list) const {
p_list->push_back(PropertyInfo(Variant::INT, "indices/" + itos(i + offset) + "_type", PROPERTY_HINT_ENUM, vtypes));
}
+ if (v.get_type() == Variant::OBJECT && Object::cast_to<EncodedObjectAsID>(v)) {
+ p_list->push_back(PropertyInfo(Variant::INT, "indices/" + itos(i + offset), PROPERTY_HINT_OBJECT_ID, "Object"));
+ continue;
+ }
+
if (is_typed || v.get_type() != Variant::NIL) {
PropertyInfo pi(v.get_type(), "indices/" + itos(i + offset));
if (subtype != Variant::NIL) {
diff --git a/editor/code_editor.cpp b/editor/code_editor.cpp
index 3136b0f012..2a11f70274 100644
--- a/editor/code_editor.cpp
+++ b/editor/code_editor.cpp
@@ -1130,6 +1130,19 @@ void CodeTextEditor::set_edit_state(const Variant &p_state) {
void CodeTextEditor::set_error(const String &p_error) {
error->set_text(p_error);
+ error->set_tooltip(p_error);
+ error->set_visible(p_error != "");
+}
+
+void CodeTextEditor::set_error_pos(int p_line, int p_column) {
+ error_line = p_line;
+ error_column = p_column;
+}
+
+void CodeTextEditor::_error_pressed() {
+ text_editor->cursor_set_line(error_line);
+ text_editor->cursor_set_column(error_column);
+ text_editor->center_viewport_to_cursor();
}
void CodeTextEditor::_update_font() {
@@ -1191,6 +1204,7 @@ void CodeTextEditor::_bind_methods() {
ClassDB::bind_method("_code_complete_timer_timeout", &CodeTextEditor::_code_complete_timer_timeout);
ClassDB::bind_method("_complete_request", &CodeTextEditor::_complete_request);
ClassDB::bind_method("_font_resize_timeout", &CodeTextEditor::_font_resize_timeout);
+ ClassDB::bind_method("_error_pressed", &CodeTextEditor::_error_pressed);
ADD_SIGNAL(MethodInfo("validate_script"));
ADD_SIGNAL(MethodInfo("load_theme_settings"));
@@ -1239,13 +1253,22 @@ CodeTextEditor::CodeTextEditor() {
code_complete_timer->set_wait_time(EDITOR_DEF("text_editor/completion/code_complete_delay", .3f));
- error = memnew(Label);
- status_bar->add_child(error);
- error->set_autowrap(true);
- error->set_valign(Label::VALIGN_CENTER);
+ error_line = 0;
+ error_column = 0;
+
+ Control *error_box = memnew(Control);
+ status_bar->add_child(error_box);
+ error_box->set_v_size_flags(SIZE_EXPAND_FILL);
+ error_box->set_h_size_flags(SIZE_EXPAND_FILL);
+ error_box->set_clip_contents(true);
+
+ error = memnew(LinkButton);
+ error_box->add_child(error);
+ error->set_anchors_and_margins_preset(Control::PRESET_CENTER_LEFT);
+ error->set_underline_mode(LinkButton::UNDERLINE_MODE_ON_HOVER);
error->add_color_override("font_color", EditorNode::get_singleton()->get_gui_base()->get_color("error_color", "Editor"));
error->add_font_override("font", EditorNode::get_singleton()->get_gui_base()->get_font("status_source", "EditorFonts"));
- error->set_h_size_flags(SIZE_EXPAND_FILL); //required for it to display, given now it's clipping contents, do not touch
+ error->connect("pressed", this, "_error_pressed");
find_replace_bar->connect("error", error, "set_text");
status_bar->add_child(memnew(Label)); //to keep the height if the other labels are not visible
diff --git a/editor/code_editor.h b/editor/code_editor.h
index 2f9403843e..311b6a959b 100644
--- a/editor/code_editor.h
+++ b/editor/code_editor.h
@@ -36,6 +36,7 @@
#include "scene/gui/check_button.h"
#include "scene/gui/dialogs.h"
#include "scene/gui/line_edit.h"
+#include "scene/gui/link_button.h"
#include "scene/gui/text_edit.h"
#include "scene/gui/tool_button.h"
#include "scene/main/timer.h"
@@ -157,7 +158,9 @@ class CodeTextEditor : public VBoxContainer {
int font_resize_val;
real_t font_size;
- Label *error;
+ LinkButton *error;
+ int error_line;
+ int error_column;
void _on_settings_change();
@@ -171,6 +174,7 @@ class CodeTextEditor : public VBoxContainer {
void _zoom_out();
void _zoom_changed();
void _reset_zoom();
+ void _error_pressed();
CodeTextEditorCodeCompleteFunc code_complete_func;
void *code_complete_ud;
@@ -213,6 +217,7 @@ public:
void update_editor_settings();
void set_error(const String &p_error);
+ void set_error_pos(int p_line, int p_column);
void update_line_and_column() { _line_col_changed(); }
TextEdit *get_text_edit() { return text_editor; }
FindReplaceBar *get_find_replace_bar() { return find_replace_bar; }
diff --git a/editor/create_dialog.cpp b/editor/create_dialog.cpp
index c4516c1f17..926fa37040 100644
--- a/editor/create_dialog.cpp
+++ b/editor/create_dialog.cpp
@@ -118,8 +118,10 @@ void CreateDialog::popup_create(bool p_dont_clear, bool p_replace_mode) {
if (enable_rl) {
search_options->add_constant_override("draw_relationship_lines", 1);
search_options->add_color_override("relationship_line_color", rl_color);
+ search_options->add_constant_override("draw_guides", 0);
} else {
search_options->add_constant_override("draw_relationship_lines", 0);
+ search_options->add_constant_override("draw_guides", 1);
}
is_replace_mode = p_replace_mode;
diff --git a/editor/editor_about.cpp b/editor/editor_about.cpp
index 2f2840192a..14abaa835c 100644
--- a/editor/editor_about.cpp
+++ b/editor/editor_about.cpp
@@ -209,7 +209,6 @@ EditorAbout::EditorAbout() {
TreeItem *tpl_ti_lc = _tpl_tree->create_item(root);
tpl_ti_lc->set_text(0, TTR("Licenses"));
tpl_ti_lc->set_selectable(0, false);
- int read_idx = 0;
String long_text = "";
for (int component_index = 0; component_index < COPYRIGHT_INFO_COUNT; component_index++) {
@@ -234,7 +233,6 @@ EditorAbout::EditorAbout() {
String license = "\n License: " + String(part.license) + "\n";
text += license;
long_text += license + "\n";
- read_idx++;
}
ti->set_metadata(0, text);
}
diff --git a/editor/editor_data.cpp b/editor/editor_data.cpp
index 9420452da1..bd6ce797b5 100644
--- a/editor/editor_data.cpp
+++ b/editor/editor_data.cpp
@@ -946,16 +946,18 @@ void EditorData::script_class_save_icon_paths() {
void EditorData::script_class_load_icon_paths() {
script_class_clear_icon_paths();
- Dictionary d = ProjectSettings::get_singleton()->get("_global_script_class_icons");
- List<Variant> keys;
- d.get_key_list(&keys);
+ if (ProjectSettings::get_singleton()->has_setting("_global_script_class_icons")) {
+ Dictionary d = ProjectSettings::get_singleton()->get("_global_script_class_icons");
+ List<Variant> keys;
+ d.get_key_list(&keys);
- for (List<Variant>::Element *E = keys.front(); E; E = E->next()) {
- String name = E->get().operator String();
- _script_class_icon_paths[name] = d[name];
+ for (List<Variant>::Element *E = keys.front(); E; E = E->next()) {
+ String name = E->get().operator String();
+ _script_class_icon_paths[name] = d[name];
- String path = ScriptServer::get_global_class_path(name);
- script_class_set_name(path, name);
+ String path = ScriptServer::get_global_class_path(name);
+ script_class_set_name(path, name);
+ }
}
}
diff --git a/editor/editor_file_system.cpp b/editor/editor_file_system.cpp
index a99c9656ba..94eb1a3399 100644
--- a/editor/editor_file_system.cpp
+++ b/editor/editor_file_system.cpp
@@ -466,6 +466,7 @@ bool EditorFileSystem::_update_scan_actions() {
bool fs_changed = false;
Vector<String> reimports;
+ Vector<String> reloads;
for (List<ItemAction>::Element *E = scan_actions.front(); E; E = E->next()) {
@@ -545,12 +546,25 @@ bool EditorFileSystem::_update_scan_actions() {
fs_changed = true;
} break;
+ case ItemAction::ACTION_FILE_RELOAD: {
+
+ int idx = ia.dir->find_file_index(ia.file);
+ ERR_CONTINUE(idx == -1);
+ String full_path = ia.dir->get_file_path(idx);
+
+ reloads.push_back(full_path);
+
+ } break;
}
}
if (reimports.size()) {
reimport_files(reimports);
}
+
+ if (reloads.size()) {
+ emit_signal("resources_reload", reloads);
+ }
scan_actions.clear();
return fs_changed;
@@ -905,11 +919,11 @@ void EditorFileSystem::_scan_fs_changes(EditorFileSystemDirectory *p_dir, const
continue;
}
+ String path = cd.plus_file(p_dir->files[i]->file);
+
if (import_extensions.has(p_dir->files[i]->file.get_extension().to_lower())) {
//check here if file must be imported or not
- String path = cd.plus_file(p_dir->files[i]->file);
-
uint64_t mt = FileAccess::get_modified_time(path);
bool reimport = false;
@@ -936,6 +950,20 @@ void EditorFileSystem::_scan_fs_changes(EditorFileSystemDirectory *p_dir, const
ia.file = p_dir->files[i]->file;
scan_actions.push_back(ia);
}
+ } else if (ResourceCache::has(path)) { //test for potential reload
+
+ uint64_t mt = FileAccess::get_modified_time(path);
+
+ if (mt != p_dir->files[i]->modified_time) {
+
+ p_dir->files[i]->modified_time = mt; //save new time, but test for reload
+
+ ItemAction ia;
+ ia.action = ItemAction::ACTION_FILE_RELOAD;
+ ia.dir = p_dir;
+ ia.file = p_dir->files[i]->file;
+ scan_actions.push_back(ia);
+ }
}
}
@@ -1726,6 +1754,7 @@ 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("resources_reload", PropertyInfo(Variant::POOL_STRING_ARRAY, "resources")));
}
void EditorFileSystem::_update_extensions() {
diff --git a/editor/editor_file_system.h b/editor/editor_file_system.h
index f6eef2a152..51b3fd38f0 100644
--- a/editor/editor_file_system.h
+++ b/editor/editor_file_system.h
@@ -116,7 +116,8 @@ class EditorFileSystem : public Node {
ACTION_DIR_REMOVE,
ACTION_FILE_ADD,
ACTION_FILE_REMOVE,
- ACTION_FILE_TEST_REIMPORT
+ ACTION_FILE_TEST_REIMPORT,
+ ACTION_FILE_RELOAD
};
Action action;
diff --git a/editor/editor_folding.cpp b/editor/editor_folding.cpp
index eec4438f96..011fe20564 100644
--- a/editor/editor_folding.cpp
+++ b/editor/editor_folding.cpp
@@ -165,7 +165,7 @@ void EditorFolding::load_scene_folding(Node *p_scene, const String &p_path) {
}
bool EditorFolding::has_folding_data(const String &p_path) {
- String path = EditorSettings::get_singleton()->get_project_settings_dir();
+
String file = p_path.get_file() + "-folding-" + p_path.md5_text() + ".cfg";
file = EditorSettings::get_singleton()->get_project_settings_dir().plus_file(file);
return FileAccess::exists(file);
diff --git a/editor/editor_fonts.cpp b/editor/editor_fonts.cpp
index 8b1818b595..a54ad7894a 100644
--- a/editor/editor_fonts.cpp
+++ b/editor/editor_fonts.cpp
@@ -93,12 +93,14 @@ void editor_register_fonts(Ref<Theme> p_theme) {
/* Custom font */
+ bool font_antialiased = (bool)EditorSettings::get_singleton()->get("interface/editor/main_font_antialiased");
DynamicFontData::Hinting font_hinting = (DynamicFontData::Hinting)(int)EditorSettings::get_singleton()->get("interface/editor/main_font_hinting");
String custom_font_path = EditorSettings::get_singleton()->get("interface/editor/main_font");
Ref<DynamicFontData> CustomFont;
if (custom_font_path.length() > 0 && dir->file_exists(custom_font_path)) {
CustomFont.instance();
+ CustomFont->set_antialiased(font_antialiased);
CustomFont->set_hinting(font_hinting);
CustomFont->set_font_path(custom_font_path);
CustomFont->set_force_autohinter(true); //just looks better..i think?
@@ -112,6 +114,7 @@ void editor_register_fonts(Ref<Theme> p_theme) {
Ref<DynamicFontData> CustomFontBold;
if (custom_font_path_bold.length() > 0 && dir->file_exists(custom_font_path_bold)) {
CustomFontBold.instance();
+ CustomFontBold->set_antialiased(font_antialiased);
CustomFontBold->set_hinting(font_hinting);
CustomFontBold->set_font_path(custom_font_path_bold);
CustomFontBold->set_force_autohinter(true); //just looks better..i think?
@@ -122,10 +125,12 @@ void editor_register_fonts(Ref<Theme> p_theme) {
/* Custom source code font */
String custom_font_path_source = EditorSettings::get_singleton()->get("interface/editor/code_font");
+ bool font_source_antialiased = (bool)EditorSettings::get_singleton()->get("interface/editor/code_font_antialiased");
DynamicFontData::Hinting font_source_hinting = (DynamicFontData::Hinting)(int)EditorSettings::get_singleton()->get("interface/editor/code_font_hinting");
Ref<DynamicFontData> CustomFontSource;
if (custom_font_path_source.length() > 0 && dir->file_exists(custom_font_path_source)) {
CustomFontSource.instance();
+ CustomFontSource->set_antialiased(font_source_antialiased);
CustomFontSource->set_hinting(font_source_hinting);
CustomFontSource->set_font_path(custom_font_path_source);
} else {
@@ -138,48 +143,56 @@ void editor_register_fonts(Ref<Theme> p_theme) {
Ref<DynamicFontData> DefaultFont;
DefaultFont.instance();
+ DefaultFont->set_antialiased(font_antialiased);
DefaultFont->set_hinting(font_hinting);
DefaultFont->set_font_ptr(_font_NotoSansUI_Regular, _font_NotoSansUI_Regular_size);
DefaultFont->set_force_autohinter(true); //just looks better..i think?
Ref<DynamicFontData> DefaultFontBold;
DefaultFontBold.instance();
- DefaultFont->set_hinting(font_hinting);
+ DefaultFontBold->set_antialiased(font_antialiased);
+ DefaultFontBold->set_hinting(font_hinting);
DefaultFontBold->set_font_ptr(_font_NotoSansUI_Bold, _font_NotoSansUI_Bold_size);
DefaultFontBold->set_force_autohinter(true); // just looks better..i think?
Ref<DynamicFontData> FontFallback;
FontFallback.instance();
+ FontFallback->set_antialiased(font_antialiased);
FontFallback->set_hinting(font_hinting);
FontFallback->set_font_ptr(_font_DroidSansFallback, _font_DroidSansFallback_size);
FontFallback->set_force_autohinter(true); //just looks better..i think?
Ref<DynamicFontData> FontJapanese;
FontJapanese.instance();
+ FontJapanese->set_antialiased(font_antialiased);
FontJapanese->set_hinting(font_hinting);
FontJapanese->set_font_ptr(_font_DroidSansJapanese, _font_DroidSansJapanese_size);
FontJapanese->set_force_autohinter(true); //just looks better..i think?
Ref<DynamicFontData> FontArabic;
FontArabic.instance();
+ FontArabic->set_antialiased(font_antialiased);
FontArabic->set_hinting(font_hinting);
FontArabic->set_font_ptr(_font_NotoNaskhArabicUI_Regular, _font_NotoNaskhArabicUI_Regular_size);
FontArabic->set_force_autohinter(true); //just looks better..i think?
Ref<DynamicFontData> FontHebrew;
FontHebrew.instance();
+ FontHebrew->set_antialiased(font_antialiased);
FontHebrew->set_hinting(font_hinting);
FontHebrew->set_font_ptr(_font_NotoSansHebrew_Regular, _font_NotoSansHebrew_Regular_size);
FontHebrew->set_force_autohinter(true); //just looks better..i think?
Ref<DynamicFontData> FontThai;
FontThai.instance();
+ FontThai->set_antialiased(font_antialiased);
FontThai->set_hinting(font_hinting);
FontThai->set_font_ptr(_font_NotoSansThaiUI_Regular, _font_NotoSansThaiUI_Regular_size);
FontThai->set_force_autohinter(true); //just looks better..i think?
Ref<DynamicFontData> FontHindi;
FontHindi.instance();
+ FontHindi->set_antialiased(font_antialiased);
FontHindi->set_hinting(font_hinting);
FontHindi->set_font_ptr(_font_NotoSansDevanagariUI_Regular, _font_NotoSansDevanagariUI_Regular_size);
FontHindi->set_force_autohinter(true); //just looks better..i think?
@@ -188,6 +201,7 @@ void editor_register_fonts(Ref<Theme> p_theme) {
Ref<DynamicFontData> dfmono;
dfmono.instance();
+ dfmono->set_antialiased(font_source_antialiased);
dfmono->set_hinting(font_source_hinting);
dfmono->set_font_ptr(_font_Hack_Regular, _font_Hack_Regular_size);
//dfd->set_force_autohinter(true); //just looks better..i think?
diff --git a/editor/editor_help.cpp b/editor/editor_help.cpp
index 3ee8d9c6c5..de1f856608 100644
--- a/editor/editor_help.cpp
+++ b/editor/editor_help.cpp
@@ -399,8 +399,10 @@ void EditorHelpIndex::_notification(int p_what) {
if (enable_rl) {
class_list->add_constant_override("draw_relationship_lines", 1);
class_list->add_color_override("relationship_line_color", rl_color);
+ class_list->add_constant_override("draw_guides", 0);
} else {
class_list->add_constant_override("draw_relationship_lines", 0);
+ class_list->add_constant_override("draw_guides", 1);
}
}
}
diff --git a/editor/editor_inspector.cpp b/editor/editor_inspector.cpp
index d6f337cc20..a564a2a113 100644
--- a/editor/editor_inspector.cpp
+++ b/editor/editor_inspector.cpp
@@ -1153,6 +1153,11 @@ void EditorInspectorSection::_gui_input(const Ref<InputEvent> &p_event) {
Ref<InputEventMouseButton> mb = p_event;
if (mb.is_valid() && mb->is_pressed() && mb->get_button_index() == BUTTON_LEFT) {
+ Ref<Font> font = get_font("font", "Tree");
+ if (mb->get_position().y > font->get_height()) { //clicked outside
+ return;
+ }
+
_test_unfold();
bool unfold = !object->editor_is_section_unfolded(section);
diff --git a/editor/editor_node.cpp b/editor/editor_node.cpp
index dbbf5d08b8..5d29acff75 100644
--- a/editor/editor_node.cpp
+++ b/editor/editor_node.cpp
@@ -410,51 +410,50 @@ void EditorNode::_on_plugin_ready(Object *p_script, const String &p_activate_nam
push_item(script.operator->());
}
-void EditorNode::_fs_changed() {
+void EditorNode::_resources_changed(const PoolVector<String> &p_resources) {
- for (Set<FileDialog *>::Element *E = file_dialogs.front(); E; E = E->next()) {
+ List<Ref<Resource> > changed;
- E->get()->invalidate();
- }
+ int rc = p_resources.size();
+ for (int i = 0; i < rc; i++) {
- for (Set<EditorFileDialog *>::Element *E = editor_file_dialogs.front(); E; E = E->next()) {
+ Ref<Resource> res(ResourceCache::get(p_resources.get(i)));
+ if (res.is_null()) {
+ continue;
+ }
- E->get()->invalidate();
- }
+ if (!res->editor_can_reload_from_file())
+ continue;
+ if (!res->get_path().is_resource_file() && !res->get_path().is_abs_path())
+ continue;
+ if (!FileAccess::exists(res->get_path()))
+ continue;
- {
- //reload changed resources
- List<Ref<Resource> > changed;
+ if (res->get_import_path() != String()) {
+ //this is an imported resource, will be reloaded if reimported via the _resources_reimported() callback
+ continue;
+ }
- List<Ref<Resource> > cached;
- ResourceCache::get_cached_resources(&cached);
- // FIXME: This should be done in a thread.
- for (List<Ref<Resource> >::Element *E = cached.front(); E; E = E->next()) {
+ changed.push_back(res);
+ }
- if (!E->get()->editor_can_reload_from_file())
- continue;
- if (!E->get()->get_path().is_resource_file() && !E->get()->get_path().is_abs_path())
- continue;
- if (!FileAccess::exists(E->get()->get_path()))
- continue;
+ if (changed.size()) {
+ for (List<Ref<Resource> >::Element *E = changed.front(); E; E = E->next()) {
+ E->get()->reload_from_file();
+ }
+ }
+}
- if (E->get()->get_import_path() != String()) {
- //this is an imported resource, will be reloaded if reimported via the _resources_reimported() callback
- continue;
- }
+void EditorNode::_fs_changed() {
- uint64_t mt = FileAccess::get_modified_time(E->get()->get_path());
+ for (Set<FileDialog *>::Element *E = file_dialogs.front(); E; E = E->next()) {
- if (mt != E->get()->get_last_modified_time()) {
- changed.push_back(E->get());
- }
- }
+ E->get()->invalidate();
+ }
- if (changed.size()) {
- for (List<Ref<Resource> >::Element *E = changed.front(); E; E = E->next()) {
- E->get()->reload_from_file();
- }
- }
+ for (Set<EditorFileDialog *>::Element *E = editor_file_dialogs.front(); E; E = E->next()) {
+
+ E->get()->invalidate();
}
_mark_unsaved_scenes();
@@ -637,6 +636,7 @@ void EditorNode::save_resource(const Ref<Resource> &p_resource) {
void EditorNode::save_resource_as(const Ref<Resource> &p_resource, const String &p_at_path) {
file->set_mode(EditorFileDialog::MODE_SAVE_FILE);
+ saving_resource = p_resource;
current_option = RESOURCE_SAVE_AS;
List<String> extensions;
@@ -1263,15 +1263,13 @@ void EditorNode::_dialog_action(String p_file) {
case RESOURCE_SAVE:
case RESOURCE_SAVE_AS: {
- uint32_t current = editor_history.get_current();
+ ERR_FAIL_COND(saving_resource.is_null())
+ save_resource_in_path(saving_resource, p_file);
+ saving_resource = Ref<Resource>();
+ ObjectID current = editor_history.get_current();
Object *current_obj = current > 0 ? ObjectDB::get_instance(current) : NULL;
-
- ERR_FAIL_COND(!Object::cast_to<Resource>(current_obj))
-
- RES current_res = RES(Object::cast_to<Resource>(current_obj));
-
- save_resource_in_path(current_res, p_file);
-
+ ERR_FAIL_COND(!current_obj);
+ current_obj->_change_notify();
} break;
case SETTINGS_LAYOUT_SAVE: {
@@ -2003,7 +2001,7 @@ void EditorNode::_menu_option_confirm(int p_option, bool p_confirmed) {
if (err != OK)
ERR_PRINT("Failed to load scene");
editor_data.move_edited_scene_to_index(cur_idx);
- get_undo_redo()->clear_history();
+ get_undo_redo()->clear_history(false);
scene_tabs->set_current_tab(cur_idx);
} break;
@@ -2570,6 +2568,12 @@ void EditorNode::set_addon_plugin_enabled(const String &p_addon, bool p_enabled)
return;
}
+ //errors in the script cause the base_type to be ""
+ if (String(script->get_instance_base_type()) == "") {
+ show_warning(vformat(TTR("Unable to load addon script from path: '%s' There seems to be an error in the code, please check the syntax."), path));
+ return;
+ }
+
//could check inheritance..
if (String(script->get_instance_base_type()) != "EditorPlugin") {
show_warning(vformat(TTR("Unable to load addon script from path: '%s' Base type is not EditorPlugin."), path));
@@ -2613,7 +2617,7 @@ void EditorNode::_remove_edited_scene() {
}
_scene_tab_changed(new_index);
editor_data.remove_scene(old_index);
- editor_data.get_undo_redo().clear_history();
+ editor_data.get_undo_redo().clear_history(false);
_update_title();
_update_scene_tabs();
}
@@ -4651,6 +4655,8 @@ void EditorNode::_bind_methods() {
ClassDB::bind_method(D_METHOD("_video_driver_selected"), &EditorNode::_video_driver_selected);
+ ClassDB::bind_method(D_METHOD("_resources_changed"), &EditorNode::_resources_changed);
+
ADD_SIGNAL(MethodInfo("play_pressed"));
ADD_SIGNAL(MethodInfo("pause_pressed"));
ADD_SIGNAL(MethodInfo("stop_pressed"));
@@ -5777,6 +5783,7 @@ EditorNode::EditorNode() {
_edit_current();
current = NULL;
+ saving_resource = Ref<Resource>();
reference_resource_mem = true;
save_external_resources_mem = true;
@@ -5819,6 +5826,7 @@ EditorNode::EditorNode() {
EditorFileSystem::get_singleton()->connect("sources_changed", this, "_sources_changed");
EditorFileSystem::get_singleton()->connect("filesystem_changed", this, "_fs_changed");
EditorFileSystem::get_singleton()->connect("resources_reimported", this, "_resources_reimported");
+ EditorFileSystem::get_singleton()->connect("resources_reload", this, "_resources_changed");
_build_icon_type_cache();
diff --git a/editor/editor_node.h b/editor/editor_node.h
index b828a4d7d5..eda7ebcf53 100644
--- a/editor/editor_node.h
+++ b/editor/editor_node.h
@@ -356,6 +356,7 @@ private:
EditorExport *editor_export;
Object *current;
+ Ref<Resource> saving_resource;
bool _playing_edited;
String run_custom_filename;
@@ -605,6 +606,8 @@ private:
static void _resource_saved(RES p_resource, const String &p_path);
static void _resource_loaded(RES p_resource, const String &p_path);
+ void _resources_changed(const PoolVector<String> &p_resources);
+
protected:
void _notification(int p_what);
static void _bind_methods();
diff --git a/editor/editor_properties.cpp b/editor/editor_properties.cpp
index 9c1d22f6ec..57c6fa3547 100644
--- a/editor/editor_properties.cpp
+++ b/editor/editor_properties.cpp
@@ -1802,14 +1802,26 @@ void EditorPropertyNodePath::_node_selected(const NodePath &p_path) {
NodePath path = p_path;
Node *base_node = Object::cast_to<Node>(get_edited_object());
- if (base_node == NULL) {
- if (Object::cast_to<Resource>(get_edited_object())) {
- Node *to_node = get_node(p_path);
- path = get_tree()->get_edited_scene_root()->get_path_to(to_node);
- } else if (get_edited_object()->has_method("get_root_path")) {
- base_node = get_edited_object()->call("get_root_path");
+ if (!base_node) {
+ //try a base node within history
+ if (EditorNode::get_singleton()->get_editor_history()->get_path_size() > 0) {
+ Object *base = ObjectDB::get_instance(EditorNode::get_singleton()->get_editor_history()->get_path_object(0));
+ if (base) {
+ base_node = Object::cast_to<Node>(base);
+ }
}
}
+
+ if (!base_node && get_edited_object()->has_method("get_root_path")) {
+ base_node = get_edited_object()->call("get_root_path");
+ }
+
+ if (!base_node && Object::cast_to<Reference>(get_edited_object())) {
+ Node *to_node = get_node(p_path);
+ ERR_FAIL_COND(!to_node);
+ path = get_tree()->get_edited_scene_root()->get_path_to(to_node);
+ }
+
if (base_node) { // for AnimationTrackKeyEdit
path = base_node->get_path().rel_path_to(p_path);
}
@@ -2016,6 +2028,13 @@ void EditorPropertyResource::_menu_option(int p_which) {
} break;
+ case OBJ_MENU_SAVE: {
+ RES res = get_edited_object()->get(get_edited_property());
+ if (res.is_null())
+ return;
+ EditorNode::get_singleton()->save_resource(res);
+ } break;
+
case OBJ_MENU_COPY: {
RES res = get_edited_object()->get(get_edited_property());
@@ -2145,7 +2164,8 @@ void EditorPropertyResource::_resource_preview(const String &p_path, const Ref<T
}
}
-void EditorPropertyResource::_update_menu() {
+void EditorPropertyResource::_update_menu_items() {
+
//////////////////// UPDATE MENU //////////////////////////
RES res = get_edited_object()->get(get_edited_property());
@@ -2232,6 +2252,7 @@ void EditorPropertyResource::_update_menu() {
menu->add_icon_item(get_icon("Edit", "EditorIcons"), TTR("Edit"), OBJ_MENU_EDIT);
menu->add_icon_item(get_icon("Clear", "EditorIcons"), TTR("Clear"), OBJ_MENU_CLEAR);
menu->add_icon_item(get_icon("Duplicate", "EditorIcons"), TTR("Make Unique"), OBJ_MENU_MAKE_UNIQUE);
+ menu->add_icon_item(get_icon("Save", "EditorIcons"), TTR("Save"), OBJ_MENU_SAVE);
RES r = res;
if (r.is_valid() && r->get_path().is_resource_file()) {
menu->add_separator();
@@ -2287,6 +2308,11 @@ void EditorPropertyResource::_update_menu() {
menu->add_icon_item(icon, vformat(TTR("Convert To %s"), what), CONVERT_BASE_ID + i);
}
}
+}
+
+void EditorPropertyResource::_update_menu() {
+
+ _update_menu_items();
Rect2 gt = edit->get_global_rect();
menu->set_as_minsize();
@@ -2311,6 +2337,20 @@ void EditorPropertyResource::_sub_inspector_object_id_selected(int p_id) {
emit_signal("object_id_selected", get_edited_property(), p_id);
}
+void EditorPropertyResource::_button_input(const Ref<InputEvent> &p_event) {
+ Ref<InputEventMouseButton> mb = p_event;
+ if (mb.is_valid()) {
+ if (mb->is_pressed() && mb->get_button_index() == BUTTON_RIGHT) {
+ _update_menu_items();
+ Vector2 pos = mb->get_global_position();
+ //pos = assign->get_global_transform().xform(pos);
+ menu->set_as_minsize();
+ menu->set_global_position(pos);
+ menu->popup();
+ }
+ }
+}
+
void EditorPropertyResource::_open_editor_pressed() {
RES res = get_edited_object()->get(get_edited_property());
if (res.is_valid()) {
@@ -2598,6 +2638,7 @@ void EditorPropertyResource::_bind_methods() {
ClassDB::bind_method(D_METHOD("drop_data_fw"), &EditorPropertyResource::drop_data_fw);
ClassDB::bind_method(D_METHOD("_button_draw"), &EditorPropertyResource::_button_draw);
ClassDB::bind_method(D_METHOD("_open_editor_pressed"), &EditorPropertyResource::_open_editor_pressed);
+ ClassDB::bind_method(D_METHOD("_button_input"), &EditorPropertyResource::_button_input);
}
EditorPropertyResource::EditorPropertyResource() {
@@ -2624,6 +2665,7 @@ EditorPropertyResource::EditorPropertyResource() {
preview->set_margin(MARGIN_BOTTOM, -1);
preview->set_margin(MARGIN_RIGHT, -1);
assign->add_child(preview);
+ assign->connect("gui_input", this, "_button_input");
menu = memnew(PopupMenu);
add_child(menu);
@@ -2632,6 +2674,7 @@ EditorPropertyResource::EditorPropertyResource() {
menu->connect("id_pressed", this, "_menu_option");
edit->connect("pressed", this, "_update_menu");
hbc->add_child(edit);
+ edit->connect("gui_input", this, "_button_input");
file = NULL;
scene_tree = NULL;
diff --git a/editor/editor_properties.h b/editor/editor_properties.h
index 35d8f4d306..b82ef977ef 100644
--- a/editor/editor_properties.h
+++ b/editor/editor_properties.h
@@ -522,10 +522,11 @@ class EditorPropertyResource : public EditorProperty {
OBJ_MENU_EDIT = 1,
OBJ_MENU_CLEAR = 2,
OBJ_MENU_MAKE_UNIQUE = 3,
- OBJ_MENU_COPY = 4,
- OBJ_MENU_PASTE = 5,
- OBJ_MENU_NEW_SCRIPT = 6,
- OBJ_MENU_SHOW_IN_FILE_SYSTEM = 7,
+ OBJ_MENU_SAVE = 4,
+ OBJ_MENU_COPY = 5,
+ OBJ_MENU_PASTE = 6,
+ OBJ_MENU_NEW_SCRIPT = 7,
+ OBJ_MENU_SHOW_IN_FILE_SYSTEM = 8,
TYPE_BASE_ID = 100,
CONVERT_BASE_ID = 1000
@@ -552,6 +553,8 @@ class EditorPropertyResource : public EditorProperty {
void _resource_selected();
void _viewport_selected(const NodePath &p_path);
+ void _update_menu_items();
+
void _update_menu();
void _sub_inspector_property_keyed(const String &p_property, const Variant &p_value, bool);
@@ -564,6 +567,7 @@ class EditorPropertyResource : public EditorProperty {
bool can_drop_data_fw(const Point2 &p_point, const Variant &p_data, Control *p_from) const;
void drop_data_fw(const Point2 &p_point, const Variant &p_data, Control *p_from);
+ void _button_input(const Ref<InputEvent> &p_event);
void _open_editor_pressed();
protected:
diff --git a/editor/editor_properties_array_dict.cpp b/editor/editor_properties_array_dict.cpp
index 24360813a2..431f608f46 100644
--- a/editor/editor_properties_array_dict.cpp
+++ b/editor/editor_properties_array_dict.cpp
@@ -29,9 +29,9 @@
/*************************************************************************/
#include "editor_properties_array_dict.h"
+#include "core/io/marshalls.h"
#include "editor/editor_scale.h"
#include "editor_properties.h"
-
bool EditorPropertyArrayObject::_set(const StringName &p_name, const Variant &p_value) {
String pn = p_name;
@@ -54,6 +54,10 @@ bool EditorPropertyArrayObject::_get(const StringName &p_name, Variant &r_ret) c
int idx = pn.get_slicec('/', 1).to_int();
bool valid;
r_ret = array.get(idx, &valid);
+ if (r_ret.get_type() == Variant::OBJECT && Object::cast_to<EncodedObjectAsID>(r_ret)) {
+ r_ret = Object::cast_to<EncodedObjectAsID>(r_ret)->get_object_id();
+ }
+
return valid;
}
@@ -120,6 +124,10 @@ bool EditorPropertyDictionaryObject::_get(const StringName &p_name, Variant &r_r
int idx = pn.get_slicec('/', 1).to_int();
Variant key = dict.get_key_at_index(idx);
r_ret = dict[key];
+ if (r_ret.get_type() == Variant::OBJECT && Object::cast_to<EncodedObjectAsID>(r_ret)) {
+ r_ret = Object::cast_to<EncodedObjectAsID>(r_ret)->get_object_id();
+ }
+
return true;
}
@@ -198,6 +206,10 @@ void EditorPropertyArray::_change_type_menu(int p_index) {
update_property();
}
+void EditorPropertyArray::_object_id_selected(const String &p_property, ObjectID p_id) {
+ emit_signal("object_id_selected", p_property, p_id);
+}
+
void EditorPropertyArray::update_property() {
Variant array = get_edited_object()->get(get_edited_property());
@@ -431,9 +443,19 @@ void EditorPropertyArray::update_property() {
} break;
case Variant::OBJECT: {
- EditorPropertyResource *editor = memnew(EditorPropertyResource);
- editor->setup("Resource");
- prop = editor;
+
+ if (Object::cast_to<EncodedObjectAsID>(value)) {
+
+ EditorPropertyObjectID *editor = memnew(EditorPropertyObjectID);
+ editor->setup("Object");
+ prop = editor;
+
+ } else {
+
+ EditorPropertyResource *editor = memnew(EditorPropertyResource);
+ editor->setup("Resource");
+ prop = editor;
+ }
} break;
case Variant::DICTIONARY: {
@@ -497,6 +519,7 @@ void EditorPropertyArray::update_property() {
prop->set_label(itos(i + offset));
prop->set_selectable(false);
prop->connect("property_changed", this, "_property_changed");
+ prop->connect("object_id_selected", this, "_object_id_selected");
if (array.get_type() == Variant::ARRAY) {
HBoxContainer *hb = memnew(HBoxContainer);
vbox->add_child(hb);
@@ -578,6 +601,7 @@ void EditorPropertyArray::_bind_methods() {
ClassDB::bind_method("_property_changed", &EditorPropertyArray::_property_changed, DEFVAL(false));
ClassDB::bind_method("_change_type", &EditorPropertyArray::_change_type);
ClassDB::bind_method("_change_type_menu", &EditorPropertyArray::_change_type_menu);
+ ClassDB::bind_method("_object_id_selected", &EditorPropertyArray::_object_id_selected);
}
EditorPropertyArray::EditorPropertyArray() {
@@ -893,9 +917,19 @@ void EditorPropertyDictionary::update_property() {
} break;
case Variant::OBJECT: {
- EditorPropertyResource *editor = memnew(EditorPropertyResource);
- editor->setup("Resource");
- prop = editor;
+
+ if (Object::cast_to<EncodedObjectAsID>(value)) {
+
+ EditorPropertyObjectID *editor = memnew(EditorPropertyObjectID);
+ editor->setup("Object");
+ prop = editor;
+
+ } else {
+
+ EditorPropertyResource *editor = memnew(EditorPropertyResource);
+ editor->setup("Resource");
+ prop = editor;
+ }
} break;
case Variant::DICTIONARY: {
@@ -986,6 +1020,7 @@ void EditorPropertyDictionary::update_property() {
prop->set_selectable(false);
prop->connect("property_changed", this, "_property_changed");
+ prop->connect("object_id_selected", this, "_object_id_selected");
HBoxContainer *hb = memnew(HBoxContainer);
if (add_vbox) {
@@ -1022,6 +1057,10 @@ void EditorPropertyDictionary::update_property() {
#endif
}
+void EditorPropertyDictionary::_object_id_selected(const String &p_property, ObjectID p_id) {
+ emit_signal("object_id_selected", p_property, p_id);
+}
+
void EditorPropertyDictionary::_notification(int p_what) {
if (p_what == NOTIFICATION_ENTER_TREE || p_what == NOTIFICATION_THEME_CHANGED) {
@@ -1055,6 +1094,7 @@ void EditorPropertyDictionary::_bind_methods() {
ClassDB::bind_method("_change_type", &EditorPropertyDictionary::_change_type);
ClassDB::bind_method("_change_type_menu", &EditorPropertyDictionary::_change_type_menu);
ClassDB::bind_method("_add_key_value", &EditorPropertyDictionary::_add_key_value);
+ ClassDB::bind_method("_object_id_selected", &EditorPropertyDictionary::_object_id_selected);
}
EditorPropertyDictionary::EditorPropertyDictionary() {
diff --git a/editor/editor_properties_array_dict.h b/editor/editor_properties_array_dict.h
index d2bd849f30..d5eecd9106 100644
--- a/editor/editor_properties_array_dict.h
+++ b/editor/editor_properties_array_dict.h
@@ -101,6 +101,8 @@ class EditorPropertyArray : public EditorProperty {
void _change_type(Object *p_button, int p_index);
void _change_type_menu(int p_index);
+ void _object_id_selected(const String &p_property, ObjectID p_id);
+
protected:
static void _bind_methods();
void _notification(int p_what);
@@ -134,6 +136,7 @@ class EditorPropertyDictionary : public EditorProperty {
void _change_type_menu(int p_index);
void _add_key_value();
+ void _object_id_selected(const String &p_property, ObjectID p_id);
protected:
static void _bind_methods();
diff --git a/editor/editor_settings.cpp b/editor/editor_settings.cpp
index 34c273fbae..fdfa094ba2 100644
--- a/editor/editor_settings.cpp
+++ b/editor/editor_settings.cpp
@@ -300,6 +300,8 @@ void EditorSettings::_load_defaults(Ref<ConfigFile> p_extra_config) {
hints["interface/editor/main_font_size"] = PropertyInfo(Variant::INT, "interface/editor/main_font_size", PROPERTY_HINT_RANGE, "10,40,1", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_RESTART_IF_CHANGED);
_initial_set("interface/editor/code_font_size", 14);
hints["interface/editor/code_font_size"] = PropertyInfo(Variant::INT, "interface/editor/code_font_size", PROPERTY_HINT_RANGE, "8,96,1", PROPERTY_USAGE_DEFAULT);
+ _initial_set("interface/editor/main_font_antialiased", true);
+ _initial_set("interface/editor/code_font_antialiased", true);
_initial_set("interface/editor/main_font_hinting", 2);
hints["interface/editor/main_font_hinting"] = PropertyInfo(Variant::INT, "interface/editor/main_font_hinting", PROPERTY_HINT_ENUM, "None,Light,Normal", PROPERTY_USAGE_DEFAULT);
_initial_set("interface/editor/code_font_hinting", 2);
@@ -433,7 +435,7 @@ void EditorSettings::_load_defaults(Ref<ConfigFile> p_extra_config) {
// navigation
_initial_set("editors/3d/navigation/navigation_scheme", 0);
- _initial_set("editors/3d/navigation/invert_y-axis", false);
+ _initial_set("editors/3d/navigation/invert_y_axis", false);
hints["editors/3d/navigation/navigation_scheme"] = PropertyInfo(Variant::INT, "editors/3d/navigation/navigation_scheme", PROPERTY_HINT_ENUM, "Godot,Maya,Modo");
_initial_set("editors/3d/navigation/zoom_style", 0);
hints["editors/3d/navigation/zoom_style"] = PropertyInfo(Variant::INT, "editors/3d/navigation/zoom_style", PROPERTY_HINT_ENUM, "Vertical, Horizontal");
diff --git a/editor/import/editor_import_collada.cpp b/editor/import/editor_import_collada.cpp
index e8bb772a64..b133efead7 100644
--- a/editor/import/editor_import_collada.cpp
+++ b/editor/import/editor_import_collada.cpp
@@ -771,7 +771,7 @@ Error ColladaImport::_create_mesh_surfaces(bool p_optimize, Ref<ArrayMesh> &p_me
int binormal_pos = (binormal_src->stride ? binormal_src->stride : 3) * p.indices[src + binormal_ofs];
ERR_FAIL_INDEX_V(binormal_pos, binormal_src->array.size(), ERR_INVALID_DATA);
- Vector3 binormal = Vector3(binormal_src->array[binormal_pos + 0], binormal_src->array[binormal_pos + 1], binormal_src->array[binormal_pos + 2]);
+ Vector3 binormal = Vector3(-binormal_src->array[binormal_pos + 0], -binormal_src->array[binormal_pos + 1], -binormal_src->array[binormal_pos + 2]); // Due to Godots face order it seems we need to flip our binormal!
int tangent_pos = (tangent_src->stride ? tangent_src->stride : 3) * p.indices[src + tangent_ofs];
ERR_FAIL_INDEX_V(tangent_pos, tangent_src->array.size(), ERR_INVALID_DATA);
diff --git a/editor/import/editor_scene_importer_gltf.cpp b/editor/import/editor_scene_importer_gltf.cpp
index cb15be35f2..f47252d388 100644
--- a/editor/import/editor_scene_importer_gltf.cpp
+++ b/editor/import/editor_scene_importer_gltf.cpp
@@ -899,7 +899,16 @@ Error EditorSceneImporterGLTF::_parse_meshes(GLTFState &state) {
array[Mesh::ARRAY_NORMAL] = _decode_accessor_as_vec3(state, a["NORMAL"], true);
}
if (a.has("TANGENT")) {
- array[Mesh::ARRAY_TANGENT] = _decode_accessor_as_floats(state, a["TANGENT"], true);
+ PoolVector<float> tans = _decode_accessor_as_floats(state, a["TANGENT"], true);
+ { // we need our binormals inversed, so flip our w component.
+ int ts = tans.size();
+ PoolVector<float>::Write w = tans.write();
+
+ for (int j = 3; j < ts; j += 4) {
+ w[j] *= -1.0;
+ }
+ }
+ array[Mesh::ARRAY_TANGENT] = tans;
}
if (a.has("TEXCOORD_0")) {
array[Mesh::ARRAY_TEX_UV] = _decode_accessor_as_vec2(state, a["TEXCOORD_0"], true);
diff --git a/editor/import/resource_importer_texture.cpp b/editor/import/resource_importer_texture.cpp
index 8e91a88adb..b38f4c4f14 100644
--- a/editor/import/resource_importer_texture.cpp
+++ b/editor/import/resource_importer_texture.cpp
@@ -216,7 +216,7 @@ void ResourceImporterTexture::get_import_options(List<ImportOption> *r_options,
r_options->push_back(ImportOption(PropertyInfo(Variant::INT, "stream"), false));
r_options->push_back(ImportOption(PropertyInfo(Variant::INT, "size_limit", PROPERTY_HINT_RANGE, "0,4096,1"), 0));
r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL, "detect_3d"), p_preset == PRESET_DETECT));
- r_options->push_back(ImportOption(PropertyInfo(Variant::REAL, "svg/scale", PROPERTY_HINT_RANGE, "0.001,100,0.1"), 1.0));
+ r_options->push_back(ImportOption(PropertyInfo(Variant::REAL, "svg/scale", PROPERTY_HINT_RANGE, "0.001,100,0.001"), 1.0));
}
void ResourceImporterTexture::_save_stex(const Ref<Image> &p_image, const String &p_to_path, int p_compress_mode, float p_lossy_quality, Image::CompressMode p_vram_compression, bool p_mipmaps, int p_texture_flags, bool p_streamable, bool p_detect_3d, bool p_detect_srgb, bool p_force_rgbe, bool p_detect_normal, bool p_force_normal) {
diff --git a/editor/multi_node_edit.cpp b/editor/multi_node_edit.cpp
index be4e752d55..420d8ad3cf 100644
--- a/editor/multi_node_edit.cpp
+++ b/editor/multi_node_edit.cpp
@@ -52,7 +52,7 @@ bool MultiNodeEdit::_set_impl(const StringName &p_name, const Variant &p_value,
UndoRedo *ur = EditorNode::get_singleton()->get_undo_redo();
- ur->create_action(TTR("MultiNode Set") + " " + String(name));
+ ur->create_action(TTR("MultiNode Set") + " " + String(name), UndoRedo::MERGE_ENDS);
for (const List<NodePath>::Element *E = nodes.front(); E; E = E->next()) {
if (!es->has_node(E->get()))
diff --git a/editor/plugins/animation_blend_space_2d_editor.cpp b/editor/plugins/animation_blend_space_2d_editor.cpp
index 394b888d0e..e2fe9a91d8 100644
--- a/editor/plugins/animation_blend_space_2d_editor.cpp
+++ b/editor/plugins/animation_blend_space_2d_editor.cpp
@@ -607,6 +607,8 @@ void AnimationNodeBlendSpace2DEditor::_update_space() {
auto_triangles->set_pressed(blend_space->get_auto_triangles());
+ interpolation->select(blend_space->get_blend_mode());
+
max_x_value->set_value(blend_space->get_max_space().x);
max_y_value->set_value(blend_space->get_max_space().y);
@@ -636,6 +638,8 @@ void AnimationNodeBlendSpace2DEditor::_config_changed(double) {
undo_redo->add_undo_method(blend_space.ptr(), "set_min_space", blend_space->get_min_space());
undo_redo->add_do_method(blend_space.ptr(), "set_snap", Vector2(snap_x->get_value(), snap_y->get_value()));
undo_redo->add_undo_method(blend_space.ptr(), "set_snap", blend_space->get_snap());
+ undo_redo->add_do_method(blend_space.ptr(), "set_blend_mode", interpolation->get_selected());
+ undo_redo->add_undo_method(blend_space.ptr(), "set_blend_mode", blend_space->get_blend_mode());
undo_redo->add_do_method(this, "_update_space");
undo_redo->add_undo_method(this, "_update_space");
undo_redo->commit_action();
@@ -752,6 +756,10 @@ void AnimationNodeBlendSpace2DEditor::_notification(int p_what) {
snap->set_icon(get_icon("SnapGrid", "EditorIcons"));
open_editor->set_icon(get_icon("Edit", "EditorIcons"));
auto_triangles->set_icon(get_icon("AutoTriangle", "EditorIcons"));
+ interpolation->clear();
+ interpolation->add_icon_item(get_icon("TrackContinuous", "EditorIcons"), "", 0);
+ interpolation->add_icon_item(get_icon("TrackDiscrete", "EditorIcons"), "", 1);
+ interpolation->add_icon_item(get_icon("TrackCapture", "EditorIcons"), "", 2);
}
if (p_what == NOTIFICATION_PROCESS) {
@@ -914,6 +922,13 @@ AnimationNodeBlendSpace2DEditor::AnimationNodeBlendSpace2DEditor() {
snap_y->set_step(0.01);
snap_y->set_max(1000);
+ top_hb->add_child(memnew(VSeparator));
+
+ top_hb->add_child(memnew(Label(TTR("Blend:"))));
+ interpolation = memnew(OptionButton);
+ top_hb->add_child(interpolation);
+ interpolation->connect("item_selected", this, "_config_changed");
+
edit_hb = memnew(HBoxContainer);
top_hb->add_child(edit_hb);
edit_hb->add_child(memnew(VSeparator));
diff --git a/editor/plugins/animation_blend_space_2d_editor.h b/editor/plugins/animation_blend_space_2d_editor.h
index 613289e4d8..603fa1cd19 100644
--- a/editor/plugins/animation_blend_space_2d_editor.h
+++ b/editor/plugins/animation_blend_space_2d_editor.h
@@ -60,6 +60,7 @@ class AnimationNodeBlendSpace2DEditor : public AnimationTreeNodeEditorPlugin {
ToolButton *snap;
SpinBox *snap_x;
SpinBox *snap_y;
+ OptionButton *interpolation;
ToolButton *auto_triangles;
diff --git a/editor/plugins/canvas_item_editor_plugin.cpp b/editor/plugins/canvas_item_editor_plugin.cpp
index 1add99bdcc..ee2283a035 100644
--- a/editor/plugins/canvas_item_editor_plugin.cpp
+++ b/editor/plugins/canvas_item_editor_plugin.cpp
@@ -5070,19 +5070,13 @@ void CanvasItemEditorViewport::_create_nodes(Node *parent, Node *child, String &
editor_data->get_undo_redo().add_do_property(child, "polygon", list);
}
- // locate at preview position
- Point2 pos = Point2(0, 0);
- if (parent && parent->has_method("get_global_position")) {
- pos = parent->call("get_global_position");
- }
- Transform2D trans = canvas->get_canvas_transform();
- Point2 target_position = (p_point - trans.get_origin()) / trans.get_scale().x - pos;
- if (default_type == "Polygon2D" || default_type == "TouchScreenButton" || default_type == "TextureRect" || default_type == "NinePatchRect") {
- target_position -= texture_size / 2;
- }
+ // Compute the global position
+ Transform2D xform = canvas_item_editor->get_canvas_transform();
+ Point2 target_position = xform.affine_inverse().xform(p_point);
+
// there's nothing to be used as source position so snapping will work as absolute if enabled
- target_position = canvas->snap_point(target_position);
- editor_data->get_undo_redo().add_do_method(child, "set_position", target_position);
+ target_position = canvas_item_editor->snap_point(target_position);
+ editor_data->get_undo_redo().add_do_method(child, "set_global_position", target_position);
}
bool CanvasItemEditorViewport::_create_instance(Node *parent, String &path, const Point2 &p_point) {
@@ -5117,8 +5111,8 @@ bool CanvasItemEditorViewport::_create_instance(Node *parent, String &path, cons
CanvasItem *parent_ci = Object::cast_to<CanvasItem>(parent);
if (parent_ci) {
- Vector2 target_pos = canvas->get_canvas_transform().affine_inverse().xform(p_point);
- target_pos = canvas->snap_point(target_pos);
+ Vector2 target_pos = canvas_item_editor->get_canvas_transform().affine_inverse().xform(p_point);
+ target_pos = canvas_item_editor->snap_point(target_pos);
target_pos = parent_ci->get_global_transform_with_canvas().affine_inverse().xform(target_pos);
editor_data->get_undo_redo().add_do_method(instanced_scene, "set_position", target_pos);
}
@@ -5238,7 +5232,7 @@ bool CanvasItemEditorViewport::can_drop_data(const Point2 &p_point, const Varian
if (!preview_node->get_parent()) { // create preview only once
_create_preview(files);
}
- Transform2D trans = canvas->get_canvas_transform();
+ Transform2D trans = canvas_item_editor->get_canvas_transform();
preview_node->set_position((p_point - trans.get_origin()) / trans.get_scale().x);
label->set_text(vformat(TTR("Adding %s..."), default_type));
}
@@ -5333,7 +5327,7 @@ void CanvasItemEditorViewport::_bind_methods() {
ClassDB::bind_method(D_METHOD("_on_mouse_exit"), &CanvasItemEditorViewport::_on_mouse_exit);
}
-CanvasItemEditorViewport::CanvasItemEditorViewport(EditorNode *p_node, CanvasItemEditor *p_canvas) {
+CanvasItemEditorViewport::CanvasItemEditorViewport(EditorNode *p_node, CanvasItemEditor *p_canvas_item_editor) {
default_type = "Sprite";
// Node2D
types.push_back("Sprite");
@@ -5348,7 +5342,7 @@ CanvasItemEditorViewport::CanvasItemEditorViewport(EditorNode *p_node, CanvasIte
target_node = NULL;
editor = p_node;
editor_data = editor->get_scene_tree_dock()->get_editor_data();
- canvas = p_canvas;
+ canvas_item_editor = p_canvas_item_editor;
preview_node = memnew(Node2D);
accept = memnew(AcceptDialog);
diff --git a/editor/plugins/canvas_item_editor_plugin.h b/editor/plugins/canvas_item_editor_plugin.h
index f71eb1b605..207e57dbe2 100644
--- a/editor/plugins/canvas_item_editor_plugin.h
+++ b/editor/plugins/canvas_item_editor_plugin.h
@@ -608,7 +608,7 @@ class CanvasItemEditorViewport : public Control {
EditorNode *editor;
EditorData *editor_data;
- CanvasItemEditor *canvas;
+ CanvasItemEditor *canvas_item_editor;
Node2D *preview_node;
AcceptDialog *accept;
WindowDialog *selector;
@@ -642,7 +642,7 @@ public:
virtual bool can_drop_data(const Point2 &p_point, const Variant &p_data) const;
virtual void drop_data(const Point2 &p_point, const Variant &p_data);
- CanvasItemEditorViewport(EditorNode *p_node, CanvasItemEditor *p_canvas);
+ CanvasItemEditorViewport(EditorNode *p_node, CanvasItemEditor *p_canvas_item_editor);
~CanvasItemEditorViewport();
};
diff --git a/editor/plugins/script_text_editor.cpp b/editor/plugins/script_text_editor.cpp
index c3e2aa86f0..ad1eab1340 100644
--- a/editor/plugins/script_text_editor.cpp
+++ b/editor/plugins/script_text_editor.cpp
@@ -443,6 +443,7 @@ void ScriptTextEditor::_validate_script() {
if (!script->get_language()->validate(text, line, col, errortxt, script->get_path(), &fnc, &warnings, &safe_lines)) {
String error_text = "error(" + itos(line) + "," + itos(col) + "): " + errortxt;
code_editor->set_error(error_text);
+ code_editor->set_error_pos(line - 1, col - 1);
} else {
code_editor->set_error("");
line = -1;
diff --git a/editor/plugins/shader_editor_plugin.cpp b/editor/plugins/shader_editor_plugin.cpp
index 638de1b213..6bc5c77df2 100644
--- a/editor/plugins/shader_editor_plugin.cpp
+++ b/editor/plugins/shader_editor_plugin.cpp
@@ -193,6 +193,7 @@ void ShaderTextEditor::_validate_script() {
if (err != OK) {
String error_text = "error(" + itos(sl.get_error_line()) + "): " + sl.get_error_text();
set_error(error_text);
+ set_error_pos(sl.get_error_line() - 1, 0);
for (int i = 0; i < get_text_edit()->get_line_count(); i++)
get_text_edit()->set_line_as_marked(i, false);
get_text_edit()->set_line_as_marked(sl.get_error_line() - 1, true);
diff --git a/editor/plugins/spatial_editor_plugin.cpp b/editor/plugins/spatial_editor_plugin.cpp
index fa2f54d0b3..a5563c0497 100644
--- a/editor/plugins/spatial_editor_plugin.cpp
+++ b/editor/plugins/spatial_editor_plugin.cpp
@@ -1901,7 +1901,7 @@ void SpatialEditorViewport::_nav_orbit(Ref<InputEventWithModifiers> p_event, con
real_t degrees_per_pixel = EditorSettings::get_singleton()->get("editors/3d/navigation_feel/orbit_sensitivity");
real_t radians_per_pixel = Math::deg2rad(degrees_per_pixel);
- bool invert_y_axis = EditorSettings::get_singleton()->get("editors/3d/navigation/invert_y-axis");
+ bool invert_y_axis = EditorSettings::get_singleton()->get("editors/3d/navigation/invert_y_axis");
if (invert_y_axis) {
cursor.x_rot -= p_relative.y * radians_per_pixel;
@@ -1926,7 +1926,7 @@ void SpatialEditorViewport::_nav_look(Ref<InputEventWithModifiers> p_event, cons
real_t degrees_per_pixel = EditorSettings::get_singleton()->get("editors/3d/navigation_feel/orbit_sensitivity");
real_t radians_per_pixel = Math::deg2rad(degrees_per_pixel);
- bool invert_y_axis = EditorSettings::get_singleton()->get("editors/3d/navigation/invert_y-axis");
+ bool invert_y_axis = EditorSettings::get_singleton()->get("editors/3d/navigation/invert_y_axis");
// Note: do NOT assume the camera has the "current" transform, because it is interpolated and may have "lag".
Transform prev_camera_transform = to_camera_transform(cursor);
@@ -4204,10 +4204,10 @@ void SpatialEditor::set_state(const Dictionary &p_state) {
gizmo_plugins.write[j]->set_state(state);
switch (state) {
- case EditorSpatialGizmoPlugin::ON_TOP:
+ case EditorSpatialGizmoPlugin::VISIBLE:
gizmos_menu->set_item_icon(idx, gizmos_menu->get_icon("visibility_visible"));
break;
- case EditorSpatialGizmoPlugin::VISIBLE:
+ case EditorSpatialGizmoPlugin::ON_TOP:
gizmos_menu->set_item_icon(idx, gizmos_menu->get_icon("visibility_xray"));
break;
case EditorSpatialGizmoPlugin::HIDDEN:
@@ -4317,10 +4317,10 @@ void SpatialEditor::_menu_gizmo_toggled(int p_option) {
// Change icon
const int state = gizmos_menu->get_item_state(idx);
switch (state) {
- case EditorSpatialGizmoPlugin::ON_TOP:
+ case EditorSpatialGizmoPlugin::VISIBLE:
gizmos_menu->set_item_icon(idx, view_menu->get_popup()->get_icon("visibility_visible"));
break;
- case EditorSpatialGizmoPlugin::VISIBLE:
+ case EditorSpatialGizmoPlugin::ON_TOP:
gizmos_menu->set_item_icon(idx, view_menu->get_popup()->get_icon("visibility_xray"));
break;
case EditorSpatialGizmoPlugin::HIDDEN:
@@ -4839,7 +4839,7 @@ void SpatialEditor::_init_gizmos_menu() {
for (int i = 0; i < gizmo_plugins.size(); ++i) {
if (!gizmo_plugins[i]->can_be_hidden()) continue;
String plugin_name = gizmo_plugins[i]->get_name();
- gizmos_menu->add_multistate_item(TTR(plugin_name), 3, EditorSpatialGizmoPlugin::ON_TOP, i);
+ gizmos_menu->add_multistate_item(TTR(plugin_name), 3, EditorSpatialGizmoPlugin::VISIBLE, i);
gizmos_menu->set_item_icon(gizmos_menu->get_item_index(i), gizmos_menu->get_icon("visibility_visible"));
}
}
@@ -5919,7 +5919,7 @@ void EditorSpatialGizmoPlugin::unregister_gizmo(EditorSpatialGizmo *p_gizmo) {
}
EditorSpatialGizmoPlugin::EditorSpatialGizmoPlugin() {
- current_state = ON_TOP;
+ current_state = VISIBLE;
}
EditorSpatialGizmoPlugin::~EditorSpatialGizmoPlugin() {
diff --git a/editor/plugins/spatial_editor_plugin.h b/editor/plugins/spatial_editor_plugin.h
index 3cce76cc17..c515a4aaf9 100644
--- a/editor/plugins/spatial_editor_plugin.h
+++ b/editor/plugins/spatial_editor_plugin.h
@@ -754,9 +754,9 @@ class EditorSpatialGizmoPlugin : public Resource {
GDCLASS(EditorSpatialGizmoPlugin, Resource);
public:
- static const int ON_TOP = 0;
- static const int VISIBLE = 1;
- static const int HIDDEN = 2;
+ static const int VISIBLE = 0;
+ static const int HIDDEN = 1;
+ static const int ON_TOP = 2;
private:
int current_state;
diff --git a/editor/scene_tree_editor.cpp b/editor/scene_tree_editor.cpp
index 6614e24df7..95f0c4870e 100644
--- a/editor/scene_tree_editor.cpp
+++ b/editor/scene_tree_editor.cpp
@@ -980,8 +980,11 @@ void SceneTreeEditor::_editor_settings_changed() {
if (enable_rl) {
tree->add_constant_override("draw_relationship_lines", 1);
tree->add_color_override("relationship_line_color", rl_color);
- } else
+ tree->add_constant_override("draw_guides", 0);
+ } else {
tree->add_constant_override("draw_relationship_lines", 0);
+ tree->add_constant_override("draw_guides", 1);
+ }
}
void SceneTreeEditor::_bind_methods() {
diff --git a/editor/script_editor_debugger.cpp b/editor/script_editor_debugger.cpp
index 089ffa285d..559ab32505 100644
--- a/editor/script_editor_debugger.cpp
+++ b/editor/script_editor_debugger.cpp
@@ -602,6 +602,7 @@ void ScriptEditorDebugger::_parse_message(const String &p_msg, const Array &p_da
String n = p_data[ofs + i * 2 + 0];
Variant v = p_data[ofs + i * 2 + 1];
+
PropertyHint h = PROPERTY_HINT_NONE;
String hs = String();
@@ -1041,8 +1042,11 @@ void ScriptEditorDebugger::_notification(int p_what) {
if (enable_rl) {
inspect_scene_tree->add_constant_override("draw_relationship_lines", 1);
inspect_scene_tree->add_color_override("relationship_line_color", rl_color);
- } else
+ inspect_scene_tree->add_constant_override("draw_guides", 0);
+ } else {
inspect_scene_tree->add_constant_override("draw_relationship_lines", 0);
+ inspect_scene_tree->add_constant_override("draw_guides", 1);
+ }
} break;
case NOTIFICATION_PROCESS: {
diff --git a/gles_builders.py b/gles_builders.py
index f9fd6d3fa2..e56ccc4431 100644
--- a/gles_builders.py
+++ b/gles_builders.py
@@ -231,9 +231,9 @@ def build_legacygl_header(filename, include, class_suffix, output_attribs, gles2
fd.write("\t_FORCE_INLINE_ void set_conditional(Conditionals p_conditional,bool p_enable) { _set_conditional(p_conditional,p_enable); }\n\n")
fd.write("\t#ifdef DEBUG_ENABLED\n ")
fd.write("\t#define _FU if (get_uniform(p_uniform)<0) return; if (!is_version_valid()) return; ERR_FAIL_COND( get_active()!=this ); \n\n ")
- fd.write("\t#else\n ")
+ fd.write("\t#else\n ")
fd.write("\t#define _FU if (get_uniform(p_uniform)<0) return; \n\n ")
- fd.write("\t#endif\n")
+ fd.write("\t#endif\n")
fd.write("\t_FORCE_INLINE_ void set_uniform(Uniforms p_uniform, float p_value) { _FU glUniform1f(get_uniform(p_uniform),p_value); }\n\n")
fd.write("\t_FORCE_INLINE_ void set_uniform(Uniforms p_uniform, double p_value) { _FU glUniform1f(get_uniform(p_uniform),p_value); }\n\n")
fd.write("\t_FORCE_INLINE_ void set_uniform(Uniforms p_uniform, uint8_t p_value) { _FU glUniform1i(get_uniform(p_uniform),p_value); }\n\n")
diff --git a/methods.py b/methods.py
index 111a2347be..5fcbc94298 100644
--- a/methods.py
+++ b/methods.py
@@ -591,7 +591,7 @@ def generate_vs_project(env, num_jobs):
release_debug_targets = ['bin\\godot.windows.opt.tools.32.exe'] + ['bin\\godot.windows.opt.tools.64.exe']
targets = debug_targets + release_targets + release_debug_targets
if not env.get('MSVS'):
- env['MSVS']['PROJECTSUFFIX'] = '.vcxproj'
+ env['MSVS']['PROJECTSUFFIX'] = '.vcxproj'
env['MSVS']['SOLUTIONSUFFIX'] = '.sln'
env.MSVSProject(
target=['#godot' + env['MSVSPROJECTSUFFIX']],
@@ -628,3 +628,27 @@ def CommandNoCache(env, target, sources, command, **args):
result = env.Command(target, sources, command, **args)
env.NoCache(result)
return result
+
+def detect_darwin_sdk_path(platform, env):
+ sdk_name = ''
+ if platform == 'osx':
+ sdk_name = 'macosx'
+ var_name = 'MACOS_SDK_PATH'
+ elif platform == 'iphone':
+ sdk_name = 'iphoneos'
+ var_name = 'IPHONESDK'
+ elif platform == 'iphonesimulator':
+ sdk_name = 'iphonesimulator'
+ var_name = 'IPHONESDK'
+ else:
+ raise Exception("Invalid platform argument passed to detect_darwin_sdk_path")
+
+ if not env[var_name]:
+ try:
+ sdk_path = subprocess.check_output(['xcrun', '--sdk', sdk_name, '--show-sdk-path']).strip()
+ if sdk_path:
+ env[var_name] = sdk_path
+ except (subprocess.CalledProcessError, OSError) as e:
+ print("Failed to find SDK path while running xcrun --sdk {} --show-sdk-path.".format(sdk_name))
+ raise
+
diff --git a/modules/bullet/bullet_physics_server.h b/modules/bullet/bullet_physics_server.h
index 6b7dcd86e6..c8c782267e 100644
--- a/modules/bullet/bullet_physics_server.h
+++ b/modules/bullet/bullet_physics_server.h
@@ -397,6 +397,8 @@ public:
virtual void flush_queries();
virtual void finish();
+ virtual bool is_flushing_queries() const { return false; }
+
virtual int get_process_info(ProcessInfo p_info);
CollisionObjectBullet *get_collisin_object(RID p_object) const;
diff --git a/modules/bullet/collision_object_bullet.cpp b/modules/bullet/collision_object_bullet.cpp
index 402a276f95..441fa7c8af 100644
--- a/modules/bullet/collision_object_bullet.cpp
+++ b/modules/bullet/collision_object_bullet.cpp
@@ -304,7 +304,11 @@ bool RigidCollisionObjectBullet::is_shape_disabled(int p_index) {
}
void RigidCollisionObjectBullet::shape_changed(int p_shape_index) {
- bulletdelete(shapes.write[p_shape_index].bt_shape);
+ ShapeWrapper &shp = shapes.write[p_shape_index];
+ if (shp.bt_shape == mainShape) {
+ mainShape = NULL;
+ }
+ bulletdelete(shp.bt_shape);
reload_shapes();
}
@@ -366,5 +370,8 @@ void RigidCollisionObjectBullet::body_scale_changed() {
void RigidCollisionObjectBullet::internal_shape_destroy(int p_index, bool p_permanentlyFromThisBody) {
ShapeWrapper &shp = shapes.write[p_index];
shp.shape->remove_owner(this, p_permanentlyFromThisBody);
+ if (shp.bt_shape == mainShape) {
+ mainShape = NULL;
+ }
bulletdelete(shp.bt_shape);
}
diff --git a/modules/bullet/generic_6dof_joint_bullet.cpp b/modules/bullet/generic_6dof_joint_bullet.cpp
index a36f1123bc..a94b88d566 100644
--- a/modules/bullet/generic_6dof_joint_bullet.cpp
+++ b/modules/bullet/generic_6dof_joint_bullet.cpp
@@ -135,6 +135,15 @@ void Generic6DOFJointBullet::set_param(Vector3::Axis p_axis, PhysicsServer::G6DO
case PhysicsServer::G6DOF_JOINT_LINEAR_MOTOR_FORCE_LIMIT:
sixDOFConstraint->getTranslationalLimitMotor()->m_maxMotorForce.m_floats[p_axis] = p_value;
break;
+ case PhysicsServer::G6DOF_JOINT_LINEAR_SPRING_DAMPING:
+ sixDOFConstraint->getTranslationalLimitMotor()->m_springDamping.m_floats[p_axis] = p_value;
+ break;
+ case PhysicsServer::G6DOF_JOINT_LINEAR_SPRING_STIFFNESS:
+ sixDOFConstraint->getTranslationalLimitMotor()->m_springStiffness.m_floats[p_axis] = p_value;
+ break;
+ case PhysicsServer::G6DOF_JOINT_LINEAR_SPRING_EQUILIBRIUM_POINT:
+ sixDOFConstraint->getTranslationalLimitMotor()->m_equilibriumPoint.m_floats[p_axis] = p_value;
+ break;
case PhysicsServer::G6DOF_JOINT_ANGULAR_LOWER_LIMIT:
limits_lower[1][p_axis] = p_value;
set_flag(p_axis, PhysicsServer::G6DOF_JOINT_FLAG_ENABLE_ANGULAR_LIMIT, flags[p_axis][PhysicsServer::G6DOF_JOINT_FLAG_ENABLE_ANGULAR_LIMIT]); // Reload bullet parameter
@@ -143,6 +152,9 @@ void Generic6DOFJointBullet::set_param(Vector3::Axis p_axis, PhysicsServer::G6DO
limits_upper[1][p_axis] = p_value;
set_flag(p_axis, PhysicsServer::G6DOF_JOINT_FLAG_ENABLE_ANGULAR_LIMIT, flags[p_axis][PhysicsServer::G6DOF_JOINT_FLAG_ENABLE_ANGULAR_LIMIT]); // Reload bullet parameter
break;
+ case PhysicsServer::G6DOF_JOINT_ANGULAR_RESTITUTION:
+ sixDOFConstraint->getRotationalLimitMotor(p_axis)->m_bounce = p_value;
+ break;
case PhysicsServer::G6DOF_JOINT_ANGULAR_ERP:
sixDOFConstraint->getRotationalLimitMotor(p_axis)->m_stopERP = p_value;
break;
@@ -152,6 +164,15 @@ void Generic6DOFJointBullet::set_param(Vector3::Axis p_axis, PhysicsServer::G6DO
case PhysicsServer::G6DOF_JOINT_ANGULAR_MOTOR_FORCE_LIMIT:
sixDOFConstraint->getRotationalLimitMotor(p_axis)->m_maxMotorForce = p_value;
break;
+ case PhysicsServer::G6DOF_JOINT_ANGULAR_SPRING_STIFFNESS:
+ sixDOFConstraint->getRotationalLimitMotor(p_axis)->m_springStiffness = p_value;
+ break;
+ case PhysicsServer::G6DOF_JOINT_ANGULAR_SPRING_DAMPING:
+ sixDOFConstraint->getRotationalLimitMotor(p_axis)->m_springDamping = p_value;
+ break;
+ case PhysicsServer::G6DOF_JOINT_ANGULAR_SPRING_EQUILIBRIUM_POINT:
+ sixDOFConstraint->getRotationalLimitMotor(p_axis)->m_equilibriumPoint = p_value;
+ break;
default:
ERR_EXPLAIN("This parameter " + itos(p_param) + " is deprecated");
WARN_DEPRECATED
@@ -170,6 +191,12 @@ real_t Generic6DOFJointBullet::get_param(Vector3::Axis p_axis, PhysicsServer::G6
return sixDOFConstraint->getTranslationalLimitMotor()->m_targetVelocity.m_floats[p_axis];
case PhysicsServer::G6DOF_JOINT_LINEAR_MOTOR_FORCE_LIMIT:
return sixDOFConstraint->getTranslationalLimitMotor()->m_maxMotorForce.m_floats[p_axis];
+ case PhysicsServer::G6DOF_JOINT_LINEAR_SPRING_DAMPING:
+ return sixDOFConstraint->getTranslationalLimitMotor()->m_springDamping.m_floats[p_axis];
+ case PhysicsServer::G6DOF_JOINT_LINEAR_SPRING_STIFFNESS:
+ return sixDOFConstraint->getTranslationalLimitMotor()->m_springStiffness.m_floats[p_axis];
+ case PhysicsServer::G6DOF_JOINT_LINEAR_SPRING_EQUILIBRIUM_POINT:
+ return sixDOFConstraint->getTranslationalLimitMotor()->m_equilibriumPoint.m_floats[p_axis];
case PhysicsServer::G6DOF_JOINT_ANGULAR_LOWER_LIMIT:
return limits_lower[1][p_axis];
case PhysicsServer::G6DOF_JOINT_ANGULAR_UPPER_LIMIT:
@@ -182,6 +209,12 @@ real_t Generic6DOFJointBullet::get_param(Vector3::Axis p_axis, PhysicsServer::G6
return sixDOFConstraint->getRotationalLimitMotor(p_axis)->m_targetVelocity;
case PhysicsServer::G6DOF_JOINT_ANGULAR_MOTOR_FORCE_LIMIT:
return sixDOFConstraint->getRotationalLimitMotor(p_axis)->m_maxMotorForce;
+ case PhysicsServer::G6DOF_JOINT_ANGULAR_SPRING_STIFFNESS:
+ return sixDOFConstraint->getRotationalLimitMotor(p_axis)->m_springStiffness;
+ case PhysicsServer::G6DOF_JOINT_ANGULAR_SPRING_DAMPING:
+ return sixDOFConstraint->getRotationalLimitMotor(p_axis)->m_springDamping;
+ case PhysicsServer::G6DOF_JOINT_ANGULAR_SPRING_EQUILIBRIUM_POINT:
+ return sixDOFConstraint->getRotationalLimitMotor(p_axis)->m_equilibriumPoint;
default:
ERR_EXPLAIN("This parameter " + itos(p_param) + " is deprecated");
WARN_DEPRECATED;
@@ -215,6 +248,12 @@ void Generic6DOFJointBullet::set_flag(Vector3::Axis p_axis, PhysicsServer::G6DOF
case PhysicsServer::G6DOF_JOINT_FLAG_ENABLE_LINEAR_MOTOR:
sixDOFConstraint->getTranslationalLimitMotor()->m_enableMotor[p_axis] = flags[p_axis][p_flag];
break;
+ case PhysicsServer::G6DOF_JOINT_FLAG_ENABLE_LINEAR_SPRING:
+ sixDOFConstraint->getTranslationalLimitMotor()->m_enableSpring[p_axis] = p_value;
+ break;
+ case PhysicsServer::G6DOF_JOINT_FLAG_ENABLE_ANGULAR_SPRING:
+ sixDOFConstraint->getRotationalLimitMotor(p_axis)->m_enableSpring = p_value;
+ break;
default:
ERR_EXPLAIN("This flag " + itos(p_flag) + " is deprecated");
WARN_DEPRECATED
@@ -224,6 +263,5 @@ void Generic6DOFJointBullet::set_flag(Vector3::Axis p_axis, PhysicsServer::G6DOF
bool Generic6DOFJointBullet::get_flag(Vector3::Axis p_axis, PhysicsServer::G6DOFJointAxisFlag p_flag) const {
ERR_FAIL_INDEX_V(p_axis, 3, false);
-
return flags[p_axis][p_flag];
}
diff --git a/modules/bullet/rigid_body_bullet.cpp b/modules/bullet/rigid_body_bullet.cpp
index 37e7718969..9dd04100ed 100644
--- a/modules/bullet/rigid_body_bullet.cpp
+++ b/modules/bullet/rigid_body_bullet.cpp
@@ -268,6 +268,7 @@ RigidBodyBullet::RigidBodyBullet() :
can_integrate_forces(false),
maxCollisionsDetection(0),
collisionsCount(0),
+ prev_collision_count(0),
maxAreasWhereIam(10),
areaWhereIamCount(0),
countGravityPointSpaces(0),
@@ -293,6 +294,9 @@ RigidBodyBullet::RigidBodyBullet() :
areasWhereIam.write[i] = NULL;
}
btBody->setSleepingThresholds(0.2, 0.2);
+
+ prev_collision_traces = &collision_traces_1;
+ curr_collision_traces = &collision_traces_2;
}
RigidBodyBullet::~RigidBodyBullet() {
@@ -410,7 +414,14 @@ void RigidBodyBullet::on_collision_filters_change() {
}
void RigidBodyBullet::on_collision_checker_start() {
+
+ prev_collision_count = collisionsCount;
collisionsCount = 0;
+
+ // Swap array
+ Vector<RigidBodyBullet *> *s = prev_collision_traces;
+ prev_collision_traces = curr_collision_traces;
+ curr_collision_traces = s;
}
void RigidBodyBullet::on_collision_checker_end() {
@@ -433,10 +444,20 @@ bool RigidBodyBullet::add_collision_object(RigidBodyBullet *p_otherObject, const
cd.other_object_shape = p_other_shape_index;
cd.local_shape = p_local_shape_index;
+ curr_collision_traces->write[collisionsCount] = p_otherObject;
+
++collisionsCount;
return true;
}
+bool RigidBodyBullet::was_colliding(RigidBodyBullet *p_other_object) {
+ for (int i = prev_collision_count - 1; 0 <= i; --i) {
+ if ((*prev_collision_traces)[i] == p_other_object)
+ return true;
+ }
+ return false;
+}
+
void RigidBodyBullet::assert_no_constraints() {
if (btBody->getNumConstraintRefs()) {
WARN_PRINT("A body with a joints is destroyed. Please check the implementation in order to destroy the joint before the body.");
@@ -797,7 +818,10 @@ void RigidBodyBullet::reload_shapes() {
const btScalar mass = invMass == 0 ? 0 : 1 / invMass;
if (mainShape) {
- btVector3 inertia;
+ // inertia initialised zero here because some of bullet's collision
+ // shapes incorrectly do not set the vector in calculateLocalIntertia.
+ // Arbitrary zero is preferable to undefined behaviour.
+ btVector3 inertia(0, 0, 0);
mainShape->calculateLocalInertia(mass, inertia);
btBody->setMassProps(mass, inertia);
}
diff --git a/modules/bullet/rigid_body_bullet.h b/modules/bullet/rigid_body_bullet.h
index 26e5018c87..0696073d21 100644
--- a/modules/bullet/rigid_body_bullet.h
+++ b/modules/bullet/rigid_body_bullet.h
@@ -205,9 +205,15 @@ private:
bool can_integrate_forces;
Vector<CollisionData> collisions;
+ Vector<RigidBodyBullet *> collision_traces_1;
+ Vector<RigidBodyBullet *> collision_traces_2;
+ Vector<RigidBodyBullet *> *prev_collision_traces;
+ Vector<RigidBodyBullet *> *curr_collision_traces;
+
// these parameters are used to avoid vector resize
int maxCollisionsDetection;
int collisionsCount;
+ int prev_collision_count;
Vector<AreaBullet *> areasWhereIam;
// these parameters are used to avoid vector resize
@@ -244,9 +250,17 @@ public:
virtual void on_collision_checker_end();
void set_max_collisions_detection(int p_maxCollisionsDetection) {
+
+ ERR_FAIL_COND(0 > p_maxCollisionsDetection);
+
maxCollisionsDetection = p_maxCollisionsDetection;
+
collisions.resize(p_maxCollisionsDetection);
+ collision_traces_1.resize(p_maxCollisionsDetection);
+ collision_traces_2.resize(p_maxCollisionsDetection);
+
collisionsCount = 0;
+ prev_collision_count = MIN(prev_collision_count, p_maxCollisionsDetection);
}
int get_max_collisions_detection() {
return maxCollisionsDetection;
@@ -254,6 +268,7 @@ public:
bool can_add_collision() { return collisionsCount < maxCollisionsDetection; }
bool add_collision_object(RigidBodyBullet *p_otherObject, const Vector3 &p_hitWorldLocation, const Vector3 &p_hitLocalLocation, const Vector3 &p_hitNormal, const float &p_appliedImpulse, int p_other_shape_index, int p_local_shape_index);
+ bool was_colliding(RigidBodyBullet *p_other_object);
void assert_no_constraints();
diff --git a/modules/bullet/space_bullet.cpp b/modules/bullet/space_bullet.cpp
index ab2d1781ad..fed12cd5ed 100644
--- a/modules/bullet/space_bullet.cpp
+++ b/modules/bullet/space_bullet.cpp
@@ -786,16 +786,22 @@ void SpaceBullet::check_body_collision() {
}
const int numContacts = contactManifold->getNumContacts();
+
+ /// Since I don't need report all contacts for these objects,
+ /// So report only the first
#define REPORT_ALL_CONTACTS 0
#if REPORT_ALL_CONTACTS
for (int j = 0; j < numContacts; j++) {
btManifoldPoint &pt = contactManifold->getContactPoint(j);
#else
- // Since I don't need report all contacts for these objects, I'll report only the first
if (numContacts) {
btManifoldPoint &pt = contactManifold->getContactPoint(0);
#endif
- if (pt.getDistance() <= 0.0) {
+ if (
+ pt.getDistance() <= 0.0 ||
+ bodyA->was_colliding(bodyB) ||
+ bodyB->was_colliding(bodyA)) {
+
Vector3 collisionWorldPosition;
Vector3 collisionLocalPosition;
Vector3 normalOnB;
diff --git a/modules/csg/csg_shape.cpp b/modules/csg/csg_shape.cpp
index 4eb798de11..a4c34e7583 100644
--- a/modules/csg/csg_shape.cpp
+++ b/modules/csg/csg_shape.cpp
@@ -159,6 +159,72 @@ CSGBrush *CSGShape::_get_brush() {
return brush;
}
+int CSGShape::mikktGetNumFaces(const SMikkTSpaceContext *pContext) {
+ ShapeUpdateSurface &surface = *((ShapeUpdateSurface *)pContext->m_pUserData);
+
+ return surface.vertices.size() / 3;
+}
+
+int CSGShape::mikktGetNumVerticesOfFace(const SMikkTSpaceContext *pContext, const int iFace) {
+ // always 3
+ return 3;
+}
+
+void CSGShape::mikktGetPosition(const SMikkTSpaceContext *pContext, float fvPosOut[], const int iFace, const int iVert) {
+ ShapeUpdateSurface &surface = *((ShapeUpdateSurface *)pContext->m_pUserData);
+
+ Vector3 v = surface.verticesw[iFace * 3 + iVert];
+ fvPosOut[0] = v.x;
+ fvPosOut[1] = v.y;
+ fvPosOut[2] = v.z;
+}
+
+void CSGShape::mikktGetNormal(const SMikkTSpaceContext *pContext, float fvNormOut[], const int iFace, const int iVert) {
+ ShapeUpdateSurface &surface = *((ShapeUpdateSurface *)pContext->m_pUserData);
+
+ Vector3 n = surface.normalsw[iFace * 3 + iVert];
+ fvNormOut[0] = n.x;
+ fvNormOut[1] = n.y;
+ fvNormOut[2] = n.z;
+}
+
+void CSGShape::mikktGetTexCoord(const SMikkTSpaceContext *pContext, float fvTexcOut[], const int iFace, const int iVert) {
+ ShapeUpdateSurface &surface = *((ShapeUpdateSurface *)pContext->m_pUserData);
+
+ Vector2 t = surface.uvsw[iFace * 3 + iVert];
+ fvTexcOut[0] = t.x;
+ fvTexcOut[1] = t.y;
+}
+
+void CSGShape::mikktSetTSpaceBasic(const SMikkTSpaceContext *pContext, const float fvTangent[], const float fSign, const int iFace, const int iVert) {
+ ShapeUpdateSurface &surface = *((ShapeUpdateSurface *)pContext->m_pUserData);
+
+ int i = (iFace * 3 + iVert) * 4;
+
+ surface.tansw[i++] = fvTangent[0];
+ surface.tansw[i++] = fvTangent[1];
+ surface.tansw[i++] = fvTangent[2];
+ surface.tansw[i++] = fSign;
+}
+
+void CSGShape::mikktSetTSpaceDefault(const SMikkTSpaceContext *pContext, const float fvTangent[], const float fvBiTangent[], const float fMagS, const float fMagT,
+ const tbool bIsOrientationPreserving, const int iFace, const int iVert) {
+
+ ShapeUpdateSurface &surface = *((ShapeUpdateSurface *)pContext->m_pUserData);
+
+ int i = iFace * 3 + iVert;
+ Vector3 normal = surface.normalsw[i];
+ Vector3 tangent = Vector3(fvTangent[0], fvTangent[1], fvTangent[2]);
+ Vector3 bitangent = Vector3(fvBiTangent[0], fvBiTangent[1], fvBiTangent[2]);
+ float d = bitangent.dot(normal.cross(tangent));
+
+ i *= 4;
+ surface.tansw[i++] = tangent.x;
+ surface.tansw[i++] = tangent.y;
+ surface.tansw[i++] = tangent.z;
+ surface.tansw[i++] = d < 0 ? -1 : 1;
+}
+
void CSGShape::_update_shape() {
if (parent)
@@ -211,6 +277,9 @@ void CSGShape::_update_shape() {
surfaces.write[i].vertices.resize(face_count[i] * 3);
surfaces.write[i].normals.resize(face_count[i] * 3);
surfaces.write[i].uvs.resize(face_count[i] * 3);
+ if (calculate_tangents) {
+ surfaces.write[i].tans.resize(face_count[i] * 3 * 4);
+ }
surfaces.write[i].last_added = 0;
if (i != surfaces.size() - 1) {
@@ -220,6 +289,9 @@ void CSGShape::_update_shape() {
surfaces.write[i].verticesw = surfaces.write[i].vertices.write();
surfaces.write[i].normalsw = surfaces.write[i].normals.write();
surfaces.write[i].uvsw = surfaces.write[i].uvs.write();
+ if (calculate_tangents) {
+ surfaces.write[i].tansw = surfaces.write[i].tans.write();
+ }
}
//fill arrays
@@ -274,9 +346,19 @@ void CSGShape::_update_shape() {
normal = -normal;
}
- surfaces[idx].verticesw[last + order[j]] = v;
- surfaces[idx].uvsw[last + order[j]] = n->faces[i].uvs[j];
- surfaces[idx].normalsw[last + order[j]] = normal;
+ int k = last + order[j];
+ surfaces[idx].verticesw[k] = v;
+ surfaces[idx].uvsw[k] = n->faces[i].uvs[j];
+ surfaces[idx].normalsw[k] = normal;
+
+ if (calculate_tangents) {
+ // zero out our tangents for now
+ k *= 4;
+ surfaces[idx].tansw[k++] = 0.0;
+ surfaces[idx].tansw[k++] = 0.0;
+ surfaces[idx].tansw[k++] = 0.0;
+ surfaces[idx].tansw[k++] = 0.0;
+ }
}
surfaces.write[idx].last_added += 3;
@@ -287,20 +369,43 @@ void CSGShape::_update_shape() {
//create surfaces
for (int i = 0; i < surfaces.size(); i++) {
+ // calculate tangents for this surface
+ bool have_tangents = calculate_tangents;
+ if (have_tangents) {
+ SMikkTSpaceInterface mkif;
+ mkif.m_getNormal = mikktGetNormal;
+ mkif.m_getNumFaces = mikktGetNumFaces;
+ mkif.m_getNumVerticesOfFace = mikktGetNumVerticesOfFace;
+ mkif.m_getPosition = mikktGetPosition;
+ mkif.m_getTexCoord = mikktGetTexCoord;
+ mkif.m_setTSpace = mikktSetTSpaceDefault;
+ mkif.m_setTSpaceBasic = NULL;
+
+ SMikkTSpaceContext msc;
+ msc.m_pInterface = &mkif;
+ msc.m_pUserData = &surfaces.write[i];
+ have_tangents = genTangSpaceDefault(&msc);
+ }
+ // unset write access
surfaces.write[i].verticesw = PoolVector<Vector3>::Write();
surfaces.write[i].normalsw = PoolVector<Vector3>::Write();
surfaces.write[i].uvsw = PoolVector<Vector2>::Write();
+ surfaces.write[i].tansw = PoolVector<float>::Write();
if (surfaces[i].last_added == 0)
continue;
+ // and convert to surface array
Array array;
array.resize(Mesh::ARRAY_MAX);
array[Mesh::ARRAY_VERTEX] = surfaces[i].vertices;
array[Mesh::ARRAY_NORMAL] = surfaces[i].normals;
array[Mesh::ARRAY_TEX_UV] = surfaces[i].uvs;
+ if (have_tangents) {
+ array[Mesh::ARRAY_TANGENT] = surfaces[i].tans;
+ }
int idx = root_mesh->get_surface_count();
root_mesh->add_surface_from_arrays(Mesh::PRIMITIVE_TRIANGLES, array);
@@ -400,6 +505,15 @@ CSGShape::Operation CSGShape::get_operation() const {
return operation;
}
+void CSGShape::set_calculate_tangents(bool p_calculate_tangents) {
+ calculate_tangents = p_calculate_tangents;
+ _make_dirty();
+}
+
+bool CSGShape::is_calculating_tangents() const {
+ return calculate_tangents;
+}
+
void CSGShape::_validate_property(PropertyInfo &property) const {
if (is_inside_tree() && property.name.begins_with("use_collision") && !is_root_shape()) {
//hide collision if not root
@@ -421,9 +535,13 @@ void CSGShape::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_snap", "snap"), &CSGShape::set_snap);
ClassDB::bind_method(D_METHOD("get_snap"), &CSGShape::get_snap);
+ ClassDB::bind_method(D_METHOD("set_calculate_tangents", "enabled"), &CSGShape::set_calculate_tangents);
+ ClassDB::bind_method(D_METHOD("is_calculating_tangents"), &CSGShape::is_calculating_tangents);
+
ADD_PROPERTY(PropertyInfo(Variant::INT, "operation", PROPERTY_HINT_ENUM, "Union,Intersection,Subtraction"), "set_operation", "get_operation");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "use_collision"), "set_use_collision", "is_using_collision");
ADD_PROPERTY(PropertyInfo(Variant::REAL, "snap", PROPERTY_HINT_RANGE, "0.0001,1,0.001"), "set_snap", "get_snap");
+ ADD_PROPERTY(PropertyInfo(Variant::BOOL, "calculate_tangents"), "set_calculate_tangents", "is_calculating_tangents");
BIND_ENUM_CONSTANT(OPERATION_UNION);
BIND_ENUM_CONSTANT(OPERATION_INTERSECTION);
@@ -438,6 +556,7 @@ CSGShape::CSGShape() {
use_collision = false;
operation = OPERATION_UNION;
snap = 0.001;
+ calculate_tangents = true;
}
CSGShape::~CSGShape() {
@@ -1545,6 +1664,24 @@ CSGBrush *CSGPolygon::_build_brush() {
Path *path = NULL;
Ref<Curve3D> curve;
+ // get bounds for our polygon
+ Vector2 final_polygon_min;
+ Vector2 final_polygon_max;
+ for (int i = 0; i < final_polygon.size(); i++) {
+ Vector2 p = final_polygon[i];
+ if (i == 0) {
+ final_polygon_min = p;
+ final_polygon_max = final_polygon_min;
+ } else {
+ if (p.x < final_polygon_min.x) final_polygon_min.x = p.x;
+ if (p.y < final_polygon_min.y) final_polygon_min.y = p.y;
+
+ if (p.x > final_polygon_max.x) final_polygon_max.x = p.x;
+ if (p.y > final_polygon_max.y) final_polygon_max.y = p.y;
+ }
+ }
+ Vector2 final_polygon_size = final_polygon_max - final_polygon_min;
+
if (mode == MODE_PATH) {
if (!has_node(path_node))
return NULL;
@@ -1636,6 +1773,10 @@ CSGBrush *CSGPolygon::_build_brush() {
v.z -= depth;
}
facesw[face * 3 + k] = v;
+ uvsw[face * 3 + k] = (p - final_polygon_min) / final_polygon_size;
+ if (i == 0) {
+ uvsw[face * 3 + k].x = 1.0 - uvsw[face * 3 + k].x; /* flip x */
+ }
}
smoothw[face] = false;
@@ -1767,6 +1908,7 @@ CSGBrush *CSGPolygon::_build_brush() {
Vector2 p = final_polygon[triangles[j + src[k]]];
Vector3 v = Vector3(p.x, p.y, 0);
facesw[face * 3 + k] = v;
+ uvsw[face * 3 + k] = (p - final_polygon_min) / final_polygon_size;
}
smoothw[face] = false;
@@ -1784,6 +1926,8 @@ CSGBrush *CSGPolygon::_build_brush() {
Vector2 p = final_polygon[triangles[j + src[k]]];
Vector3 v = Vector3(normali_n.x * p.x, p.y, normali_n.z * p.x);
facesw[face * 3 + k] = v;
+ uvsw[face * 3 + k] = (p - final_polygon_min) / final_polygon_size;
+ uvsw[face * 3 + k].x = 1.0 - uvsw[face * 3 + k].x; /* flip x */
}
smoothw[face] = false;
@@ -1869,10 +2013,10 @@ CSGBrush *CSGPolygon::_build_brush() {
};
Vector2 u[4] = {
- Vector2(u1, 0),
Vector2(u1, 1),
- Vector2(u2, 1),
- Vector2(u2, 0)
+ Vector2(u1, 0),
+ Vector2(u2, 0),
+ Vector2(u2, 1)
};
// face 1
@@ -1915,6 +2059,7 @@ CSGBrush *CSGPolygon::_build_brush() {
Vector2 p = final_polygon[triangles[j + src[k]]];
Vector3 v = Vector3(p.x, p.y, 0);
facesw[face * 3 + k] = xf.xform(v);
+ uvsw[face * 3 + k] = (p - final_polygon_min) / final_polygon_size;
}
smoothw[face] = false;
@@ -1932,6 +2077,8 @@ CSGBrush *CSGPolygon::_build_brush() {
Vector2 p = final_polygon[triangles[j + src[k]]];
Vector3 v = Vector3(p.x, p.y, 0);
facesw[face * 3 + k] = xf.xform(v);
+ uvsw[face * 3 + k] = (p - final_polygon_min) / final_polygon_size;
+ uvsw[face * 3 + k].x = 1.0 - uvsw[face * 3 + k].x; /* flip x */
}
smoothw[face] = false;
@@ -1956,6 +2103,9 @@ CSGBrush *CSGPolygon::_build_brush() {
} else {
aabb.expand_to(facesw[i]);
}
+
+ // invert UVs on the Y-axis OpenGL = upside down
+ uvsw[i].y = 1.0 - uvsw[i].y;
}
}
diff --git a/modules/csg/csg_shape.h b/modules/csg/csg_shape.h
index 6898cdaf64..0a4bb5f665 100644
--- a/modules/csg/csg_shape.h
+++ b/modules/csg/csg_shape.h
@@ -36,6 +36,7 @@
#include "csg.h"
#include "scene/3d/visual_instance.h"
#include "scene/resources/concave_polygon_shape.h"
+#include "thirdparty/misc/mikktspace.h"
class CSGShape : public VisualInstance {
GDCLASS(CSGShape, VisualInstance);
@@ -63,6 +64,8 @@ private:
Ref<ConcavePolygonShape> root_collision_shape;
RID root_collision_instance;
+ bool calculate_tangents;
+
Ref<ArrayMesh> root_mesh;
struct Vector3Hasher {
@@ -78,14 +81,26 @@ private:
PoolVector<Vector3> vertices;
PoolVector<Vector3> normals;
PoolVector<Vector2> uvs;
+ PoolVector<float> tans;
Ref<Material> material;
int last_added;
PoolVector<Vector3>::Write verticesw;
PoolVector<Vector3>::Write normalsw;
PoolVector<Vector2>::Write uvsw;
+ PoolVector<float>::Write tansw;
};
+ //mikktspace callbacks
+ static int mikktGetNumFaces(const SMikkTSpaceContext *pContext);
+ static int mikktGetNumVerticesOfFace(const SMikkTSpaceContext *pContext, const int iFace);
+ static void mikktGetPosition(const SMikkTSpaceContext *pContext, float fvPosOut[], const int iFace, const int iVert);
+ static void mikktGetNormal(const SMikkTSpaceContext *pContext, float fvNormOut[], const int iFace, const int iVert);
+ static void mikktGetTexCoord(const SMikkTSpaceContext *pContext, float fvTexcOut[], const int iFace, const int iVert);
+ static void mikktSetTSpaceBasic(const SMikkTSpaceContext *pContext, const float fvTangent[], const float fSign, const int iFace, const int iVert);
+ static void mikktSetTSpaceDefault(const SMikkTSpaceContext *pContext, const float fvTangent[], const float fvBiTangent[], const float fMagS, const float fMagT,
+ const tbool bIsOrientationPreserving, const int iFace, const int iVert);
+
void _update_shape();
protected:
@@ -115,6 +130,9 @@ public:
void set_snap(float p_snap);
float get_snap() const;
+ void set_calculate_tangents(bool p_calculate_tangents);
+ bool is_calculating_tangents() const;
+
bool is_root_shape() const;
CSGShape();
~CSGShape();
diff --git a/modules/csg/doc_classes/CSGShape.xml b/modules/csg/doc_classes/CSGShape.xml
index 90621b94f4..ac3c2342fc 100644
--- a/modules/csg/doc_classes/CSGShape.xml
+++ b/modules/csg/doc_classes/CSGShape.xml
@@ -20,6 +20,9 @@
</method>
</methods>
<members>
+ <member name="calculate_tangents" type="bool" setter="set_calculate_tangents" getter="is_calculating_tangents">
+ Calculate tangents for the CSG shape which allows the use of normal maps. This is only applied on the root shape, this setting is ignored on any child.
+ </member>
<member name="operation" type="int" setter="set_operation" getter="get_operation" enum="CSGShape.Operation">
The operation that is performed on this shape. This is ignored for the first CSG child node as the operation is between this node and the previous child of this nodes parent.
</member>
diff --git a/modules/gdnative/gdnative_builders.py b/modules/gdnative/gdnative_builders.py
index f9d1ed9dc5..ff18a3ae69 100644
--- a/modules/gdnative/gdnative_builders.py
+++ b/modules/gdnative/gdnative_builders.py
@@ -87,20 +87,20 @@ def _build_gdnative_api_struct_header(api):
ret_val = []
if core['next']:
ret_val += generate_core_extension_struct(core['next'])
-
+
ret_val += [
'typedef struct godot_gdnative_core_' + ('{0}_{1}'.format(core['version']['major'], core['version']['minor'])) + '_api_struct {',
'\tunsigned int type;',
'\tgodot_gdnative_api_version version;',
'\tconst godot_gdnative_api_struct *next;',
]
-
+
for funcdef in core['api']:
args = ', '.join(['%s%s' % (_spaced(t), n) for t, n in funcdef['arguments']])
ret_val.append('\t%s(*%s)(%s);' % (_spaced(funcdef['return_type']), funcdef['name'], args))
-
+
ret_val += ['} godot_gdnative_core_' + '{0}_{1}'.format(core['version']['major'], core['version']['minor']) + '_api_struct;', '']
-
+
return ret_val
@@ -171,26 +171,26 @@ def _build_gdnative_api_struct_source(api):
ret_val += ['};\n']
return ret_val
-
-
+
+
def get_core_struct_definition(core):
ret_val = []
-
+
if core['next']:
ret_val += get_core_struct_definition(core['next'])
-
+
ret_val += [
'extern const godot_gdnative_core_' + ('{0}_{1}_api_struct api_{0}_{1}'.format(core['version']['major'], core['version']['minor'])) + ' = {',
'\tGDNATIVE_' + core['type'] + ',',
'\t{' + str(core['version']['major']) + ', ' + str(core['version']['minor']) + '},',
'\t' + ('NULL' if not core['next'] else ('(const godot_gdnative_api_struct *)& api_{0}_{1}'.format(core['version']['major'], core['version']['minor']))) + ','
]
-
+
for funcdef in core['api']:
ret_val.append('\t%s,' % funcdef['name'])
-
+
ret_val += ['};\n']
-
+
return ret_val
for ext in api['extensions']:
@@ -204,7 +204,7 @@ def _build_gdnative_api_struct_source(api):
out += ['\t(godot_gdnative_api_struct *)&api_extension_' + name + '_struct,']
out += ['};\n']
-
+
if api['core']['next']:
out += get_core_struct_definition(api['core']['next'])
diff --git a/modules/gdscript/gdscript_function.cpp b/modules/gdscript/gdscript_function.cpp
index 31115a4bd9..c67cf124c0 100644
--- a/modules/gdscript/gdscript_function.cpp
+++ b/modules/gdscript/gdscript_function.cpp
@@ -477,56 +477,53 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a
GET_VARIANT_PTR(dst, 3);
#ifdef DEBUG_ENABLED
- if (a->get_type() != Variant::OBJECT || a->operator Object *() == NULL) {
-
- err_text = "Left operand of 'is' is not an instance of anything.";
- OPCODE_BREAK;
- }
if (b->get_type() != Variant::OBJECT || b->operator Object *() == NULL) {
err_text = "Right operand of 'is' is not a class.";
OPCODE_BREAK;
}
#endif
- Object *obj_A = *a;
- Object *obj_B = *b;
-
- GDScript *scr_B = Object::cast_to<GDScript>(obj_B);
bool extends_ok = false;
+ if (a->get_type() == Variant::OBJECT && a->operator Object *() != NULL) {
+ Object *obj_A = *a;
+ Object *obj_B = *b;
- if (scr_B) {
- //if B is a script, the only valid condition is that A has an instance which inherits from the script
- //in other situation, this shoul return false.
+ GDScript *scr_B = Object::cast_to<GDScript>(obj_B);
- if (obj_A->get_script_instance() && obj_A->get_script_instance()->get_language() == GDScriptLanguage::get_singleton()) {
+ if (scr_B) {
+ //if B is a script, the only valid condition is that A has an instance which inherits from the script
+ //in other situation, this shoul return false.
- GDScript *cmp = static_cast<GDScript *>(obj_A->get_script_instance()->get_script().ptr());
- //bool found=false;
- while (cmp) {
+ if (obj_A->get_script_instance() && obj_A->get_script_instance()->get_language() == GDScriptLanguage::get_singleton()) {
- if (cmp == scr_B) {
- //inherits from script, all ok
- extends_ok = true;
- break;
- }
+ GDScript *cmp = static_cast<GDScript *>(obj_A->get_script_instance()->get_script().ptr());
+ //bool found=false;
+ while (cmp) {
- cmp = cmp->_base;
+ if (cmp == scr_B) {
+ //inherits from script, all ok
+ extends_ok = true;
+ break;
+ }
+
+ cmp = cmp->_base;
+ }
}
- }
- } else {
+ } else {
- GDScriptNativeClass *nc = Object::cast_to<GDScriptNativeClass>(obj_B);
+ GDScriptNativeClass *nc = Object::cast_to<GDScriptNativeClass>(obj_B);
#ifdef DEBUG_ENABLED
- if (!nc) {
+ if (!nc) {
- err_text = "Right operand of 'is' is not a class (type: '" + obj_B->get_class() + "').";
- OPCODE_BREAK;
- }
+ err_text = "Right operand of 'is' is not a class (type: '" + obj_B->get_class() + "').";
+ OPCODE_BREAK;
+ }
#endif
- extends_ok = ClassDB::is_parent_class(obj_A->get_class_name(), nc->get_name());
+ extends_ok = ClassDB::is_parent_class(obj_A->get_class_name(), nc->get_name());
+ }
}
*dst = extends_ok;
diff --git a/modules/gdscript/gdscript_parser.cpp b/modules/gdscript/gdscript_parser.cpp
index 09b3a5631f..a4bda42b16 100644
--- a/modules/gdscript/gdscript_parser.cpp
+++ b/modules/gdscript/gdscript_parser.cpp
@@ -6432,6 +6432,10 @@ bool GDScriptParser::_get_function_signature(DataType &p_base_type, const String
StringName native;
if (p_base_type.kind == DataType::GDSCRIPT) {
base_gdscript = p_base_type.script_type;
+ if (base_gdscript.is_null() || !base_gdscript->is_valid()) {
+ // GDScript wasn't properly compíled, don't bother trying
+ return false;
+ }
} else if (p_base_type.kind == DataType::SCRIPT) {
base_script = p_base_type.script_type;
} else if (p_base_type.kind == DataType::NATIVE) {
@@ -6472,6 +6476,12 @@ bool GDScriptParser::_get_function_signature(DataType &p_base_type, const String
base_script = base_script->get_base_script();
}
+ if (native == StringName()) {
+ // Empty native class, might happen in some Script implementations
+ // Just ignore it
+ return false;
+ }
+
#ifdef DEBUG_METHODS_ENABLED
// Only native remains
@@ -6914,6 +6924,10 @@ bool GDScriptParser::_get_member_type(const DataType &p_base_type, const StringN
Ref<GDScript> gds;
if (base_type.kind == DataType::GDSCRIPT) {
gds = base_type.script_type;
+ if (gds.is_null() || !gds->is_valid()) {
+ // GDScript wasn't properly compíled, don't bother trying
+ return false;
+ }
}
Ref<Script> scr;
@@ -6976,6 +6990,12 @@ bool GDScriptParser::_get_member_type(const DataType &p_base_type, const StringN
scr = scr->get_base_script();
}
+ if (native == StringName()) {
+ // Empty native class, might happen in some Script implementations
+ // Just ignore it
+ return false;
+ }
+
// Check ClassDB
if (!ClassDB::class_exists(native)) {
native = "_" + native.operator String();
diff --git a/modules/gridmap/grid_map_editor_plugin.cpp b/modules/gridmap/grid_map_editor_plugin.cpp
index fae88042af..126b49832a 100644
--- a/modules/gridmap/grid_map_editor_plugin.cpp
+++ b/modules/gridmap/grid_map_editor_plugin.cpp
@@ -802,7 +802,9 @@ void GridMapEditor::edit(GridMap *p_gridmap) {
VisualServer::get_singleton()->instance_set_visible(grid_instance[i], false);
}
- VisualServer::get_singleton()->instance_set_visible(cursor_instance, false);
+ if (cursor_instance.is_valid()) {
+ VisualServer::get_singleton()->instance_set_visible(cursor_instance, false);
+ }
return;
}
diff --git a/modules/mono/glue/Managed/Files/AABB.cs b/modules/mono/glue/Managed/Files/AABB.cs
index 66490b5e25..33b2b46712 100644
--- a/modules/mono/glue/Managed/Files/AABB.cs
+++ b/modules/mono/glue/Managed/Files/AABB.cs
@@ -407,8 +407,8 @@ namespace Godot
return new AABB(min, max - min);
}
-
- // Constructors
+
+ // Constructors
public AABB(Vector3 position, Vector3 size)
{
_position = position;
diff --git a/modules/mono/glue/Managed/Files/Basis.cs b/modules/mono/glue/Managed/Files/Basis.cs
index a5618cb28d..b318d96bb9 100644
--- a/modules/mono/glue/Managed/Files/Basis.cs
+++ b/modules/mono/glue/Managed/Files/Basis.cs
@@ -13,9 +13,9 @@ namespace Godot
{
private static readonly Basis identity = new Basis
(
- new Vector3(1f, 0f, 0f),
- new Vector3(0f, 1f, 0f),
- new Vector3(0f, 0f, 1f)
+ 1f, 0f, 0f,
+ 0f, 1f, 0f,
+ 0f, 0f, 1f
);
private static readonly Basis[] orthoBases = {
@@ -159,9 +159,9 @@ namespace Godot
{
return new Basis
(
- new Vector3(xAxis.x, yAxis.x, zAxis.x),
- new Vector3(xAxis.y, yAxis.y, zAxis.y),
- new Vector3(xAxis.z, yAxis.z, zAxis.z)
+ xAxis.x, yAxis.x, zAxis.x,
+ xAxis.y, yAxis.y, zAxis.y,
+ xAxis.z, yAxis.z, zAxis.z
);
}
@@ -410,10 +410,12 @@ namespace Godot
);
}
- public Quat Quat() {
+ public Quat Quat()
+ {
real_t trace = _x[0] + _y[1] + _z[2];
- if (trace > 0.0f) {
+ if (trace > 0.0f)
+ {
real_t s = Mathf.Sqrt(trace + 1.0f) * 2f;
real_t inv_s = 1f / s;
return new Quat(
@@ -424,7 +426,8 @@ namespace Godot
);
}
- if (_x[0] > _y[1] && _x[0] > _z[2]) {
+ if (_x[0] > _y[1] && _x[0] > _z[2])
+ {
real_t s = Mathf.Sqrt(_x[0] - _y[1] - _z[2] + 1.0f) * 2f;
real_t inv_s = 1f / s;
return new Quat(
@@ -435,7 +438,8 @@ namespace Godot
);
}
- if (_y[1] > _z[2]) {
+ if (_y[1] > _z[2])
+ {
real_t s = Mathf.Sqrt(-_x[0] + _y[1] - _z[2] + 1.0f) * 2f;
real_t inv_s = 1f / s;
return new Quat(
@@ -444,7 +448,9 @@ namespace Godot
(_y[2] + _z[1]) * inv_s,
(_x[2] - _z[0]) * inv_s
);
- } else {
+ }
+ else
+ {
real_t s = Mathf.Sqrt(-_x[0] - _y[1] + _z[2] + 1.0f) * 2f;
real_t inv_s = 1f / s;
return new Quat(
@@ -502,8 +508,8 @@ namespace Godot
{
var axis_sq = new Vector3(axis.x * axis.x, axis.y * axis.y, axis.z * axis.z);
- real_t cosine = Mathf.Cos( phi);
- real_t sine = Mathf.Sin( phi);
+ real_t cosine = Mathf.Cos(phi);
+ real_t sine = Mathf.Sin(phi);
_x = new Vector3
(
@@ -529,12 +535,17 @@ namespace Godot
public Basis(Vector3 xAxis, Vector3 yAxis, Vector3 zAxis)
{
- _x = xAxis;
- _y = yAxis;
- _z = zAxis;
+ _x = new Vector3(xAxis.x, yAxis.x, zAxis.x);
+ _y = new Vector3(xAxis.y, yAxis.y, zAxis.y);
+ _z = new Vector3(xAxis.z, yAxis.z, zAxis.z);
+ // Same as:
+ // SetAxis(0, xAxis);
+ // SetAxis(1, yAxis);
+ // SetAxis(2, zAxis);
+ // We need to assign the struct fields so we can't do that...
}
- public Basis(real_t xx, real_t xy, real_t xz, real_t yx, real_t yy, real_t yz, real_t zx, real_t zy, real_t zz)
+ internal Basis(real_t xx, real_t xy, real_t xz, real_t yx, real_t yy, real_t yz, real_t zx, real_t zy, real_t zz)
{
_x = new Vector3(xx, xy, xz);
_y = new Vector3(yx, yy, yz);
diff --git a/modules/mono/glue/Managed/Files/Color.cs b/modules/mono/glue/Managed/Files/Color.cs
index 88cb8524b8..fc5bb010a9 100644
--- a/modules/mono/glue/Managed/Files/Color.cs
+++ b/modules/mono/glue/Managed/Files/Color.cs
@@ -379,8 +379,8 @@ namespace Godot
return txt;
}
-
- // Constructors
+
+ // Constructors
public Color(float r, float g, float b, float a = 1.0f)
{
this.r = r;
diff --git a/modules/mono/glue/Managed/Files/Mathf.cs b/modules/mono/glue/Managed/Files/Mathf.cs
index a89dfe5f27..dcab3c1ffc 100644
--- a/modules/mono/glue/Managed/Files/Mathf.cs
+++ b/modules/mono/glue/Managed/Files/Mathf.cs
@@ -206,7 +206,7 @@ namespace Godot
public static real_t PosMod(real_t a, real_t b)
{
real_t c = a % b;
- if ((c < 0 && b > 0) || (c > 0 && b < 0))
+ if ((c < 0 && b > 0) || (c > 0 && b < 0))
{
c += b;
}
@@ -219,7 +219,7 @@ namespace Godot
public static int PosMod(int a, int b)
{
int c = a % b;
- if ((c < 0 && b > 0) || (c > 0 && b < 0))
+ if ((c < 0 && b > 0) || (c > 0 && b < 0))
{
c += b;
}
diff --git a/modules/mono/glue/Managed/Files/MathfEx.cs b/modules/mono/glue/Managed/Files/MathfEx.cs
index 739b7fb568..2ef02cc288 100644
--- a/modules/mono/glue/Managed/Files/MathfEx.cs
+++ b/modules/mono/glue/Managed/Files/MathfEx.cs
@@ -29,7 +29,7 @@ namespace Godot
public static int FloorToInt(real_t s)
{
return (int)Math.Floor(s);
- }
+ }
public static int RoundToInt(real_t s)
{
diff --git a/modules/mono/glue/Managed/Files/Plane.cs b/modules/mono/glue/Managed/Files/Plane.cs
index 9611dce11e..f11cd490a9 100644
--- a/modules/mono/glue/Managed/Files/Plane.cs
+++ b/modules/mono/glue/Managed/Files/Plane.cs
@@ -144,7 +144,7 @@ namespace Godot
{
return point - _normal * DistanceTo(point);
}
-
+
// Constants
private static readonly Plane _planeYZ = new Plane(1, 0, 0, 0);
private static readonly Plane _planeXZ = new Plane(0, 1, 0, 0);
@@ -153,8 +153,8 @@ namespace Godot
public static Plane PlaneYZ { get { return _planeYZ; } }
public static Plane PlaneXZ { get { return _planeXZ; } }
public static Plane PlaneXY { get { return _planeXY; } }
-
- // Constructors
+
+ // Constructors
public Plane(real_t a, real_t b, real_t c, real_t d)
{
_normal = new Vector3(a, b, c);
diff --git a/modules/mono/glue/Managed/Files/Quat.cs b/modules/mono/glue/Managed/Files/Quat.cs
index eaa027eb69..fd1ac01083 100644
--- a/modules/mono/glue/Managed/Files/Quat.cs
+++ b/modules/mono/glue/Managed/Files/Quat.cs
@@ -202,7 +202,7 @@ namespace Godot
// Static Readonly Properties
public static Quat Identity { get; } = new Quat(0f, 0f, 0f, 1f);
- // Constructors
+ // Constructors
public Quat(real_t x, real_t y, real_t z, real_t w)
{
this.x = x;
diff --git a/modules/mono/glue/Managed/Files/Rect2.cs b/modules/mono/glue/Managed/Files/Rect2.cs
index cb25c267bc..888f300347 100644
--- a/modules/mono/glue/Managed/Files/Rect2.cs
+++ b/modules/mono/glue/Managed/Files/Rect2.cs
@@ -182,8 +182,8 @@ namespace Godot
return newRect;
}
-
- // Constructors
+
+ // Constructors
public Rect2(Vector2 position, Vector2 size)
{
_position = position;
diff --git a/modules/mono/glue/Managed/Files/StringExtensions.cs b/modules/mono/glue/Managed/Files/StringExtensions.cs
index 21c9be98c1..c194facd0b 100644
--- a/modules/mono/glue/Managed/Files/StringExtensions.cs
+++ b/modules/mono/glue/Managed/Files/StringExtensions.cs
@@ -185,7 +185,7 @@ namespace Godot
int instanceIndex = 0;
int toIndex = 0;
-
+
if (caseSensitive) // Outside while loop to avoid checking multiple times, despite some code duplication.
{
while (true)
@@ -480,9 +480,9 @@ namespace Godot
return false; // Don't start with number plz
}
- bool validChar = instance[i] >= '0' &&
- instance[i] <= '9' || instance[i] >= 'a' &&
- instance[i] <= 'z' || instance[i] >= 'A' &&
+ bool validChar = instance[i] >= '0' &&
+ instance[i] <= '9' || instance[i] >= 'a' &&
+ instance[i] <= 'z' || instance[i] >= 'A' &&
instance[i] <= 'Z' || instance[i] == '_';
if (!validChar)
diff --git a/modules/mono/glue/Managed/Files/Transform.cs b/modules/mono/glue/Managed/Files/Transform.cs
index 068007d7f0..fa85855edd 100644
--- a/modules/mono/glue/Managed/Files/Transform.cs
+++ b/modules/mono/glue/Managed/Files/Transform.cs
@@ -124,16 +124,16 @@ namespace Godot
// Constants
private static readonly Transform _identity = new Transform(Basis.Identity, Vector3.Zero);
- private static readonly Transform _flipX = new Transform(new Basis(new Vector3(-1, 0, 0), new Vector3(0, 1, 0), new Vector3(0, 0, 1)), Vector3.Zero);
- private static readonly Transform _flipY = new Transform(new Basis(new Vector3(1, 0, 0), new Vector3(0, -1, 0), new Vector3(0, 0, 1)), Vector3.Zero);
- private static readonly Transform _flipZ = new Transform(new Basis(new Vector3(1, 0, 0), new Vector3(0, 1, 0), new Vector3(0, 0, -1)), Vector3.Zero);
+ private static readonly Transform _flipX = new Transform(new Basis(-1, 0, 0, 0, 1, 0, 0, 0, 1), Vector3.Zero);
+ private static readonly Transform _flipY = new Transform(new Basis(1, 0, 0, 0, -1, 0, 0, 0, 1), Vector3.Zero);
+ private static readonly Transform _flipZ = new Transform(new Basis(1, 0, 0, 0, 1, 0, 0, 0, -1), Vector3.Zero);
public static Transform Identity { get { return _identity; } }
public static Transform FlipX { get { return _flipX; } }
public static Transform FlipY { get { return _flipY; } }
public static Transform FlipZ { get { return _flipZ; } }
- // Constructors
+ // Constructors
public Transform(Vector3 xAxis, Vector3 yAxis, Vector3 zAxis, Vector3 origin)
{
basis = Basis.CreateFromAxes(xAxis, yAxis, zAxis);
diff --git a/modules/mono/glue/Managed/Files/Transform2D.cs b/modules/mono/glue/Managed/Files/Transform2D.cs
index 8d30833066..c9e5b560b2 100644
--- a/modules/mono/glue/Managed/Files/Transform2D.cs
+++ b/modules/mono/glue/Managed/Files/Transform2D.cs
@@ -261,15 +261,15 @@ namespace Godot
public static Transform2D Identity { get { return _identity; } }
public static Transform2D FlipX { get { return _flipX; } }
public static Transform2D FlipY { get { return _flipY; } }
-
- // Constructors
+
+ // Constructors
public Transform2D(Vector2 xAxis, Vector2 yAxis, Vector2 origin)
{
x = xAxis;
y = yAxis;
o = origin;
}
-
+
public Transform2D(real_t xx, real_t xy, real_t yx, real_t yy, real_t ox, real_t oy)
{
x = new Vector2(xx, xy);
diff --git a/modules/mono/glue/Managed/Files/Vector2.cs b/modules/mono/glue/Managed/Files/Vector2.cs
index 080b8802ba..ce41886bfc 100644
--- a/modules/mono/glue/Managed/Files/Vector2.cs
+++ b/modules/mono/glue/Managed/Files/Vector2.cs
@@ -215,7 +215,7 @@ namespace Godot
x = v.x;
y = v.y;
}
-
+
public Vector2 Slerp(Vector2 b, real_t t)
{
real_t theta = AngleTo(b);
@@ -242,7 +242,7 @@ namespace Godot
private static readonly Vector2 _one = new Vector2(1, 1);
private static readonly Vector2 _negOne = new Vector2(-1, -1);
private static readonly Vector2 _inf = new Vector2(Mathf.Inf, Mathf.Inf);
-
+
private static readonly Vector2 _up = new Vector2(0, -1);
private static readonly Vector2 _down = new Vector2(0, 1);
private static readonly Vector2 _right = new Vector2(1, 0);
diff --git a/modules/mono/glue/Managed/Files/Vector3.cs b/modules/mono/glue/Managed/Files/Vector3.cs
index 6fffe5e4d6..f6ff27989d 100644
--- a/modules/mono/glue/Managed/Files/Vector3.cs
+++ b/modules/mono/glue/Managed/Files/Vector3.cs
@@ -204,9 +204,9 @@ namespace Godot
public Basis Outer(Vector3 b)
{
return new Basis(
- new Vector3(x * b.x, x * b.y, x * b.z),
- new Vector3(y * b.x, y * b.y, y * b.z),
- new Vector3(z * b.x, z * b.y, z * b.z)
+ x * b.x, x * b.y, x * b.z,
+ y * b.x, y * b.y, y * b.z,
+ z * b.x, z * b.y, z * b.z
);
}
@@ -276,13 +276,13 @@ namespace Godot
0f, 0f, z
);
}
-
+
// Constants
private static readonly Vector3 _zero = new Vector3(0, 0, 0);
private static readonly Vector3 _one = new Vector3(1, 1, 1);
private static readonly Vector3 _negOne = new Vector3(-1, -1, -1);
private static readonly Vector3 _inf = new Vector3(Mathf.Inf, Mathf.Inf, Mathf.Inf);
-
+
private static readonly Vector3 _up = new Vector3(0, 1, 0);
private static readonly Vector3 _down = new Vector3(0, -1, 0);
private static readonly Vector3 _right = new Vector3(1, 0, 0);
@@ -294,7 +294,7 @@ namespace Godot
public static Vector3 One { get { return _one; } }
public static Vector3 NegOne { get { return _negOne; } }
public static Vector3 Inf { get { return _inf; } }
-
+
public static Vector3 Up { get { return _up; } }
public static Vector3 Down { get { return _down; } }
public static Vector3 Right { get { return _right; } }
diff --git a/modules/mono/glue/Managed/Properties/AssemblyInfo.cs b/modules/mono/glue/Managed/Properties/AssemblyInfo.cs
index 7ed68acad7..77b3774e81 100644
--- a/modules/mono/glue/Managed/Properties/AssemblyInfo.cs
+++ b/modules/mono/glue/Managed/Properties/AssemblyInfo.cs
@@ -1,7 +1,7 @@
using System.Reflection;
using System.Runtime.CompilerServices;
-// Information about this assembly is defined by the following attributes.
+// Information about this assembly is defined by the following attributes.
// Change them to the values specific to your project.
[assembly: AssemblyTitle("Managed")]
@@ -19,7 +19,7 @@ using System.Runtime.CompilerServices;
[assembly: AssemblyVersion("1.0.*")]
-// The following attributes are used to specify the signing key for the assembly,
+// The following attributes are used to specify the signing key for the assembly,
// if desired. See the Mono documentation for more information about signing.
//[assembly: AssemblyDelaySign(false)]
diff --git a/modules/squish/image_compress_squish.cpp b/modules/squish/image_compress_squish.cpp
index 26cb76011c..a08ac7bd28 100644
--- a/modules/squish/image_compress_squish.cpp
+++ b/modules/squish/image_compress_squish.cpp
@@ -64,12 +64,13 @@ void image_decompress_squish(Image *p_image) {
return;
}
- int dst_ofs = 0;
-
for (int i = 0; i <= mm_count; i++) {
int src_ofs = 0, mipmap_size = 0, mipmap_w = 0, mipmap_h = 0;
p_image->get_mipmap_offset_size_and_dimensions(i, src_ofs, mipmap_size, mipmap_w, mipmap_h);
- squish::DecompressImage(&wb[dst_ofs], mipmap_w, mipmap_h, &rb[src_ofs], squish_flags);
+ int dst_ofs = Image::get_image_mipmap_offset(p_image->get_width(), p_image->get_height(), target_format, i);
+ squish::DecompressImage(&wb[dst_ofs], w, h, &rb[src_ofs], squish_flags);
+ w >>= 1;
+ h >>= 1;
}
p_image->create(p_image->get_width(), p_image->get_height(), p_image->has_mipmaps(), target_format, data);
diff --git a/modules/visual_script/doc_classes/VisualScriptCustomNode.xml b/modules/visual_script/doc_classes/VisualScriptCustomNode.xml
index b8e77a1b0f..ff3ed66e81 100644
--- a/modules/visual_script/doc_classes/VisualScriptCustomNode.xml
+++ b/modules/visual_script/doc_classes/VisualScriptCustomNode.xml
@@ -125,12 +125,10 @@
</argument>
<description>
Execute the custom node's logic, returning the index of the output sequence port to use or a [String] when there is an error.
-
The [code]inputs[/code] array contains the values of the input ports.
[code]outputs[/code] is an array whose indices should be set to the respective outputs.
The [code]start_mode[/code] is usually [code]START_MODE_BEGIN_SEQUENCE[/code], unless you have used the STEP_* constants.
[code]working_mem[/code] is an array which can be used to persist information between runs of the custom node.
-
When returning, you can mask the returned value with one of the STEP_* constants.
</description>
</method>
diff --git a/modules/visual_script/visual_script_editor.cpp b/modules/visual_script/visual_script_editor.cpp
index c5f2070963..afaa6a9b95 100644
--- a/modules/visual_script/visual_script_editor.cpp
+++ b/modules/visual_script/visual_script_editor.cpp
@@ -1923,7 +1923,7 @@ void VisualScriptEditor::drop_data_fw(const Point2 &p_point, const Variant &p_da
}
}
-void VisualScriptEditor::_selected_method(const String &p_method, const String &p_type) {
+void VisualScriptEditor::_selected_method(const String &p_method, const String &p_type, const bool p_connecting) {
Ref<VisualScriptFunctionCall> vsfc = script->get_node(edited_func, selecting_method_id);
if (!vsfc.is_valid())
diff --git a/modules/visual_script/visual_script_editor.h b/modules/visual_script/visual_script_editor.h
index ce3245bc28..5f707c9e4c 100644
--- a/modules/visual_script/visual_script_editor.h
+++ b/modules/visual_script/visual_script_editor.h
@@ -234,7 +234,7 @@ class VisualScriptEditor : public ScriptEditorBase {
void _comment_node_resized(const Vector2 &p_new_size, int p_node);
int selecting_method_id;
- void _selected_method(const String &p_method, const String &p_type);
+ void _selected_method(const String &p_method, const String &p_type, const bool p_connecting);
void _draw_color_over_button(Object *obj, Color p_color);
void _button_resource_previewed(const String &p_path, const Ref<Texture> &p_preview, const Ref<Texture> &p_small_preview, Variant p_ud);
diff --git a/platform/android/detect.py b/platform/android/detect.py
index e4cab2fb23..7a728e4ef1 100644
--- a/platform/android/detect.py
+++ b/platform/android/detect.py
@@ -223,7 +223,7 @@ def configure(env):
else:
print("Using NDK deprecated headers")
env.Append(CPPFLAGS=["-isystem", lib_sysroot + "/usr/include"])
-
+
env.Append(CPPFLAGS='-fpic -ffunction-sections -funwind-tables -fstack-protector-strong -fvisibility=hidden -fno-strict-aliasing'.split())
env.Append(CPPFLAGS='-DNO_STATVFS -DGLES_ENABLED'.split())
@@ -267,12 +267,12 @@ def configure(env):
env.Append(LINKFLAGS=['-shared', '--sysroot=' + lib_sysroot, '-Wl,--warn-shared-textrel'])
if mt_link:
env.Append(LINKFLAGS=['-Wl,--threads'])
-
+
if env["android_arch"] == "armv7":
env.Append(LINKFLAGS='-Wl,--fix-cortex-a8'.split())
env.Append(LINKFLAGS='-Wl,--no-undefined -Wl,-z,noexecstack -Wl,-z,relro -Wl,-z,now'.split())
env.Append(LINKFLAGS='-Wl,-soname,libgodot_android.so -Wl,--gc-sections'.split())
-
+
env.Append(LINKFLAGS=target_opts)
env.Append(LINKFLAGS=common_opts)
diff --git a/platform/android/java/res/layout/status_bar_ongoing_event_progress_bar.xml b/platform/android/java/res/layout/status_bar_ongoing_event_progress_bar.xml
index 23bac02294..104993da7e 100644
--- a/platform/android/java/res/layout/status_bar_ongoing_event_progress_bar.xml
+++ b/platform/android/java/res/layout/status_bar_ongoing_event_progress_bar.xml
@@ -32,9 +32,9 @@
android:id="@+id/appIcon"
android:layout_width="fill_parent"
android:layout_height="25dp"
- android:scaleType="centerInside"
+ android:scaleType="centerInside"
android:layout_alignParentLeft="true"
- android:layout_alignParentTop="true"
+ android:layout_alignParentTop="true"
android:src="@android:drawable/stat_sys_download" />
<TextView
diff --git a/platform/android/java/src/org/godotengine/godot/utils/CustomSSLSocketFactory.java b/platform/android/java/src/org/godotengine/godot/utils/CustomSSLSocketFactory.java
index 7216d8b5a4..03a7a71bb1 100644
--- a/platform/android/java/src/org/godotengine/godot/utils/CustomSSLSocketFactory.java
+++ b/platform/android/java/src/org/godotengine/godot/utils/CustomSSLSocketFactory.java
@@ -44,7 +44,7 @@ import javax.net.ssl.TrustManagerFactory;
import org.apache.http.conn.ssl.SSLSocketFactory;
/**
- *
+ *
* @author Luis Linietsky <luis.linietsky@gmail.com>
*/
public class CustomSSLSocketFactory extends SSLSocketFactory {
diff --git a/platform/android/java/src/org/godotengine/godot/utils/HttpRequester.java b/platform/android/java/src/org/godotengine/godot/utils/HttpRequester.java
index b84f5cce2e..cfe9c4fef0 100644
--- a/platform/android/java/src/org/godotengine/godot/utils/HttpRequester.java
+++ b/platform/android/java/src/org/godotengine/godot/utils/HttpRequester.java
@@ -69,7 +69,7 @@ import android.content.SharedPreferences;
import android.util.Log;
/**
- *
+ *
* @author Luis Linietsky <luis.linietsky@gmail.com>
*/
public class HttpRequester {
diff --git a/platform/android/java/src/org/godotengine/godot/utils/RequestParams.java b/platform/android/java/src/org/godotengine/godot/utils/RequestParams.java
index 2368766afa..a1d5b26b3c 100644
--- a/platform/android/java/src/org/godotengine/godot/utils/RequestParams.java
+++ b/platform/android/java/src/org/godotengine/godot/utils/RequestParams.java
@@ -39,7 +39,7 @@ import org.apache.http.NameValuePair;
import org.apache.http.message.BasicNameValuePair;
/**
- *
+ *
* @author Luis Linietsky <luis.linietsky@gmail.com>
*/
public class RequestParams {
diff --git a/platform/android/java_glue.cpp b/platform/android/java_glue.cpp
index 07e4048c12..43bd841baf 100644
--- a/platform/android/java_glue.cpp
+++ b/platform/android/java_glue.cpp
@@ -268,11 +268,11 @@ Variant _jobject_to_variant(JNIEnv *env, jobject obj) {
return ret;
};
- if (name == "java.lang.Integer") {
+ if (name == "java.lang.Integer" || name == "java.lang.Long") {
jclass nclass = env->FindClass("java/lang/Number");
- jmethodID intValue = env->GetMethodID(nclass, "intValue", "()I");
- int ret = env->CallIntMethod(obj, intValue);
+ jmethodID longValue = env->GetMethodID(nclass, "longValue", "()J");
+ jlong ret = env->CallLongMethod(obj, longValue);
return ret;
};
diff --git a/platform/android/power_android.cpp b/platform/android/power_android.cpp
index 51283183df..0a6bf9dfcb 100644
--- a/platform/android/power_android.cpp
+++ b/platform/android/power_android.cpp
@@ -98,7 +98,7 @@ ANativeWindow *Android_JNI_GetNativeWindow(void) {
return anw;
}
-/*
+/*
* CODE CHUNK IMPORTED FROM SDL 2.0
* returns 0 on success or -1 on error (others undefined then)
* returns truthy or falsy value in plugged, charged and battery
diff --git a/platform/iphone/detect.py b/platform/iphone/detect.py
index 417571f6f3..c9f37931b0 100644
--- a/platform/iphone/detect.py
+++ b/platform/iphone/detect.py
@@ -1,7 +1,7 @@
import os
import string
import sys
-
+from methods import detect_darwin_sdk_path
def is_active():
return True
@@ -22,9 +22,8 @@ def can_build():
def get_opts():
from SCons.Variables import BoolVariable
return [
- ('IPHONEPLATFORM', 'Name of the iPhone platform', 'iPhoneOS'),
('IPHONEPATH', 'Path to iPhone toolchain', '/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain'),
- ('IPHONESDK', 'Path to the iPhone SDK', '/Applications/Xcode.app/Contents/Developer/Platforms/${IPHONEPLATFORM}.platform/Developer/SDKs/${IPHONEPLATFORM}.sdk/'),
+ ('IPHONESDK', 'Path to the iPhone SDK', ''),
BoolVariable('game_center', 'Support for game center', True),
BoolVariable('store_kit', 'Support for in-app store', True),
BoolVariable('icloud', 'Support for iCloud', True),
@@ -103,13 +102,15 @@ def configure(env):
## Compile flags
if (env["arch"] == "x86" or env["arch"] == "x86_64"):
- env['IPHONEPLATFORM'] = 'iPhoneSimulator'
+ detect_darwin_sdk_path('iphonesimulator', env)
env['ENV']['MACOSX_DEPLOYMENT_TARGET'] = '10.9'
arch_flag = "i386" if env["arch"] == "x86" else env["arch"]
env.Append(CCFLAGS=('-arch ' + arch_flag + ' -fobjc-abi-version=2 -fobjc-legacy-dispatch -fmessage-length=0 -fpascal-strings -fblocks -fasm-blocks -isysroot $IPHONESDK -mios-simulator-version-min=9.0 -DCUSTOM_MATRIX_TRANSFORM_H=\\\"build/iphone/matrix4_iphone.h\\\" -DCUSTOM_VECTOR3_TRANSFORM_H=\\\"build/iphone/vector3_iphone.h\\\"').split())
elif (env["arch"] == "arm"):
+ detect_darwin_sdk_path('iphone', env)
env.Append(CCFLAGS='-fno-objc-arc -arch armv7 -fmessage-length=0 -fno-strict-aliasing -fdiagnostics-print-source-range-info -fdiagnostics-show-category=id -fdiagnostics-parseable-fixits -fpascal-strings -fblocks -isysroot $IPHONESDK -fvisibility=hidden -mthumb "-DIBOutlet=__attribute__((iboutlet))" "-DIBOutletCollection(ClassName)=__attribute__((iboutletcollection(ClassName)))" "-DIBAction=void)__attribute__((ibaction)" -miphoneos-version-min=9.0 -MMD -MT dependencies'.split())
elif (env["arch"] == "arm64"):
+ detect_darwin_sdk_path('iphone', env)
env.Append(CCFLAGS='-fno-objc-arc -arch arm64 -fmessage-length=0 -fno-strict-aliasing -fdiagnostics-print-source-range-info -fdiagnostics-show-category=id -fdiagnostics-parseable-fixits -fpascal-strings -fblocks -fvisibility=hidden -MMD -MT dependencies -miphoneos-version-min=9.0 -isysroot $IPHONESDK'.split())
env.Append(CPPFLAGS=['-DNEED_LONG_INT'])
env.Append(CPPFLAGS=['-DLIBYUV_DISABLE_NEON'])
diff --git a/platform/osx/detect.py b/platform/osx/detect.py
index c5bd64b15c..051836b66d 100644
--- a/platform/osx/detect.py
+++ b/platform/osx/detect.py
@@ -1,5 +1,6 @@
import os
import sys
+from methods import detect_darwin_sdk_path
def is_active():
@@ -23,6 +24,7 @@ def get_opts():
return [
('osxcross_sdk', 'OSXCross SDK version', 'darwin14'),
+ ('MACOS_SDK_PATH', 'Path to the macOS SDK', ''),
EnumVariable('debug_symbols', 'Add debugging symbols to release builds', 'yes', ('yes', 'no', 'full')),
BoolVariable('separate_debug_symbols', 'Create a separate file containing debugging symbols', False),
]
@@ -84,6 +86,10 @@ def configure(env):
env['AS'] = mpprefix + "/libexec/llvm-" + mpclangver + "/bin/llvm-as"
env.Append(CCFLAGS=['-D__MACPORTS__']) #hack to fix libvpx MM256_BROADCASTSI128_SI256 define
+ detect_darwin_sdk_path('osx', env)
+ env.Append(CPPFLAGS=['-isysroot', '$MACOS_SDK_PATH'])
+ env.Append(LINKFLAGS=['-isysroot', '$MACOS_SDK_PATH'])
+
else: # osxcross build
root = os.environ.get("OSXCROSS_ROOT", 0)
basecmd = root + "/target/bin/x86_64-apple-" + env["osxcross_sdk"] + "-"
diff --git a/platform/osx/os_osx.mm b/platform/osx/os_osx.mm
index 81dc861f3f..e7b3e35381 100644
--- a/platform/osx/os_osx.mm
+++ b/platform/osx/os_osx.mm
@@ -76,6 +76,13 @@
#define NSWindowStyleMaskBorderless NSBorderlessWindowMask
#endif
+#ifndef NSAppKitVersionNumber10_12
+#define NSAppKitVersionNumber10_12 1504
+#endif
+#ifndef NSAppKitVersionNumber10_14
+#define NSAppKitVersionNumber10_14 1671
+#endif
+
static void get_key_modifier_state(unsigned int p_osx_state, Ref<InputEventWithModifiers> state) {
state->set_shift((p_osx_state & NSEventModifierFlagShift));
@@ -1237,7 +1244,9 @@ Error OS_OSX::initialize(const VideoMode &p_desired, int p_video_driver, int p_a
ERR_FAIL_COND_V(window_object == nil, ERR_UNAVAILABLE);
window_view = [[GodotContentView alloc] init];
- [window_view setWantsLayer:TRUE];
+ if (NSAppKitVersionNumber >= NSAppKitVersionNumber10_14) {
+ [window_view setWantsLayer:TRUE];
+ }
float displayScale = 1.0;
if (is_hidpi_allowed()) {
@@ -1470,7 +1479,7 @@ public:
switch (p_type) {
case ERR_WARNING:
- if (floor(NSAppKitVersionNumber) >= NSAppKitVersionNumber10_12) {
+ if (NSAppKitVersionNumber >= NSAppKitVersionNumber10_12) {
os_log_info(OS_LOG_DEFAULT,
"WARNING: %{public}s: %{public}s\nAt: %{public}s:%i.",
p_function, err_details, p_file, p_line);
@@ -1480,7 +1489,7 @@ public:
logf_error("\E[0;33m At: %s:%i.\E[0m\n", p_file, p_line);
break;
case ERR_SCRIPT:
- if (floor(NSAppKitVersionNumber) >= NSAppKitVersionNumber10_12) {
+ if (NSAppKitVersionNumber >= NSAppKitVersionNumber10_12) {
os_log_error(OS_LOG_DEFAULT,
"SCRIPT ERROR: %{public}s: %{public}s\nAt: %{public}s:%i.",
p_function, err_details, p_file, p_line);
@@ -1490,7 +1499,7 @@ public:
logf_error("\E[0;35m At: %s:%i.\E[0m\n", p_file, p_line);
break;
case ERR_SHADER:
- if (floor(NSAppKitVersionNumber) >= NSAppKitVersionNumber10_12) {
+ if (NSAppKitVersionNumber >= NSAppKitVersionNumber10_12) {
os_log_error(OS_LOG_DEFAULT,
"SHADER ERROR: %{public}s: %{public}s\nAt: %{public}s:%i.",
p_function, err_details, p_file, p_line);
@@ -1501,7 +1510,7 @@ public:
break;
case ERR_ERROR:
default:
- if (floor(NSAppKitVersionNumber) >= NSAppKitVersionNumber10_12) {
+ if (NSAppKitVersionNumber >= NSAppKitVersionNumber10_12) {
os_log_error(OS_LOG_DEFAULT,
"ERROR: %{public}s: %{public}s\nAt: %{public}s:%i.",
p_function, err_details, p_file, p_line);
@@ -2172,11 +2181,7 @@ void OS_OSX::set_window_size(const Size2 p_size) {
if (menuBarHeight != 0.f) {
size.y += menuBarHeight;
} else {
-#if MAC_OS_X_VERSION_MAX_ALLOWED >= 101200
if (floor(NSAppKitVersionNumber) < NSAppKitVersionNumber10_12) {
-#else
- {
-#endif
size.y += [[NSStatusBar systemStatusBar] thickness];
}
}
diff --git a/platform/windows/detect.py b/platform/windows/detect.py
index 5d5af17086..dd0042668f 100644
--- a/platform/windows/detect.py
+++ b/platform/windows/detect.py
@@ -262,7 +262,7 @@ def configure_mingw(env):
env.Append(CCFLAGS=['-O2'])
else: #optimize for size
env.Prepend(CCFLAGS=['-Os'])
-
+
env.Append(LINKFLAGS=['-Wl,--subsystem,windows'])
@@ -281,7 +281,7 @@ def configure_mingw(env):
env.Append(CCFLAGS=['-O2'])
else: #optimize for size
env.Prepend(CCFLAGS=['-Os'])
-
+
elif (env["target"] == "debug"):
env.Append(CCFLAGS=['-g3', '-DDEBUG_ENABLED', '-DDEBUG_MEMORY_ENABLED'])
diff --git a/platform/x11/os_x11.cpp b/platform/x11/os_x11.cpp
index 2ab7b835b6..04854e93b6 100644
--- a/platform/x11/os_x11.cpp
+++ b/platform/x11/os_x11.cpp
@@ -369,7 +369,7 @@ Error OS_X11::initialize(const VideoMode &p_desired, int p_video_driver, int p_a
}
// disable resizable window
- if (!current_videomode.resizable) {
+ if (!current_videomode.resizable && !current_videomode.fullscreen) {
XSizeHints *xsh;
xsh = XAllocSizeHints();
xsh->flags = PMinSize | PMaxSize;
diff --git a/scene/2d/area_2d.cpp b/scene/2d/area_2d.cpp
index 48537f3cfc..ae5891fa50 100644
--- a/scene/2d/area_2d.cpp
+++ b/scene/2d/area_2d.cpp
@@ -399,7 +399,7 @@ void Area2D::set_monitoring(bool p_enable) {
if (p_enable == monitoring)
return;
if (locked) {
- ERR_EXPLAIN("Function blocked during in/out signal. Use call_deferred(\"set_monitoring\",true/false)");
+ ERR_EXPLAIN("Function blocked during in/out signal. Use set_deferred(\"monitoring\",true/false)");
}
ERR_FAIL_COND(locked);
@@ -424,10 +424,10 @@ bool Area2D::is_monitoring() const {
void Area2D::set_monitorable(bool p_enable) {
- if (locked) {
- ERR_EXPLAIN("This function can't be used during the in/out signal.");
+ if (locked || Physics2DServer::get_singleton()->is_flushing_queries()) {
+ ERR_EXPLAIN("Function blocked during in/out signal. Use set_deferred(\"monitorable\",true/false)");
}
- ERR_FAIL_COND(locked);
+ ERR_FAIL_COND(locked || Physics2DServer::get_singleton()->is_flushing_queries());
if (p_enable == monitorable)
return;
diff --git a/scene/2d/audio_stream_player_2d.cpp b/scene/2d/audio_stream_player_2d.cpp
index a092ef826f..c2af725919 100644
--- a/scene/2d/audio_stream_player_2d.cpp
+++ b/scene/2d/audio_stream_player_2d.cpp
@@ -323,6 +323,7 @@ void AudioStreamPlayer2D::play(float p_from_pos) {
}
if (stream_playback.is_valid()) {
+ active = true;
setplay = p_from_pos;
output_ready = false;
set_physics_process_internal(true);
diff --git a/scene/2d/canvas_item.cpp b/scene/2d/canvas_item.cpp
index 6056a7f76f..0ea2e85dfa 100644
--- a/scene/2d/canvas_item.cpp
+++ b/scene/2d/canvas_item.cpp
@@ -376,6 +376,9 @@ bool CanvasItem::is_visible_in_tree() const {
void CanvasItem::_propagate_visibility_changed(bool p_visible) {
+ if (p_visible && first_draw) { //avoid propagating it twice
+ first_draw = false;
+ }
notification(NOTIFICATION_VISIBILITY_CHANGED);
if (p_visible)
diff --git a/scene/2d/cpu_particles_2d.cpp b/scene/2d/cpu_particles_2d.cpp
index a1b624a246..4fc2282ae7 100644
--- a/scene/2d/cpu_particles_2d.cpp
+++ b/scene/2d/cpu_particles_2d.cpp
@@ -1313,7 +1313,7 @@ void CPUParticles2D::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "color_ramp", PROPERTY_HINT_RESOURCE_TYPE, "GradientTexture"), "set_color_ramp", "get_color_ramp");
ADD_GROUP("Hue Variation", "hue_");
- ADD_PROPERTYI(PropertyInfo(Variant::REAL, "hue_variation", PROPERTY_HINT_RANGE, "-1,1,0.1"), "set_param", "get_param", PARAM_HUE_VARIATION);
+ ADD_PROPERTYI(PropertyInfo(Variant::REAL, "hue_variation", PROPERTY_HINT_RANGE, "-1,1,0.01"), "set_param", "get_param", PARAM_HUE_VARIATION);
ADD_PROPERTYI(PropertyInfo(Variant::REAL, "hue_variation_random", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_param_randomness", "get_param_randomness", PARAM_HUE_VARIATION);
ADD_PROPERTYI(PropertyInfo(Variant::OBJECT, "hue_variation_curve", PROPERTY_HINT_RESOURCE_TYPE, "Curve"), "set_param_curve", "get_param_curve", PARAM_HUE_VARIATION);
ADD_GROUP("Animation", "anim_");
diff --git a/scene/2d/physics_body_2d.cpp b/scene/2d/physics_body_2d.cpp
index 929b4624ee..3dde228bfa 100644
--- a/scene/2d/physics_body_2d.cpp
+++ b/scene/2d/physics_body_2d.cpp
@@ -1425,6 +1425,10 @@ void KinematicBody2D::set_sync_to_physics(bool p_enable) {
return;
}
sync_to_physics = p_enable;
+
+ if (Engine::get_singleton()->is_editor_hint())
+ return;
+
if (p_enable) {
Physics2DServer::get_singleton()->body_set_force_integration_callback(get_rid(), this, "_direct_state_changed");
set_only_update_transform_changes(true);
diff --git a/scene/2d/skeleton_2d.cpp b/scene/2d/skeleton_2d.cpp
index 2c362f1b31..1c504d00fc 100644
--- a/scene/2d/skeleton_2d.cpp
+++ b/scene/2d/skeleton_2d.cpp
@@ -298,6 +298,7 @@ Skeleton2D::Skeleton2D() {
transform_dirty = true;
skeleton = VS::get_singleton()->skeleton_create();
+ set_notify_transform(true);
}
Skeleton2D::~Skeleton2D() {
diff --git a/scene/2d/visibility_notifier_2d.cpp b/scene/2d/visibility_notifier_2d.cpp
index 7d7c47619a..d656ba0f64 100644
--- a/scene/2d/visibility_notifier_2d.cpp
+++ b/scene/2d/visibility_notifier_2d.cpp
@@ -190,7 +190,7 @@ void VisibilityEnabler2D::_find_nodes(Node *p_node) {
if (enabler[ENABLER_FREEZE_BODIES]) {
RigidBody2D *rb2d = Object::cast_to<RigidBody2D>(p_node);
- if (rb2d && ((rb2d->get_mode() == RigidBody2D::MODE_CHARACTER || (rb2d->get_mode() == RigidBody2D::MODE_RIGID && !rb2d->is_able_to_sleep())))) {
+ if (rb2d && ((rb2d->get_mode() == RigidBody2D::MODE_CHARACTER || rb2d->get_mode() == RigidBody2D::MODE_RIGID))) {
add = true;
meta = rb2d->get_mode();
diff --git a/scene/3d/area.cpp b/scene/3d/area.cpp
index 40a1029201..5e78368804 100644
--- a/scene/3d/area.cpp
+++ b/scene/3d/area.cpp
@@ -290,7 +290,7 @@ void Area::_notification(int p_what) {
void Area::set_monitoring(bool p_enable) {
if (locked) {
- ERR_EXPLAIN("This function can't be used during the in/out signal.");
+ ERR_EXPLAIN("Function blocked during in/out signal. Use set_deferred(\"monitoring\",true/false)");
}
ERR_FAIL_COND(locked);
@@ -437,10 +437,10 @@ Array Area::get_overlapping_bodies() const {
void Area::set_monitorable(bool p_enable) {
- if (locked) {
- ERR_EXPLAIN("This function can't be used during the in/out signal.");
+ if (locked || PhysicsServer::get_singleton()->is_flushing_queries()) {
+ ERR_EXPLAIN("Function blocked during in/out signal. Use set_deferred(\"monitorable\",true/false)");
}
- ERR_FAIL_COND(locked);
+ ERR_FAIL_COND(locked || PhysicsServer::get_singleton()->is_flushing_queries());
if (p_enable == monitorable)
return;
diff --git a/scene/3d/audio_stream_player_3d.cpp b/scene/3d/audio_stream_player_3d.cpp
index 401a1971c6..afd87deca6 100644
--- a/scene/3d/audio_stream_player_3d.cpp
+++ b/scene/3d/audio_stream_player_3d.cpp
@@ -641,6 +641,7 @@ float AudioStreamPlayer3D::get_pitch_scale() const {
void AudioStreamPlayer3D::play(float p_from_pos) {
if (stream_playback.is_valid()) {
+ active = true;
setplay = p_from_pos;
output_ready = false;
set_physics_process_internal(true);
diff --git a/scene/3d/cpu_particles.cpp b/scene/3d/cpu_particles.cpp
index a22708ac99..69839a0087 100644
--- a/scene/3d/cpu_particles.cpp
+++ b/scene/3d/cpu_particles.cpp
@@ -1369,7 +1369,7 @@ void CPUParticles::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "color_ramp", PROPERTY_HINT_RESOURCE_TYPE, "GradientTexture"), "set_color_ramp", "get_color_ramp");
ADD_GROUP("Hue Variation", "hue_");
- ADD_PROPERTYI(PropertyInfo(Variant::REAL, "hue_variation", PROPERTY_HINT_RANGE, "-1,1,0.1"), "set_param", "get_param", PARAM_HUE_VARIATION);
+ ADD_PROPERTYI(PropertyInfo(Variant::REAL, "hue_variation", PROPERTY_HINT_RANGE, "-1,1,0.01"), "set_param", "get_param", PARAM_HUE_VARIATION);
ADD_PROPERTYI(PropertyInfo(Variant::REAL, "hue_variation_random", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_param_randomness", "get_param_randomness", PARAM_HUE_VARIATION);
ADD_PROPERTYI(PropertyInfo(Variant::OBJECT, "hue_variation_curve", PROPERTY_HINT_RESOURCE_TYPE, "Curve"), "set_param_curve", "get_param_curve", PARAM_HUE_VARIATION);
ADD_GROUP("Animation", "anim_");
diff --git a/scene/3d/physics_body.cpp b/scene/3d/physics_body.cpp
index 9148b436a0..bcfcf33e57 100644
--- a/scene/3d/physics_body.cpp
+++ b/scene/3d/physics_body.cpp
@@ -1907,6 +1907,26 @@ bool PhysicalBone::SixDOFJointData::_set(const StringName &p_name, const Variant
if (j.is_valid())
PhysicsServer::get_singleton()->generic_6dof_joint_set_param(j, axis, PhysicsServer::G6DOF_JOINT_LINEAR_LIMIT_SOFTNESS, axis_data[axis].linear_limit_softness);
+ } else if ("linear_spring_enabled" == var_name) {
+ axis_data[axis].linear_spring_enabled = p_value;
+ if (j.is_valid())
+ PhysicsServer::get_singleton()->generic_6dof_joint_set_flag(j, axis, PhysicsServer::G6DOF_JOINT_FLAG_ENABLE_LINEAR_SPRING, axis_data[axis].linear_spring_enabled);
+
+ } else if ("linear_spring_stiffness" == var_name) {
+ axis_data[axis].linear_spring_stiffness = p_value;
+ if (j.is_valid())
+ PhysicsServer::get_singleton()->generic_6dof_joint_set_param(j, axis, PhysicsServer::G6DOF_JOINT_LINEAR_SPRING_STIFFNESS, axis_data[axis].linear_spring_stiffness);
+
+ } else if ("linear_spring_damping" == var_name) {
+ axis_data[axis].linear_spring_damping = p_value;
+ if (j.is_valid())
+ PhysicsServer::get_singleton()->generic_6dof_joint_set_param(j, axis, PhysicsServer::G6DOF_JOINT_LINEAR_SPRING_DAMPING, axis_data[axis].linear_spring_damping);
+
+ } else if ("linear_equilibrium_point" == var_name) {
+ axis_data[axis].linear_equilibrium_point = p_value;
+ if (j.is_valid())
+ PhysicsServer::get_singleton()->generic_6dof_joint_set_param(j, axis, PhysicsServer::G6DOF_JOINT_LINEAR_SPRING_EQUILIBRIUM_POINT, axis_data[axis].linear_equilibrium_point);
+
} else if ("linear_restitution" == var_name) {
axis_data[axis].linear_restitution = p_value;
if (j.is_valid())
@@ -1952,6 +1972,26 @@ bool PhysicalBone::SixDOFJointData::_set(const StringName &p_name, const Variant
if (j.is_valid())
PhysicsServer::get_singleton()->generic_6dof_joint_set_param(j, axis, PhysicsServer::G6DOF_JOINT_ANGULAR_ERP, axis_data[axis].erp);
+ } else if ("angular_spring_enabled" == var_name) {
+ axis_data[axis].angular_spring_enabled = p_value;
+ if (j.is_valid())
+ PhysicsServer::get_singleton()->generic_6dof_joint_set_flag(j, axis, PhysicsServer::G6DOF_JOINT_FLAG_ENABLE_ANGULAR_SPRING, axis_data[axis].angular_spring_enabled);
+
+ } else if ("angular_spring_stiffness" == var_name) {
+ axis_data[axis].angular_spring_stiffness = p_value;
+ if (j.is_valid())
+ PhysicsServer::get_singleton()->generic_6dof_joint_set_param(j, axis, PhysicsServer::G6DOF_JOINT_ANGULAR_SPRING_STIFFNESS, axis_data[axis].angular_spring_stiffness);
+
+ } else if ("angular_spring_damping" == var_name) {
+ axis_data[axis].angular_spring_damping = p_value;
+ if (j.is_valid())
+ PhysicsServer::get_singleton()->generic_6dof_joint_set_param(j, axis, PhysicsServer::G6DOF_JOINT_ANGULAR_SPRING_DAMPING, axis_data[axis].angular_spring_damping);
+
+ } else if ("angular_equilibrium_point" == var_name) {
+ axis_data[axis].angular_equilibrium_point = p_value;
+ if (j.is_valid())
+ PhysicsServer::get_singleton()->generic_6dof_joint_set_param(j, axis, PhysicsServer::G6DOF_JOINT_ANGULAR_SPRING_EQUILIBRIUM_POINT, axis_data[axis].angular_equilibrium_point);
+
} else {
return false;
}
@@ -1990,6 +2030,14 @@ bool PhysicalBone::SixDOFJointData::_get(const StringName &p_name, Variant &r_re
r_ret = axis_data[axis].linear_limit_lower;
} else if ("linear_limit_softness" == var_name) {
r_ret = axis_data[axis].linear_limit_softness;
+ } else if ("linear_spring_enabled" == var_name) {
+ r_ret = axis_data[axis].linear_spring_enabled;
+ } else if ("linear_spring_stiffness" == var_name) {
+ r_ret = axis_data[axis].linear_spring_stiffness;
+ } else if ("linear_spring_damping" == var_name) {
+ r_ret = axis_data[axis].linear_spring_damping;
+ } else if ("linear_equilibrium_point" == var_name) {
+ r_ret = axis_data[axis].linear_equilibrium_point;
} else if ("linear_restitution" == var_name) {
r_ret = axis_data[axis].linear_restitution;
} else if ("linear_damping" == var_name) {
@@ -2008,6 +2056,14 @@ bool PhysicalBone::SixDOFJointData::_get(const StringName &p_name, Variant &r_re
r_ret = axis_data[axis].angular_damping;
} else if ("erp" == var_name) {
r_ret = axis_data[axis].erp;
+ } else if ("angular_spring_enabled" == var_name) {
+ r_ret = axis_data[axis].angular_spring_enabled;
+ } else if ("angular_spring_stiffness" == var_name) {
+ r_ret = axis_data[axis].angular_spring_stiffness;
+ } else if ("angular_spring_damping" == var_name) {
+ r_ret = axis_data[axis].angular_spring_damping;
+ } else if ("angular_equilibrium_point" == var_name) {
+ r_ret = axis_data[axis].angular_equilibrium_point;
} else {
return false;
}
@@ -2022,6 +2078,10 @@ void PhysicalBone::SixDOFJointData::_get_property_list(List<PropertyInfo> *p_lis
p_list->push_back(PropertyInfo(Variant::REAL, "joint_constraints/" + axis_names[i] + "/linear_limit_upper"));
p_list->push_back(PropertyInfo(Variant::REAL, "joint_constraints/" + axis_names[i] + "/linear_limit_lower"));
p_list->push_back(PropertyInfo(Variant::REAL, "joint_constraints/" + axis_names[i] + "/linear_limit_softness", PROPERTY_HINT_RANGE, "0.01,16,0.01"));
+ p_list->push_back(PropertyInfo(Variant::BOOL, "joint_constraints/" + axis_names[i] + "/linear_spring_enabled"));
+ p_list->push_back(PropertyInfo(Variant::REAL, "joint_constraints/" + axis_names[i] + "/linear_spring_stiffness"));
+ p_list->push_back(PropertyInfo(Variant::REAL, "joint_constraints/" + axis_names[i] + "/linear_spring_damping"));
+ p_list->push_back(PropertyInfo(Variant::REAL, "joint_constraints/" + axis_names[i] + "/linear_equilibrium_point"));
p_list->push_back(PropertyInfo(Variant::REAL, "joint_constraints/" + axis_names[i] + "/linear_restitution", PROPERTY_HINT_RANGE, "0.01,16,0.01"));
p_list->push_back(PropertyInfo(Variant::REAL, "joint_constraints/" + axis_names[i] + "/linear_damping", PROPERTY_HINT_RANGE, "0.01,16,0.01"));
p_list->push_back(PropertyInfo(Variant::BOOL, "joint_constraints/" + axis_names[i] + "/angular_limit_enabled"));
@@ -2031,6 +2091,10 @@ void PhysicalBone::SixDOFJointData::_get_property_list(List<PropertyInfo> *p_lis
p_list->push_back(PropertyInfo(Variant::REAL, "joint_constraints/" + axis_names[i] + "/angular_restitution", PROPERTY_HINT_RANGE, "0.01,16,0.01"));
p_list->push_back(PropertyInfo(Variant::REAL, "joint_constraints/" + axis_names[i] + "/angular_damping", PROPERTY_HINT_RANGE, "0.01,16,0.01"));
p_list->push_back(PropertyInfo(Variant::REAL, "joint_constraints/" + axis_names[i] + "/erp"));
+ p_list->push_back(PropertyInfo(Variant::BOOL, "joint_constraints/" + axis_names[i] + "/angular_spring_enabled"));
+ p_list->push_back(PropertyInfo(Variant::REAL, "joint_constraints/" + axis_names[i] + "/angular_spring_stiffness"));
+ p_list->push_back(PropertyInfo(Variant::REAL, "joint_constraints/" + axis_names[i] + "/angular_spring_damping"));
+ p_list->push_back(PropertyInfo(Variant::REAL, "joint_constraints/" + axis_names[i] + "/angular_equilibrium_point"));
}
}
@@ -2294,6 +2358,10 @@ void PhysicalBone::_reload_joint() {
PhysicsServer::get_singleton()->generic_6dof_joint_set_param(joint, static_cast<Vector3::Axis>(axis), PhysicsServer::G6DOF_JOINT_LINEAR_UPPER_LIMIT, g6dofjd->axis_data[axis].linear_limit_upper);
PhysicsServer::get_singleton()->generic_6dof_joint_set_param(joint, static_cast<Vector3::Axis>(axis), PhysicsServer::G6DOF_JOINT_LINEAR_LOWER_LIMIT, g6dofjd->axis_data[axis].linear_limit_lower);
PhysicsServer::get_singleton()->generic_6dof_joint_set_param(joint, static_cast<Vector3::Axis>(axis), PhysicsServer::G6DOF_JOINT_LINEAR_LIMIT_SOFTNESS, g6dofjd->axis_data[axis].linear_limit_softness);
+ PhysicsServer::get_singleton()->generic_6dof_joint_set_flag(joint, static_cast<Vector3::Axis>(axis), PhysicsServer::G6DOF_JOINT_FLAG_ENABLE_LINEAR_SPRING, g6dofjd->axis_data[axis].linear_spring_enabled);
+ PhysicsServer::get_singleton()->generic_6dof_joint_set_param(joint, static_cast<Vector3::Axis>(axis), PhysicsServer::G6DOF_JOINT_LINEAR_SPRING_STIFFNESS, g6dofjd->axis_data[axis].linear_spring_stiffness);
+ PhysicsServer::get_singleton()->generic_6dof_joint_set_param(joint, static_cast<Vector3::Axis>(axis), PhysicsServer::G6DOF_JOINT_LINEAR_SPRING_DAMPING, g6dofjd->axis_data[axis].linear_spring_damping);
+ PhysicsServer::get_singleton()->generic_6dof_joint_set_param(joint, static_cast<Vector3::Axis>(axis), PhysicsServer::G6DOF_JOINT_LINEAR_SPRING_EQUILIBRIUM_POINT, g6dofjd->axis_data[axis].linear_equilibrium_point);
PhysicsServer::get_singleton()->generic_6dof_joint_set_param(joint, static_cast<Vector3::Axis>(axis), PhysicsServer::G6DOF_JOINT_LINEAR_RESTITUTION, g6dofjd->axis_data[axis].linear_restitution);
PhysicsServer::get_singleton()->generic_6dof_joint_set_param(joint, static_cast<Vector3::Axis>(axis), PhysicsServer::G6DOF_JOINT_LINEAR_DAMPING, g6dofjd->axis_data[axis].linear_damping);
PhysicsServer::get_singleton()->generic_6dof_joint_set_flag(joint, static_cast<Vector3::Axis>(axis), PhysicsServer::G6DOF_JOINT_FLAG_ENABLE_ANGULAR_LIMIT, g6dofjd->axis_data[axis].angular_limit_enabled);
@@ -2303,6 +2371,10 @@ void PhysicalBone::_reload_joint() {
PhysicsServer::get_singleton()->generic_6dof_joint_set_param(joint, static_cast<Vector3::Axis>(axis), PhysicsServer::G6DOF_JOINT_ANGULAR_RESTITUTION, g6dofjd->axis_data[axis].angular_restitution);
PhysicsServer::get_singleton()->generic_6dof_joint_set_param(joint, static_cast<Vector3::Axis>(axis), PhysicsServer::G6DOF_JOINT_ANGULAR_DAMPING, g6dofjd->axis_data[axis].angular_damping);
PhysicsServer::get_singleton()->generic_6dof_joint_set_param(joint, static_cast<Vector3::Axis>(axis), PhysicsServer::G6DOF_JOINT_ANGULAR_ERP, g6dofjd->axis_data[axis].erp);
+ PhysicsServer::get_singleton()->generic_6dof_joint_set_flag(joint, static_cast<Vector3::Axis>(axis), PhysicsServer::G6DOF_JOINT_FLAG_ENABLE_ANGULAR_SPRING, g6dofjd->axis_data[axis].angular_spring_enabled);
+ PhysicsServer::get_singleton()->generic_6dof_joint_set_param(joint, static_cast<Vector3::Axis>(axis), PhysicsServer::G6DOF_JOINT_ANGULAR_SPRING_STIFFNESS, g6dofjd->axis_data[axis].angular_spring_stiffness);
+ PhysicsServer::get_singleton()->generic_6dof_joint_set_param(joint, static_cast<Vector3::Axis>(axis), PhysicsServer::G6DOF_JOINT_ANGULAR_SPRING_DAMPING, g6dofjd->axis_data[axis].angular_spring_damping);
+ PhysicsServer::get_singleton()->generic_6dof_joint_set_param(joint, static_cast<Vector3::Axis>(axis), PhysicsServer::G6DOF_JOINT_ANGULAR_SPRING_EQUILIBRIUM_POINT, g6dofjd->axis_data[axis].angular_equilibrium_point);
}
} break;
diff --git a/scene/3d/physics_body.h b/scene/3d/physics_body.h
index 20d948b6eb..5474290c07 100644
--- a/scene/3d/physics_body.h
+++ b/scene/3d/physics_body.h
@@ -494,6 +494,10 @@ public:
real_t linear_limit_softness;
real_t linear_restitution;
real_t linear_damping;
+ bool linear_spring_enabled;
+ real_t linear_spring_stiffness;
+ real_t linear_spring_damping;
+ real_t linear_equilibrium_point;
bool angular_limit_enabled;
real_t angular_limit_upper;
real_t angular_limit_lower;
@@ -501,6 +505,10 @@ public:
real_t angular_restitution;
real_t angular_damping;
real_t erp;
+ bool angular_spring_enabled;
+ real_t angular_spring_stiffness;
+ real_t angular_spring_damping;
+ real_t angular_equilibrium_point;
SixDOFAxisData() :
linear_limit_enabled(true),
@@ -509,13 +517,21 @@ public:
linear_limit_softness(0.7),
linear_restitution(0.5),
linear_damping(1.),
+ linear_spring_enabled(false),
+ linear_spring_stiffness(0),
+ linear_spring_damping(0),
+ linear_equilibrium_point(0),
angular_limit_enabled(true),
angular_limit_upper(0),
angular_limit_lower(0),
angular_limit_softness(0.5),
angular_restitution(0),
angular_damping(1.),
- erp(0.5) {}
+ erp(0.5),
+ angular_spring_enabled(false),
+ angular_spring_stiffness(0),
+ angular_spring_damping(0.),
+ angular_equilibrium_point(0) {}
};
virtual JointType get_joint_type() { return JOINT_TYPE_6DOF; }
diff --git a/scene/3d/physics_joint.cpp b/scene/3d/physics_joint.cpp
index a30fc0ac3e..02c6b1d969 100644
--- a/scene/3d/physics_joint.cpp
+++ b/scene/3d/physics_joint.cpp
@@ -716,6 +716,11 @@ void Generic6DOFJoint::_bind_methods() {
ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "linear_motor_x/enabled"), "set_flag_x", "get_flag_x", FLAG_ENABLE_LINEAR_MOTOR);
ADD_PROPERTYI(PropertyInfo(Variant::REAL, "linear_motor_x/target_velocity"), "set_param_x", "get_param_x", PARAM_LINEAR_MOTOR_TARGET_VELOCITY);
ADD_PROPERTYI(PropertyInfo(Variant::REAL, "linear_motor_x/force_limit"), "set_param_x", "get_param_x", PARAM_LINEAR_MOTOR_FORCE_LIMIT);
+ ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "linear_spring_x/enabled"), "set_flag_x", "get_flag_x", FLAG_ENABLE_LINEAR_SPRING);
+ ADD_PROPERTYI(PropertyInfo(Variant::REAL, "linear_spring_x/stiffness"), "set_param_x", "get_param_x", PARAM_LINEAR_SPRING_STIFFNESS);
+ ADD_PROPERTYI(PropertyInfo(Variant::REAL, "linear_spring_x/damping"), "set_param_x", "get_param_x", PARAM_LINEAR_SPRING_DAMPING);
+ ADD_PROPERTYI(PropertyInfo(Variant::REAL, "linear_spring_x/equilibrium_point"), "set_param_x", "get_param_x", PARAM_LINEAR_SPRING_EQUILIBRIUM_POINT);
+
ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "angular_limit_x/enabled"), "set_flag_x", "get_flag_x", FLAG_ENABLE_ANGULAR_LIMIT);
ADD_PROPERTY(PropertyInfo(Variant::REAL, "angular_limit_x/upper_angle", PROPERTY_HINT_RANGE, "-180,180,0.01"), "_set_angular_hi_limit_x", "_get_angular_hi_limit_x");
ADD_PROPERTY(PropertyInfo(Variant::REAL, "angular_limit_x/lower_angle", PROPERTY_HINT_RANGE, "-180,180,0.01"), "_set_angular_lo_limit_x", "_get_angular_lo_limit_x");
@@ -727,6 +732,10 @@ void Generic6DOFJoint::_bind_methods() {
ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "angular_motor_x/enabled"), "set_flag_x", "get_flag_x", FLAG_ENABLE_MOTOR);
ADD_PROPERTYI(PropertyInfo(Variant::REAL, "angular_motor_x/target_velocity"), "set_param_x", "get_param_x", PARAM_ANGULAR_MOTOR_TARGET_VELOCITY);
ADD_PROPERTYI(PropertyInfo(Variant::REAL, "angular_motor_x/force_limit"), "set_param_x", "get_param_x", PARAM_ANGULAR_MOTOR_FORCE_LIMIT);
+ ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "angular_spring_x/enabled"), "set_flag_x", "get_flag_x", FLAG_ENABLE_ANGULAR_SPRING);
+ ADD_PROPERTYI(PropertyInfo(Variant::REAL, "angular_spring_x/stiffness"), "set_param_x", "get_param_x", PARAM_ANGULAR_SPRING_STIFFNESS);
+ ADD_PROPERTYI(PropertyInfo(Variant::REAL, "angular_spring_x/damping"), "set_param_x", "get_param_x", PARAM_ANGULAR_SPRING_DAMPING);
+ ADD_PROPERTYI(PropertyInfo(Variant::REAL, "angular_spring_x/equilibrium_point"), "set_param_x", "get_param_x", PARAM_ANGULAR_SPRING_EQUILIBRIUM_POINT);
ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "linear_limit_y/enabled"), "set_flag_y", "get_flag_y", FLAG_ENABLE_LINEAR_LIMIT);
ADD_PROPERTYI(PropertyInfo(Variant::REAL, "linear_limit_y/upper_distance"), "set_param_y", "get_param_y", PARAM_LINEAR_UPPER_LIMIT);
@@ -737,6 +746,10 @@ void Generic6DOFJoint::_bind_methods() {
ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "linear_motor_y/enabled"), "set_flag_y", "get_flag_y", FLAG_ENABLE_LINEAR_MOTOR);
ADD_PROPERTYI(PropertyInfo(Variant::REAL, "linear_motor_y/target_velocity"), "set_param_y", "get_param_y", PARAM_LINEAR_MOTOR_TARGET_VELOCITY);
ADD_PROPERTYI(PropertyInfo(Variant::REAL, "linear_motor_y/force_limit"), "set_param_y", "get_param_y", PARAM_LINEAR_MOTOR_FORCE_LIMIT);
+ ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "linear_spring_y/enabled"), "set_flag_y", "get_flag_y", FLAG_ENABLE_LINEAR_SPRING);
+ ADD_PROPERTYI(PropertyInfo(Variant::REAL, "linear_spring_y/stiffness"), "set_param_y", "get_param_y", PARAM_LINEAR_SPRING_STIFFNESS);
+ ADD_PROPERTYI(PropertyInfo(Variant::REAL, "linear_spring_y/damping"), "set_param_y", "get_param_y", PARAM_LINEAR_SPRING_DAMPING);
+ ADD_PROPERTYI(PropertyInfo(Variant::REAL, "linear_spring_y/equilibrium_point"), "set_param_y", "get_param_y", PARAM_LINEAR_SPRING_EQUILIBRIUM_POINT);
ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "angular_limit_y/enabled"), "set_flag_y", "get_flag_y", FLAG_ENABLE_ANGULAR_LIMIT);
ADD_PROPERTY(PropertyInfo(Variant::REAL, "angular_limit_y/upper_angle", PROPERTY_HINT_RANGE, "-180,180,0.01"), "_set_angular_hi_limit_y", "_get_angular_hi_limit_y");
ADD_PROPERTY(PropertyInfo(Variant::REAL, "angular_limit_y/lower_angle", PROPERTY_HINT_RANGE, "-180,180,0.01"), "_set_angular_lo_limit_y", "_get_angular_lo_limit_y");
@@ -748,6 +761,10 @@ void Generic6DOFJoint::_bind_methods() {
ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "angular_motor_y/enabled"), "set_flag_y", "get_flag_y", FLAG_ENABLE_MOTOR);
ADD_PROPERTYI(PropertyInfo(Variant::REAL, "angular_motor_y/target_velocity"), "set_param_y", "get_param_y", PARAM_ANGULAR_MOTOR_TARGET_VELOCITY);
ADD_PROPERTYI(PropertyInfo(Variant::REAL, "angular_motor_y/force_limit"), "set_param_y", "get_param_y", PARAM_ANGULAR_MOTOR_FORCE_LIMIT);
+ ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "angular_spring_y/enabled"), "set_flag_y", "get_flag_y", FLAG_ENABLE_ANGULAR_SPRING);
+ ADD_PROPERTYI(PropertyInfo(Variant::REAL, "angular_spring_y/stiffness"), "set_param_y", "get_param_y", PARAM_ANGULAR_SPRING_STIFFNESS);
+ ADD_PROPERTYI(PropertyInfo(Variant::REAL, "angular_spring_y/damping"), "set_param_y", "get_param_y", PARAM_ANGULAR_SPRING_DAMPING);
+ ADD_PROPERTYI(PropertyInfo(Variant::REAL, "angular_spring_y/equilibrium_point"), "set_param_y", "get_param_y", PARAM_ANGULAR_SPRING_EQUILIBRIUM_POINT);
ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "linear_limit_z/enabled"), "set_flag_z", "get_flag_z", FLAG_ENABLE_LINEAR_LIMIT);
ADD_PROPERTYI(PropertyInfo(Variant::REAL, "linear_limit_z/upper_distance"), "set_param_z", "get_param_z", PARAM_LINEAR_UPPER_LIMIT);
@@ -758,6 +775,10 @@ void Generic6DOFJoint::_bind_methods() {
ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "linear_motor_z/enabled"), "set_flag_z", "get_flag_z", FLAG_ENABLE_LINEAR_MOTOR);
ADD_PROPERTYI(PropertyInfo(Variant::REAL, "linear_motor_z/target_velocity"), "set_param_z", "get_param_z", PARAM_LINEAR_MOTOR_TARGET_VELOCITY);
ADD_PROPERTYI(PropertyInfo(Variant::REAL, "linear_motor_z/force_limit"), "set_param_z", "get_param_z", PARAM_LINEAR_MOTOR_FORCE_LIMIT);
+ ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "linear_spring_z/enabled"), "set_flag_z", "get_flag_z", FLAG_ENABLE_LINEAR_SPRING);
+ ADD_PROPERTYI(PropertyInfo(Variant::REAL, "linear_spring_z/stiffness"), "set_param_z", "get_param_z", PARAM_LINEAR_SPRING_STIFFNESS);
+ ADD_PROPERTYI(PropertyInfo(Variant::REAL, "linear_spring_z/damping"), "set_param_z", "get_param_z", PARAM_LINEAR_SPRING_DAMPING);
+ ADD_PROPERTYI(PropertyInfo(Variant::REAL, "linear_spring_z/equilibrium_point"), "set_param_z", "get_param_z", PARAM_LINEAR_SPRING_EQUILIBRIUM_POINT);
ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "angular_limit_z/enabled"), "set_flag_z", "get_flag_z", FLAG_ENABLE_ANGULAR_LIMIT);
ADD_PROPERTY(PropertyInfo(Variant::REAL, "angular_limit_z/upper_angle", PROPERTY_HINT_RANGE, "-180,180,0.01"), "_set_angular_hi_limit_z", "_get_angular_hi_limit_z");
ADD_PROPERTY(PropertyInfo(Variant::REAL, "angular_limit_z/lower_angle", PROPERTY_HINT_RANGE, "-180,180,0.01"), "_set_angular_lo_limit_z", "_get_angular_lo_limit_z");
@@ -769,6 +790,10 @@ void Generic6DOFJoint::_bind_methods() {
ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "angular_motor_z/enabled"), "set_flag_z", "get_flag_z", FLAG_ENABLE_MOTOR);
ADD_PROPERTYI(PropertyInfo(Variant::REAL, "angular_motor_z/target_velocity"), "set_param_z", "get_param_z", PARAM_ANGULAR_MOTOR_TARGET_VELOCITY);
ADD_PROPERTYI(PropertyInfo(Variant::REAL, "angular_motor_z/force_limit"), "set_param_z", "get_param_z", PARAM_ANGULAR_MOTOR_FORCE_LIMIT);
+ ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "angular_spring_z/enabled"), "set_flag_z", "get_flag_z", FLAG_ENABLE_ANGULAR_SPRING);
+ ADD_PROPERTYI(PropertyInfo(Variant::REAL, "angular_spring_z/stiffness"), "set_param_z", "get_param_z", PARAM_ANGULAR_SPRING_STIFFNESS);
+ ADD_PROPERTYI(PropertyInfo(Variant::REAL, "angular_spring_z/damping"), "set_param_z", "get_param_z", PARAM_ANGULAR_SPRING_DAMPING);
+ ADD_PROPERTYI(PropertyInfo(Variant::REAL, "angular_spring_z/equilibrium_point"), "set_param_z", "get_param_z", PARAM_ANGULAR_SPRING_EQUILIBRIUM_POINT);
BIND_ENUM_CONSTANT(PARAM_LINEAR_LOWER_LIMIT);
BIND_ENUM_CONSTANT(PARAM_LINEAR_UPPER_LIMIT);
@@ -790,6 +815,8 @@ void Generic6DOFJoint::_bind_methods() {
BIND_ENUM_CONSTANT(FLAG_ENABLE_LINEAR_LIMIT);
BIND_ENUM_CONSTANT(FLAG_ENABLE_ANGULAR_LIMIT);
+ BIND_ENUM_CONSTANT(FLAG_ENABLE_LINEAR_SPRING);
+ BIND_ENUM_CONSTANT(FLAG_ENABLE_ANGULAR_SPRING);
BIND_ENUM_CONSTANT(FLAG_ENABLE_MOTOR);
BIND_ENUM_CONSTANT(FLAG_ENABLE_LINEAR_MOTOR);
BIND_ENUM_CONSTANT(FLAG_MAX);
@@ -923,6 +950,9 @@ Generic6DOFJoint::Generic6DOFJoint() {
set_param_x(PARAM_LINEAR_DAMPING, 1.0);
set_param_x(PARAM_LINEAR_MOTOR_TARGET_VELOCITY, 0);
set_param_x(PARAM_LINEAR_MOTOR_FORCE_LIMIT, 0);
+ set_param_x(PARAM_LINEAR_SPRING_STIFFNESS, 0.01);
+ set_param_x(PARAM_LINEAR_SPRING_DAMPING, 0.01);
+ set_param_x(PARAM_LINEAR_SPRING_EQUILIBRIUM_POINT, 0.0);
set_param_x(PARAM_ANGULAR_LOWER_LIMIT, 0);
set_param_x(PARAM_ANGULAR_UPPER_LIMIT, 0);
set_param_x(PARAM_ANGULAR_LIMIT_SOFTNESS, 0.5f);
@@ -932,9 +962,14 @@ Generic6DOFJoint::Generic6DOFJoint() {
set_param_x(PARAM_ANGULAR_ERP, 0.5);
set_param_x(PARAM_ANGULAR_MOTOR_TARGET_VELOCITY, 0);
set_param_x(PARAM_ANGULAR_MOTOR_FORCE_LIMIT, 300);
+ set_param_x(PARAM_ANGULAR_SPRING_STIFFNESS, 0);
+ set_param_x(PARAM_ANGULAR_SPRING_DAMPING, 0);
+ set_param_x(PARAM_ANGULAR_SPRING_EQUILIBRIUM_POINT, 0);
set_flag_x(FLAG_ENABLE_ANGULAR_LIMIT, true);
set_flag_x(FLAG_ENABLE_LINEAR_LIMIT, true);
+ set_flag_x(FLAG_ENABLE_ANGULAR_SPRING, false);
+ set_flag_x(FLAG_ENABLE_LINEAR_SPRING, false);
set_flag_x(FLAG_ENABLE_MOTOR, false);
set_flag_x(FLAG_ENABLE_LINEAR_MOTOR, false);
@@ -945,6 +980,9 @@ Generic6DOFJoint::Generic6DOFJoint() {
set_param_y(PARAM_LINEAR_DAMPING, 1.0);
set_param_y(PARAM_LINEAR_MOTOR_TARGET_VELOCITY, 0);
set_param_y(PARAM_LINEAR_MOTOR_FORCE_LIMIT, 0);
+ set_param_y(PARAM_LINEAR_SPRING_STIFFNESS, 0.01);
+ set_param_y(PARAM_LINEAR_SPRING_DAMPING, 0.01);
+ set_param_y(PARAM_LINEAR_SPRING_EQUILIBRIUM_POINT, 0.0);
set_param_y(PARAM_ANGULAR_LOWER_LIMIT, 0);
set_param_y(PARAM_ANGULAR_UPPER_LIMIT, 0);
set_param_y(PARAM_ANGULAR_LIMIT_SOFTNESS, 0.5f);
@@ -954,9 +992,14 @@ Generic6DOFJoint::Generic6DOFJoint() {
set_param_y(PARAM_ANGULAR_ERP, 0.5);
set_param_y(PARAM_ANGULAR_MOTOR_TARGET_VELOCITY, 0);
set_param_y(PARAM_ANGULAR_MOTOR_FORCE_LIMIT, 300);
+ set_param_y(PARAM_ANGULAR_SPRING_STIFFNESS, 0);
+ set_param_y(PARAM_ANGULAR_SPRING_DAMPING, 0);
+ set_param_y(PARAM_ANGULAR_SPRING_EQUILIBRIUM_POINT, 0);
set_flag_y(FLAG_ENABLE_ANGULAR_LIMIT, true);
set_flag_y(FLAG_ENABLE_LINEAR_LIMIT, true);
+ set_flag_y(FLAG_ENABLE_ANGULAR_SPRING, false);
+ set_flag_y(FLAG_ENABLE_LINEAR_SPRING, false);
set_flag_y(FLAG_ENABLE_MOTOR, false);
set_flag_y(FLAG_ENABLE_LINEAR_MOTOR, false);
@@ -967,6 +1010,9 @@ Generic6DOFJoint::Generic6DOFJoint() {
set_param_z(PARAM_LINEAR_DAMPING, 1.0);
set_param_z(PARAM_LINEAR_MOTOR_TARGET_VELOCITY, 0);
set_param_z(PARAM_LINEAR_MOTOR_FORCE_LIMIT, 0);
+ set_param_z(PARAM_LINEAR_SPRING_STIFFNESS, 0.01);
+ set_param_z(PARAM_LINEAR_SPRING_DAMPING, 0.01);
+ set_param_z(PARAM_LINEAR_SPRING_EQUILIBRIUM_POINT, 0.0);
set_param_z(PARAM_ANGULAR_LOWER_LIMIT, 0);
set_param_z(PARAM_ANGULAR_UPPER_LIMIT, 0);
set_param_z(PARAM_ANGULAR_LIMIT_SOFTNESS, 0.5f);
@@ -976,9 +1022,14 @@ Generic6DOFJoint::Generic6DOFJoint() {
set_param_z(PARAM_ANGULAR_ERP, 0.5);
set_param_z(PARAM_ANGULAR_MOTOR_TARGET_VELOCITY, 0);
set_param_z(PARAM_ANGULAR_MOTOR_FORCE_LIMIT, 300);
+ set_param_z(PARAM_ANGULAR_SPRING_STIFFNESS, 0);
+ set_param_z(PARAM_ANGULAR_SPRING_DAMPING, 0);
+ set_param_z(PARAM_ANGULAR_SPRING_EQUILIBRIUM_POINT, 0);
set_flag_z(FLAG_ENABLE_ANGULAR_LIMIT, true);
set_flag_z(FLAG_ENABLE_LINEAR_LIMIT, true);
+ set_flag_z(FLAG_ENABLE_ANGULAR_SPRING, false);
+ set_flag_z(FLAG_ENABLE_LINEAR_SPRING, false);
set_flag_z(FLAG_ENABLE_MOTOR, false);
set_flag_z(FLAG_ENABLE_LINEAR_MOTOR, false);
}
diff --git a/scene/3d/physics_joint.h b/scene/3d/physics_joint.h
index 37870d6f30..ee4ca28658 100644
--- a/scene/3d/physics_joint.h
+++ b/scene/3d/physics_joint.h
@@ -251,6 +251,9 @@ public:
PARAM_LINEAR_DAMPING = PhysicsServer::G6DOF_JOINT_LINEAR_DAMPING,
PARAM_LINEAR_MOTOR_TARGET_VELOCITY = PhysicsServer::G6DOF_JOINT_LINEAR_MOTOR_TARGET_VELOCITY,
PARAM_LINEAR_MOTOR_FORCE_LIMIT = PhysicsServer::G6DOF_JOINT_LINEAR_MOTOR_FORCE_LIMIT,
+ PARAM_LINEAR_SPRING_STIFFNESS = PhysicsServer::G6DOF_JOINT_LINEAR_SPRING_STIFFNESS,
+ PARAM_LINEAR_SPRING_DAMPING = PhysicsServer::G6DOF_JOINT_LINEAR_SPRING_DAMPING,
+ PARAM_LINEAR_SPRING_EQUILIBRIUM_POINT = PhysicsServer::G6DOF_JOINT_LINEAR_SPRING_EQUILIBRIUM_POINT,
PARAM_ANGULAR_LOWER_LIMIT = PhysicsServer::G6DOF_JOINT_ANGULAR_LOWER_LIMIT,
PARAM_ANGULAR_UPPER_LIMIT = PhysicsServer::G6DOF_JOINT_ANGULAR_UPPER_LIMIT,
PARAM_ANGULAR_LIMIT_SOFTNESS = PhysicsServer::G6DOF_JOINT_ANGULAR_LIMIT_SOFTNESS,
@@ -260,12 +263,17 @@ public:
PARAM_ANGULAR_ERP = PhysicsServer::G6DOF_JOINT_ANGULAR_ERP,
PARAM_ANGULAR_MOTOR_TARGET_VELOCITY = PhysicsServer::G6DOF_JOINT_ANGULAR_MOTOR_TARGET_VELOCITY,
PARAM_ANGULAR_MOTOR_FORCE_LIMIT = PhysicsServer::G6DOF_JOINT_ANGULAR_MOTOR_FORCE_LIMIT,
+ PARAM_ANGULAR_SPRING_STIFFNESS = PhysicsServer::G6DOF_JOINT_ANGULAR_SPRING_STIFFNESS,
+ PARAM_ANGULAR_SPRING_DAMPING = PhysicsServer::G6DOF_JOINT_ANGULAR_SPRING_DAMPING,
+ PARAM_ANGULAR_SPRING_EQUILIBRIUM_POINT = PhysicsServer::G6DOF_JOINT_ANGULAR_SPRING_EQUILIBRIUM_POINT,
PARAM_MAX = PhysicsServer::G6DOF_JOINT_MAX,
};
enum Flag {
FLAG_ENABLE_LINEAR_LIMIT = PhysicsServer::G6DOF_JOINT_FLAG_ENABLE_LINEAR_LIMIT,
FLAG_ENABLE_ANGULAR_LIMIT = PhysicsServer::G6DOF_JOINT_FLAG_ENABLE_ANGULAR_LIMIT,
+ FLAG_ENABLE_LINEAR_SPRING = PhysicsServer::G6DOF_JOINT_FLAG_ENABLE_LINEAR_SPRING,
+ FLAG_ENABLE_ANGULAR_SPRING = PhysicsServer::G6DOF_JOINT_FLAG_ENABLE_ANGULAR_SPRING,
FLAG_ENABLE_MOTOR = PhysicsServer::G6DOF_JOINT_FLAG_ENABLE_MOTOR,
FLAG_ENABLE_LINEAR_MOTOR = PhysicsServer::G6DOF_JOINT_FLAG_ENABLE_LINEAR_MOTOR,
FLAG_MAX = PhysicsServer::G6DOF_JOINT_FLAG_MAX
diff --git a/scene/3d/sprite_3d.cpp b/scene/3d/sprite_3d.cpp
index 8e00fbe735..5bde224ce3 100644
--- a/scene/3d/sprite_3d.cpp
+++ b/scene/3d/sprite_3d.cpp
@@ -461,6 +461,13 @@ void Sprite3D::_draw() {
int axis = get_axis();
normal[axis] = 1.0;
+ Plane tangent;
+ if (axis == Vector3::AXIS_X) {
+ tangent = Plane(0, 0, -1, -1);
+ } else {
+ tangent = Plane(1, 0, 0, -1);
+ }
+
RID mat = SpatialMaterial::get_material_rid_for_2d(get_draw_flag(FLAG_SHADED), get_draw_flag(FLAG_TRANSPARENT), get_draw_flag(FLAG_DOUBLE_SIDED), get_alpha_cut_mode() == ALPHA_CUT_DISCARD, get_alpha_cut_mode() == ALPHA_CUT_OPAQUE_PREPASS);
VS::get_singleton()->immediate_set_material(immediate, mat);
@@ -487,6 +494,7 @@ void Sprite3D::_draw() {
for (int i = 0; i < 4; i++) {
VS::get_singleton()->immediate_normal(immediate, normal);
+ VS::get_singleton()->immediate_tangent(immediate, tangent);
VS::get_singleton()->immediate_color(immediate, color);
VS::get_singleton()->immediate_uv(immediate, uvs[i]);
@@ -761,6 +769,13 @@ void AnimatedSprite3D::_draw() {
int axis = get_axis();
normal[axis] = 1.0;
+ Plane tangent;
+ if (axis == Vector3::AXIS_X) {
+ tangent = Plane(0, 0, -1, -1);
+ } else {
+ tangent = Plane(1, 0, 0, -1);
+ }
+
RID mat = SpatialMaterial::get_material_rid_for_2d(get_draw_flag(FLAG_SHADED), get_draw_flag(FLAG_TRANSPARENT), get_draw_flag(FLAG_DOUBLE_SIDED), get_alpha_cut_mode() == ALPHA_CUT_DISCARD, get_alpha_cut_mode() == ALPHA_CUT_OPAQUE_PREPASS);
VS::get_singleton()->immediate_set_material(immediate, mat);
@@ -788,6 +803,7 @@ void AnimatedSprite3D::_draw() {
for (int i = 0; i < 4; i++) {
VS::get_singleton()->immediate_normal(immediate, normal);
+ VS::get_singleton()->immediate_tangent(immediate, tangent);
VS::get_singleton()->immediate_color(immediate, color);
VS::get_singleton()->immediate_uv(immediate, uvs[i]);
diff --git a/scene/3d/visibility_notifier.cpp b/scene/3d/visibility_notifier.cpp
index c69387d082..9a0832b27a 100644
--- a/scene/3d/visibility_notifier.cpp
+++ b/scene/3d/visibility_notifier.cpp
@@ -153,7 +153,7 @@ void VisibilityEnabler::_find_nodes(Node *p_node) {
if (enabler[ENABLER_FREEZE_BODIES]) {
RigidBody *rb = Object::cast_to<RigidBody>(p_node);
- if (rb && ((rb->get_mode() == RigidBody::MODE_CHARACTER || (rb->get_mode() == RigidBody::MODE_RIGID && !rb->is_able_to_sleep())))) {
+ if (rb && ((rb->get_mode() == RigidBody::MODE_CHARACTER || rb->get_mode() == RigidBody::MODE_RIGID))) {
add = true;
meta = rb->get_mode();
diff --git a/scene/animation/animation_blend_space_2d.cpp b/scene/animation/animation_blend_space_2d.cpp
index 9321133d5f..866b85c4c7 100644
--- a/scene/animation/animation_blend_space_2d.cpp
+++ b/scene/animation/animation_blend_space_2d.cpp
@@ -33,9 +33,17 @@
void AnimationNodeBlendSpace2D::get_parameter_list(List<PropertyInfo> *r_list) const {
r_list->push_back(PropertyInfo(Variant::VECTOR2, blend_position));
+ r_list->push_back(PropertyInfo(Variant::INT, closest, PROPERTY_HINT_NONE, "", 0));
+ r_list->push_back(PropertyInfo(Variant::REAL, length_internal, PROPERTY_HINT_NONE, "", 0));
}
Variant AnimationNodeBlendSpace2D::get_parameter_default_value(const StringName &p_parameter) const {
- return Vector2();
+ if (p_parameter == closest) {
+ return -1;
+ } else if (p_parameter == length_internal) {
+ return 0;
+ } else {
+ return Vector2();
+ }
}
void AnimationNodeBlendSpace2D::get_child_nodes(List<ChildNode> *r_child_nodes) {
@@ -412,84 +420,124 @@ float AnimationNodeBlendSpace2D::process(float p_time, bool p_seek) {
_update_triangles();
Vector2 blend_pos = get_parameter(blend_position);
+ int closest = get_parameter(this->closest);
+ float length_internal = get_parameter(this->length_internal);
+ float mind = 0; //time of min distance point
- if (triangles.size() == 0)
- return 0;
+ if (blend_mode == BLEND_MODE_INTERPOLATED) {
- Vector2 best_point;
- bool first = true;
- int blend_triangle = -1;
- float blend_weights[3] = { 0, 0, 0 };
+ if (triangles.size() == 0)
+ return 0;
- for (int i = 0; i < triangles.size(); i++) {
- Vector2 points[3];
- for (int j = 0; j < 3; j++) {
- points[j] = get_blend_point_position(get_triangle_point(i, j));
- }
+ Vector2 best_point;
+ bool first = true;
+ int blend_triangle = -1;
+ float blend_weights[3] = { 0, 0, 0 };
- if (Geometry::is_point_in_triangle(blend_pos, points[0], points[1], points[2])) {
+ for (int i = 0; i < triangles.size(); i++) {
+ Vector2 points[3];
+ for (int j = 0; j < 3; j++) {
+ points[j] = get_blend_point_position(get_triangle_point(i, j));
+ }
- blend_triangle = i;
- _blend_triangle(blend_pos, points, blend_weights);
- break;
- }
+ if (Geometry::is_point_in_triangle(blend_pos, points[0], points[1], points[2])) {
- for (int j = 0; j < 3; j++) {
- Vector2 s[2] = {
- points[j],
- points[(j + 1) % 3]
- };
- Vector2 closest = Geometry::get_closest_point_to_segment_2d(blend_pos, s);
- if (first || closest.distance_to(blend_pos) < best_point.distance_to(blend_pos)) {
- best_point = closest;
blend_triangle = i;
- first = false;
- float d = s[0].distance_to(s[1]);
- if (d == 0.0) {
- blend_weights[j] = 1.0;
- blend_weights[(j + 1) % 3] = 0.0;
- blend_weights[(j + 2) % 3] = 0.0;
- } else {
- float c = s[0].distance_to(closest) / d;
-
- blend_weights[j] = 1.0 - c;
- blend_weights[(j + 1) % 3] = c;
- blend_weights[(j + 2) % 3] = 0.0;
+ _blend_triangle(blend_pos, points, blend_weights);
+ break;
+ }
+
+ for (int j = 0; j < 3; j++) {
+ Vector2 s[2] = {
+ points[j],
+ points[(j + 1) % 3]
+ };
+ Vector2 closest = Geometry::get_closest_point_to_segment_2d(blend_pos, s);
+ if (first || closest.distance_to(blend_pos) < best_point.distance_to(blend_pos)) {
+ best_point = closest;
+ blend_triangle = i;
+ first = false;
+ float d = s[0].distance_to(s[1]);
+ if (d == 0.0) {
+ blend_weights[j] = 1.0;
+ blend_weights[(j + 1) % 3] = 0.0;
+ blend_weights[(j + 2) % 3] = 0.0;
+ } else {
+ float c = s[0].distance_to(closest) / d;
+
+ blend_weights[j] = 1.0 - c;
+ blend_weights[(j + 1) % 3] = c;
+ blend_weights[(j + 2) % 3] = 0.0;
+ }
}
}
}
- }
- ERR_FAIL_COND_V(blend_triangle == -1, 0); //should never reach here
+ ERR_FAIL_COND_V(blend_triangle == -1, 0); //should never reach here
- int triangle_points[3];
- for (int j = 0; j < 3; j++) {
- triangle_points[j] = get_triangle_point(blend_triangle, j);
- }
+ int triangle_points[3];
+ for (int j = 0; j < 3; j++) {
+ triangle_points[j] = get_triangle_point(blend_triangle, j);
+ }
- first = true;
- float mind = 0;
- for (int i = 0; i < blend_points_used; i++) {
+ first = true;
- bool found = false;
- for (int j = 0; j < 3; j++) {
- if (i == triangle_points[j]) {
- //blend with the given weight
- float t = blend_node(blend_points[i].name, blend_points[i].node, p_time, p_seek, blend_weights[j], FILTER_IGNORE, false);
- if (first || t < mind) {
- mind = t;
- first = false;
+ for (int i = 0; i < blend_points_used; i++) {
+
+ bool found = false;
+ for (int j = 0; j < 3; j++) {
+ if (i == triangle_points[j]) {
+ //blend with the given weight
+ float t = blend_node(blend_points[i].name, blend_points[i].node, p_time, p_seek, blend_weights[j], FILTER_IGNORE, false);
+ if (first || t < mind) {
+ mind = t;
+ first = false;
+ }
+ found = true;
+ break;
}
- found = true;
- break;
+ }
+
+ if (!found) {
+ //ignore
+ blend_node(blend_points[i].name, blend_points[i].node, p_time, p_seek, 0, FILTER_IGNORE, false);
+ }
+ }
+ } else {
+
+ int new_closest = -1;
+ float new_closest_dist = 1e20;
+
+ for (int i = 0; i < blend_points_used; i++) {
+
+ float d = blend_points[i].position.distance_squared_to(blend_pos);
+ if (d < new_closest_dist) {
+
+ new_closest = i;
+ new_closest_dist = d;
}
}
- if (!found) {
- //ignore
- blend_node(blend_points[i].name, blend_points[i].node, p_time, p_seek, 0, FILTER_IGNORE, false);
+ if (new_closest != closest) {
+
+ float from = 0;
+ if (blend_mode == BLEND_MODE_DISCRETE_CARRY && closest != -1) {
+ //see how much animation remains
+ from = blend_node(blend_points[closest].name, blend_points[closest].node, p_time, true, 0.0, FILTER_IGNORE, false) - length_internal;
+ }
+
+ mind = blend_node(blend_points[new_closest].name, blend_points[new_closest].node, from, true, 1.0, FILTER_IGNORE, false) + from;
+ length_internal = from + mind;
+
+ closest = new_closest;
+
+ } else {
+ mind = blend_node(blend_points[closest].name, blend_points[closest].node, p_time, p_seek, 1.0, FILTER_IGNORE, false);
}
}
+
+ set_parameter(this->closest, closest);
+ set_parameter(this->length_internal, length_internal);
return mind;
}
@@ -527,6 +575,14 @@ void AnimationNodeBlendSpace2D::_tree_changed() {
emit_signal("tree_changed");
}
+void AnimationNodeBlendSpace2D::set_blend_mode(BlendMode p_blend_mode) {
+ blend_mode = p_blend_mode;
+}
+
+AnimationNodeBlendSpace2D::BlendMode AnimationNodeBlendSpace2D::get_blend_mode() const {
+ return blend_mode;
+}
+
void AnimationNodeBlendSpace2D::_bind_methods() {
ClassDB::bind_method(D_METHOD("add_blend_point", "node", "pos", "at_index"), &AnimationNodeBlendSpace2D::add_blend_point, DEFVAL(-1));
@@ -565,6 +621,9 @@ void AnimationNodeBlendSpace2D::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_auto_triangles", "enable"), &AnimationNodeBlendSpace2D::set_auto_triangles);
ClassDB::bind_method(D_METHOD("get_auto_triangles"), &AnimationNodeBlendSpace2D::get_auto_triangles);
+ ClassDB::bind_method(D_METHOD("set_blend_mode", "mode"), &AnimationNodeBlendSpace2D::set_blend_mode);
+ ClassDB::bind_method(D_METHOD("get_blend_mode"), &AnimationNodeBlendSpace2D::get_blend_mode);
+
ClassDB::bind_method(D_METHOD("_tree_changed"), &AnimationNodeBlendSpace2D::_tree_changed);
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "auto_triangles", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR), "set_auto_triangles", "get_auto_triangles");
@@ -581,6 +640,11 @@ void AnimationNodeBlendSpace2D::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "snap", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR), "set_snap", "get_snap");
ADD_PROPERTY(PropertyInfo(Variant::STRING, "x_label", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR), "set_x_label", "get_x_label");
ADD_PROPERTY(PropertyInfo(Variant::STRING, "y_label", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR), "set_y_label", "get_y_label");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "blend_mode", PROPERTY_HINT_ENUM, "Interpolated,Discrete,Carry", PROPERTY_USAGE_NOEDITOR), "set_blend_mode", "get_blend_mode");
+
+ BIND_ENUM_CONSTANT(BLEND_MODE_INTERPOLATED);
+ BIND_ENUM_CONSTANT(BLEND_MODE_DISCRETE);
+ BIND_ENUM_CONSTANT(BLEND_MODE_DISCRETE_CARRY);
}
AnimationNodeBlendSpace2D::AnimationNodeBlendSpace2D() {
@@ -597,6 +661,9 @@ AnimationNodeBlendSpace2D::AnimationNodeBlendSpace2D() {
y_label = "y";
trianges_dirty = false;
blend_position = "blend_position";
+ closest = "closest";
+ length_internal = "length_internal";
+ blend_mode = BLEND_MODE_INTERPOLATED;
}
AnimationNodeBlendSpace2D::~AnimationNodeBlendSpace2D() {
diff --git a/scene/animation/animation_blend_space_2d.h b/scene/animation/animation_blend_space_2d.h
index 2c684687de..60671f1816 100644
--- a/scene/animation/animation_blend_space_2d.h
+++ b/scene/animation/animation_blend_space_2d.h
@@ -35,7 +35,14 @@
class AnimationNodeBlendSpace2D : public AnimationRootNode {
GDCLASS(AnimationNodeBlendSpace2D, AnimationRootNode)
+public:
+ enum BlendMode {
+ BLEND_MODE_INTERPOLATED,
+ BLEND_MODE_DISCRETE,
+ BLEND_MODE_DISCRETE_CARRY,
+ };
+protected:
enum {
MAX_BLEND_POINTS = 64
};
@@ -56,11 +63,14 @@ class AnimationNodeBlendSpace2D : public AnimationRootNode {
Vector<BlendTriangle> triangles;
StringName blend_position;
+ StringName closest;
+ StringName length_internal;
Vector2 max_space;
Vector2 min_space;
Vector2 snap;
String x_label;
String y_label;
+ BlendMode blend_mode;
void _add_blend_point(int p_index, const Ref<AnimationRootNode> &p_node);
void _set_triangles(const Vector<int> &p_triangles);
@@ -122,10 +132,15 @@ public:
void set_auto_triangles(bool p_enable);
bool get_auto_triangles() const;
+ void set_blend_mode(BlendMode p_blend_mode);
+ BlendMode get_blend_mode() const;
+
virtual Ref<AnimationNode> get_child_by_name(const StringName &p_name);
AnimationNodeBlendSpace2D();
~AnimationNodeBlendSpace2D();
};
+VARIANT_ENUM_CAST(AnimationNodeBlendSpace2D::BlendMode)
+
#endif // ANIMATION_BLEND_SPACE_2D_H
diff --git a/scene/animation/animation_blend_tree.cpp b/scene/animation/animation_blend_tree.cpp
index a08639089e..5b413737a9 100644
--- a/scene/animation/animation_blend_tree.cpp
+++ b/scene/animation/animation_blend_tree.cpp
@@ -700,7 +700,7 @@ String AnimationNodeTransition::get_input_caption(int p_input) const {
if (tree.is_valid() && current >= 0) {
prev = current;
- prev_xfading = xfade;
+ prev_xfading = xfade;
time = 0;
current = p_current;
switched = true;
diff --git a/scene/animation/animation_player.cpp b/scene/animation/animation_player.cpp
index 102f05a146..64202ba0e3 100644
--- a/scene/animation/animation_player.cpp
+++ b/scene/animation/animation_player.cpp
@@ -1348,6 +1348,9 @@ void AnimationPlayer::_animation_changed() {
clear_caches();
emit_signal("caches_cleared");
+ if (is_playing()) {
+ playback.seeked = true; //need to restart stuff, like audio
+ }
}
void AnimationPlayer::_stop_playing_caches() {
diff --git a/scene/animation/skeleton_ik.cpp b/scene/animation/skeleton_ik.cpp
index 83f45afac8..3119e29586 100644
--- a/scene/animation/skeleton_ik.cpp
+++ b/scene/animation/skeleton_ik.cpp
@@ -280,7 +280,7 @@ void FabrikInverseKinematic::make_goal(Task *p_task, const Transform &p_inverse_
}
}
-void FabrikInverseKinematic::solve(Task *p_task, real_t blending_delta, bool p_use_magnet, const Vector3 &p_magnet_position) {
+void FabrikInverseKinematic::solve(Task *p_task, real_t blending_delta, bool override_tip_basis, bool p_use_magnet, const Vector3 &p_magnet_position) {
if (blending_delta <= 0.01f) {
return; // Skip solving
@@ -314,7 +314,10 @@ void FabrikInverseKinematic::solve(Task *p_task, real_t blending_delta, bool p_u
}
} else {
// Set target orientation to tip
- new_bone_pose.basis = p_task->chain.tips[0].end_effector->goal_transform.basis;
+ if (override_tip_basis)
+ new_bone_pose.basis = p_task->chain.tips[0].end_effector->goal_transform.basis;
+ else
+ new_bone_pose.basis = new_bone_pose.basis * p_task->chain.tips[0].end_effector->goal_transform.basis;
}
p_task->skeleton->set_bone_global_pose(ci->bone, new_bone_pose);
@@ -366,6 +369,9 @@ void SkeletonIK::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_target_node", "node"), &SkeletonIK::set_target_node);
ClassDB::bind_method(D_METHOD("get_target_node"), &SkeletonIK::get_target_node);
+ ClassDB::bind_method(D_METHOD("set_override_tip_basis", "override"), &SkeletonIK::set_override_tip_basis);
+ ClassDB::bind_method(D_METHOD("is_override_tip_basis"), &SkeletonIK::is_override_tip_basis);
+
ClassDB::bind_method(D_METHOD("set_use_magnet", "use"), &SkeletonIK::set_use_magnet);
ClassDB::bind_method(D_METHOD("is_using_magnet"), &SkeletonIK::is_using_magnet);
@@ -388,6 +394,7 @@ void SkeletonIK::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::STRING, "tip_bone"), "set_tip_bone", "get_tip_bone");
ADD_PROPERTY(PropertyInfo(Variant::REAL, "interpolation", PROPERTY_HINT_RANGE, "0,1,0.001"), "set_interpolation", "get_interpolation");
ADD_PROPERTY(PropertyInfo(Variant::TRANSFORM, "target"), "set_target_transform", "get_target_transform");
+ ADD_PROPERTY(PropertyInfo(Variant::BOOL, "override_tip_basis"), "set_override_tip_basis", "is_override_tip_basis");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "use_magnet"), "set_use_magnet", "is_using_magnet");
ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "magnet"), "set_magnet_position", "get_magnet_position");
ADD_PROPERTY(PropertyInfo(Variant::NODE_PATH, "target_node"), "set_target_node", "get_target_node");
@@ -418,6 +425,7 @@ void SkeletonIK::_notification(int p_what) {
SkeletonIK::SkeletonIK() :
Node(),
interpolation(1),
+ override_tip_basis(true),
use_magnet(false),
min_distance(0.01),
max_iterations(10),
@@ -478,6 +486,14 @@ NodePath SkeletonIK::get_target_node() {
return target_node_path_override;
}
+void SkeletonIK::set_override_tip_basis(bool p_override) {
+ override_tip_basis = p_override;
+}
+
+bool SkeletonIK::is_override_tip_basis() const {
+ return override_tip_basis;
+}
+
void SkeletonIK::set_use_magnet(bool p_use) {
use_magnet = p_use;
}
@@ -555,7 +571,7 @@ void SkeletonIK::reload_goal() {
void SkeletonIK::_solve_chain() {
if (!task)
return;
- FabrikInverseKinematic::solve(task, interpolation, use_magnet, magnet_position);
+ FabrikInverseKinematic::solve(task, interpolation, override_tip_basis, use_magnet, magnet_position);
}
#endif // _3D_DISABLED
diff --git a/scene/animation/skeleton_ik.h b/scene/animation/skeleton_ik.h
index 202d6959bb..b9628c479c 100644
--- a/scene/animation/skeleton_ik.h
+++ b/scene/animation/skeleton_ik.h
@@ -138,7 +138,7 @@ public:
// The goal of chain should be always in local space
static void set_goal(Task *p_task, const Transform &p_goal);
static void make_goal(Task *p_task, const Transform &p_inverse_transf, real_t blending_delta);
- static void solve(Task *p_task, real_t blending_delta, bool p_use_magnet, const Vector3 &p_magnet_position);
+ static void solve(Task *p_task, real_t blending_delta, bool override_tip_basis, bool p_use_magnet, const Vector3 &p_magnet_position);
};
class SkeletonIK : public Node {
@@ -149,6 +149,7 @@ class SkeletonIK : public Node {
real_t interpolation;
Transform target;
NodePath target_node_path_override;
+ bool override_tip_basis;
bool use_magnet;
Vector3 magnet_position;
@@ -185,6 +186,9 @@ public:
void set_target_node(const NodePath &p_node);
NodePath get_target_node();
+ void set_override_tip_basis(bool p_override);
+ bool is_override_tip_basis() const;
+
void set_use_magnet(bool p_use);
bool is_using_magnet() const;
diff --git a/scene/gui/scroll_container.cpp b/scene/gui/scroll_container.cpp
index 26da16569a..9c22a049b8 100644
--- a/scene/gui/scroll_container.cpp
+++ b/scene/gui/scroll_container.cpp
@@ -246,7 +246,7 @@ void ScrollContainer::_notification(int p_what) {
size.y -= h_scroll->get_minimum_size().y;
if (v_scroll->is_visible_in_tree() && v_scroll->get_parent() == this) //scrolls may have been moved out for reasons
- size.x -= h_scroll->get_minimum_size().x;
+ size.x -= v_scroll->get_minimum_size().x;
for (int i = 0; i < get_child_count(); i++) {
diff --git a/scene/gui/split_container.cpp b/scene/gui/split_container.cpp
index c38c411333..3554f04cc0 100644
--- a/scene/gui/split_container.cpp
+++ b/scene/gui/split_container.cpp
@@ -62,39 +62,28 @@ void SplitContainer::_resort() {
// If we have only one element
if (!first || !second) {
if (first) {
- fit_child_in_rect(_getch(0), Rect2(Point2(), get_size()));
+ fit_child_in_rect(first, Rect2(Point2(), get_size()));
} else if (second) {
- fit_child_in_rect(_getch(1), Rect2(Point2(), get_size()));
+ fit_child_in_rect(second, Rect2(Point2(), get_size()));
}
return;
}
// Determine expanded children
- bool first_expanded = false;
- bool second_expanded = false;
- if (vertical) {
- first_expanded = first->get_v_size_flags() & SIZE_EXPAND;
- second_expanded = second->get_v_size_flags() & SIZE_EXPAND;
- } else {
- first_expanded = first->get_h_size_flags() & SIZE_EXPAND;
- second_expanded = second->get_h_size_flags() & SIZE_EXPAND;
- }
+ bool first_expanded = (vertical ? first->get_v_size_flags() : first->get_h_size_flags()) & SIZE_EXPAND;
+ bool second_expanded = (vertical ? second->get_v_size_flags() : second->get_h_size_flags()) & SIZE_EXPAND;
// Determine the separation between items
Ref<Texture> g = get_icon("grabber");
int sep = get_constant("separation");
- if (dragger_visibility == DRAGGER_HIDDEN_COLLAPSED) {
- sep = 0;
- } else {
- sep = MAX(sep, vertical ? g->get_height() : g->get_width());
- }
+ sep = (dragger_visibility != DRAGGER_HIDDEN_COLLAPSED) ? MAX(sep, vertical ? g->get_height() : g->get_width()) : 0;
// Compute the minimum size
Size2 ms_first = first->get_combined_minimum_size();
Size2 ms_second = second->get_combined_minimum_size();
+ // Compute the separator position without the split offset
float ratio = first->get_stretch_ratio() / (first->get_stretch_ratio() + second->get_stretch_ratio());
-
int no_offset_middle_sep = 0;
if (first_expanded && second_expanded) {
no_offset_middle_sep = get_size()[axis] * ratio - sep / 2;
@@ -104,12 +93,13 @@ void SplitContainer::_resort() {
no_offset_middle_sep = ms_first[axis];
}
- middle_sep = no_offset_middle_sep;
- middle_sep += (collapsed) ? 0 : split_offset;
- middle_sep = MIN(middle_sep, get_size()[axis] - ms_second[axis] - sep);
- middle_sep = MAX(middle_sep, ms_first[axis]);
- if (!collapsed) {
- split_offset = middle_sep - no_offset_middle_sep;
+ // Compute the final middle separation
+ int clamped_split_offset = CLAMP(split_offset, ms_first[axis] - no_offset_middle_sep, (get_size()[axis] - ms_second[axis] - sep) - no_offset_middle_sep);
+ middle_sep = no_offset_middle_sep + clamped_split_offset;
+ if (!collapsed && should_clamp_split_offset) {
+ split_offset = clamped_split_offset;
+ _change_notify("split_offset");
+ should_clamp_split_offset = false;
}
if (vertical) {
@@ -123,7 +113,6 @@ void SplitContainer::_resort() {
}
update();
- _change_notify("split_offset");
}
Size2 SplitContainer::get_minimum_size() const {
@@ -131,8 +120,8 @@ Size2 SplitContainer::get_minimum_size() const {
/* Calculate MINIMUM SIZE */
Size2i minimum;
- int sep = get_constant("separation");
Ref<Texture> g = get_icon("grabber");
+ int sep = get_constant("separation");
sep = (dragger_visibility != DRAGGER_HIDDEN_COLLAPSED) ? MAX(sep, vertical ? g->get_height() : g->get_width()) : 0;
for (int i = 0; i < 2; i++) {
@@ -248,6 +237,7 @@ void SplitContainer::_gui_input(const Ref<InputEvent> &p_event) {
if (mm.is_valid() && dragging) {
split_offset = drag_ofs + ((vertical ? mm->get_position().y : mm->get_position().x) - drag_from);
+ should_clamp_split_offset = true;
queue_sort();
emit_signal("dragged", get_split_offset());
}
@@ -282,6 +272,7 @@ void SplitContainer::set_split_offset(int p_offset) {
return;
split_offset = p_offset;
+
queue_sort();
}
@@ -290,6 +281,12 @@ int SplitContainer::get_split_offset() const {
return split_offset;
}
+void SplitContainer::clamp_split_offset() {
+ should_clamp_split_offset = true;
+
+ queue_sort();
+}
+
void SplitContainer::set_collapsed(bool p_collapsed) {
if (collapsed == p_collapsed)
@@ -319,8 +316,10 @@ bool SplitContainer::is_collapsed() const {
void SplitContainer::_bind_methods() {
ClassDB::bind_method(D_METHOD("_gui_input"), &SplitContainer::_gui_input);
+
ClassDB::bind_method(D_METHOD("set_split_offset", "offset"), &SplitContainer::set_split_offset);
ClassDB::bind_method(D_METHOD("get_split_offset"), &SplitContainer::get_split_offset);
+ ClassDB::bind_method(D_METHOD("clamp_split_offset"), &SplitContainer::clamp_split_offset);
ClassDB::bind_method(D_METHOD("set_collapsed", "collapsed"), &SplitContainer::set_collapsed);
ClassDB::bind_method(D_METHOD("is_collapsed"), &SplitContainer::is_collapsed);
@@ -343,6 +342,7 @@ SplitContainer::SplitContainer(bool p_vertical) {
mouse_inside = false;
split_offset = 0;
+ should_clamp_split_offset = false;
middle_sep = 0;
vertical = p_vertical;
dragging = false;
diff --git a/scene/gui/split_container.h b/scene/gui/split_container.h
index 321f7fd3b7..f8b3343aa8 100644
--- a/scene/gui/split_container.h
+++ b/scene/gui/split_container.h
@@ -45,9 +45,10 @@ public:
};
private:
- bool vertical;
+ bool should_clamp_split_offset;
int split_offset;
int middle_sep;
+ bool vertical;
bool dragging;
int drag_from;
int drag_ofs;
@@ -67,6 +68,7 @@ protected:
public:
void set_split_offset(int p_offset);
int get_split_offset() const;
+ void clamp_split_offset();
void set_collapsed(bool p_collapsed);
bool is_collapsed() const;
diff --git a/scene/gui/tree.cpp b/scene/gui/tree.cpp
index 31f7a21114..c083e727d1 100644
--- a/scene/gui/tree.cpp
+++ b/scene/gui/tree.cpp
@@ -901,6 +901,7 @@ void Tree::update_cache() {
cache.item_margin = get_constant("item_margin");
cache.button_margin = get_constant("button_margin");
cache.guide_width = get_constant("guide_width");
+ cache.draw_guides = get_constant("draw_guides");
cache.draw_relationship_lines = get_constant("draw_relationship_lines");
cache.relationship_line_color = get_color("relationship_line_color");
cache.scroll_border = get_constant("scroll_border");
@@ -1132,7 +1133,9 @@ int Tree::draw_item(const Point2i &p_pos, const Point2 &p_draw_ofs, const Size2
cell_rect.size.x += cache.hseparation;
}
- VisualServer::get_singleton()->canvas_item_add_line(ci, Point2i(cell_rect.position.x, cell_rect.position.y + cell_rect.size.height), cell_rect.position + cell_rect.size, cache.guide_color, 1);
+ if (cache.draw_guides) {
+ VisualServer::get_singleton()->canvas_item_add_line(ci, Point2i(cell_rect.position.x, cell_rect.position.y + cell_rect.size.height), cell_rect.position + cell_rect.size, cache.guide_color, 1);
+ }
if (i == 0) {
diff --git a/scene/gui/tree.h b/scene/gui/tree.h
index 34138acb85..886ce66e2c 100644
--- a/scene/gui/tree.h
+++ b/scene/gui/tree.h
@@ -434,6 +434,7 @@ private:
int button_margin;
Point2 offset;
int draw_relationship_lines;
+ int draw_guides;
int scroll_border;
int scroll_speed;
diff --git a/scene/main/canvas_layer.cpp b/scene/main/canvas_layer.cpp
index 93f51a44f4..89bc8c1226 100644
--- a/scene/main/canvas_layer.cpp
+++ b/scene/main/canvas_layer.cpp
@@ -164,7 +164,9 @@ void CanvasLayer::_notification(int p_what) {
} break;
case NOTIFICATION_MOVED_IN_PARENT: {
- VisualServer::get_singleton()->viewport_set_canvas_stacking(viewport, canvas, layer, get_position_in_parent());
+ if (is_inside_tree())
+ VisualServer::get_singleton()->viewport_set_canvas_stacking(viewport, canvas, layer, get_position_in_parent());
+
} break;
}
}
diff --git a/scene/main/node.cpp b/scene/main/node.cpp
index 3242068bf7..ea50e7289d 100644
--- a/scene/main/node.cpp
+++ b/scene/main/node.cpp
@@ -157,7 +157,7 @@ void Node::_notification(int p_notification) {
// kill children as cleanly as possible
while (data.children.size()) {
- Node *child = data.children[0];
+ Node *child = data.children[data.children.size() - 1]; //begin from the end because its faster and more consistent with creation
remove_child(child);
memdelete(child);
}
@@ -1008,6 +1008,32 @@ void Node::_validate_child_name(Node *p_child, bool p_force_human_readable) {
}
}
+// Return s + 1 as if it were an integer
+String increase_numeric_string(const String &s) {
+
+ String res = s;
+ bool carry = res.length() > 0;
+
+ for (int i = res.length() - 1; i >= 0; i--) {
+ if (!carry) {
+ break;
+ }
+ CharType n = s[i];
+ if (n == '9') { // keep carry as true: 9 + 1
+ res[i] = '0';
+ } else {
+ res[i] = s[i] + 1;
+ carry = false;
+ }
+ }
+
+ if (carry) {
+ res = "1" + res;
+ }
+
+ return res;
+}
+
String Node::_generate_serial_child_name(Node *p_child) {
String name = p_child->data.name;
@@ -1040,42 +1066,38 @@ String Node::_generate_serial_child_name(Node *p_child) {
}
String nnsep = _get_name_num_separator();
- int num = 0;
- bool explicit_zero = false;
- if (nums.length() > 0 && name.substr(name.length() - nnsep.length() - nums.length(), nnsep.length()) == nnsep) {
- // Base name + Separator + Number
- num = nums.to_int();
- name = name.substr(0, name.length() - nnsep.length() - nums.length()); // Keep base name
- if (num == 0) {
- explicit_zero = true;
+ int name_last_index = name.length() - nnsep.length() - nums.length();
+
+ // Assign the base name + separator to name if we have numbers preceded by a separator
+ if (nums.length() > 0 && name.substr(name_last_index, nnsep.length()) == nnsep) {
+ name = name.substr(0, name_last_index + nnsep.length()).strip_edges();
+ } else {
+ nums = "";
+ }
+
+ Vector<String> children_names;
+
+ for (int i = 0; i < data.children.size(); i++) {
+ String child_name = data.children[i]->data.name;
+ if (data.children[i] == p_child)
+ continue;
+ if (child_name.begins_with(name)) {
+ children_names.push_back(child_name);
}
}
- int num_places = nums.length();
for (;;) {
- String attempt = (name + (num > 0 || explicit_zero ? nnsep + itos(num).pad_zeros(num_places) : "")).strip_edges();
- bool found = false;
- for (int i = 0; i < data.children.size(); i++) {
- if (data.children[i] == p_child)
- continue;
- if (data.children[i]->data.name == attempt) {
- found = true;
- break;
- }
- }
- if (!found) {
+ String attempt = name + nums;
+
+ if (children_names.find(attempt) == -1) {
return attempt;
} else {
- if (num == 0) {
- if (explicit_zero) {
- // Name ended in separator + 0; user expects to get to separator + 1
- num = 1;
- } else {
- // Name was undecorated so skip to 2 for a more natural result
- num = 2;
- }
+ if (nums.length() == 0) {
+ // Name was undecorated so skip to 2 for a more natural result
+ nums = "2";
+ name += nnsep; // Add separator because nums.length() > 0 was false
} else {
- num++;
+ nums = increase_numeric_string(nums);
}
}
}
@@ -1182,13 +1204,24 @@ void Node::remove_child(Node *p_child) {
ERR_FAIL_COND(data.blocked > 0);
}
+ int child_count = data.children.size();
+ Node **children = data.children.ptrw();
int idx = -1;
- for (int i = 0; i < data.children.size(); i++) {
- if (data.children[i] == p_child) {
+ if (p_child->data.pos >= 0 && p_child->data.pos < child_count) {
+ if (children[p_child->data.pos] == p_child) {
+ idx = p_child->data.pos;
+ }
+ }
- idx = i;
- break;
+ if (idx == -1) { //maybe removed while unparenting or something and index was not updated, so just in case the above fails, try this.
+ for (int i = 0; i < child_count; i++) {
+
+ if (children[i] == p_child) {
+
+ idx = i;
+ break;
+ }
}
}
@@ -1205,10 +1238,14 @@ void Node::remove_child(Node *p_child) {
data.children.remove(idx);
- for (int i = idx; i < data.children.size(); i++) {
+ //update pointer and size
+ child_count = data.children.size();
+ children = data.children.ptrw();
- data.children[i]->data.pos = i;
- data.children[i]->notification(NOTIFICATION_MOVED_IN_PARENT);
+ for (int i = idx; i < child_count; i++) {
+
+ children[i]->data.pos = i;
+ children[i]->notification(NOTIFICATION_MOVED_IN_PARENT);
}
p_child->data.parent = NULL;
diff --git a/scene/main/viewport.cpp b/scene/main/viewport.cpp
index 82645aa17a..8545efb966 100644
--- a/scene/main/viewport.cpp
+++ b/scene/main/viewport.cpp
@@ -1510,12 +1510,17 @@ void Viewport::_gui_call_input(Control *p_control, const Ref<InputEvent> &p_inpu
Control *control = Object::cast_to<Control>(ci);
if (control) {
- control->emit_signal(SceneStringNames::get_singleton()->gui_input, ev); //signal should be first, so it's possible to override an event (and then accept it)
+ if (control->data.mouse_filter != Control::MOUSE_FILTER_IGNORE) {
+ control->emit_signal(SceneStringNames::get_singleton()->gui_input, ev); //signal should be first, so it's possible to override an event (and then accept it)
+ }
if (gui.key_event_accepted)
break;
if (!control->is_inside_tree())
break;
- control->call_multilevel(SceneStringNames::get_singleton()->_gui_input, ev);
+
+ if (control->data.mouse_filter != Control::MOUSE_FILTER_IGNORE) {
+ control->call_multilevel(SceneStringNames::get_singleton()->_gui_input, ev);
+ }
if (!control->is_inside_tree() || control->is_set_as_toplevel())
break;
@@ -1895,7 +1900,13 @@ void Viewport::_gui_input_event(Ref<InputEvent> p_event) {
if (gui.drag_data.get_type() != Variant::NIL) {
gui.mouse_focus = NULL;
+ break;
} else {
+ if (gui.drag_preview != NULL) {
+ ERR_PRINT("Don't set a drag preview and return null data. Preview was deleted and drag request ignored.");
+ memdelete(gui.drag_preview);
+ gui.drag_preview = NULL;
+ }
gui.dragging = false;
}
diff --git a/scene/resources/default_theme/default_theme.cpp b/scene/resources/default_theme/default_theme.cpp
index 4de47b2cb0..fff136cdc3 100644
--- a/scene/resources/default_theme/default_theme.cpp
+++ b/scene/resources/default_theme/default_theme.cpp
@@ -653,6 +653,7 @@ void fill_default_theme(Ref<Theme> &theme, const Ref<Font> &default_font, const
theme->set_constant("item_margin", "Tree", 12 * scale);
theme->set_constant("button_margin", "Tree", 4 * scale);
theme->set_constant("draw_relationship_lines", "Tree", 0);
+ theme->set_constant("draw_guides", "Tree", 1);
theme->set_constant("scroll_border", "Tree", 4);
theme->set_constant("scroll_speed", "Tree", 12);
diff --git a/scene/resources/dynamic_font.cpp b/scene/resources/dynamic_font.cpp
index d6b40766a2..ad22d6530c 100644
--- a/scene/resources/dynamic_font.cpp
+++ b/scene/resources/dynamic_font.cpp
@@ -82,11 +82,14 @@ void DynamicFontData::set_force_autohinter(bool p_force) {
}
void DynamicFontData::_bind_methods() {
+ ClassDB::bind_method(D_METHOD("set_antialiased", "antialiased"), &DynamicFontData::set_antialiased);
+ ClassDB::bind_method(D_METHOD("is_antialiased"), &DynamicFontData::is_antialiased);
ClassDB::bind_method(D_METHOD("set_font_path", "path"), &DynamicFontData::set_font_path);
ClassDB::bind_method(D_METHOD("get_font_path"), &DynamicFontData::get_font_path);
ClassDB::bind_method(D_METHOD("set_hinting", "mode"), &DynamicFontData::set_hinting);
ClassDB::bind_method(D_METHOD("get_hinting"), &DynamicFontData::get_hinting);
+ ADD_PROPERTY(PropertyInfo(Variant::BOOL, "antialiased"), "set_antialiased", "is_antialiased");
ADD_PROPERTY(PropertyInfo(Variant::INT, "hinting", PROPERTY_HINT_ENUM, "None,Light,Normal"), "set_hinting", "get_hinting");
BIND_ENUM_CONSTANT(HINTING_NONE);
@@ -98,6 +101,7 @@ void DynamicFontData::_bind_methods() {
DynamicFontData::DynamicFontData() {
+ antialiased = true;
force_autohinter = false;
hinting = DynamicFontData::HINTING_NORMAL;
font_mem = NULL;
@@ -632,7 +636,7 @@ void DynamicFontAtSize::_update_char(CharType p_char) {
if (id.outline_size > 0) {
character = _make_outline_char(p_char);
} else {
- error = FT_Render_Glyph(face->glyph, FT_RENDER_MODE_NORMAL);
+ error = FT_Render_Glyph(face->glyph, font->antialiased ? FT_RENDER_MODE_NORMAL : FT_RENDER_MODE_MONO);
if (!error)
character = _bitmap_to_character(slot->bitmap, slot->bitmap_top, slot->bitmap_left, slot->advance.x / 64.0);
}
@@ -785,6 +789,18 @@ void DynamicFont::set_use_filter(bool p_enable) {
_reload_cache();
}
+bool DynamicFontData::is_antialiased() const {
+
+ return antialiased;
+}
+
+void DynamicFontData::set_antialiased(bool p_antialiased) {
+
+ if (antialiased == p_antialiased)
+ return;
+ antialiased = p_antialiased;
+}
+
DynamicFontData::Hinting DynamicFontData::get_hinting() const {
return hinting;
diff --git a/scene/resources/dynamic_font.h b/scene/resources/dynamic_font.h
index bd3f84d62c..96437e8982 100644
--- a/scene/resources/dynamic_font.h
+++ b/scene/resources/dynamic_font.h
@@ -71,12 +71,15 @@ public:
HINTING_NORMAL
};
+ bool is_antialiased() const;
+ void set_antialiased(bool p_antialiased);
Hinting get_hinting() const;
void set_hinting(Hinting p_hinting);
private:
const uint8_t *font_mem;
int font_mem_size;
+ bool antialiased;
bool force_autohinter;
Hinting hinting;
diff --git a/scene/resources/material.cpp b/scene/resources/material.cpp
index 8ff08f91f2..5327ed318f 100644
--- a/scene/resources/material.cpp
+++ b/scene/resources/material.cpp
@@ -699,7 +699,7 @@ void SpatialMaterial::_update_shader() {
if (features[FEATURE_DEPTH_MAPPING] && !flags[FLAG_UV1_USE_TRIPLANAR]) { //depthmap not supported with triplanar
code += "\t{\n";
- code += "\t\tvec3 view_dir = normalize(normalize(-VERTEX)*mat3(TANGENT*depth_flip.x,BINORMAL*depth_flip.y,NORMAL));\n"; //binormal is negative due to mikktpsace
+ code += "\t\tvec3 view_dir = normalize(normalize(-VERTEX)*mat3(TANGENT*depth_flip.x,BINORMAL*depth_flip.y,NORMAL));\n"; // binormal is negative due to mikktspace
if (deep_parallax) {
code += "\t\tfloat num_layers = mix(float(depth_max_layers),float(depth_min_layers), abs(dot(vec3(0.0, 0.0, 1.0), view_dir)));\n";
@@ -2277,7 +2277,7 @@ SpatialMaterial::SpatialMaterial() :
deep_parallax = false;
depth_parallax_flip_tangent = false;
- depth_parallax_flip_binormal = true;
+ depth_parallax_flip_binormal = false;
set_depth_deep_parallax_min_layers(8);
set_depth_deep_parallax_max_layers(32);
set_depth_deep_parallax_flip_tangent(false); //also sets binormal
diff --git a/scene/resources/mesh.cpp b/scene/resources/mesh.cpp
index 838d73edb3..80191367ce 100644
--- a/scene/resources/mesh.cpp
+++ b/scene/resources/mesh.cpp
@@ -706,6 +706,7 @@ bool ArrayMesh::_get(const StringName &p_name, Variant &r_ret) const {
Vector<AABB> skel_aabb = VS::get_singleton()->mesh_surface_get_skeleton_aabb(mesh, idx);
Array arr;
+ arr.resize(skel_aabb.size());
for (int i = 0; i < skel_aabb.size(); i++) {
arr[i] = skel_aabb[i];
}
diff --git a/scene/resources/particles_material.cpp b/scene/resources/particles_material.cpp
index b3fc13b79e..dae01e8d96 100644
--- a/scene/resources/particles_material.cpp
+++ b/scene/resources/particles_material.cpp
@@ -1154,7 +1154,7 @@ void ParticlesMaterial::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "color_ramp", PROPERTY_HINT_RESOURCE_TYPE, "GradientTexture"), "set_color_ramp", "get_color_ramp");
ADD_GROUP("Hue Variation", "hue_");
- ADD_PROPERTYI(PropertyInfo(Variant::REAL, "hue_variation", PROPERTY_HINT_RANGE, "-1,1,0.1"), "set_param", "get_param", PARAM_HUE_VARIATION);
+ ADD_PROPERTYI(PropertyInfo(Variant::REAL, "hue_variation", PROPERTY_HINT_RANGE, "-1,1,0.01"), "set_param", "get_param", PARAM_HUE_VARIATION);
ADD_PROPERTYI(PropertyInfo(Variant::REAL, "hue_variation_random", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_param_randomness", "get_param_randomness", PARAM_HUE_VARIATION);
ADD_PROPERTYI(PropertyInfo(Variant::OBJECT, "hue_variation_curve", PROPERTY_HINT_RESOURCE_TYPE, "CurveTexture"), "set_param_texture", "get_param_texture", PARAM_HUE_VARIATION);
ADD_GROUP("Animation", "anim_");
diff --git a/scene/resources/primitive_meshes.cpp b/scene/resources/primitive_meshes.cpp
index 4906ceb2eb..dafdddd990 100644
--- a/scene/resources/primitive_meshes.cpp
+++ b/scene/resources/primitive_meshes.cpp
@@ -306,7 +306,7 @@ void CapsuleMesh::_create_mesh_array(Array &p_arr) const {
Vector3 p = Vector3(x * radius * w, y * radius * w, z);
points.push_back(p + Vector3(0.0, 0.0, 0.5 * mid_height));
normals.push_back(p.normalized());
- ADD_TANGENT(y, -x, 0.0, -1.0)
+ ADD_TANGENT(-y, x, 0.0, -1.0)
uvs.push_back(Vector2(u, v * onethird));
point++;
@@ -345,7 +345,7 @@ void CapsuleMesh::_create_mesh_array(Array &p_arr) const {
Vector3 p = Vector3(x * radius, y * radius, z);
points.push_back(p);
normals.push_back(Vector3(x, y, 0.0));
- ADD_TANGENT(y, -x, 0.0, -1.0)
+ ADD_TANGENT(-y, x, 0.0, -1.0)
uvs.push_back(Vector2(u, onethird + (v * onethird)));
point++;
@@ -385,7 +385,7 @@ void CapsuleMesh::_create_mesh_array(Array &p_arr) const {
Vector3 p = Vector3(x * radius * w, y * radius * w, z);
points.push_back(p + Vector3(0.0, 0.0, -0.5 * mid_height));
normals.push_back(p.normalized());
- ADD_TANGENT(y, -x, 0.0, -1.0)
+ ADD_TANGENT(-y, x, 0.0, -1.0)
uvs.push_back(Vector2(u, twothirds + ((v - 1.0) * onethird)));
point++;
@@ -514,14 +514,14 @@ void CubeMesh::_create_mesh_array(Array &p_arr) const {
// front
points.push_back(Vector3(x, -y, -start_pos.z)); // double negative on the Z!
normals.push_back(Vector3(0.0, 0.0, 1.0));
- ADD_TANGENT(-1.0, 0.0, 0.0, -1.0);
+ ADD_TANGENT(1.0, 0.0, 0.0, -1.0);
uvs.push_back(Vector2(u, v));
point++;
// back
points.push_back(Vector3(-x, -y, start_pos.z));
normals.push_back(Vector3(0.0, 0.0, -1.0));
- ADD_TANGENT(1.0, 0.0, 0.0, -1.0);
+ ADD_TANGENT(-1.0, 0.0, 0.0, -1.0);
uvs.push_back(Vector2(twothirds + u, v));
point++;
@@ -568,14 +568,14 @@ void CubeMesh::_create_mesh_array(Array &p_arr) const {
// right
points.push_back(Vector3(-start_pos.x, -y, -z));
normals.push_back(Vector3(1.0, 0.0, 0.0));
- ADD_TANGENT(0.0, 0.0, 1.0, -1.0);
+ ADD_TANGENT(0.0, 0.0, -1.0, -1.0);
uvs.push_back(Vector2(onethird + u, v));
point++;
// left
points.push_back(Vector3(start_pos.x, -y, z));
normals.push_back(Vector3(-1.0, 0.0, 0.0));
- ADD_TANGENT(0.0, 0.0, -1.0, -1.0);
+ ADD_TANGENT(0.0, 0.0, 1.0, -1.0);
uvs.push_back(Vector2(u, 0.5 + v));
point++;
@@ -622,14 +622,14 @@ void CubeMesh::_create_mesh_array(Array &p_arr) const {
// top
points.push_back(Vector3(-x, -start_pos.y, -z));
normals.push_back(Vector3(0.0, 1.0, 0.0));
- ADD_TANGENT(1.0, 0.0, 0.0, -1.0);
+ ADD_TANGENT(-1.0, 0.0, 0.0, -1.0);
uvs.push_back(Vector2(onethird + u, 0.5 + v));
point++;
// bottom
points.push_back(Vector3(x, start_pos.y, -z));
normals.push_back(Vector3(0.0, -1.0, 0.0));
- ADD_TANGENT(-1.0, 0.0, 0.0, -1.0);
+ ADD_TANGENT(1.0, 0.0, 0.0, -1.0);
uvs.push_back(Vector2(twothirds + u, 0.5 + v));
point++;
@@ -773,7 +773,7 @@ void CylinderMesh::_create_mesh_array(Array &p_arr) const {
Vector3 p = Vector3(x * radius, y, z * radius);
points.push_back(p);
normals.push_back(Vector3(x, 0.0, z));
- ADD_TANGENT(-z, 0.0, x, -1.0)
+ ADD_TANGENT(z, 0.0, -x, -1.0)
uvs.push_back(Vector2(u, v * 0.5));
point++;
@@ -799,7 +799,7 @@ void CylinderMesh::_create_mesh_array(Array &p_arr) const {
thisrow = point;
points.push_back(Vector3(0.0, y, 0.0));
normals.push_back(Vector3(0.0, 1.0, 0.0));
- ADD_TANGENT(1.0, 0.0, 0.0, 1.0)
+ ADD_TANGENT(1.0, 0.0, 0.0, -1.0)
uvs.push_back(Vector2(0.25, 0.75));
point++;
@@ -816,7 +816,7 @@ void CylinderMesh::_create_mesh_array(Array &p_arr) const {
Vector3 p = Vector3(x * top_radius, y, z * top_radius);
points.push_back(p);
normals.push_back(Vector3(0.0, 1.0, 0.0));
- ADD_TANGENT(1.0, 0.0, 0.0, 1.0)
+ ADD_TANGENT(1.0, 0.0, 0.0, -1.0)
uvs.push_back(Vector2(u, v));
point++;
@@ -835,7 +835,7 @@ void CylinderMesh::_create_mesh_array(Array &p_arr) const {
thisrow = point;
points.push_back(Vector3(0.0, y, 0.0));
normals.push_back(Vector3(0.0, -1.0, 0.0));
- ADD_TANGENT(-1.0, 0.0, 0.0, -1.0)
+ ADD_TANGENT(1.0, 0.0, 0.0, -1.0)
uvs.push_back(Vector2(0.75, 0.75));
point++;
@@ -852,7 +852,7 @@ void CylinderMesh::_create_mesh_array(Array &p_arr) const {
Vector3 p = Vector3(x * bottom_radius, y, z * bottom_radius);
points.push_back(p);
normals.push_back(Vector3(0.0, -1.0, 0.0));
- ADD_TANGENT(-1.0, 0.0, 0.0, -1.0)
+ ADD_TANGENT(1.0, 0.0, 0.0, -1.0)
uvs.push_back(Vector2(u, v));
point++;
@@ -983,7 +983,7 @@ void PlaneMesh::_create_mesh_array(Array &p_arr) const {
points.push_back(Vector3(-x, 0.0, -z));
normals.push_back(Vector3(0.0, 1.0, 0.0));
ADD_TANGENT(1.0, 0.0, 0.0, -1.0);
- uvs.push_back(Vector2(u, v));
+ uvs.push_back(Vector2(1.0 - u, 1.0 - v)); /* 1.0 - uv to match orientation with Quad */
point++;
if (i > 0 && j > 0) {
@@ -1108,14 +1108,14 @@ void PrismMesh::_create_mesh_array(Array &p_arr) const {
/* front */
points.push_back(Vector3(start_x + x, -y, -start_pos.z)); // double negative on the Z!
normals.push_back(Vector3(0.0, 0.0, 1.0));
- ADD_TANGENT(-1.0, 0.0, 0.0, -1.0);
+ ADD_TANGENT(1.0, 0.0, 0.0, -1.0);
uvs.push_back(Vector2(offset_front + u, v));
point++;
/* back */
points.push_back(Vector3(start_x + scaled_size_x - x, -y, start_pos.z));
normals.push_back(Vector3(0.0, 0.0, -1.0));
- ADD_TANGENT(1.0, 0.0, 0.0, -1.0);
+ ADD_TANGENT(-1.0, 0.0, 0.0, -1.0);
uvs.push_back(Vector2(twothirds + offset_back + u, v));
point++;
@@ -1187,14 +1187,14 @@ void PrismMesh::_create_mesh_array(Array &p_arr) const {
/* right */
points.push_back(Vector3(right, -y, -z));
normals.push_back(normal_right);
- ADD_TANGENT(0.0, 0.0, 1.0, -1.0);
+ ADD_TANGENT(0.0, 0.0, -1.0, -1.0);
uvs.push_back(Vector2(onethird + u, v));
point++;
/* left */
points.push_back(Vector3(left, -y, z));
normals.push_back(normal_left);
- ADD_TANGENT(0.0, 0.0, -1.0, -1.0);
+ ADD_TANGENT(0.0, 0.0, 1.0, -1.0);
uvs.push_back(Vector2(u, 0.5 + v));
point++;
@@ -1241,7 +1241,7 @@ void PrismMesh::_create_mesh_array(Array &p_arr) const {
/* bottom */
points.push_back(Vector3(x, start_pos.y, -z));
normals.push_back(Vector3(0.0, -1.0, 0.0));
- ADD_TANGENT(-1.0, 0.0, 0.0, -1.0);
+ ADD_TANGENT(1.0, 0.0, 0.0, -1.0);
uvs.push_back(Vector2(twothirds + u, 0.5 + v));
point++;
@@ -1382,7 +1382,7 @@ void QuadMesh::_create_mesh_array(Array &p_arr) const {
tangents.set(i * 4 + 0, 1.0);
tangents.set(i * 4 + 1, 0.0);
tangents.set(i * 4 + 2, 0.0);
- tangents.set(i * 4 + 3, 1.0);
+ tangents.set(i * 4 + 3, -1.0);
static const Vector2 quad_uv[4] = {
Vector2(0, 1),
@@ -1468,7 +1468,7 @@ void SphereMesh::_create_mesh_array(Array &p_arr) const {
points.push_back(p);
normals.push_back(p.normalized());
};
- ADD_TANGENT(-z, 0.0, x, -1.0)
+ ADD_TANGENT(z, 0.0, -x, -1.0)
uvs.push_back(Vector2(u, v));
point++;
diff --git a/scene/resources/sky_box.cpp b/scene/resources/sky_box.cpp
index a6a52c7bba..347bca4400 100644
--- a/scene/resources/sky_box.cpp
+++ b/scene/resources/sky_box.cpp
@@ -190,9 +190,15 @@ Ref<Image> ProceduralSky::_generate_sky() {
float c = (v_angle - (Math_PI * 0.5)) / (Math_PI * 0.5);
color = ground_horizon_linear.linear_interpolate(ground_bottom_linear, Math::ease(c, ground_curve));
+ color.r *= ground_energy;
+ color.g *= ground_energy;
+ color.b *= ground_energy;
} else {
float c = v_angle / (Math_PI * 0.5);
color = sky_horizon_linear.linear_interpolate(sky_top_linear, Math::ease(1.0 - c, sky_curve));
+ color.r *= sky_energy;
+ color.g *= sky_energy;
+ color.b *= sky_energy;
float sun_angle = Math::rad2deg(Math::acos(CLAMP(sun.dot(normal), -1.0, 1.0)));
diff --git a/servers/audio/audio_rb_resampler.cpp b/servers/audio/audio_rb_resampler.cpp
index 84a87de2e2..d9b3579812 100644
--- a/servers/audio/audio_rb_resampler.cpp
+++ b/servers/audio/audio_rb_resampler.cpp
@@ -79,53 +79,27 @@ uint32_t AudioRBResampler::_resample(AudioFrame *p_dest, int p_todo, int32_t p_i
p_dest[i] = AudioFrame(v0, v1);
}
- // For now, channels higher than stereo are almost ignored
+ // This will probably never be used, but added anyway
if (C == 4) {
- // FIXME: v2 and v3 are not being used (thus were commented out to prevent
- // compilation warnings, but they should likely be uncommented *and* used).
- // See also C == 6 with similar issues.
float v0 = rb[(pos << 2) + 0];
float v1 = rb[(pos << 2) + 1];
- /*
- float v2 = rb[(pos << 2) + 2];
- float v3 = rb[(pos << 2) + 3];
- */
float v0n = rb[(pos_next << 2) + 0];
float v1n = rb[(pos_next << 2) + 1];
- /*
- float v2n = rb[(pos_next << 2) + 2];
- float v3n = rb[(pos_next << 2) + 3];
- */
-
v0 += (v0n - v0) * frac;
v1 += (v1n - v1) * frac;
- /*
- v2 += (v2n - v2) * frac;
- v3 += (v3n - v3) * frac;
- */
p_dest[i] = AudioFrame(v0, v1);
}
if (C == 6) {
- // FIXME: Lot of unused assignments here, but it seems like intermediate calculations
- // should be done as for C == 2 (C == 4 also has some unused assignments).
float v0 = rb[(pos * 6) + 0];
float v1 = rb[(pos * 6) + 1];
- /*
- float v2 = rb[(pos * 6) + 2];
- float v3 = rb[(pos * 6) + 3];
- float v4 = rb[(pos * 6) + 4];
- float v5 = rb[(pos * 6) + 5];
float v0n = rb[(pos_next * 6) + 0];
float v1n = rb[(pos_next * 6) + 1];
- float v2n = rb[(pos_next * 6) + 2];
- float v3n = rb[(pos_next * 6) + 3];
- float v4n = rb[(pos_next * 6) + 4];
- float v5n = rb[(pos_next * 6) + 5];
- */
+ v0 += (v0n - v0) * frac;
+ v1 += (v1n - v1) * frac;
p_dest[i] = AudioFrame(v0, v1);
}
}
diff --git a/servers/audio/effects/audio_effect_filter.h b/servers/audio/effects/audio_effect_filter.h
index 11978882bc..e8f12e5efa 100644
--- a/servers/audio/effects/audio_effect_filter.h
+++ b/servers/audio/effects/audio_effect_filter.h
@@ -96,6 +96,11 @@ VARIANT_ENUM_CAST(AudioEffectFilter::FilterDB)
class AudioEffectLowPassFilter : public AudioEffectFilter {
GDCLASS(AudioEffectLowPassFilter, AudioEffectFilter)
+
+ void _validate_property(PropertyInfo &property) const {
+ if (property.name == "gain") property.usage = 0;
+ }
+
public:
AudioEffectLowPassFilter() :
AudioEffectFilter(AudioFilterSW::LOWPASS) {}
@@ -103,6 +108,10 @@ public:
class AudioEffectHighPassFilter : public AudioEffectFilter {
GDCLASS(AudioEffectHighPassFilter, AudioEffectFilter)
+ void _validate_property(PropertyInfo &property) const {
+ if (property.name == "gain") property.usage = 0;
+ }
+
public:
AudioEffectHighPassFilter() :
AudioEffectFilter(AudioFilterSW::HIGHPASS) {}
@@ -110,6 +119,10 @@ public:
class AudioEffectBandPassFilter : public AudioEffectFilter {
GDCLASS(AudioEffectBandPassFilter, AudioEffectFilter)
+ void _validate_property(PropertyInfo &property) const {
+ if (property.name == "gain") property.usage = 0;
+ }
+
public:
AudioEffectBandPassFilter() :
AudioEffectFilter(AudioFilterSW::BANDPASS) {}
diff --git a/servers/physics/joints/generic_6dof_joint_sw.cpp b/servers/physics/joints/generic_6dof_joint_sw.cpp
index 60505c08c5..3a965ff800 100644
--- a/servers/physics/joints/generic_6dof_joint_sw.cpp
+++ b/servers/physics/joints/generic_6dof_joint_sw.cpp
@@ -503,6 +503,24 @@ void Generic6DOFJointSW::set_param(Vector3::Axis p_axis, PhysicsServer::G6DOFJoi
case PhysicsServer::G6DOF_JOINT_LINEAR_MOTOR_FORCE_LIMIT: {
// Not implemented in GodotPhysics backend
} break;
+ case PhysicsServer::G6DOF_JOINT_LINEAR_SPRING_STIFFNESS: {
+ // Not implemented in GodotPhysics backend
+ } break;
+ case PhysicsServer::G6DOF_JOINT_LINEAR_SPRING_DAMPING: {
+ // Not implemented in GodotPhysics backend
+ } break;
+ case PhysicsServer::G6DOF_JOINT_LINEAR_SPRING_EQUILIBRIUM_POINT: {
+ // Not implemented in GodotPhysics backend
+ } break;
+ case PhysicsServer::G6DOF_JOINT_ANGULAR_SPRING_STIFFNESS: {
+ // Not implemented in GodotPhysics backend
+ } break;
+ case PhysicsServer::G6DOF_JOINT_ANGULAR_SPRING_DAMPING: {
+ // Not implemented in GodotPhysics backend
+ } break;
+ case PhysicsServer::G6DOF_JOINT_ANGULAR_SPRING_EQUILIBRIUM_POINT: {
+ // Not implemented in GodotPhysics backend
+ } break;
case PhysicsServer::G6DOF_JOINT_MAX: break; // Can't happen, but silences warning
}
}
@@ -585,6 +603,24 @@ real_t Generic6DOFJointSW::get_param(Vector3::Axis p_axis, PhysicsServer::G6DOFJ
case PhysicsServer::G6DOF_JOINT_LINEAR_MOTOR_FORCE_LIMIT: {
// Not implemented in GodotPhysics backend
} break;
+ case PhysicsServer::G6DOF_JOINT_LINEAR_SPRING_STIFFNESS: {
+ // Not implemented in GodotPhysics backend
+ } break;
+ case PhysicsServer::G6DOF_JOINT_LINEAR_SPRING_DAMPING: {
+ // Not implemented in GodotPhysics backend
+ } break;
+ case PhysicsServer::G6DOF_JOINT_LINEAR_SPRING_EQUILIBRIUM_POINT: {
+ // Not implemented in GodotPhysics backend
+ } break;
+ case PhysicsServer::G6DOF_JOINT_ANGULAR_SPRING_STIFFNESS: {
+ // Not implemented in GodotPhysics backend
+ } break;
+ case PhysicsServer::G6DOF_JOINT_ANGULAR_SPRING_DAMPING: {
+ // Not implemented in GodotPhysics backend
+ } break;
+ case PhysicsServer::G6DOF_JOINT_ANGULAR_SPRING_EQUILIBRIUM_POINT: {
+ // Not implemented in GodotPhysics backend
+ } break;
case PhysicsServer::G6DOF_JOINT_MAX: break; // Can't happen, but silences warning
}
return 0;
@@ -610,6 +646,12 @@ void Generic6DOFJointSW::set_flag(Vector3::Axis p_axis, PhysicsServer::G6DOFJoin
case PhysicsServer::G6DOF_JOINT_FLAG_ENABLE_LINEAR_MOTOR: {
// Not implemented in GodotPhysics backend
} break;
+ case PhysicsServer::G6DOF_JOINT_FLAG_ENABLE_LINEAR_SPRING: {
+ // Not implemented in GodotPhysics backend
+ } break;
+ case PhysicsServer::G6DOF_JOINT_FLAG_ENABLE_ANGULAR_SPRING: {
+ // Not implemented in GodotPhysics backend
+ } break;
case PhysicsServer::G6DOF_JOINT_FLAG_MAX: break; // Can't happen, but silences warning
}
}
@@ -632,6 +674,12 @@ bool Generic6DOFJointSW::get_flag(Vector3::Axis p_axis, PhysicsServer::G6DOFJoin
case PhysicsServer::G6DOF_JOINT_FLAG_ENABLE_LINEAR_MOTOR: {
// Not implemented in GodotPhysics backend
} break;
+ case PhysicsServer::G6DOF_JOINT_FLAG_ENABLE_LINEAR_SPRING: {
+ // Not implemented in GodotPhysics backend
+ } break;
+ case PhysicsServer::G6DOF_JOINT_FLAG_ENABLE_ANGULAR_SPRING: {
+ // Not implemented in GodotPhysics backend
+ } break;
case PhysicsServer::G6DOF_JOINT_FLAG_MAX: break; // Can't happen, but silences warning
}
diff --git a/servers/physics/physics_server_sw.cpp b/servers/physics/physics_server_sw.cpp
index 76a6138817..fddb531a4f 100644
--- a/servers/physics/physics_server_sw.cpp
+++ b/servers/physics/physics_server_sw.cpp
@@ -40,6 +40,12 @@
#include "joints/pin_joint_sw.h"
#include "joints/slider_joint_sw.h"
+#define FLUSH_QUERY_CHECK \
+ if (flushing_queries) { \
+ ERR_EXPLAIN("Can't change this state while flushing queries. Use call_deferred()/set_deferred() to change monitoring state instead"); \
+ ERR_FAIL(); \
+ }
+
RID PhysicsServerSW::shape_create(ShapeType p_shape) {
ShapeSW *shape = NULL;
@@ -352,6 +358,8 @@ void PhysicsServerSW::area_clear_shapes(RID p_area) {
void PhysicsServerSW::area_set_shape_disabled(RID p_area, int p_shape_idx, bool p_disabled) {
+ FLUSH_QUERY_CHECK
+
AreaSW *area = area_owner.get(p_area);
ERR_FAIL_COND(!area);
ERR_FAIL_INDEX(p_shape_idx, area->get_shape_count());
@@ -435,6 +443,8 @@ void PhysicsServerSW::area_set_collision_mask(RID p_area, uint32_t p_mask) {
void PhysicsServerSW::area_set_monitorable(RID p_area, bool p_monitorable) {
+ FLUSH_QUERY_CHECK
+
AreaSW *area = area_owner.get(p_area);
ERR_FAIL_COND(!area);
@@ -582,6 +592,8 @@ RID PhysicsServerSW::body_get_shape(RID p_body, int p_shape_idx) const {
void PhysicsServerSW::body_set_shape_disabled(RID p_body, int p_shape_idx, bool p_disabled) {
+ FLUSH_QUERY_CHECK
+
BodySW *body = body_owner.get(p_body);
ERR_FAIL_COND(!body);
ERR_FAIL_INDEX(p_shape_idx, body->get_shape_count());
@@ -1459,6 +1471,8 @@ void PhysicsServerSW::flush_queries() {
doing_sync = true;
+ flushing_queries = true;
+
uint64_t time_beg = OS::get_singleton()->get_ticks_usec();
for (Set<const SpaceSW *>::Element *E = active_spaces.front(); E; E = E->next()) {
@@ -1467,6 +1481,8 @@ void PhysicsServerSW::flush_queries() {
space->call_queries();
}
+ flushing_queries = false;
+
if (ScriptDebugger::get_singleton() && ScriptDebugger::get_singleton()->is_profiling()) {
uint64_t total_time[SpaceSW::ELAPSED_TIME_MAX];
@@ -1580,6 +1596,7 @@ PhysicsServerSW::PhysicsServerSW() {
collision_pairs = 0;
active = true;
+ flushing_queries = false;
};
PhysicsServerSW::~PhysicsServerSW(){
diff --git a/servers/physics/physics_server_sw.h b/servers/physics/physics_server_sw.h
index 4131c5e248..b3c61403aa 100644
--- a/servers/physics/physics_server_sw.h
+++ b/servers/physics/physics_server_sw.h
@@ -51,6 +51,8 @@ class PhysicsServerSW : public PhysicsServer {
int active_objects;
int collision_pairs;
+ bool flushing_queries;
+
StepSW *stepper;
Set<const SpaceSW *> active_spaces;
@@ -365,6 +367,8 @@ public:
virtual void flush_queries();
virtual void finish();
+ virtual bool is_flushing_queries() const { return flushing_queries; }
+
int get_process_info(ProcessInfo p_info);
PhysicsServerSW();
diff --git a/servers/physics_2d/physics_2d_server_sw.cpp b/servers/physics_2d/physics_2d_server_sw.cpp
index 2df09057c4..45310ec4b3 100644
--- a/servers/physics_2d/physics_2d_server_sw.cpp
+++ b/servers/physics_2d/physics_2d_server_sw.cpp
@@ -36,6 +36,12 @@
#include "core/project_settings.h"
#include "core/script_language.h"
+#define FLUSH_QUERY_CHECK \
+ if (flushing_queries) { \
+ ERR_EXPLAIN("Can't change this state while flushing queries. Use call_deferred() or set_deferred() to change monitoring state instead"); \
+ ERR_FAIL(); \
+ }
+
RID Physics2DServerSW::_shape_create(ShapeType p_shape) {
Shape2DSW *shape = NULL;
@@ -401,6 +407,8 @@ void Physics2DServerSW::area_set_shape_transform(RID p_area, int p_shape_idx, co
void Physics2DServerSW::area_set_shape_disabled(RID p_area, int p_shape, bool p_disabled) {
+ FLUSH_QUERY_CHECK
+
Area2DSW *area = area_owner.get(p_area);
ERR_FAIL_COND(!area);
@@ -539,6 +547,8 @@ void Physics2DServerSW::area_set_pickable(RID p_area, bool p_pickable) {
void Physics2DServerSW::area_set_monitorable(RID p_area, bool p_monitorable) {
+ FLUSH_QUERY_CHECK
+
Area2DSW *area = area_owner.get(p_area);
ERR_FAIL_COND(!area);
@@ -617,6 +627,8 @@ RID Physics2DServerSW::body_get_space(RID p_body) const {
void Physics2DServerSW::body_set_mode(RID p_body, BodyMode p_mode) {
+ FLUSH_QUERY_CHECK
+
Body2DSW *body = body_owner.get(p_body);
ERR_FAIL_COND(!body);
@@ -719,6 +731,8 @@ void Physics2DServerSW::body_clear_shapes(RID p_body) {
void Physics2DServerSW::body_set_shape_disabled(RID p_body, int p_shape_idx, bool p_disabled) {
+ FLUSH_QUERY_CHECK
+
Body2DSW *body = body_owner.get(p_body);
ERR_FAIL_COND(!body);
@@ -1348,6 +1362,8 @@ void Physics2DServerSW::flush_queries() {
if (!active)
return;
+ flushing_queries = true;
+
uint64_t time_beg = OS::get_singleton()->get_ticks_usec();
for (Set<const Space2DSW *>::Element *E = active_spaces.front(); E; E = E->next()) {
@@ -1356,6 +1372,8 @@ void Physics2DServerSW::flush_queries() {
space->call_queries();
}
+ flushing_queries = false;
+
if (ScriptDebugger::get_singleton() && ScriptDebugger::get_singleton()->is_profiling()) {
uint64_t total_time[Space2DSW::ELAPSED_TIME_MAX];
@@ -1434,6 +1452,7 @@ Physics2DServerSW::Physics2DServerSW() {
active_objects = 0;
collision_pairs = 0;
using_threads = int(ProjectSettings::get_singleton()->get("physics/2d/thread_model")) == 2;
+ flushing_queries = false;
};
Physics2DServerSW::~Physics2DServerSW(){
diff --git a/servers/physics_2d/physics_2d_server_sw.h b/servers/physics_2d/physics_2d_server_sw.h
index f41c599579..4f33873219 100644
--- a/servers/physics_2d/physics_2d_server_sw.h
+++ b/servers/physics_2d/physics_2d_server_sw.h
@@ -54,6 +54,8 @@ class Physics2DServerSW : public Physics2DServer {
bool using_threads;
+ bool flushing_queries;
+
Step2DSW *stepper;
Set<const Space2DSW *> active_spaces;
@@ -278,6 +280,8 @@ public:
virtual void end_sync();
virtual void finish();
+ virtual bool is_flushing_queries() const { return flushing_queries; }
+
int get_process_info(ProcessInfo p_info);
Physics2DServerSW();
diff --git a/servers/physics_2d/physics_2d_server_wrap_mt.h b/servers/physics_2d/physics_2d_server_wrap_mt.h
index 58517bf1a7..e736854077 100644
--- a/servers/physics_2d/physics_2d_server_wrap_mt.h
+++ b/servers/physics_2d/physics_2d_server_wrap_mt.h
@@ -312,6 +312,10 @@ public:
virtual void flush_queries();
virtual void finish();
+ virtual bool is_flushing_queries() const {
+ return physics_2d_server->is_flushing_queries();
+ }
+
int get_process_info(ProcessInfo p_info) {
return physics_2d_server->get_process_info(p_info);
}
diff --git a/servers/physics_2d_server.h b/servers/physics_2d_server.h
index 2e91d89c53..32e1dd1a08 100644
--- a/servers/physics_2d_server.h
+++ b/servers/physics_2d_server.h
@@ -584,6 +584,8 @@ public:
virtual void end_sync() = 0;
virtual void finish() = 0;
+ virtual bool is_flushing_queries() const = 0;
+
enum ProcessInfo {
INFO_ACTIVE_OBJECTS,
diff --git a/servers/physics_server.h b/servers/physics_server.h
index d80d76305a..15b353f768 100644
--- a/servers/physics_server.h
+++ b/servers/physics_server.h
@@ -697,6 +697,9 @@ public:
G6DOF_JOINT_LINEAR_DAMPING,
G6DOF_JOINT_LINEAR_MOTOR_TARGET_VELOCITY,
G6DOF_JOINT_LINEAR_MOTOR_FORCE_LIMIT,
+ G6DOF_JOINT_LINEAR_SPRING_STIFFNESS,
+ G6DOF_JOINT_LINEAR_SPRING_DAMPING,
+ G6DOF_JOINT_LINEAR_SPRING_EQUILIBRIUM_POINT,
G6DOF_JOINT_ANGULAR_LOWER_LIMIT,
G6DOF_JOINT_ANGULAR_UPPER_LIMIT,
G6DOF_JOINT_ANGULAR_LIMIT_SOFTNESS,
@@ -706,6 +709,9 @@ public:
G6DOF_JOINT_ANGULAR_ERP,
G6DOF_JOINT_ANGULAR_MOTOR_TARGET_VELOCITY,
G6DOF_JOINT_ANGULAR_MOTOR_FORCE_LIMIT,
+ G6DOF_JOINT_ANGULAR_SPRING_STIFFNESS,
+ G6DOF_JOINT_ANGULAR_SPRING_DAMPING,
+ G6DOF_JOINT_ANGULAR_SPRING_EQUILIBRIUM_POINT,
G6DOF_JOINT_MAX
};
@@ -713,6 +719,8 @@ public:
G6DOF_JOINT_FLAG_ENABLE_LINEAR_LIMIT,
G6DOF_JOINT_FLAG_ENABLE_ANGULAR_LIMIT,
+ G6DOF_JOINT_FLAG_ENABLE_ANGULAR_SPRING,
+ G6DOF_JOINT_FLAG_ENABLE_LINEAR_SPRING,
G6DOF_JOINT_FLAG_ENABLE_MOTOR,
G6DOF_JOINT_FLAG_ENABLE_LINEAR_MOTOR,
G6DOF_JOINT_FLAG_MAX
@@ -744,6 +752,8 @@ public:
virtual void flush_queries() = 0;
virtual void finish() = 0;
+ virtual bool is_flushing_queries() const = 0;
+
enum ProcessInfo {
INFO_ACTIVE_OBJECTS,
diff --git a/servers/visual/rasterizer.h b/servers/visual/rasterizer.h
index f9beeb226c..4329203ccb 100644
--- a/servers/visual/rasterizer.h
+++ b/servers/visual/rasterizer.h
@@ -518,6 +518,8 @@ public:
virtual void particles_set_fractional_delta(RID p_particles, bool p_enable) = 0;
virtual void particles_restart(RID p_particles) = 0;
+ virtual bool particles_is_inactive(RID p_particles) const = 0;
+
virtual void particles_set_draw_order(RID p_particles, VS::ParticlesDrawOrder p_order) = 0;
virtual void particles_set_draw_passes(RID p_particles, int p_count) = 0;
diff --git a/servers/visual/shader_language.cpp b/servers/visual/shader_language.cpp
index 0783d91a59..50e45963d9 100644
--- a/servers/visual/shader_language.cpp
+++ b/servers/visual/shader_language.cpp
@@ -131,7 +131,6 @@ const char *ShaderLanguage::token_names[TK_MAX] = {
"TYPE_USAMPLER3D",
"TYPE_SAMPLERCUBE",
"INTERPOLATION_FLAT",
- "INTERPOLATION_NO_PERSPECTIVE",
"INTERPOLATION_SMOOTH",
"PRECISION_LOW",
"PRECISION_MID",
@@ -271,7 +270,6 @@ const ShaderLanguage::KeyWord ShaderLanguage::keyword_list[] = {
{ TK_TYPE_USAMPLER3D, "usampler3D" },
{ TK_TYPE_SAMPLERCUBE, "samplerCube" },
{ TK_INTERPOLATION_FLAT, "flat" },
- { TK_INTERPOLATION_NO_PERSPECTIVE, "noperspective" },
{ TK_INTERPOLATION_SMOOTH, "smooth" },
{ TK_PRECISION_LOW, "lowp" },
{ TK_PRECISION_MID, "mediump" },
@@ -759,7 +757,6 @@ bool ShaderLanguage::is_token_interpolation(TokenType p_type) {
return (
p_type == TK_INTERPOLATION_FLAT ||
- p_type == TK_INTERPOLATION_NO_PERSPECTIVE ||
p_type == TK_INTERPOLATION_SMOOTH);
}
@@ -767,8 +764,6 @@ ShaderLanguage::DataInterpolation ShaderLanguage::get_token_interpolation(TokenT
if (p_type == TK_INTERPOLATION_FLAT)
return INTERPOLATION_FLAT;
- else if (p_type == TK_INTERPOLATION_NO_PERSPECTIVE)
- return INTERPOLATION_NO_PERSPECTIVE;
else
return INTERPOLATION_SMOOTH;
}
@@ -2353,7 +2348,7 @@ bool ShaderLanguage::is_sampler_type(DataType p_type) {
p_type == TYPE_SAMPLERCUBE;
}
-Variant ShaderLanguage::constant_value_to_variant(const Vector<ShaderLanguage::ConstantNode::Value> &p_value, DataType p_type) {
+Variant ShaderLanguage::constant_value_to_variant(const Vector<ShaderLanguage::ConstantNode::Value> &p_value, DataType p_type, ShaderLanguage::ShaderNode::Uniform::Hint p_hint) {
if (p_value.size() > 0) {
Variant value;
switch (p_type) {
@@ -2397,7 +2392,11 @@ Variant ShaderLanguage::constant_value_to_variant(const Vector<ShaderLanguage::C
value = Variant(Vector3(p_value[0].real, p_value[1].real, p_value[2].real));
break;
case ShaderLanguage::TYPE_VEC4:
- value = Variant(Plane(p_value[0].real, p_value[1].real, p_value[2].real, p_value[3].real));
+ if (p_hint == ShaderLanguage::ShaderNode::Uniform::HINT_COLOR) {
+ value = Variant(Color(p_value[0].real, p_value[1].real, p_value[2].real, p_value[3].real));
+ } else {
+ value = Variant(Plane(p_value[0].real, p_value[1].real, p_value[2].real, p_value[3].real));
+ }
break;
case ShaderLanguage::TYPE_MAT2:
value = Variant(Transform2D(p_value[0].real, p_value[2].real, p_value[1].real, p_value[3].real, 0.0, 0.0));
diff --git a/servers/visual/shader_language.h b/servers/visual/shader_language.h
index 9277dfa2cf..2d1851928e 100644
--- a/servers/visual/shader_language.h
+++ b/servers/visual/shader_language.h
@@ -80,7 +80,6 @@ public:
TK_TYPE_USAMPLER3D,
TK_TYPE_SAMPLERCUBE,
TK_INTERPOLATION_FLAT,
- TK_INTERPOLATION_NO_PERSPECTIVE,
TK_INTERPOLATION_SMOOTH,
TK_PRECISION_LOW,
TK_PRECISION_MID,
@@ -210,7 +209,6 @@ public:
enum DataInterpolation {
INTERPOLATION_FLAT,
- INTERPOLATION_NO_PERSPECTIVE,
INTERPOLATION_SMOOTH,
};
@@ -550,7 +548,7 @@ public:
static int get_cardinality(DataType p_type);
static bool is_scalar_type(DataType p_type);
static bool is_sampler_type(DataType p_type);
- static Variant constant_value_to_variant(const Vector<ShaderLanguage::ConstantNode::Value> &p_value, DataType p_type);
+ static Variant constant_value_to_variant(const Vector<ShaderLanguage::ConstantNode::Value> &p_value, DataType p_type, ShaderLanguage::ShaderNode::Uniform::Hint p_hint = ShaderLanguage::ShaderNode::Uniform::HINT_NONE);
static void get_keyword_list(List<String> *r_keywords);
static void get_builtin_funcs(List<String> *r_keywords);
diff --git a/servers/visual/visual_server_canvas.cpp b/servers/visual/visual_server_canvas.cpp
index 74a05ce4e4..734c295a72 100644
--- a/servers/visual/visual_server_canvas.cpp
+++ b/servers/visual/visual_server_canvas.cpp
@@ -51,7 +51,7 @@ void VisualServerCanvas::_render_canvas_item_tree(Item *p_canvas_item, const Tra
}
}
-void _collect_ysort_children(VisualServerCanvas::Item *p_canvas_item, Transform2D p_transform, VisualServerCanvas::Item **r_items, Transform2D *r_extra_transforms, int &r_index) {
+void _collect_ysort_children(VisualServerCanvas::Item *p_canvas_item, Transform2D p_transform, VisualServerCanvas::Item **r_items, int &r_index) {
int child_item_count = p_canvas_item->child_items.size();
VisualServerCanvas::Item **child_items = p_canvas_item->child_items.ptrw();
for (int i = 0; i < child_item_count; i++) {
@@ -64,7 +64,7 @@ void _collect_ysort_children(VisualServerCanvas::Item *p_canvas_item, Transform2
r_index++;
if (child_items[i]->sort_y)
- _collect_ysort_children(child_items[i], p_transform * child_items[i]->xform, r_items, r_extra_transforms, r_index);
+ _collect_ysort_children(child_items[i], p_transform * child_items[i]->xform, r_items, r_index);
}
}
@@ -100,7 +100,6 @@ void VisualServerCanvas::_render_canvas_item(Item *p_canvas_item, const Transfor
int child_item_count = ci->child_items.size();
Item **child_items = ci->child_items.ptrw();
- Transform2D *child_extra_transforms = NULL;
if (ci->clip) {
if (p_canvas_clip != NULL) {
@@ -118,14 +117,14 @@ void VisualServerCanvas::_render_canvas_item(Item *p_canvas_item, const Transfor
if (ci->ysort_children_count == -1) {
ci->ysort_children_count = 0;
- _collect_ysort_children(ci, Transform2D(), NULL, NULL, ci->ysort_children_count);
+ _collect_ysort_children(ci, Transform2D(), NULL, ci->ysort_children_count);
}
child_item_count = ci->ysort_children_count;
child_items = (Item **)alloca(child_item_count * sizeof(Item *));
int i = 0;
- _collect_ysort_children(ci, Transform2D(), child_items, child_extra_transforms, i);
+ _collect_ysort_children(ci, Transform2D(), child_items, i);
SortArray<Item *, ItemPtrSort> sorter;
sorter.sort(child_items, child_item_count);
@@ -336,7 +335,12 @@ void VisualServerCanvas::canvas_item_set_parent(RID p_item, RID p_parent) {
Item *item_owner = canvas_item_owner.get(canvas_item->parent);
item_owner->child_items.erase(canvas_item);
- item_owner->ysort_children_count = -1;
+
+ Item *ysort_owner = item_owner;
+ while (ysort_owner && ysort_owner->sort_y) {
+ item_owner->ysort_children_count = -1;
+ ysort_owner = canvas_item_owner.getornull(ysort_owner->parent);
+ }
}
canvas_item->parent = RID();
@@ -1346,6 +1350,12 @@ bool VisualServerCanvas::free(RID p_rid) {
Item *item_owner = canvas_item_owner.get(canvas_item->parent);
item_owner->child_items.erase(canvas_item);
+
+ Item *ysort_owner = item_owner;
+ while (ysort_owner && ysort_owner->sort_y) {
+ item_owner->ysort_children_count = -1;
+ ysort_owner = canvas_item_owner.getornull(ysort_owner->parent);
+ }
}
}
diff --git a/servers/visual/visual_server_scene.cpp b/servers/visual/visual_server_scene.cpp
index 13de92f226..1deca7bc66 100644
--- a/servers/visual/visual_server_scene.cpp
+++ b/servers/visual/visual_server_scene.cpp
@@ -1912,9 +1912,14 @@ void VisualServerScene::_prepare_scene(const Transform p_cam_transform, const Ca
if (ins->base_type == VS::INSTANCE_PARTICLES) {
//particles visible? process them
- VSG::storage->particles_request_process(ins->base);
- //particles visible? request redraw
- VisualServerRaster::redraw_request();
+ if (VSG::storage->particles_is_inactive(ins->base)) {
+ //but if nothing is going on, don't do it.
+ keep = false;
+ } else {
+ VSG::storage->particles_request_process(ins->base);
+ //particles visible? request redraw
+ VisualServerRaster::redraw_request();
+ }
}
if (geom->lighting_dirty) {
diff --git a/servers/visual_server.cpp b/servers/visual_server.cpp
index ca5271190c..e1db123f58 100644
--- a/servers/visual_server.cpp
+++ b/servers/visual_server.cpp
@@ -343,7 +343,7 @@ RID VisualServer::get_white_texture() {
#define SMALL_VEC2 Vector2(0.00001, 0.00001)
#define SMALL_VEC3 Vector3(0.00001, 0.00001, 0.00001)
-Error VisualServer::_surface_set_data(Array p_arrays, uint32_t p_format, uint32_t *p_offsets, uint32_t p_stride, PoolVector<uint8_t> &r_vertex_array, int p_vertex_array_len, PoolVector<uint8_t> &r_index_array, int p_index_array_len, AABB &r_aabb, Vector<AABB> r_bone_aabb) {
+Error VisualServer::_surface_set_data(Array p_arrays, uint32_t p_format, uint32_t *p_offsets, uint32_t p_stride, PoolVector<uint8_t> &r_vertex_array, int p_vertex_array_len, PoolVector<uint8_t> &r_index_array, int p_index_array_len, AABB &r_aabb, Vector<AABB> &r_bone_aabb) {
PoolVector<uint8_t>::Write vw = r_vertex_array.write();
diff --git a/servers/visual_server.h b/servers/visual_server.h
index 59eb43da97..743e010034 100644
--- a/servers/visual_server.h
+++ b/servers/visual_server.h
@@ -61,7 +61,7 @@ protected:
RID white_texture;
RID test_material;
- Error _surface_set_data(Array p_arrays, uint32_t p_format, uint32_t *p_offsets, uint32_t p_stride, PoolVector<uint8_t> &r_vertex_array, int p_vertex_array_len, PoolVector<uint8_t> &r_index_array, int p_index_array_len, AABB &r_aabb, Vector<AABB> r_bone_aabb);
+ Error _surface_set_data(Array p_arrays, uint32_t p_format, uint32_t *p_offsets, uint32_t p_stride, PoolVector<uint8_t> &r_vertex_array, int p_vertex_array_len, PoolVector<uint8_t> &r_index_array, int p_index_array_len, AABB &r_aabb, Vector<AABB> &r_bone_aabb);
static VisualServer *(*create_func)();
static void _bind_methods();
diff --git a/thirdparty/enet/godot.cpp b/thirdparty/enet/godot.cpp
index 6ba7cf0000..73a09f9b1d 100644
--- a/thirdparty/enet/godot.cpp
+++ b/thirdparty/enet/godot.cpp
@@ -33,7 +33,7 @@
*/
#include "core/io/ip.h"
-#include "core/io/packet_peer_udp.h"
+#include "core/io/net_socket.h"
#include "core/os/os.h"
// This must be last for windows to compile (tested with MinGW)
@@ -90,6 +90,16 @@ int enet_address_get_host(const ENetAddress *address, char *name, size_t nameLen
return -1;
}
+ENetSocket enet_socket_create(ENetSocketType type) {
+
+ NetSocket *socket = NetSocket::create();
+ IP::Type ip_type = IP::TYPE_ANY;
+ socket->open(NetSocket::TYPE_UDP, ip_type);
+ socket->set_blocking_enabled(false);
+
+ return socket;
+}
+
int enet_socket_bind(ENetSocket socket, const ENetAddress *address) {
IP_Address ip;
@@ -99,23 +109,15 @@ int enet_socket_bind(ENetSocket socket, const ENetAddress *address) {
ip.set_ipv6(address->host);
}
- PacketPeerUDP *sock = (PacketPeerUDP *)socket;
- if (sock->listen(address->port, ip) != OK) {
+ NetSocket *sock = (NetSocket *)socket;
+ if (sock->bind(ip, address->port) != OK) {
return -1;
}
return 0;
}
-ENetSocket enet_socket_create(ENetSocketType type) {
-
- PacketPeerUDP *socket = memnew(PacketPeerUDP);
- socket->set_blocking_mode(false);
-
- return socket;
-}
-
void enet_socket_destroy(ENetSocket socket) {
- PacketPeerUDP *sock = (PacketPeerUDP *)socket;
+ NetSocket *sock = (NetSocket *)socket;
sock->close();
memdelete(sock);
}
@@ -124,13 +126,12 @@ int enet_socket_send(ENetSocket socket, const ENetAddress *address, const ENetBu
ERR_FAIL_COND_V(address == NULL, -1);
- PacketPeerUDP *sock = (PacketPeerUDP *)socket;
+ NetSocket *sock = (NetSocket *)socket;
IP_Address dest;
Error err;
size_t i = 0;
dest.set_ipv6(address->host);
- sock->set_dest_address(dest, address->port);
// Create a single packet.
PoolVector<uint8_t> out;
@@ -148,7 +149,8 @@ int enet_socket_send(ENetSocket socket, const ENetAddress *address, const ENetBu
pos += buffers[i].dataLength;
}
- err = sock->put_packet((const uint8_t *)&w[0], size);
+ int sent = 0;
+ err = sock->sendto((const uint8_t *)&w[0], size, sent, dest, address->port);
if (err != OK) {
if (err == ERR_BUSY) { // Blocking call
@@ -159,32 +161,36 @@ int enet_socket_send(ENetSocket socket, const ENetAddress *address, const ENetBu
return -1;
}
- return size;
+ return sent;
}
int enet_socket_receive(ENetSocket socket, ENetAddress *address, ENetBuffer *buffers, size_t bufferCount) {
ERR_FAIL_COND_V(bufferCount != 1, -1);
- PacketPeerUDP *sock = (PacketPeerUDP *)socket;
+ NetSocket *sock = (NetSocket *)socket;
- int pc = sock->get_available_packet_count();
- if (pc < 1) {
- return pc;
- }
+ Error ret = sock->poll(NetSocket::POLL_TYPE_IN, 0);
- const uint8_t *buffer;
- int buffer_size;
- Error err = sock->get_packet(&buffer, buffer_size);
- if (err)
+ if (ret == ERR_BUSY)
+ return 0;
+
+ if (ret != OK)
return -1;
- copymem(buffers[0].data, buffer, buffer_size);
+ int read;
+ IP_Address ip;
- enet_address_set_ip(address, sock->get_packet_address().get_ipv6(), 16);
- address->port = sock->get_packet_port();
+ Error err = sock->recvfrom((uint8_t *)buffers[0].data, buffers[0].dataLength, read, ip, address->port);
+ if (err == ERR_BUSY)
+ return 0;
+
+ if (err != OK)
+ return -1;
+
+ enet_address_set_ip(address, ip.get_ipv6(), 16);
- return buffer_size;
+ return read;
}
// Not implemented