summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--doc/classes/@GlobalScope.xml2
-rw-r--r--doc/classes/AnimationNode.xml59
-rw-r--r--doc/classes/ProjectSettings.xml8
-rw-r--r--drivers/pulseaudio/audio_driver_pulseaudio.cpp5
-rw-r--r--editor/editor_data.cpp5
-rw-r--r--editor/import/resource_importer_texture.cpp2
-rw-r--r--modules/gdscript/gdscript_compiler.cpp20
-rw-r--r--modules/gdscript/gdscript_compiler.h10
-rw-r--r--modules/gdscript/gdscript_function.cpp33
-rw-r--r--modules/gdscript/gdscript_function.h4
-rw-r--r--modules/mono/editor/GodotSharpTools/.gitignore2
-rw-r--r--modules/mono/editor/script_class_parser.cpp101
-rw-r--r--modules/mono/editor/script_class_parser.h1
-rwxr-xr-xplatform/android/sign.sh9
-rw-r--r--scene/3d/arvr_nodes.cpp2
-rw-r--r--scene/animation/animation_tree.cpp34
-rw-r--r--scene/gui/scroll_bar.cpp2
-rw-r--r--scene/gui/text_edit.cpp1
-rw-r--r--servers/visual/shader_language.cpp9
19 files changed, 243 insertions, 66 deletions
diff --git a/doc/classes/@GlobalScope.xml b/doc/classes/@GlobalScope.xml
index e05af0f1ac..ba2eb35f8c 100644
--- a/doc/classes/@GlobalScope.xml
+++ b/doc/classes/@GlobalScope.xml
@@ -29,8 +29,6 @@
<member name="Geometry" type="Geometry" setter="" getter="">
[Geometry] singleton
</member>
- <member name="GodotSharp" type="GodotSharp" setter="" getter="">
- </member>
<member name="IP" type="IP" setter="" getter="">
[IP] singleton
</member>
diff --git a/doc/classes/AnimationNode.xml b/doc/classes/AnimationNode.xml
index d9bad150df..0f16c5e4a9 100644
--- a/doc/classes/AnimationNode.xml
+++ b/doc/classes/AnimationNode.xml
@@ -1,8 +1,11 @@
<?xml version="1.0" encoding="UTF-8" ?>
<class name="AnimationNode" inherits="Resource" category="Core" version="3.1">
<brief_description>
+ Base resource for [AnimationTree] nodes.
</brief_description>
<description>
+ Base resource for [AnimationTree] nodes. In general it's not used directly but you can create custom ones with custom blending formulas.
+ Inherit this when creating nodes mainly for use in [AnimationNodeBlendTree], otherwise [AnimationRootNode] should be used instead.
</description>
<tutorials>
</tutorials>
@@ -15,6 +18,7 @@
<argument index="0" name="name" type="String">
</argument>
<description>
+ Add an input to the node. This is only useful for nodes created for use in an [AnimationNodeBlendTree]
</description>
</method>
<method name="blend_animation">
@@ -31,6 +35,7 @@
<argument index="4" name="blend" type="float">
</argument>
<description>
+ Blend an animation by "blend" amount (name must be valid in the linked [AnimationPlayer]). A time and delta mas be passed, as well as whether seek happened.
</description>
</method>
<method name="blend_input">
@@ -49,6 +54,7 @@
<argument index="5" name="optimize" type="bool" default="true">
</argument>
<description>
+ Blend an input. This is only useful for nodes created for an AnimationBlendTree. Time is a delta, unless "seek" is true, in which case it is absolute. A filter mode may be optionally passed.
</description>
</method>
<method name="blend_node">
@@ -69,18 +75,37 @@
<argument index="6" name="optimize" type="bool" default="true">
</argument>
<description>
+ Blend another animaiton node (in case this node contains children animation nodes). This function is only useful if you inherit from [AnimationRootNode] instead, else editors will not display your node for addition.
</description>
</method>
<method name="get_caption" qualifiers="virtual">
<return type="String">
</return>
<description>
+ Get the text caption for this node (used by some editors)
+ </description>
+ </method>
+ <method name="get_child_by_name" qualifiers="virtual">
+ <return type="Object">
+ </return>
+ <argument index="0" name="name" type="String">
+ </argument>
+ <description>
+ Get the a child node by index (used by editors inheriting from [AnimationRootNode]).
+ </description>
+ </method>
+ <method name="get_child_nodes" qualifiers="virtual">
+ <return type="Dictionary">
+ </return>
+ <description>
+ Get all children nodes, in order as a name:node dictionary. Only useful when inheriting [AnimationRootNode].
</description>
</method>
<method name="get_input_count" qualifiers="const">
<return type="int">
</return>
<description>
+ Amount of inputs in this node, only useful for nodes that go into [AnimationBlendTree].
</description>
</method>
<method name="get_input_name">
@@ -89,6 +114,7 @@
<argument index="0" name="input" type="int">
</argument>
<description>
+ Get the name of an input by index.
</description>
</method>
<method name="get_parameter" qualifiers="const">
@@ -97,12 +123,31 @@
<argument index="0" name="name" type="String">
</argument>
<description>
+ Get the value of a parameter. Parameters are custom local memory used for your nodes, given a resource can be reused in multiple trees.
+ </description>
+ </method>
+ <method name="get_parameter_default_value" qualifiers="virtual">
+ <return type="Variant">
+ </return>
+ <argument index="0" name="name" type="String">
+ </argument>
+ <description>
+ Get the default value of a parameter. Parameters are custom local memory used for your nodes, given a resource can be reused in multiple trees.
+ </description>
+ </method>
+ <method name="get_parameter_list" qualifiers="virtual">
+ <return type="Array">
+ </return>
+ <description>
+ Get the property information for parameter. Parameters are custom local memory used for your nodes, given a resource can be reused in multiple trees.
+ Format is similar to [Object.get_property_list]
</description>
</method>
<method name="has_filter" qualifiers="virtual">
<return type="String">
</return>
<description>
+ Return true whether you want the blend tree editor to display filter editing on this node.
</description>
</method>
<method name="is_path_filtered" qualifiers="const">
@@ -111,6 +156,7 @@
<argument index="0" name="path" type="NodePath">
</argument>
<description>
+ Return true wether a given path is filtered.
</description>
</method>
<method name="process" qualifiers="virtual">
@@ -121,6 +167,10 @@
<argument index="1" name="seek" type="bool">
</argument>
<description>
+ Called when a custom node is processed. The argument "time" is relative, unless "seek" is true (in which case it is absolute).
+ Here, call the [method blend_input], [method blend_node] or [method blend_animation] functions.
+ You can also use [method get_parameter] and [method set_parameter] to modify local memory.
+ This function returns the time left for the current animation to finish (if unsure, just pass the value from the main blend being called).
</description>
</method>
<method name="remove_input">
@@ -129,6 +179,7 @@
<argument index="0" name="index" type="int">
</argument>
<description>
+ Remove an input, call this only when inactive.
</description>
</method>
<method name="set_filter_path">
@@ -139,6 +190,7 @@
<argument index="1" name="enable" type="bool">
</argument>
<description>
+ Add/Remove a path for the filter.
</description>
</method>
<method name="set_parameter">
@@ -149,16 +201,19 @@
<argument index="1" name="value" type="Variant">
</argument>
<description>
+ Set a custom parameter. These are used as local storage, because resources can be reused across the tree or scenes.
</description>
</method>
</methods>
<members>
<member name="filter_enabled" type="bool" setter="set_filter_enabled" getter="is_filter_enabled">
+ Return whether filtering is enabled.
</member>
</members>
<signals>
<signal name="removed_from_graph">
<description>
+ Called when the node was removed from the graph.
</description>
</signal>
<signal name="tree_changed">
@@ -168,12 +223,16 @@
</signals>
<constants>
<constant name="FILTER_IGNORE" value="0" enum="FilterAction">
+ Do not use filtering.
</constant>
<constant name="FILTER_PASS" value="1" enum="FilterAction">
+ Paths matching the filter will be allowed to pass.
</constant>
<constant name="FILTER_STOP" value="2" enum="FilterAction">
+ Paths matching the filter will be discarded.
</constant>
<constant name="FILTER_BLEND" value="3" enum="FilterAction">
+ Paths matching the filter will be blended (by the blend value).
</constant>
</constants>
</class>
diff --git a/doc/classes/ProjectSettings.xml b/doc/classes/ProjectSettings.xml
index 9706ea4e60..7a9918237f 100644
--- a/doc/classes/ProjectSettings.xml
+++ b/doc/classes/ProjectSettings.xml
@@ -588,14 +588,6 @@
<member name="memory/limits/multithreaded_server/rid_pool_prealloc" type="int" setter="" getter="">
This is used by servers when used in multi threading mode (servers and visual). RIDs are preallocated to avoid stalling the server requesting them on threads. If servers get stalled too often when loading resources in a thread, increase this number.
</member>
- <member name="mono/debugger_agent/port" type="int" setter="" getter="">
- </member>
- <member name="mono/debugger_agent/wait_for_debugger" type="bool" setter="" getter="">
- </member>
- <member name="mono/debugger_agent/wait_timeout" type="int" setter="" getter="">
- </member>
- <member name="mono/export/include_scripts_content" type="bool" setter="" getter="">
- </member>
<member name="network/limits/debugger_stdout/max_chars_per_second" type="int" setter="" getter="">
Maximum amount of characters allowed to send as output from the debugger. Over this value, content is dropped. This helps not to stall the debugger connection.
</member>
diff --git a/drivers/pulseaudio/audio_driver_pulseaudio.cpp b/drivers/pulseaudio/audio_driver_pulseaudio.cpp
index 010f7bdb0a..720824d451 100644
--- a/drivers/pulseaudio/audio_driver_pulseaudio.cpp
+++ b/drivers/pulseaudio/audio_driver_pulseaudio.cpp
@@ -374,7 +374,7 @@ void AudioDriverPulseAudio::thread_func(void *p_udata) {
const void *ptr = ad->samples_out.ptr();
ret = pa_stream_write(ad->pa_str, (char *)ptr + write_ofs, bytes_to_write, NULL, 0LL, PA_SEEK_RELATIVE);
if (ret != 0) {
- ERR_PRINT("pa_stream_write error");
+ ERR_PRINTS("PulseAudio: pa_stream_write error: " + String(pa_strerror(ret)));
} else {
avail_bytes -= bytes_to_write;
write_ofs += bytes_to_write;
@@ -401,6 +401,9 @@ void AudioDriverPulseAudio::thread_func(void *p_udata) {
break;
}
}
+
+ avail_bytes = 0;
+ write_ofs = 0;
}
if (ad->pa_rec_str && pa_stream_get_state(ad->pa_rec_str) == PA_STREAM_READY) {
diff --git a/editor/editor_data.cpp b/editor/editor_data.cpp
index bd6ce797b5..5942348999 100644
--- a/editor/editor_data.cpp
+++ b/editor/editor_data.cpp
@@ -857,11 +857,16 @@ bool EditorData::script_class_is_parent(const String &p_class, const String &p_i
if (!ScriptServer::is_global_class(p_class))
return false;
String base = script_class_get_base(p_class);
+ Ref<Script> script = ResourceLoader::load(ScriptServer::get_global_class_path(p_class), "Script");
+ Ref<Script> base_script = script->get_base_script();
+
while (p_inherits != base) {
if (ClassDB::class_exists(base)) {
return ClassDB::is_parent_class(base, p_inherits);
} else if (ScriptServer::is_global_class(base)) {
base = script_class_get_base(base);
+ } else if (base_script.is_valid()) {
+ return ClassDB::is_parent_class(base_script->get_instance_base_type(), p_inherits);
} else {
return false;
}
diff --git a/editor/import/resource_importer_texture.cpp b/editor/import/resource_importer_texture.cpp
index b38f4c4f14..724203831c 100644
--- a/editor/import/resource_importer_texture.cpp
+++ b/editor/import/resource_importer_texture.cpp
@@ -415,7 +415,7 @@ Error ResourceImporterTexture::import(const String &p_source_file, const String
image->resize(new_width, new_height, Image::INTERPOLATE_CUBIC);
}
- if (normal) {
+ if (normal == 1) {
image->normalize();
}
}
diff --git a/modules/gdscript/gdscript_compiler.cpp b/modules/gdscript/gdscript_compiler.cpp
index 45319c59e7..310c4e21f2 100644
--- a/modules/gdscript/gdscript_compiler.cpp
+++ b/modules/gdscript/gdscript_compiler.cpp
@@ -1603,13 +1603,13 @@ Error GDScriptCompiler::_parse_block(CodeGen &codegen, const GDScriptParser::Blo
return OK;
}
-Error GDScriptCompiler::_parse_function(Ref<GDScript> p_script, const GDScriptParser::ClassNode *p_class, const GDScriptParser::FunctionNode *p_func, bool p_for_ready) {
+Error GDScriptCompiler::_parse_function(GDScript *p_script, const GDScriptParser::ClassNode *p_class, const GDScriptParser::FunctionNode *p_func, bool p_for_ready) {
Vector<int> bytecode;
CodeGen codegen;
codegen.class_node = p_class;
- codegen.script = p_script.ptr();
+ codegen.script = p_script;
codegen.function_node = p_func;
codegen.stack_max = 0;
codegen.current_line = 0;
@@ -1853,7 +1853,7 @@ Error GDScriptCompiler::_parse_function(Ref<GDScript> p_script, const GDScriptPa
return OK;
}
-Error GDScriptCompiler::_parse_class_level(Ref<GDScript> p_script, Ref<GDScript> p_owner, const GDScriptParser::ClassNode *p_class, bool p_keep_state) {
+Error GDScriptCompiler::_parse_class_level(GDScript *p_script, GDScript *p_owner, const GDScriptParser::ClassNode *p_class, bool p_keep_state) {
if (p_class->owner && p_class->owner->owner) {
// Owner is not root
@@ -1887,7 +1887,7 @@ Error GDScriptCompiler::_parse_class_level(Ref<GDScript> p_script, Ref<GDScript>
p_script->initializer = NULL;
p_script->subclasses.clear();
- p_script->_owner = p_owner.ptr();
+ p_script->_owner = p_owner;
p_script->tool = p_class->tool;
p_script->name = p_class->name;
@@ -1994,7 +1994,7 @@ Error GDScriptCompiler::_parse_class_level(Ref<GDScript> p_script, Ref<GDScript>
StringName name = p_class->_signals[i].name;
- GDScript *c = p_script.ptr();
+ GDScript *c = p_script;
while (c) {
@@ -2054,7 +2054,7 @@ Error GDScriptCompiler::_parse_class_level(Ref<GDScript> p_script, Ref<GDScript>
return OK;
}
-Error GDScriptCompiler::_parse_class_blocks(Ref<GDScript> p_script, const GDScriptParser::ClassNode *p_class, bool p_keep_state) {
+Error GDScriptCompiler::_parse_class_blocks(GDScript *p_script, const GDScriptParser::ClassNode *p_class, bool p_keep_state) {
//parse methods
bool has_initializer = false;
@@ -2159,7 +2159,7 @@ Error GDScriptCompiler::_parse_class_blocks(Ref<GDScript> p_script, const GDScri
return OK;
}
-void GDScriptCompiler::_make_scripts(const Ref<GDScript> p_script, const GDScriptParser::ClassNode *p_class, bool p_keep_state) {
+void GDScriptCompiler::_make_scripts(const GDScript *p_script, const GDScriptParser::ClassNode *p_class, bool p_keep_state) {
Map<StringName, Ref<GDScript> > old_subclasses;
@@ -2178,20 +2178,20 @@ void GDScriptCompiler::_make_scripts(const Ref<GDScript> p_script, const GDScrip
subclass.instance();
}
- subclass->_owner = const_cast<GDScript *>(p_script.ptr());
+ subclass->_owner = const_cast<GDScript *>(p_script);
class_map.insert(name, subclass);
_make_scripts(subclass.ptr(), p_class->subclasses[i], p_keep_state);
}
}
-Error GDScriptCompiler::compile(const GDScriptParser *p_parser, Ref<GDScript> p_script, bool p_keep_state) {
+Error GDScriptCompiler::compile(const GDScriptParser *p_parser, GDScript *p_script, bool p_keep_state) {
err_line = -1;
err_column = -1;
error = "";
parser = p_parser;
- main_script = p_script.ptr();
+ main_script = p_script;
const GDScriptParser::Node *root = parser->get_parse_tree();
ERR_FAIL_COND_V(root->type != GDScriptParser::Node::TYPE_CLASS, ERR_INVALID_DATA);
diff --git a/modules/gdscript/gdscript_compiler.h b/modules/gdscript/gdscript_compiler.h
index 23c6450aa7..55f5e2b48e 100644
--- a/modules/gdscript/gdscript_compiler.h
+++ b/modules/gdscript/gdscript_compiler.h
@@ -148,17 +148,17 @@ class GDScriptCompiler {
int _parse_assign_right_expression(CodeGen &codegen, const GDScriptParser::OperatorNode *p_expression, int p_stack_level);
int _parse_expression(CodeGen &codegen, const GDScriptParser::Node *p_expression, int p_stack_level, bool p_root = false, bool p_initializer = false);
Error _parse_block(CodeGen &codegen, const GDScriptParser::BlockNode *p_block, int p_stack_level = 0, int p_break_addr = -1, int p_continue_addr = -1);
- Error _parse_function(Ref<GDScript> p_script, const GDScriptParser::ClassNode *p_class, const GDScriptParser::FunctionNode *p_func, bool p_for_ready = false);
- Error _parse_class_level(Ref<GDScript> p_script, Ref<GDScript> p_owner, const GDScriptParser::ClassNode *p_class, bool p_keep_state);
- Error _parse_class_blocks(Ref<GDScript> p_script, const GDScriptParser::ClassNode *p_class, bool p_keep_state);
- void _make_scripts(const Ref<GDScript> p_script, const GDScriptParser::ClassNode *p_class, bool p_keep_state);
+ Error _parse_function(GDScript *p_script, const GDScriptParser::ClassNode *p_class, const GDScriptParser::FunctionNode *p_func, bool p_for_ready = false);
+ Error _parse_class_level(GDScript *p_script, GDScript *p_owner, const GDScriptParser::ClassNode *p_class, bool p_keep_state);
+ Error _parse_class_blocks(GDScript *p_script, const GDScriptParser::ClassNode *p_class, bool p_keep_state);
+ void _make_scripts(const GDScript *p_script, const GDScriptParser::ClassNode *p_class, bool p_keep_state);
int err_line;
int err_column;
StringName source;
String error;
public:
- Error compile(const GDScriptParser *p_parser, Ref<GDScript> p_script, bool p_keep_state = false);
+ Error compile(const GDScriptParser *p_parser, GDScript *p_script, bool p_keep_state = false);
String get_error() const;
int get_error_line() const;
diff --git a/modules/gdscript/gdscript_function.cpp b/modules/gdscript/gdscript_function.cpp
index c67cf124c0..cd6c21a629 100644
--- a/modules/gdscript/gdscript_function.cpp
+++ b/modules/gdscript/gdscript_function.cpp
@@ -370,7 +370,7 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a
}
script = p_instance->script.ptr();
} else {
- script = this->_script.ptr();
+ script = _script;
}
}
@@ -1182,7 +1182,7 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a
GET_VARIANT_PTR(dst, argc + 3);
- const GDScript *gds = _script.ptr();
+ const GDScript *gds = _script;
const Map<StringName, GDScriptFunction *>::Element *E = NULL;
while (gds->base.ptr()) {
@@ -1253,7 +1253,7 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a
gdfs->state.stack_size = _stack_size;
gdfs->state.self = self;
gdfs->state.alloca_size = alloca_size;
- gdfs->state.script = _script;
+ gdfs->state.script = Ref<GDScript>(_script);
gdfs->state.ip = ip + ipofs;
gdfs->state.line = line;
gdfs->state.instance_id = (p_instance && p_instance->get_owner()) ? p_instance->get_owner()->get_instance_id() : 0;
@@ -1760,22 +1760,14 @@ GDScriptFunction::~GDScriptFunction() {
Variant GDScriptFunctionState::_signal_callback(const Variant **p_args, int p_argcount, Variant::CallError &r_error) {
-#ifdef DEBUG_ENABLED
- // Checking this first since it's faster
- if (!state.script.is_valid()) {
- ERR_EXPLAIN("Resumed after yield, but script is gone");
- ERR_FAIL_V(Variant());
- }
-
if (state.instance_id && !ObjectDB::get_instance(state.instance_id)) {
+#ifdef DEBUG_ENABLED
ERR_EXPLAIN("Resumed after yield, but class instance is gone");
ERR_FAIL_V(Variant());
- }
#else
- if (!is_valid()) {
return Variant();
- }
#endif
+ }
Variant arg;
r_error.error = Variant::CallError::CALL_OK;
@@ -1842,9 +1834,6 @@ bool GDScriptFunctionState::is_valid(bool p_extended_check) const {
return false;
if (p_extended_check) {
- //script gone? (checking this first since it's faster)
- if (!state.script.is_valid())
- return false;
//class instance gone?
if (state.instance_id && !ObjectDB::get_instance(state.instance_id))
return false;
@@ -1856,18 +1845,14 @@ bool GDScriptFunctionState::is_valid(bool p_extended_check) const {
Variant GDScriptFunctionState::resume(const Variant &p_arg) {
ERR_FAIL_COND_V(!function, Variant());
-#ifdef DEBUG_ENABLED
- // Checking this first since it's faster
- if (!state.script.is_valid()) {
- ERR_EXPLAIN("Resumed after yield, but script is gone");
- ERR_FAIL_V(Variant());
- }
-
if (state.instance_id && !ObjectDB::get_instance(state.instance_id)) {
+#ifdef DEBUG_ENABLED
ERR_EXPLAIN("Resumed after yield, but class instance is gone");
ERR_FAIL_V(Variant());
- }
+#else
+ return Variant();
#endif
+ }
state.result = p_arg;
Variant::CallError err;
diff --git a/modules/gdscript/gdscript_function.h b/modules/gdscript/gdscript_function.h
index a47070de4f..5509edf24a 100644
--- a/modules/gdscript/gdscript_function.h
+++ b/modules/gdscript/gdscript_function.h
@@ -225,7 +225,7 @@ private:
bool _static;
MultiplayerAPI::RPCMode rpc_mode;
- Ref<GDScript> _script;
+ GDScript *_script;
StringName name;
Vector<Variant> constants;
@@ -297,7 +297,7 @@ public:
int get_default_argument_addr(int p_idx) const;
GDScriptDataType get_return_type() const;
GDScriptDataType get_argument_type(int p_idx) const;
- GDScript *get_script() const { return const_cast<GDScript *>(_script.ptr()); }
+ GDScript *get_script() const { return _script; }
StringName get_source() const { return source; }
void debug_get_stack_member_state(int p_line, List<Pair<StringName, int> > *r_stackvars) const;
diff --git a/modules/mono/editor/GodotSharpTools/.gitignore b/modules/mono/editor/GodotSharpTools/.gitignore
new file mode 100644
index 0000000000..296ad48834
--- /dev/null
+++ b/modules/mono/editor/GodotSharpTools/.gitignore
@@ -0,0 +1,2 @@
+# nuget packages
+packages \ No newline at end of file
diff --git a/modules/mono/editor/script_class_parser.cpp b/modules/mono/editor/script_class_parser.cpp
index bc8eed81cf..9042bff74a 100644
--- a/modules/mono/editor/script_class_parser.cpp
+++ b/modules/mono/editor/script_class_parser.cpp
@@ -259,6 +259,8 @@ Error ScriptClassParser::_skip_generic_type_params() {
if (err)
return err;
continue;
+ } else if (tk == TK_OP_GREATER) {
+ return OK;
} else if (tk != TK_COMMA) {
error_str = "Unexpected token: " + get_token_name(tk);
error = true;
@@ -312,27 +314,108 @@ Error ScriptClassParser::_parse_class_base(Vector<String> &r_base) {
Token tk = get_token();
+ bool generic = false;
if (tk == TK_OP_LESS) {
- // We don't add it to the base list if it's generic
Error err = _skip_generic_type_params();
if (err)
return err;
- } else if (tk == TK_COMMA) {
+ // We don't add it to the base list if it's generic
+ generic = true;
+ tk = get_token();
+ }
+
+ if (tk == TK_COMMA) {
Error err = _parse_class_base(r_base);
if (err)
return err;
- r_base.push_back(name);
+ } else if (tk == TK_IDENTIFIER && String(value) == "where") {
+ Error err = _parse_type_constraints();
+ if (err) {
+ return err;
+ }
+
+ // An open curly bracket was parsed by _parse_type_constraints, so we can exit
} else if (tk == TK_CURLY_BRACKET_OPEN) {
- r_base.push_back(name);
+ // we are finished when we hit the open curly bracket
} else {
error_str = "Unexpected token: " + get_token_name(tk);
error = true;
return ERR_PARSE_ERROR;
}
+ if (!generic) {
+ r_base.push_back(name);
+ }
+
return OK;
}
+Error ScriptClassParser::_parse_type_constraints() {
+ Token tk = get_token();
+ if (tk != TK_IDENTIFIER) {
+ error_str = "Unexpected token: " + get_token_name(tk);
+ error = true;
+ return ERR_PARSE_ERROR;
+ }
+
+ tk = get_token();
+ if (tk != TK_COLON) {
+ error_str = "Unexpected token: " + get_token_name(tk);
+ error = true;
+ return ERR_PARSE_ERROR;
+ }
+
+ while (true) {
+ tk = get_token();
+ if (tk == TK_IDENTIFIER) {
+ if (String(value) == "where") {
+ return _parse_type_constraints();
+ }
+
+ tk = get_token();
+ if (tk == TK_PERIOD) {
+ while (true) {
+ tk = get_token();
+
+ if (tk != TK_IDENTIFIER) {
+ error_str = "Expected " + get_token_name(TK_IDENTIFIER) + ", found: " + get_token_name(tk);
+ error = true;
+ return ERR_PARSE_ERROR;
+ }
+
+ tk = get_token();
+
+ if (tk != TK_PERIOD)
+ break;
+ }
+ }
+ }
+
+ if (tk == TK_COMMA) {
+ continue;
+ } else if (tk == TK_IDENTIFIER && String(value) == "where") {
+ return _parse_type_constraints();
+ } else if (tk == TK_SYMBOL && String(value) == "(") {
+ tk = get_token();
+ if (tk != TK_SYMBOL || String(value) != ")") {
+ error_str = "Unexpected token: " + get_token_name(tk);
+ error = true;
+ return ERR_PARSE_ERROR;
+ }
+ } else if (tk == TK_OP_LESS) {
+ Error err = _skip_generic_type_params();
+ if (err)
+ return err;
+ } else if (tk == TK_CURLY_BRACKET_OPEN) {
+ return OK;
+ } else {
+ error_str = "Unexpected token: " + get_token_name(tk);
+ error = true;
+ return ERR_PARSE_ERROR;
+ }
+ }
+}
+
Error ScriptClassParser::_parse_namespace_name(String &r_name, int &r_curly_stack) {
Token tk = get_token();
@@ -425,6 +508,16 @@ Error ScriptClassParser::parse(const String &p_code) {
Error err = _skip_generic_type_params();
if (err)
return err;
+ } else if (tk == TK_IDENTIFIER && String(value) == "where") {
+ Error err = _parse_type_constraints();
+ if (err) {
+ return err;
+ }
+
+ // An open curly bracket was parsed by _parse_type_constraints, so we can exit
+ curly_stack++;
+ type_curly_stack++;
+ break;
} else {
error_str = "Unexpected token: " + get_token_name(tk);
error = true;
diff --git a/modules/mono/editor/script_class_parser.h b/modules/mono/editor/script_class_parser.h
index 1e174c28a9..184adebaf2 100644
--- a/modules/mono/editor/script_class_parser.h
+++ b/modules/mono/editor/script_class_parser.h
@@ -65,6 +65,7 @@ private:
Error _parse_type_full_name(String &r_full_name);
Error _parse_class_base(Vector<String> &r_base);
+ Error _parse_type_constraints();
Error _parse_namespace_name(String &r_name, int &r_curly_stack);
public:
diff --git a/platform/android/sign.sh b/platform/android/sign.sh
deleted file mode 100755
index 830da05a37..0000000000
--- a/platform/android/sign.sh
+++ /dev/null
@@ -1,9 +0,0 @@
-#!/bin/bash
-
-jarsigner -digestalg SHA1 -sigalg MD5withRSA -verbose -keystore my-release-key.keystore "$1" reduz
-
-echo ""
-echo ""
-echo "Checking if APK is verified..."
-jarsigner -verify "$1" -verbose -certs
-
diff --git a/scene/3d/arvr_nodes.cpp b/scene/3d/arvr_nodes.cpp
index 2dc500f7ab..7ea62678da 100644
--- a/scene/3d/arvr_nodes.cpp
+++ b/scene/3d/arvr_nodes.cpp
@@ -266,6 +266,7 @@ void ARVRController::set_controller_id(int p_controller_id) {
// We don't check any bounds here, this controller may not yet be active and just be a place holder until it is.
// Note that setting this to 0 means this node is not bound to a controller yet.
controller_id = p_controller_id;
+ update_configuration_warning();
};
int ARVRController::get_controller_id(void) const {
@@ -446,6 +447,7 @@ void ARVRAnchor::set_anchor_id(int p_anchor_id) {
// We don't check any bounds here, this anchor may not yet be active and just be a place holder until it is.
// Note that setting this to 0 means this node is not bound to an anchor yet.
anchor_id = p_anchor_id;
+ update_configuration_warning();
};
int ARVRAnchor::get_anchor_id(void) const {
diff --git a/scene/animation/animation_tree.cpp b/scene/animation/animation_tree.cpp
index eb00f91bb3..2c8cbbdbd1 100644
--- a/scene/animation/animation_tree.cpp
+++ b/scene/animation/animation_tree.cpp
@@ -37,9 +37,20 @@
#include "servers/audio/audio_stream.h"
void AnimationNode::get_parameter_list(List<PropertyInfo> *r_list) const {
+ if (get_script_instance()) {
+ Array parameters = get_script_instance()->call("get_parameter_list");
+ for (int i = 0; i < parameters.size(); i++) {
+ Dictionary d = parameters[i];
+ ERR_CONTINUE(d.empty());
+ r_list->push_back(PropertyInfo::from_dict(d));
+ }
+ }
}
Variant AnimationNode::get_parameter_default_value(const StringName &p_parameter) const {
+ if (get_script_instance()) {
+ return get_script_instance()->call("get_parameter_default_value");
+ }
return Variant();
}
@@ -62,6 +73,18 @@ Variant AnimationNode::get_parameter(const StringName &p_name) const {
}
void AnimationNode::get_child_nodes(List<ChildNode> *r_child_nodes) {
+
+ if (get_script_instance()) {
+ Dictionary cn = get_script_instance()->call("get_child_nodes");
+ List<Variant> keys;
+ cn.get_key_list(&keys);
+ for (List<Variant>::Element *E = keys.front(); E; E = E->next()) {
+ ChildNode child;
+ child.name = E->get();
+ child.node = cn[E->get()];
+ r_child_nodes->push_back(child);
+ }
+ }
}
void AnimationNode::blend_animation(const StringName &p_animation, float p_time, float p_delta, bool p_seeked, float p_blend) {
@@ -373,6 +396,9 @@ void AnimationNode::_validate_property(PropertyInfo &property) const {
}
Ref<AnimationNode> AnimationNode::get_child_by_name(const StringName &p_name) {
+ if (get_script_instance()) {
+ return get_script_instance()->call("get_child_by_name");
+ }
return Ref<AnimationNode>();
}
@@ -403,6 +429,14 @@ void AnimationNode::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "filter_enabled", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR), "set_filter_enabled", "is_filter_enabled");
ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "filters", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR | PROPERTY_USAGE_INTERNAL), "_set_filters", "_get_filters");
+ BIND_VMETHOD(MethodInfo(Variant::DICTIONARY, "get_child_nodes"));
+ BIND_VMETHOD(MethodInfo(Variant::ARRAY, "get_parameter_list"));
+ BIND_VMETHOD(MethodInfo(Variant::OBJECT, "get_child_by_name", PropertyInfo(Variant::STRING, "name")));
+ {
+ MethodInfo mi = MethodInfo(Variant::NIL, "get_parameter_default_value", PropertyInfo(Variant::STRING, "name"));
+ mi.return_val.usage = PROPERTY_USAGE_NIL_IS_VARIANT;
+ BIND_VMETHOD(mi);
+ }
BIND_VMETHOD(MethodInfo("process", PropertyInfo(Variant::REAL, "time"), PropertyInfo(Variant::BOOL, "seek")));
BIND_VMETHOD(MethodInfo(Variant::STRING, "get_caption"));
BIND_VMETHOD(MethodInfo(Variant::STRING, "has_filter"));
diff --git a/scene/gui/scroll_bar.cpp b/scene/gui/scroll_bar.cpp
index 07380f45cc..0e68476439 100644
--- a/scene/gui/scroll_bar.cpp
+++ b/scene/gui/scroll_bar.cpp
@@ -330,6 +330,8 @@ void ScrollBar::_notification(int p_what) {
if (Math::abs(vel) >= dist) {
set_value(target_scroll);
+ scrolling = false;
+ set_physics_process_internal(false);
} else {
set_value(get_value() + vel);
}
diff --git a/scene/gui/text_edit.cpp b/scene/gui/text_edit.cpp
index 7bfcd0843c..5fe6fcdfac 100644
--- a/scene/gui/text_edit.cpp
+++ b/scene/gui/text_edit.cpp
@@ -4264,6 +4264,7 @@ void TextEdit::_clear() {
cursor.line_ofs = 0;
cursor.wrap_ofs = 0;
cursor.last_fit_x = 0;
+ selection.active = false;
}
void TextEdit::clear() {
diff --git a/servers/visual/shader_language.cpp b/servers/visual/shader_language.cpp
index 50e45963d9..1acec7ccaf 100644
--- a/servers/visual/shader_language.cpp
+++ b/servers/visual/shader_language.cpp
@@ -1215,6 +1215,15 @@ bool ShaderLanguage::_validate_operator(OperatorNode *p_op, DataType *r_ret_type
} else if (p_op->op == OP_ASSIGN_MUL && na == TYPE_MAT4 && nb == TYPE_VEC4) {
valid = true;
ret_type = TYPE_MAT4;
+ } else if (p_op->op == OP_ASSIGN_MUL && na == TYPE_VEC2 && nb == TYPE_MAT2) {
+ valid = true;
+ ret_type = TYPE_VEC2;
+ } else if (p_op->op == OP_ASSIGN_MUL && na == TYPE_VEC3 && nb == TYPE_MAT3) {
+ valid = true;
+ ret_type = TYPE_VEC3;
+ } else if (p_op->op == OP_ASSIGN_MUL && na == TYPE_VEC4 && nb == TYPE_MAT4) {
+ valid = true;
+ ret_type = TYPE_VEC4;
}
} break;
case OP_ASSIGN_BIT_AND: