diff --git a/core/script_language.cpp b/core/script_language.cpp
index 7392e7a0afc..96313898ec4 100644
--- a/core/script_language.cpp
+++ b/core/script_language.cpp
@@ -276,7 +276,11 @@ void ScriptServer::save_global_classes() {
gcarr.push_back(d);
}
- ProjectSettings::get_singleton()->set("_global_script_classes", gcarr);
+ if (gcarr.empty()) {
+ ProjectSettings::get_singleton()->clear("_global_script_classes");
+ } else {
+ ProjectSettings::get_singleton()->set("_global_script_classes", gcarr);
+ }
ProjectSettings::get_singleton()->save();
}
diff --git a/core/ustring.cpp b/core/ustring.cpp
index 3df30e096d6..1abfa8c9967 100644
--- a/core/ustring.cpp
+++ b/core/ustring.cpp
@@ -4182,11 +4182,12 @@ String String::sprintf(const Array &values, bool *error) const {
int number_len = str.length();
// Padding.
+ int pad_chars_count = (value < 0 || show_sign) ? min_chars - 1 : min_chars;
String pad_char = pad_with_zeroes ? String("0") : String(" ");
if (left_justified) {
- str = str.rpad(min_chars, pad_char);
+ str = str.rpad(pad_chars_count, pad_char);
} else {
- str = str.lpad(min_chars, pad_char);
+ str = str.lpad(pad_chars_count, pad_char);
}
// Sign.
diff --git a/doc/classes/Animation.xml b/doc/classes/Animation.xml
index 2071ac564a9..4a476b2fbae 100644
--- a/doc/classes/Animation.xml
+++ b/doc/classes/Animation.xml
@@ -681,6 +681,17 @@
Sets the update mode (see [enum UpdateMode]) of a value track.
+
+
+
+
+
+
+
+
+ Returns the interpolated value at the given time (in seconds). The [code]track_idx[/code] must be the index of a value track.
+
+
diff --git a/doc/classes/EditorSpatialGizmoPlugin.xml b/doc/classes/EditorSpatialGizmoPlugin.xml
index c9494cf78f4..864b1cc5f29 100644
--- a/doc/classes/EditorSpatialGizmoPlugin.xml
+++ b/doc/classes/EditorSpatialGizmoPlugin.xml
@@ -136,7 +136,7 @@
-
+
Override this method to set the gizmo's priority. Higher values correspond to higher priority. If a gizmo with higher priority conflicts with another gizmo, only the gizmo with higher priority will be used.
diff --git a/doc/classes/NinePatchRect.xml b/doc/classes/NinePatchRect.xml
index 8b0e4eaaf73..f543d0e121e 100644
--- a/doc/classes/NinePatchRect.xml
+++ b/doc/classes/NinePatchRect.xml
@@ -45,13 +45,13 @@
The height of the 9-slice's bottom row. A margin of 16 means the 9-slice's bottom corners and side will have a height of 16 pixels. You can set all 4 margin values individually to create panels with non-uniform borders.
- The height of the 9-slice's left column.
+ The width of the 9-slice's left column. A margin of 16 means the 9-slice's left corners and side will have a width of 16 pixels. You can set all 4 margin values individually to create panels with non-uniform borders.
- The height of the 9-slice's right column.
+ The width of the 9-slice's right column. A margin of 16 means the 9-slice's right corners and side will have a width of 16 pixels. You can set all 4 margin values individually to create panels with non-uniform borders.
- The height of the 9-slice's top row.
+ The height of the 9-slice's top row. A margin of 16 means the 9-slice's top corners and side will have a height of 16 pixels. You can set all 4 margin values individually to create panels with non-uniform borders.
Rectangular region of the texture to sample from. If you're working with an atlas, use this property to define the area the 9-slice should use. All other properties are relative to this one. If the rect is empty, NinePatchRect will use the whole texture.
diff --git a/doc/classes/ResourceLoader.xml b/doc/classes/ResourceLoader.xml
index 1511a0d9ba8..94dbd6c76ab 100644
--- a/doc/classes/ResourceLoader.xml
+++ b/doc/classes/ResourceLoader.xml
@@ -6,7 +6,6 @@
Singleton used to load resource files from the filesystem.
It uses the many [ResourceFormatLoader] classes registered in the engine (either built-in or from a plugin) to load files into memory and convert them to a format that can be used by the engine.
- GDScript has a simplified [method @GDScript.load] built-in method which can be used in most situations, leaving the use of [ResourceLoader] for more advanced scenarios.
@@ -74,7 +73,8 @@
The registered [ResourceFormatLoader]s are queried sequentially to find the first one which can handle the file's extension, and then attempt loading. If loading fails, the remaining ResourceFormatLoaders are also attempted.
An optional [code]type_hint[/code] can be used to further specify the [Resource] type that should be handled by the [ResourceFormatLoader].
If [code]no_cache[/code] is [code]true[/code], the resource cache will be bypassed and the resource will be loaded anew. Otherwise, the cached resource will be returned if it exists.
- Returns an empty resource if no ResourceFormatLoader could handle the file.
+ Returns an empty resource if no [ResourceFormatLoader] could handle the file.
+ GDScript has a simplified [method @GDScript.load] built-in method which can be used in most situations, leaving the use of [ResourceLoader] for more advanced scenarios.
diff --git a/doc/classes/RigidBody2D.xml b/doc/classes/RigidBody2D.xml
index b139541091d..db38dddd40f 100644
--- a/doc/classes/RigidBody2D.xml
+++ b/doc/classes/RigidBody2D.xml
@@ -140,7 +140,7 @@
The maximum number of contacts that will be recorded. Requires [member contact_monitor] to be set to [code]true[/code].
- [b]Note:[/b] The number of contacts is different from the number of collisions. Collisions between parallel edges will result in two contacts (one at each end), and collisions between parallel faces will result in four contacts (one at each corner).
+ [b]Note:[/b] The number of contacts is different from the number of collisions. Collisions between parallel edges will result in two contacts (one at each end).
Continuous collision detection mode.
diff --git a/editor/editor_data.cpp b/editor/editor_data.cpp
index 01cc23aaa29..93486860a77 100644
--- a/editor/editor_data.cpp
+++ b/editor/editor_data.cpp
@@ -965,7 +965,11 @@ void EditorData::script_class_save_icon_paths() {
d[E->get()] = _script_class_icon_paths[E->get()];
}
- ProjectSettings::get_singleton()->set("_global_script_class_icons", d);
+ if (d.empty()) {
+ ProjectSettings::get_singleton()->clear("_global_script_class_icons");
+ } else {
+ ProjectSettings::get_singleton()->set("_global_script_class_icons", d);
+ }
ProjectSettings::get_singleton()->save();
}
diff --git a/editor/plugins/spatial_editor_plugin.cpp b/editor/plugins/spatial_editor_plugin.cpp
index 8b2766a4a95..b825c5796c6 100644
--- a/editor/plugins/spatial_editor_plugin.cpp
+++ b/editor/plugins/spatial_editor_plugin.cpp
@@ -6624,7 +6624,7 @@ void EditorSpatialGizmoPlugin::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_material", "name", "gizmo"), &EditorSpatialGizmoPlugin::get_material); //, DEFVAL(Ref()));
BIND_VMETHOD(MethodInfo(Variant::STRING, "get_name"));
- BIND_VMETHOD(MethodInfo(Variant::STRING, "get_priority"));
+ BIND_VMETHOD(MethodInfo(Variant::INT, "get_priority"));
BIND_VMETHOD(MethodInfo(Variant::BOOL, "can_be_hidden"));
BIND_VMETHOD(MethodInfo(Variant::BOOL, "is_selectable_when_hidden"));
diff --git a/modules/bullet/bullet_types_converter.cpp b/modules/bullet/bullet_types_converter.cpp
index 7ecad9b78ad..09b90fe09e3 100644
--- a/modules/bullet/bullet_types_converter.cpp
+++ b/modules/bullet/bullet_types_converter.cpp
@@ -101,9 +101,9 @@ void UNSCALE_BT_BASIS(btTransform &scaledBasis) {
btVector3 column2 = basis.getColumn(2);
// Check for zero scaling.
- if (btFuzzyZero(column0[0])) {
- if (btFuzzyZero(column1[1])) {
- if (btFuzzyZero(column2[2])) {
+ if (column0.fuzzyZero()) {
+ if (column1.fuzzyZero()) {
+ if (column2.fuzzyZero()) {
// All dimensions are fuzzy zero. Create a default basis.
column0 = btVector3(1, 0, 0);
column1 = btVector3(0, 1, 0);
@@ -115,7 +115,7 @@ void UNSCALE_BT_BASIS(btTransform &scaledBasis) {
column0 = column1.cross(column2);
}
} else { // Column 1 scale not fuzzy zero.
- if (btFuzzyZero(column2[2])) {
+ if (column2.fuzzyZero()) {
// Create two vectors othogonal to column 1.
// Ensure that a default basis is created if column 1 = <0, 1, 0>
column0 = btVector3(column1[1], -column1[0], 0);
@@ -126,8 +126,8 @@ void UNSCALE_BT_BASIS(btTransform &scaledBasis) {
}
}
} else { // Column 0 scale not fuzzy zero.
- if (btFuzzyZero(column1[1])) {
- if (btFuzzyZero(column2[2])) {
+ if (column1.fuzzyZero()) {
+ if (column2.fuzzyZero()) {
// Create two vectors orthogonal to column 0.
// Ensure that a default basis is created if column 0 = <1, 0, 0>
column2 = btVector3(-column0[2], 0, column0[0]);
@@ -137,7 +137,7 @@ void UNSCALE_BT_BASIS(btTransform &scaledBasis) {
column1 = column2.cross(column0);
}
} else { // Column 0 and column 1 scales not fuzzy zero.
- if (btFuzzyZero(column2[2])) {
+ if (column2.fuzzyZero()) {
// Create column 2 orthogonal to column 0 and column 1.
column2 = column0.cross(column1);
}
diff --git a/modules/gdscript/doc_classes/@GDScript.xml b/modules/gdscript/doc_classes/@GDScript.xml
index 1866af282c1..1e369658742 100644
--- a/modules/gdscript/doc_classes/@GDScript.xml
+++ b/modules/gdscript/doc_classes/@GDScript.xml
@@ -634,6 +634,7 @@
var main = load("res://main.tscn") # main will contain a PackedScene resource.
[/codeblock]
[b]Important:[/b] The path must be absolute, a local path will just return [code]null[/code].
+ This method is a simplified version of [method ResourceLoader.load], which can be used for more advanced scenarios.
@@ -766,7 +767,7 @@
Returns the integer modulus of [code]a/b[/code] that wraps equally in positive and negative.
[codeblock]
for i in range(-3, 4):
- print("%2.0f %2.0f %2.0f" % [i, i % 3, posmod(i, 3)])
+ print("%2d %2d %2d" % [i, i % 3, posmod(i, 3)])
[/codeblock]
Produces:
[codeblock]
diff --git a/platform/javascript/detect.py b/platform/javascript/detect.py
index 4bcbdc11c97..1e32516edc9 100644
--- a/platform/javascript/detect.py
+++ b/platform/javascript/detect.py
@@ -1,6 +1,7 @@
import os
-from emscripten_helpers import parse_config, run_closure_compiler, create_engine_file
+from emscripten_helpers import run_closure_compiler, create_engine_file
+from SCons.Util import WhereIs
def is_active():
@@ -12,7 +13,7 @@ def get_name():
def can_build():
- return "EM_CONFIG" in os.environ or os.path.exists(os.path.expanduser("~/.emscripten"))
+ return WhereIs("emcc") is not None
def get_opts():
@@ -100,9 +101,6 @@ def configure(env):
# Closure compiler extern and support for ecmascript specs (const, let, etc).
env["ENV"]["EMCC_CLOSURE_ARGS"] = "--language_in ECMASCRIPT6"
- em_config = parse_config()
- env.PrependENVPath("PATH", em_config["EMCC_ROOT"])
-
env["CC"] = "emcc"
env["CXX"] = "em++"
env["LINK"] = "emcc"
diff --git a/platform/javascript/emscripten_helpers.py b/platform/javascript/emscripten_helpers.py
index a55c9d3f48f..f6db10fbbda 100644
--- a/platform/javascript/emscripten_helpers.py
+++ b/platform/javascript/emscripten_helpers.py
@@ -1,28 +1,11 @@
import os
-
-def parse_config():
- em_config_file = os.getenv("EM_CONFIG") or os.path.expanduser("~/.emscripten")
- if not os.path.exists(em_config_file):
- raise RuntimeError("Emscripten configuration file '%s' does not exist" % em_config_file)
-
- normalized = {}
- em_config = {}
- with open(em_config_file) as f:
- try:
- # Emscripten configuration file is a Python file with simple assignments.
- exec(f.read(), em_config)
- except StandardError as e:
- raise RuntimeError("Emscripten configuration file '%s' is invalid:\n%s" % (em_config_file, e))
- normalized["EMCC_ROOT"] = em_config.get("EMSCRIPTEN_ROOT")
- normalized["NODE_JS"] = em_config.get("NODE_JS")
- normalized["CLOSURE_BIN"] = os.path.join(normalized["EMCC_ROOT"], "node_modules", ".bin", "google-closure-compiler")
- return normalized
+from SCons.Util import WhereIs
def run_closure_compiler(target, source, env, for_signature):
- cfg = parse_config()
- cmd = [cfg["NODE_JS"], cfg["CLOSURE_BIN"]]
+ closure_bin = os.path.join(os.path.dirname(WhereIs("emcc")), "node_modules", ".bin", "google-closure-compiler")
+ cmd = [WhereIs("node"), closure_bin]
cmd.extend(["--compilation_level", "ADVANCED_OPTIMIZATIONS"])
for f in env["JSEXTERNS"]:
cmd.extend(["--externs", f.get_abspath()])
diff --git a/scene/resources/animation.cpp b/scene/resources/animation.cpp
index 98c82bf0a20..56c886c24b9 100644
--- a/scene/resources/animation.cpp
+++ b/scene/resources/animation.cpp
@@ -2788,6 +2788,7 @@ void Animation::_bind_methods() {
ClassDB::bind_method(D_METHOD("value_track_get_update_mode", "track_idx"), &Animation::value_track_get_update_mode);
ClassDB::bind_method(D_METHOD("value_track_get_key_indices", "track_idx", "time_sec", "delta"), &Animation::_value_track_get_key_indices);
+ ClassDB::bind_method(D_METHOD("value_track_interpolate", "track_idx", "time_sec"), &Animation::value_track_interpolate);
ClassDB::bind_method(D_METHOD("method_track_get_key_indices", "track_idx", "time_sec", "delta"), &Animation::_method_track_get_key_indices);
ClassDB::bind_method(D_METHOD("method_track_get_name", "track_idx", "key_idx"), &Animation::method_track_get_name);
diff --git a/servers/physics_2d/collision_solver_2d_sw.cpp b/servers/physics_2d/collision_solver_2d_sw.cpp
index 60cca6f8255..a83b6808881 100644
--- a/servers/physics_2d/collision_solver_2d_sw.cpp
+++ b/servers/physics_2d/collision_solver_2d_sw.cpp
@@ -47,7 +47,7 @@ bool CollisionSolver2DSW::solve_static_line(const Shape2DSW *p_shape_A, const Tr
Vector2 supports[2];
int support_count;
- p_shape_B->get_supports(p_transform_A.affine_inverse().basis_xform(-n).normalized(), supports, support_count);
+ p_shape_B->get_supports(p_transform_B.affine_inverse().basis_xform(-n).normalized(), supports, support_count);
bool found = false;