summaryrefslogtreecommitdiff
path: root/modules/gdscript
diff options
context:
space:
mode:
Diffstat (limited to 'modules/gdscript')
-rw-r--r--modules/gdscript/doc_classes/@GDScript.xml33
-rw-r--r--modules/gdscript/doc_classes/GDScript.xml2
-rw-r--r--modules/gdscript/gdscript.cpp402
-rw-r--r--modules/gdscript/gdscript.h39
-rw-r--r--modules/gdscript/gdscript_compiler.cpp4
-rw-r--r--modules/gdscript/gdscript_editor.cpp48
-rw-r--r--modules/gdscript/gdscript_function.cpp174
-rw-r--r--modules/gdscript/gdscript_function.h16
-rw-r--r--modules/gdscript/gdscript_functions.cpp405
-rw-r--r--modules/gdscript/gdscript_functions.h3
-rw-r--r--modules/gdscript/gdscript_parser.cpp144
-rw-r--r--modules/gdscript/gdscript_tokenizer.cpp47
-rw-r--r--modules/gdscript/gdscript_tokenizer.h2
-rw-r--r--modules/gdscript/language_server/gdscript_language_protocol.cpp201
-rw-r--r--modules/gdscript/language_server/gdscript_language_protocol.h40
-rw-r--r--modules/gdscript/language_server/gdscript_text_document.cpp2
-rw-r--r--modules/gdscript/language_server/gdscript_workspace.cpp49
-rw-r--r--modules/gdscript/language_server/gdscript_workspace.h5
18 files changed, 906 insertions, 710 deletions
diff --git a/modules/gdscript/doc_classes/@GDScript.xml b/modules/gdscript/doc_classes/@GDScript.xml
index b947d95fac..2f6f9f30a4 100644
--- a/modules/gdscript/doc_classes/@GDScript.xml
+++ b/modules/gdscript/doc_classes/@GDScript.xml
@@ -131,7 +131,7 @@
<method name="bytes2var">
<return type="Variant">
</return>
- <argument index="0" name="bytes" type="PoolByteArray">
+ <argument index="0" name="bytes" type="PackedByteArray">
</argument>
<argument index="1" name="allow_objects" type="bool" default="false">
</argument>
@@ -256,15 +256,6 @@
Converts from decibels to linear energy (audio).
</description>
</method>
- <method name="decimals">
- <return type="int">
- </return>
- <argument index="0" name="step" type="float">
- </argument>
- <description>
- Deprecated alias for [method step_decimals].
- </description>
- </method>
<method name="dectime">
<return type="float">
</return>
@@ -490,9 +481,13 @@
<argument index="2" name="weight" type="float">
</argument>
<description>
- Returns a normalized value considering the given range.
+ Returns a normalized value considering the given range. This is the opposite of [method lerp].
[codeblock]
- inverse_lerp(3, 5, 4) # Returns 0.5
+ var middle = lerp(20, 30, 0.75)
+ # `middle` is now 27.5.
+ # Now, we pretend to have forgotten the original ratio and want to get it back.
+ var ratio = inverse_lerp(20, 30, 27.5)
+ # `ratio` is now 0.75.
[/codeblock]
</description>
</method>
@@ -567,7 +562,7 @@
<argument index="2" name="weight" type="float">
</argument>
<description>
- Linearly interpolates between two values by a normalized value.
+ Linearly interpolates between two values by a normalized value. This is the opposite of [method inverse_lerp].
If the [code]from[/code] and [code]to[/code] arguments are of type [int] or [float], the return value is a [float].
If both are of the same vector type ([Vector2], [Vector3] or [Color]), the return value will be of the same type ([code]lerp[/code] then calls the vector type's [code]linear_interpolate[/code] method).
[codeblock]
@@ -587,7 +582,7 @@
</argument>
<description>
Linearly interpolates between two angles (in radians) by a normalized value.
- Similar to [method lerp] but interpolate correctly when the angles wrap around [constant @GDScript.TAU].
+ Similar to [method lerp], but interpolates correctly when the angles wrap around [constant @GDScript.TAU].
[codeblock]
extends Sprite
var elapsed = 0.0
@@ -605,7 +600,13 @@
<argument index="0" name="nrg" type="float">
</argument>
<description>
- Converts from linear energy to decibels (audio).
+ Converts from linear energy to decibels (audio). This can be used to implement volume sliders that behave as expected (since volume isn't linear). Example:
+ [codeblock]
+ # "Slider" refers to a node that inherits Range such as HSlider or VSlider.
+ # Its range must be configured to go from 0 to 1.
+ # Change the bus name if you'd like to change the volume of a specific bus only.
+ AudioServer.set_bus_volume_db(AudioServer.get_bus_index("Master"), linear2db($Slider.value))
+ [/codeblock]
</description>
</method>
<method name="load">
@@ -1254,7 +1255,7 @@
</description>
</method>
<method name="var2bytes">
- <return type="PoolByteArray">
+ <return type="PackedByteArray">
</return>
<argument index="0" name="var" type="Variant">
</argument>
diff --git a/modules/gdscript/doc_classes/GDScript.xml b/modules/gdscript/doc_classes/GDScript.xml
index 5d0e93e117..62ccb93901 100644
--- a/modules/gdscript/doc_classes/GDScript.xml
+++ b/modules/gdscript/doc_classes/GDScript.xml
@@ -12,7 +12,7 @@
</tutorials>
<methods>
<method name="get_as_byte_code" qualifiers="const">
- <return type="PoolByteArray">
+ <return type="PackedByteArray">
</return>
<description>
Returns byte code for the script source code.
diff --git a/modules/gdscript/gdscript.cpp b/modules/gdscript/gdscript.cpp
index a255b92257..c641ce37c5 100644
--- a/modules/gdscript/gdscript.cpp
+++ b/modules/gdscript/gdscript.cpp
@@ -30,6 +30,8 @@
#include "gdscript.h"
+#include <stdint.h>
+
#include "core/core_string_names.h"
#include "core/engine.h"
#include "core/global_constants.h"
@@ -82,7 +84,7 @@ Object *GDScriptNativeClass::instance() {
return ClassDB::instance(name);
}
-GDScriptInstance *GDScript::_create_instance(const Variant **p_args, int p_argcount, Object *p_owner, bool p_isref, Variant::CallError &r_error) {
+GDScriptInstance *GDScript::_create_instance(const Variant **p_args, int p_argcount, Object *p_owner, bool p_isref, Callable::CallError &r_error) {
/* STEP 1, CREATE */
@@ -91,6 +93,7 @@ GDScriptInstance *GDScript::_create_instance(const Variant **p_args, int p_argco
instance->members.resize(member_indices.size());
instance->script = Ref<GDScript>(this);
instance->owner = p_owner;
+ instance->owner_id = p_owner->get_instance_id();
#ifdef DEBUG_ENABLED
//needed for hot reloading
for (Map<StringName, MemberInfo>::Element *E = member_indices.front(); E; E = E->next()) {
@@ -101,46 +104,39 @@ GDScriptInstance *GDScript::_create_instance(const Variant **p_args, int p_argco
/* STEP 2, INITIALIZE AND CONSTRUCT */
-#ifndef NO_THREADS
- GDScriptLanguage::singleton->lock->lock();
-#endif
-
- instances.insert(instance->owner);
+ {
+ MutexLock lock(GDScriptLanguage::singleton->lock);
-#ifndef NO_THREADS
- GDScriptLanguage::singleton->lock->unlock();
-#endif
+ instances.insert(instance->owner);
+ }
initializer->call(instance, p_args, p_argcount, r_error);
- if (r_error.error != Variant::CallError::CALL_OK) {
+ if (r_error.error != Callable::CallError::CALL_OK) {
instance->script = Ref<GDScript>();
instance->owner->set_script_instance(NULL);
-#ifndef NO_THREADS
- GDScriptLanguage::singleton->lock->lock();
-#endif
- instances.erase(p_owner);
-#ifndef NO_THREADS
- GDScriptLanguage::singleton->lock->unlock();
-#endif
+ {
+ MutexLock lock(GDScriptLanguage::singleton->lock);
+ instances.erase(p_owner);
+ }
- ERR_FAIL_COND_V(r_error.error != Variant::CallError::CALL_OK, NULL); //error constructing
+ ERR_FAIL_COND_V(r_error.error != Callable::CallError::CALL_OK, NULL); //error constructing
}
//@TODO make thread safe
return instance;
}
-Variant GDScript::_new(const Variant **p_args, int p_argcount, Variant::CallError &r_error) {
+Variant GDScript::_new(const Variant **p_args, int p_argcount, Callable::CallError &r_error) {
/* STEP 1, CREATE */
if (!valid) {
- r_error.error = Variant::CallError::CALL_ERROR_INVALID_METHOD;
+ r_error.error = Callable::CallError::CALL_ERROR_INVALID_METHOD;
return Variant();
}
- r_error.error = Variant::CallError::CALL_OK;
+ r_error.error = Callable::CallError::CALL_OK;
REF ref;
Object *owner = NULL;
@@ -326,7 +322,7 @@ ScriptInstance *GDScript::instance_create(Object *p_this) {
}
}
- Variant::CallError unchecked_error;
+ Callable::CallError unchecked_error;
return _create_instance(NULL, 0, p_this, Object::cast_to<Reference>(p_this) != NULL, unchecked_error);
}
@@ -343,16 +339,9 @@ PlaceHolderScriptInstance *GDScript::placeholder_instance_create(Object *p_this)
bool GDScript::instance_has(const Object *p_this) const {
-#ifndef NO_THREADS
- GDScriptLanguage::singleton->lock->lock();
-#endif
- bool hasit = instances.has((Object *)p_this);
-
-#ifndef NO_THREADS
- GDScriptLanguage::singleton->lock->unlock();
-#endif
+ MutexLock lock(GDScriptLanguage::singleton->lock);
- return hasit;
+ return instances.has((Object *)p_this);
}
bool GDScript::has_source_code() const {
@@ -541,14 +530,12 @@ void GDScript::_set_subclass_path(Ref<GDScript> &p_sc, const String &p_path) {
Error GDScript::reload(bool p_keep_state) {
-#ifndef NO_THREADS
- GDScriptLanguage::singleton->lock->lock();
-#endif
- bool has_instances = instances.size();
+ bool has_instances;
+ {
+ MutexLock lock(GDScriptLanguage::singleton->lock);
-#ifndef NO_THREADS
- GDScriptLanguage::singleton->lock->unlock();
-#endif
+ has_instances = instances.size();
+ }
ERR_FAIL_COND_V(!p_keep_state && has_instances, ERR_ALREADY_IN_USE);
@@ -610,6 +597,53 @@ Error GDScript::reload(bool p_keep_state) {
_set_subclass_path(E->get(), path);
}
+ // Copy the base rpc methods so we don't mask their IDs.
+ rpc_functions.clear();
+ rpc_variables.clear();
+ if (base.is_valid()) {
+ rpc_functions = base->rpc_functions;
+ rpc_variables = base->rpc_variables;
+ }
+
+ GDScript *cscript = this;
+ Map<StringName, Ref<GDScript> >::Element *sub_E = subclasses.front();
+ while (cscript) {
+ // RPC Methods
+ for (Map<StringName, GDScriptFunction *>::Element *E = cscript->member_functions.front(); E; E = E->next()) {
+ if (E->get()->get_rpc_mode() != MultiplayerAPI::RPC_MODE_DISABLED) {
+ ScriptNetData nd;
+ nd.name = E->key();
+ nd.mode = E->get()->get_rpc_mode();
+ if (-1 == rpc_functions.find(nd)) {
+ rpc_functions.push_back(nd);
+ }
+ }
+ }
+ // RSet
+ for (Map<StringName, MemberInfo>::Element *E = cscript->member_indices.front(); E; E = E->next()) {
+ if (E->get().rpc_mode != MultiplayerAPI::RPC_MODE_DISABLED) {
+ ScriptNetData nd;
+ nd.name = E->key();
+ nd.mode = E->get().rpc_mode;
+ if (-1 == rpc_variables.find(nd)) {
+ rpc_variables.push_back(nd);
+ }
+ }
+ }
+
+ if (cscript != this)
+ sub_E = sub_E->next();
+
+ if (sub_E)
+ cscript = sub_E->get().ptr();
+ else
+ cscript = NULL;
+ }
+
+ // Sort so we are 100% that they are always the same.
+ rpc_functions.sort_custom<SortNetData>();
+ rpc_variables.sort_custom<SortNetData>();
+
return OK;
}
@@ -635,7 +669,61 @@ void GDScript::get_members(Set<StringName> *p_members) {
}
}
-Variant GDScript::call(const StringName &p_method, const Variant **p_args, int p_argcount, Variant::CallError &r_error) {
+Vector<ScriptNetData> GDScript::get_rpc_methods() const {
+ return rpc_functions;
+}
+
+uint16_t GDScript::get_rpc_method_id(const StringName &p_method) const {
+ for (int i = 0; i < rpc_functions.size(); i++) {
+ if (rpc_functions[i].name == p_method) {
+ return i;
+ }
+ }
+ return UINT16_MAX;
+}
+
+StringName GDScript::get_rpc_method(const uint16_t p_rpc_method_id) const {
+ ERR_FAIL_COND_V(p_rpc_method_id >= rpc_functions.size(), StringName());
+ return rpc_functions[p_rpc_method_id].name;
+}
+
+MultiplayerAPI::RPCMode GDScript::get_rpc_mode_by_id(const uint16_t p_rpc_method_id) const {
+ ERR_FAIL_COND_V(p_rpc_method_id >= rpc_functions.size(), MultiplayerAPI::RPC_MODE_DISABLED);
+ return rpc_functions[p_rpc_method_id].mode;
+}
+
+MultiplayerAPI::RPCMode GDScript::get_rpc_mode(const StringName &p_method) const {
+ return get_rpc_mode_by_id(get_rpc_method_id(p_method));
+}
+
+Vector<ScriptNetData> GDScript::get_rset_properties() const {
+ return rpc_variables;
+}
+
+uint16_t GDScript::get_rset_property_id(const StringName &p_variable) const {
+ for (int i = 0; i < rpc_variables.size(); i++) {
+ if (rpc_variables[i].name == p_variable) {
+ return i;
+ }
+ }
+ return UINT16_MAX;
+}
+
+StringName GDScript::get_rset_property(const uint16_t p_rset_member_id) const {
+ ERR_FAIL_COND_V(p_rset_member_id >= rpc_variables.size(), StringName());
+ return rpc_variables[p_rset_member_id].name;
+}
+
+MultiplayerAPI::RPCMode GDScript::get_rset_mode_by_id(const uint16_t p_rset_member_id) const {
+ ERR_FAIL_COND_V(p_rset_member_id >= rpc_functions.size(), MultiplayerAPI::RPC_MODE_DISABLED);
+ return rpc_functions[p_rset_member_id].mode;
+}
+
+MultiplayerAPI::RPCMode GDScript::get_rset_mode(const StringName &p_variable) const {
+ return get_rset_mode_by_id(get_rset_property_id(p_variable));
+}
+
+Variant GDScript::call(const StringName &p_method, const Variant **p_args, int p_argcount, Callable::CallError &r_error) {
GDScript *top = this;
while (top) {
@@ -798,7 +886,7 @@ Error GDScript::load_byte_code(const String &p_path) {
Error GDScript::load_source_code(const String &p_path) {
- PoolVector<uint8_t> sourcef;
+ Vector<uint8_t> sourcef;
Error err;
FileAccess *f = FileAccess::open(p_path, FileAccess::READ, &err);
if (err) {
@@ -808,15 +896,15 @@ Error GDScript::load_source_code(const String &p_path) {
int len = f->get_len();
sourcef.resize(len + 1);
- PoolVector<uint8_t>::Write w = sourcef.write();
- int r = f->get_buffer(w.ptr(), len);
+ uint8_t *w = sourcef.ptrw();
+ int r = f->get_buffer(w, len);
f->close();
memdelete(f);
ERR_FAIL_COND_V(r != len, ERR_CANT_OPEN);
w[len] = 0;
String s;
- if (s.parse_utf8((const char *)w.ptr())) {
+ if (s.parse_utf8((const char *)w)) {
ERR_FAIL_V_MSG(ERR_INVALID_DATA, "Script '" + p_path + "' contains invalid unicode (UTF-8), so it was not loaded. Please ensure that scripts are saved in valid UTF-8 unicode.");
}
@@ -891,7 +979,6 @@ void GDScript::get_script_signal_list(List<MethodInfo> *r_signals) const {
GDScript::GDScript() :
script_list(this) {
- _static_ref = this;
valid = false;
subclass_count = 0;
initializer = NULL;
@@ -904,13 +991,10 @@ GDScript::GDScript() :
#endif
#ifdef DEBUG_ENABLED
- if (GDScriptLanguage::get_singleton()->lock) {
- GDScriptLanguage::get_singleton()->lock->lock();
- }
- GDScriptLanguage::get_singleton()->script_list.add(&script_list);
+ {
+ MutexLock lock(GDScriptLanguage::get_singleton()->lock);
- if (GDScriptLanguage::get_singleton()->lock) {
- GDScriptLanguage::get_singleton()->lock->unlock();
+ GDScriptLanguage::get_singleton()->script_list.add(&script_list);
}
#endif
}
@@ -954,13 +1038,10 @@ GDScript::~GDScript() {
_save_orphaned_subclasses();
#ifdef DEBUG_ENABLED
- if (GDScriptLanguage::get_singleton()->lock) {
- GDScriptLanguage::get_singleton()->lock->lock();
- }
- GDScriptLanguage::get_singleton()->script_list.remove(&script_list);
+ {
+ MutexLock lock(GDScriptLanguage::get_singleton()->lock);
- if (GDScriptLanguage::get_singleton()->lock) {
- GDScriptLanguage::get_singleton()->lock->unlock();
+ GDScriptLanguage::get_singleton()->script_list.remove(&script_list);
}
#endif
}
@@ -978,18 +1059,18 @@ bool GDScriptInstance::set(const StringName &p_name, const Variant &p_value) {
const GDScript::MemberInfo *member = &E->get();
if (member->setter) {
const Variant *val = &p_value;
- Variant::CallError err;
+ Callable::CallError err;
call(member->setter, &val, 1, err);
- if (err.error == Variant::CallError::CALL_OK) {
+ if (err.error == Callable::CallError::CALL_OK) {
return true; //function exists, call was successful
}
} else {
if (!member->data_type.is_type(p_value)) {
// Try conversion
- Variant::CallError ce;
+ Callable::CallError ce;
const Variant *value = &p_value;
Variant converted = Variant::construct(member->data_type.builtin_type, &value, 1, ce);
- if (ce.error == Variant::CallError::CALL_OK) {
+ if (ce.error == Callable::CallError::CALL_OK) {
members.write[member->index] = converted;
return true;
} else {
@@ -1012,9 +1093,9 @@ bool GDScriptInstance::set(const StringName &p_name, const Variant &p_value) {
Variant name = p_name;
const Variant *args[2] = { &name, &p_value };
- Variant::CallError err;
+ Callable::CallError err;
Variant ret = E->get()->call(this, (const Variant **)args, 2, err);
- if (err.error == Variant::CallError::CALL_OK && ret.get_type() == Variant::BOOL && ret.operator bool())
+ if (err.error == Callable::CallError::CALL_OK && ret.get_type() == Variant::BOOL && ret.operator bool())
return true;
}
sptr = sptr->_base;
@@ -1032,9 +1113,9 @@ bool GDScriptInstance::get(const StringName &p_name, Variant &r_ret) const {
const Map<StringName, GDScript::MemberInfo>::Element *E = script->member_indices.find(p_name);
if (E) {
if (E->get().getter) {
- Variant::CallError err;
+ Callable::CallError err;
r_ret = const_cast<GDScriptInstance *>(this)->call(E->get().getter, NULL, 0, err);
- if (err.error == Variant::CallError::CALL_OK) {
+ if (err.error == Callable::CallError::CALL_OK) {
return true;
}
}
@@ -1063,9 +1144,9 @@ bool GDScriptInstance::get(const StringName &p_name, Variant &r_ret) const {
Variant name = p_name;
const Variant *args[1] = { &name };
- Variant::CallError err;
+ Callable::CallError err;
Variant ret = const_cast<GDScriptFunction *>(E->get())->call(const_cast<GDScriptInstance *>(this), (const Variant **)args, 1, err);
- if (err.error == Variant::CallError::CALL_OK && ret.get_type() != Variant::NIL) {
+ if (err.error == Callable::CallError::CALL_OK && ret.get_type() != Variant::NIL) {
r_ret = ret;
return true;
}
@@ -1106,9 +1187,9 @@ void GDScriptInstance::get_property_list(List<PropertyInfo> *p_properties) const
const Map<StringName, GDScriptFunction *>::Element *E = sptr->member_functions.find(GDScriptLanguage::get_singleton()->strings._get_property_list);
if (E) {
- Variant::CallError err;
+ Callable::CallError err;
Variant ret = const_cast<GDScriptFunction *>(E->get())->call(const_cast<GDScriptInstance *>(this), NULL, 0, err);
- if (err.error == Variant::CallError::CALL_OK) {
+ if (err.error == Callable::CallError::CALL_OK) {
ERR_FAIL_COND_MSG(ret.get_type() != Variant::ARRAY, "Wrong type for _get_property_list, must be an array of dictionaries.");
@@ -1193,7 +1274,7 @@ bool GDScriptInstance::has_method(const StringName &p_method) const {
return false;
}
-Variant GDScriptInstance::call(const StringName &p_method, const Variant **p_args, int p_argcount, Variant::CallError &r_error) {
+Variant GDScriptInstance::call(const StringName &p_method, const Variant **p_args, int p_argcount, Callable::CallError &r_error) {
GDScript *sptr = script.ptr();
while (sptr) {
@@ -1203,14 +1284,14 @@ Variant GDScriptInstance::call(const StringName &p_method, const Variant **p_arg
}
sptr = sptr->_base;
}
- r_error.error = Variant::CallError::CALL_ERROR_INVALID_METHOD;
+ r_error.error = Callable::CallError::CALL_ERROR_INVALID_METHOD;
return Variant();
}
void GDScriptInstance::call_multilevel(const StringName &p_method, const Variant **p_args, int p_argcount) {
GDScript *sptr = script.ptr();
- Variant::CallError ce;
+ Callable::CallError ce;
while (sptr) {
Map<StringName, GDScriptFunction *>::Element *E = sptr->member_functions.find(p_method);
@@ -1226,7 +1307,7 @@ void GDScriptInstance::_ml_call_reversed(GDScript *sptr, const StringName &p_met
if (sptr->_base)
_ml_call_reversed(sptr->_base, p_method, p_args, p_argcount);
- Variant::CallError ce;
+ Callable::CallError ce;
Map<StringName, GDScriptFunction *>::Element *E = sptr->member_functions.find(p_method);
if (E) {
@@ -1251,9 +1332,9 @@ void GDScriptInstance::notification(int p_notification) {
while (sptr) {
Map<StringName, GDScriptFunction *>::Element *E = sptr->member_functions.find(GDScriptLanguage::get_singleton()->strings._notification);
if (E) {
- Variant::CallError err;
+ Callable::CallError err;
E->get()->call(this, args, 1, err);
- if (err.error != Variant::CallError::CALL_OK) {
+ if (err.error != Callable::CallError::CALL_OK) {
//print error about notification call
}
}
@@ -1263,9 +1344,9 @@ void GDScriptInstance::notification(int p_notification) {
String GDScriptInstance::to_string(bool *r_valid) {
if (has_method(CoreStringNames::get_singleton()->_to_string)) {
- Variant::CallError ce;
+ Callable::CallError ce;
Variant ret = call(CoreStringNames::get_singleton()->_to_string, NULL, 0, ce);
- if (ce.error == Variant::CallError::CALL_OK) {
+ if (ce.error == Callable::CallError::CALL_OK) {
if (ret.get_type() != Variant::STRING) {
if (r_valid)
*r_valid = false;
@@ -1291,40 +1372,44 @@ ScriptLanguage *GDScriptInstance::get_language() {
return GDScriptLanguage::get_singleton();
}
-MultiplayerAPI::RPCMode GDScriptInstance::get_rpc_mode(const StringName &p_method) const {
+Vector<ScriptNetData> GDScriptInstance::get_rpc_methods() const {
+ return script->get_rpc_methods();
+}
- const GDScript *cscript = script.ptr();
+uint16_t GDScriptInstance::get_rpc_method_id(const StringName &p_method) const {
+ return script->get_rpc_method_id(p_method);
+}
- while (cscript) {
- const Map<StringName, GDScriptFunction *>::Element *E = cscript->member_functions.find(p_method);
- if (E) {
+StringName GDScriptInstance::get_rpc_method(const uint16_t p_rpc_method_id) const {
+ return script->get_rpc_method(p_rpc_method_id);
+}
- if (E->get()->get_rpc_mode() != MultiplayerAPI::RPC_MODE_DISABLED) {
- return E->get()->get_rpc_mode();
- }
- }
- cscript = cscript->_base;
- }
+MultiplayerAPI::RPCMode GDScriptInstance::get_rpc_mode_by_id(const uint16_t p_rpc_method_id) const {
+ return script->get_rpc_mode_by_id(p_rpc_method_id);
+}
- return MultiplayerAPI::RPC_MODE_DISABLED;
+MultiplayerAPI::RPCMode GDScriptInstance::get_rpc_mode(const StringName &p_method) const {
+ return script->get_rpc_mode(p_method);
}
-MultiplayerAPI::RPCMode GDScriptInstance::get_rset_mode(const StringName &p_variable) const {
+Vector<ScriptNetData> GDScriptInstance::get_rset_properties() const {
+ return script->get_rset_properties();
+}
- const GDScript *cscript = script.ptr();
+uint16_t GDScriptInstance::get_rset_property_id(const StringName &p_variable) const {
+ return script->get_rset_property_id(p_variable);
+}
- while (cscript) {
- const Map<StringName, GDScript::MemberInfo>::Element *E = cscript->member_indices.find(p_variable);
- if (E) {
+StringName GDScriptInstance::get_rset_property(const uint16_t p_rset_member_id) const {
+ return script->get_rset_property(p_rset_member_id);
+}
- if (E->get().rpc_mode) {
- return E->get().rpc_mode;
- }
- }
- cscript = cscript->_base;
- }
+MultiplayerAPI::RPCMode GDScriptInstance::get_rset_mode_by_id(const uint16_t p_rset_member_id) const {
+ return script->get_rset_mode_by_id(p_rset_member_id);
+}
- return MultiplayerAPI::RPC_MODE_DISABLED;
+MultiplayerAPI::RPCMode GDScriptInstance::get_rset_mode(const StringName &p_variable) const {
+ return script->get_rset_mode(p_variable);
}
void GDScriptInstance::reload_members() {
@@ -1365,14 +1450,9 @@ GDScriptInstance::GDScriptInstance() {
GDScriptInstance::~GDScriptInstance() {
if (script.is_valid() && owner) {
-#ifndef NO_THREADS
- GDScriptLanguage::singleton->lock->lock();
-#endif
+ MutexLock lock(GDScriptLanguage::singleton->lock);
script->instances.erase(owner);
-#ifndef NO_THREADS
- GDScriptLanguage::singleton->lock->unlock();
-#endif
}
}
@@ -1473,9 +1553,7 @@ void GDScriptLanguage::finish() {
void GDScriptLanguage::profiling_start() {
#ifdef DEBUG_ENABLED
- if (lock) {
- lock->lock();
- }
+ MutexLock lock(this->lock);
SelfList<GDScriptFunction> *elem = function_list.first();
while (elem) {
@@ -1492,25 +1570,15 @@ void GDScriptLanguage::profiling_start() {
}
profiling = true;
- if (lock) {
- lock->unlock();
- }
-
#endif
}
void GDScriptLanguage::profiling_stop() {
#ifdef DEBUG_ENABLED
- if (lock) {
- lock->lock();
- }
+ MutexLock lock(this->lock);
profiling = false;
- if (lock) {
- lock->unlock();
- }
-
#endif
}
@@ -1518,9 +1586,8 @@ int GDScriptLanguage::profiling_get_accumulated_data(ProfilingInfo *p_info_arr,
int current = 0;
#ifdef DEBUG_ENABLED
- if (lock) {
- lock->lock();
- }
+
+ MutexLock lock(this->lock);
SelfList<GDScriptFunction> *elem = function_list.first();
while (elem) {
@@ -1533,11 +1600,6 @@ int GDScriptLanguage::profiling_get_accumulated_data(ProfilingInfo *p_info_arr,
elem = elem->next();
current++;
}
-
- if (lock) {
- lock->unlock();
- }
-
#endif
return current;
@@ -1548,9 +1610,7 @@ int GDScriptLanguage::profiling_get_frame_data(ProfilingInfo *p_info_arr, int p_
int current = 0;
#ifdef DEBUG_ENABLED
- if (lock) {
- lock->lock();
- }
+ MutexLock lock(this->lock);
SelfList<GDScriptFunction> *elem = function_list.first();
while (elem) {
@@ -1565,11 +1625,6 @@ int GDScriptLanguage::profiling_get_frame_data(ProfilingInfo *p_info_arr, int p_
}
elem = elem->next();
}
-
- if (lock) {
- lock->unlock();
- }
-
#endif
return current;
@@ -1600,23 +1655,18 @@ void GDScriptLanguage::reload_all_scripts() {
#ifdef DEBUG_ENABLED
print_verbose("GDScript: Reloading all scripts");
- if (lock) {
- lock->lock();
- }
-
List<Ref<GDScript> > scripts;
+ {
+ MutexLock lock(this->lock);
- SelfList<GDScript> *elem = script_list.first();
- while (elem) {
- if (elem->self()->get_path().is_resource_file()) {
- print_verbose("GDScript: Found: " + elem->self()->get_path());
- scripts.push_back(Ref<GDScript>(elem->self())); //cast to gdscript to avoid being erased by accident
+ SelfList<GDScript> *elem = script_list.first();
+ while (elem) {
+ if (elem->self()->get_path().is_resource_file()) {
+ print_verbose("GDScript: Found: " + elem->self()->get_path());
+ scripts.push_back(Ref<GDScript>(elem->self())); //cast to gdscript to avoid being erased by accident
+ }
+ elem = elem->next();
}
- elem = elem->next();
- }
-
- if (lock) {
- lock->unlock();
}
//as scripts are going to be reloaded, must proceed without locking here
@@ -1636,23 +1686,18 @@ void GDScriptLanguage::reload_tool_script(const Ref<Script> &p_script, bool p_so
#ifdef DEBUG_ENABLED
- if (lock) {
- lock->lock();
- }
-
List<Ref<GDScript> > scripts;
+ {
+ MutexLock lock(this->lock);
- SelfList<GDScript> *elem = script_list.first();
- while (elem) {
- if (elem->self()->get_path().is_resource_file()) {
+ SelfList<GDScript> *elem = script_list.first();
+ while (elem) {
+ if (elem->self()->get_path().is_resource_file()) {
- scripts.push_back(Ref<GDScript>(elem->self())); //cast to gdscript to avoid being erased by accident
+ scripts.push_back(Ref<GDScript>(elem->self())); //cast to gdscript to avoid being erased by accident
+ }
+ elem = elem->next();
}
- elem = elem->next();
- }
-
- if (lock) {
- lock->unlock();
}
//when someone asks you why dynamically typed languages are easier to write....
@@ -1685,7 +1730,7 @@ void GDScriptLanguage::reload_tool_script(const Ref<Script> &p_script, bool p_so
obj->get_script_instance()->get_property_state(state);
map[obj->get_instance_id()] = state;
- obj->set_script(RefPtr());
+ obj->set_script(Variant());
}
}
@@ -1701,7 +1746,7 @@ void GDScriptLanguage::reload_tool_script(const Ref<Script> &p_script, bool p_so
map.insert(obj->get_instance_id(), List<Pair<StringName, Variant> >());
List<Pair<StringName, Variant> > &state = map[obj->get_instance_id()];
obj->get_script_instance()->get_property_state(state);
- obj->set_script(RefPtr());
+ obj->set_script(Variant());
} else {
// no instance found. Let's remove it so we don't loop forever
E->get()->placeholders.erase(E->get()->placeholders.front()->get());
@@ -1732,9 +1777,9 @@ void GDScriptLanguage::reload_tool_script(const Ref<Script> &p_script, bool p_so
if (!p_soft_reload) {
//clear it just in case (may be a pending reload state)
- obj->set_script(RefPtr());
+ obj->set_script(Variant());
}
- obj->set_script(scr.get_ref_ptr());
+ obj->set_script(scr);
ScriptInstance *script_instance = obj->get_script_instance();
@@ -1772,9 +1817,7 @@ void GDScriptLanguage::frame() {
#ifdef DEBUG_ENABLED
if (profiling) {
- if (lock) {
- lock->lock();
- }
+ MutexLock lock(this->lock);
SelfList<GDScriptFunction> *elem = function_list.first();
while (elem) {
@@ -1786,10 +1829,6 @@ void GDScriptLanguage::frame() {
elem->self()->profile.frame_total_time = 0;
elem = elem->next();
}
-
- if (lock) {
- lock->unlock();
- }
}
#endif
@@ -1850,10 +1889,8 @@ void GDScriptLanguage::get_reserved_words(List<String> *p_words) const {
"match",
"while",
"remote",
- "sync",
"master",
"puppet",
- "slave",
"remotesync",
"mastersync",
"puppetsync",
@@ -1880,7 +1917,7 @@ bool GDScriptLanguage::handles_global_class_type(const String &p_type) const {
String GDScriptLanguage::get_global_class_name(const String &p_path, String *r_base_type, String *r_icon_path) const {
- PoolVector<uint8_t> sourcef;
+ Vector<uint8_t> sourcef;
Error err;
FileAccessRef f = FileAccess::open(p_path, FileAccess::READ, &err);
if (err) {
@@ -2157,11 +2194,6 @@ GDScriptLanguage::GDScriptLanguage() {
_debug_parse_err_line = -1;
_debug_parse_err_file = "";
-#ifdef NO_THREADS
- lock = NULL;
-#else
- lock = Mutex::create();
-#endif
profiling = false;
script_frame_time = 0;
@@ -2195,10 +2227,6 @@ GDScriptLanguage::GDScriptLanguage() {
GDScriptLanguage::~GDScriptLanguage() {
- if (lock) {
- memdelete(lock);
- lock = NULL;
- }
if (_call_stack) {
memdelete_arr(_call_stack);
}
@@ -2223,7 +2251,7 @@ Ref<GDScript> GDScriptLanguage::get_orphan_subclass(const String &p_qualified_na
/*************** RESOURCE ***************/
-RES ResourceFormatLoaderGDScript::load(const String &p_path, const String &p_original_path, Error *r_error) {
+RES ResourceFormatLoaderGDScript::load(const String &p_path, const String &p_original_path, Error *r_error, bool p_use_sub_threads, float *r_progress) {
if (r_error)
*r_error = ERR_FILE_CANT_OPEN;
diff --git a/modules/gdscript/gdscript.h b/modules/gdscript/gdscript.h
index 4ae52238ce..3a90f0fc20 100644
--- a/modules/gdscript/gdscript.h
+++ b/modules/gdscript/gdscript.h
@@ -73,7 +73,6 @@ class GDScript : public Script {
friend class GDScriptFunctions;
friend class GDScriptLanguage;
- Variant _static_ref; //used for static call
Ref<GDScriptNativeClass> native;
Ref<GDScript> base;
GDScript *_base; //fast pointer access
@@ -85,6 +84,8 @@ class GDScript : public Script {
Map<StringName, MemberInfo> member_indices; //members are just indices to the instanced script.
Map<StringName, Ref<GDScript> > subclasses;
Map<StringName, Vector<StringName> > _signals;
+ Vector<ScriptNetData> rpc_functions;
+ Vector<ScriptNetData> rpc_variables;
#ifdef TOOLS_ENABLED
@@ -114,7 +115,7 @@ class GDScript : public Script {
String fully_qualified_name;
SelfList<GDScript> script_list;
- GDScriptInstance *_create_instance(const Variant **p_args, int p_argcount, Object *p_owner, bool p_isref, Variant::CallError &r_error);
+ GDScriptInstance *_create_instance(const Variant **p_args, int p_argcount, Object *p_owner, bool p_isref, Callable::CallError &r_error);
void _set_subclass_path(Ref<GDScript> &p_sc, const String &p_path);
@@ -139,7 +140,7 @@ protected:
bool _set(const StringName &p_name, const Variant &p_value);
void _get_property_list(List<PropertyInfo> *p_properties) const;
- Variant call(const StringName &p_method, const Variant **p_args, int p_argcount, Variant::CallError &r_error);
+ Variant call(const StringName &p_method, const Variant **p_args, int p_argcount, Callable::CallError &r_error);
//void call_multilevel(const StringName& p_method,const Variant** p_args,int p_argcount);
static void _bind_methods();
@@ -168,7 +169,7 @@ public:
const Map<StringName, GDScriptFunction *> &debug_get_member_functions() const; //this is debug only
StringName debug_get_member_by_index(int p_idx) const;
- Variant _new(const Variant **p_args, int p_argcount, Variant::CallError &r_error);
+ Variant _new(const Variant **p_args, int p_argcount, Callable::CallError &r_error);
virtual bool can_instance() const;
virtual Ref<Script> get_base_script() const;
@@ -213,6 +214,18 @@ public:
virtual void get_constants(Map<StringName, Variant> *p_constants);
virtual void get_members(Set<StringName> *p_members);
+ virtual Vector<ScriptNetData> get_rpc_methods() const;
+ virtual uint16_t get_rpc_method_id(const StringName &p_method) const;
+ virtual StringName get_rpc_method(const uint16_t p_rpc_method_id) const;
+ virtual MultiplayerAPI::RPCMode get_rpc_mode_by_id(const uint16_t p_rpc_method_id) const;
+ virtual MultiplayerAPI::RPCMode get_rpc_mode(const StringName &p_method) const;
+
+ virtual Vector<ScriptNetData> get_rset_properties() const;
+ virtual uint16_t get_rset_property_id(const StringName &p_variable) const;
+ virtual StringName get_rset_property(const uint16_t p_variable_id) const;
+ virtual MultiplayerAPI::RPCMode get_rset_mode_by_id(const uint16_t p_variable_id) const;
+ virtual MultiplayerAPI::RPCMode get_rset_mode(const StringName &p_variable) const;
+
#ifdef TOOLS_ENABLED
virtual bool is_placeholder_fallback_enabled() const { return placeholder_fallback_enabled; }
#endif
@@ -227,6 +240,7 @@ class GDScriptInstance : public ScriptInstance {
friend class GDScriptFunctions;
friend class GDScriptCompiler;
+ ObjectID owner_id;
Object *owner;
Ref<GDScript> script;
#ifdef DEBUG_ENABLED
@@ -247,7 +261,7 @@ public:
virtual void get_method_list(List<MethodInfo> *p_list) const;
virtual bool has_method(const StringName &p_method) const;
- virtual Variant call(const StringName &p_method, const Variant **p_args, int p_argcount, Variant::CallError &r_error);
+ virtual Variant call(const StringName &p_method, const Variant **p_args, int p_argcount, Callable::CallError &r_error);
virtual void call_multilevel(const StringName &p_method, const Variant **p_args, int p_argcount);
virtual void call_multilevel_reversed(const StringName &p_method, const Variant **p_args, int p_argcount);
@@ -264,7 +278,16 @@ public:
void reload_members();
+ virtual Vector<ScriptNetData> get_rpc_methods() const;
+ virtual uint16_t get_rpc_method_id(const StringName &p_method) const;
+ virtual StringName get_rpc_method(const uint16_t p_rpc_method_id) const;
+ virtual MultiplayerAPI::RPCMode get_rpc_mode_by_id(const uint16_t p_rpc_method_id) const;
virtual MultiplayerAPI::RPCMode get_rpc_mode(const StringName &p_method) const;
+
+ virtual Vector<ScriptNetData> get_rset_properties() const;
+ virtual uint16_t get_rset_property_id(const StringName &p_variable) const;
+ virtual StringName get_rset_property(const uint16_t p_variable_id) const;
+ virtual MultiplayerAPI::RPCMode get_rset_mode_by_id(const uint16_t p_variable_id) const;
virtual MultiplayerAPI::RPCMode get_rset_mode(const StringName &p_variable) const;
GDScriptInstance();
@@ -346,7 +369,7 @@ class GDScriptLanguage : public ScriptLanguage {
friend class GDScriptInstance;
- Mutex *lock;
+ Mutex lock;
friend class GDScript;
@@ -463,7 +486,7 @@ public:
virtual bool supports_builtin_mode() const;
virtual bool can_inherit_from_file() { return true; }
virtual int find_function(const String &p_function, const String &p_code) const;
- virtual String make_function(const String &p_class, const String &p_name, const PoolStringArray &p_args) const;
+ virtual String make_function(const String &p_class, const String &p_name, const PackedStringArray &p_args) const;
virtual Error complete_code(const String &p_code, const String &p_path, Object *p_owner, List<ScriptCodeCompletionOption> *r_options, bool &r_forced, String &r_call_hint);
#ifdef TOOLS_ENABLED
virtual Error lookup_code(const String &p_code, const String &p_symbol, const String &p_path, Object *p_owner, LookupResult &r_result);
@@ -519,7 +542,7 @@ public:
class ResourceFormatLoaderGDScript : public ResourceFormatLoader {
public:
- virtual RES load(const String &p_path, const String &p_original_path = "", Error *r_error = NULL);
+ virtual RES load(const String &p_path, const String &p_original_path = "", Error *r_error = NULL, bool p_use_sub_threads = false, float *r_progress = nullptr);
virtual void get_recognized_extensions(List<String> *p_extensions) const;
virtual bool handles_type(const String &p_type) const;
virtual String get_resource_type(const String &p_path) const;
diff --git a/modules/gdscript/gdscript_compiler.cpp b/modules/gdscript/gdscript_compiler.cpp
index fba1b992ec..4bd425f999 100644
--- a/modules/gdscript/gdscript_compiler.cpp
+++ b/modules/gdscript/gdscript_compiler.cpp
@@ -2076,10 +2076,10 @@ Error GDScriptCompiler::_parse_class_blocks(GDScript *p_script, const GDScriptPa
/* STEP 2, INITIALIZE AND CONSTRUCT */
- Variant::CallError ce;
+ Callable::CallError ce;
p_script->initializer->call(instance, NULL, 0, ce);
- if (ce.error != Variant::CallError::CALL_OK) {
+ if (ce.error != Callable::CallError::CALL_OK) {
//well, tough luck, not goinna do anything here
}
}
diff --git a/modules/gdscript/gdscript_editor.cpp b/modules/gdscript/gdscript_editor.cpp
index 65c61cb57c..1bc1aae0d2 100644
--- a/modules/gdscript/gdscript_editor.cpp
+++ b/modules/gdscript/gdscript_editor.cpp
@@ -457,7 +457,7 @@ void GDScriptLanguage::get_public_constants(List<Pair<String, Variant> > *p_cons
p_constants->push_back(nan);
}
-String GDScriptLanguage::make_function(const String &p_class, const String &p_name, const PoolStringArray &p_args) const {
+String GDScriptLanguage::make_function(const String &p_class, const String &p_name, const PackedStringArray &p_args) const {
#ifdef TOOLS_ENABLED
bool th = EditorSettings::get_singleton()->get_setting("text_editor/completion/add_type_hints");
@@ -905,10 +905,10 @@ static bool _guess_expression_type(GDScriptCompletionContext &p_context, const G
argptr.push_back(&args[i]);
}
- Variant::CallError ce;
+ Callable::CallError ce;
Variant ret = mb->call(baseptr, (const Variant **)argptr.ptr(), argptr.size(), ce);
- if (ce.error == Variant::CallError::CALL_OK && ret.get_type() != Variant::NIL) {
+ if (ce.error == Callable::CallError::CALL_OK && ret.get_type() != Variant::NIL) {
if (ret.get_type() != Variant::OBJECT || ret.operator Object *() != NULL) {
r_type = _type_from_variant(ret);
found = true;
@@ -1060,7 +1060,7 @@ static bool _guess_expression_type(GDScriptCompletionContext &p_context, const G
StringName id = index.value;
found = _guess_identifier_type_from_base(c, base, id, r_type);
} else if (!found && index.type.kind == GDScriptParser::DataType::BUILTIN) {
- Variant::CallError err;
+ Callable::CallError err;
Variant base_val = Variant::construct(base.type.builtin_type, NULL, 0, err);
bool valid = false;
Variant res = base_val.get(index.value, &valid);
@@ -1114,7 +1114,7 @@ static bool _guess_expression_type(GDScriptCompletionContext &p_context, const G
break;
}
- Variant::CallError ce;
+ Callable::CallError ce;
bool v1_use_value = p1.value.get_type() != Variant::NIL && p1.value.get_type() != Variant::OBJECT;
Variant v1 = (v1_use_value) ? p1.value : Variant::construct(p1.type.builtin_type, NULL, 0, ce);
bool v2_use_value = p2.value.get_type() != Variant::NIL && p2.value.get_type() != Variant::OBJECT;
@@ -1124,7 +1124,7 @@ static bool _guess_expression_type(GDScriptCompletionContext &p_context, const G
v2 = 1;
v2_use_value = false;
}
- if (vop == Variant::OP_DIVIDE && v2.get_type() == Variant::REAL) {
+ if (vop == Variant::OP_DIVIDE && v2.get_type() == Variant::FLOAT) {
v2 = 1.0;
v2_use_value = false;
}
@@ -1533,10 +1533,10 @@ static bool _guess_identifier_type_from_base(GDScriptCompletionContext &p_contex
return false;
} break;
case GDScriptParser::DataType::BUILTIN: {
- Variant::CallError err;
+ Callable::CallError err;
Variant tmp = Variant::construct(base_type.builtin_type, NULL, 0, err);
- if (err.error != Variant::CallError::CALL_OK) {
+ if (err.error != Callable::CallError::CALL_OK) {
return false;
}
bool valid = false;
@@ -1703,9 +1703,9 @@ static bool _guess_method_return_type_from_base(GDScriptCompletionContext &p_con
return false;
} break;
case GDScriptParser::DataType::BUILTIN: {
- Variant::CallError err;
+ Callable::CallError err;
Variant tmp = Variant::construct(base_type.builtin_type, NULL, 0, err);
- if (err.error != Variant::CallError::CALL_OK) {
+ if (err.error != Callable::CallError::CALL_OK) {
return false;
}
@@ -2088,9 +2088,9 @@ static void _find_identifiers_in_base(const GDScriptCompletionContext &p_context
return;
} break;
case GDScriptParser::DataType::BUILTIN: {
- Variant::CallError err;
+ Callable::CallError err;
Variant tmp = Variant::construct(base_type.builtin_type, NULL, 0, err);
- if (err.error != Variant::CallError::CALL_OK) {
+ if (err.error != Callable::CallError::CALL_OK) {
return;
}
@@ -2172,9 +2172,9 @@ static void _find_identifiers(const GDScriptCompletionContext &p_context, bool p
}
static const char *_type_names[Variant::VARIANT_MAX] = {
- "null", "bool", "int", "float", "String", "Vector2", "Rect2", "Vector3", "Transform2D", "Plane", "Quat", "AABB", "Basis", "Transform",
- "Color", "NodePath", "RID", "Object", "Dictionary", "Array", "PoolByteArray", "PoolIntArray", "PoolRealArray", "PoolStringArray",
- "PoolVector2Array", "PoolVector3Array", "PoolColorArray"
+ "null", "bool", "int", "float", "String", "Vector2", "Vector2i", "Rect2", "Rect2i", "Vector3", "Vector3i", "Transform2D", "Plane", "Quat", "AABB", "Basis", "Transform",
+ "Color", "StringName", "NodePath", "RID", "Object", "Callable", "Signal", "Dictionary", "Array", "PackedByteArray", "PackedInt32Array", "PackedInt64Array", "PackedFloat32Array", "PackedFloat64Array", "PackedStringArray",
+ "PackedVector2Array", "PackedVector3Array", "PackedColorArray"
};
for (int i = 0; i < Variant::VARIANT_MAX; i++) {
@@ -2186,7 +2186,7 @@ static void _find_identifiers(const GDScriptCompletionContext &p_context, bool p
"and", "in", "not", "or", "false", "PI", "TAU", "INF", "NAN", "self", "true", "as", "assert",
"breakpoint", "class", "extends", "is", "func", "preload", "setget", "signal", "tool", "yield",
"const", "enum", "export", "onready", "static", "var", "break", "continue", "if", "elif",
- "else", "for", "pass", "return", "match", "while", "remote", "sync", "master", "puppet", "slave",
+ "else", "for", "pass", "return", "match", "while", "remote", "master", "puppet",
"remotesync", "mastersync", "puppetsync",
0
};
@@ -2372,9 +2372,9 @@ static void _find_call_arguments(const GDScriptCompletionContext &p_context, con
} break;
case GDScriptParser::DataType::BUILTIN: {
if (base.get_type() == Variant::NIL) {
- Variant::CallError err;
+ Callable::CallError err;
base = Variant::construct(base_type.builtin_type, NULL, 0, err);
- if (err.error != Variant::CallError::CALL_OK) {
+ if (err.error != Callable::CallError::CALL_OK) {
return;
}
}
@@ -2565,7 +2565,7 @@ Error GDScriptLanguage::complete_code(const String &p_code, const String &p_path
} break;
case GDScriptParser::COMPLETION_FUNCTION: {
is_function = true;
- FALLTHROUGH;
+ [[fallthrough]];
}
case GDScriptParser::COMPLETION_IDENTIFIER: {
_find_identifiers(context, is_function, options);
@@ -2608,7 +2608,7 @@ Error GDScriptLanguage::complete_code(const String &p_code, const String &p_path
} break;
case GDScriptParser::COMPLETION_METHOD: {
is_function = true;
- FALLTHROUGH;
+ [[fallthrough]];
}
case GDScriptParser::COMPLETION_INDEX: {
const GDScriptParser::Node *node = parser.get_completion_node();
@@ -3219,9 +3219,9 @@ static Error _lookup_symbol_from_base(const GDScriptParser::DataType &p_base, co
v_ref.instance();
v = v_ref;
} else {
- Variant::CallError err;
+ Callable::CallError err;
v = Variant::construct(base_type.builtin_type, NULL, 0, err);
- if (err.error != Variant::CallError::CALL_OK) {
+ if (err.error != Callable::CallError::CALL_OK) {
break;
}
}
@@ -3330,7 +3330,7 @@ Error GDScriptLanguage::lookup_code(const String &p_code, const String &p_symbol
case GDScriptParser::COMPLETION_PARENT_FUNCTION:
case GDScriptParser::COMPLETION_FUNCTION: {
is_function = true;
- FALLTHROUGH;
+ [[fallthrough]];
}
case GDScriptParser::COMPLETION_IDENTIFIER: {
@@ -3462,7 +3462,7 @@ Error GDScriptLanguage::lookup_code(const String &p_code, const String &p_symbol
} break;
case GDScriptParser::COMPLETION_METHOD: {
is_function = true;
- FALLTHROUGH;
+ [[fallthrough]];
}
case GDScriptParser::COMPLETION_INDEX: {
const GDScriptParser::Node *node = parser.get_completion_node();
diff --git a/modules/gdscript/gdscript_function.cpp b/modules/gdscript/gdscript_function.cpp
index 452b1933eb..79c550c81c 100644
--- a/modules/gdscript/gdscript_function.cpp
+++ b/modules/gdscript/gdscript_function.cpp
@@ -34,7 +34,7 @@
#include "gdscript.h"
#include "gdscript_functions.h"
-Variant *GDScriptFunction::_get_variant(int p_address, GDScriptInstance *p_instance, GDScript *p_script, Variant &self, Variant *p_stack, String &r_error) const {
+Variant *GDScriptFunction::_get_variant(int p_address, GDScriptInstance *p_instance, GDScript *p_script, Variant &self, Variant &static_ref, Variant *p_stack, String &r_error) const {
int address = p_address & ADDR_MASK;
@@ -52,7 +52,7 @@ Variant *GDScriptFunction::_get_variant(int p_address, GDScriptInstance *p_insta
} break;
case ADDR_TYPE_CLASS: {
- return &p_script->_static_ref;
+ return &static_ref;
} break;
case ADDR_TYPE_MEMBER: {
#ifdef DEBUG_ENABLED
@@ -137,18 +137,19 @@ static String _get_var_type(const Variant *p_var) {
String basestr;
if (p_var->get_type() == Variant::OBJECT) {
- Object *bobj = *p_var;
+ bool was_freed;
+ Object *bobj = p_var->get_validated_object_with_check(was_freed);
if (!bobj) {
- basestr = "null instance";
- } else {
- if (ObjectDB::instance_validate(bobj)) {
- if (bobj->get_script_instance())
- basestr = bobj->get_class() + " (" + bobj->get_script_instance()->get_script()->get_path().get_file() + ")";
- else
- basestr = bobj->get_class();
+ if (was_freed) {
+ basestr = "null instance";
} else {
- basestr = "previously freed instance";
+ basestr = "previously freed";
}
+ } else {
+ if (bobj->get_script_instance())
+ basestr = bobj->get_class() + " (" + bobj->get_script_instance()->get_script()->get_path().get_file() + ")";
+ else
+ basestr = bobj->get_class();
}
} else {
@@ -159,11 +160,11 @@ static String _get_var_type(const Variant *p_var) {
}
#endif // DEBUG_ENABLED
-String GDScriptFunction::_get_call_error(const Variant::CallError &p_err, const String &p_where, const Variant **argptrs) const {
+String GDScriptFunction::_get_call_error(const Callable::CallError &p_err, const String &p_where, const Variant **argptrs) const {
String err_text;
- if (p_err.error == Variant::CallError::CALL_ERROR_INVALID_ARGUMENT) {
+ if (p_err.error == Callable::CallError::CALL_ERROR_INVALID_ARGUMENT) {
int errorarg = p_err.argument;
// Handle the Object to Object case separately as we don't have further class details.
#ifdef DEBUG_ENABLED
@@ -172,15 +173,15 @@ String GDScriptFunction::_get_call_error(const Variant::CallError &p_err, const
} else
#endif // DEBUG_ENABLED
{
- err_text = "Invalid type in " + p_where + ". Cannot convert argument " + itos(errorarg + 1) + " from " + Variant::get_type_name(argptrs[errorarg]->get_type()) + " to " + Variant::get_type_name(p_err.expected) + ".";
+ err_text = "Invalid type in " + p_where + ". Cannot convert argument " + itos(errorarg + 1) + " from " + Variant::get_type_name(argptrs[errorarg]->get_type()) + " to " + Variant::get_type_name(Variant::Type(p_err.expected)) + ".";
}
- } else if (p_err.error == Variant::CallError::CALL_ERROR_TOO_MANY_ARGUMENTS) {
+ } else if (p_err.error == Callable::CallError::CALL_ERROR_TOO_MANY_ARGUMENTS) {
err_text = "Invalid call to " + p_where + ". Expected " + itos(p_err.argument) + " arguments.";
- } else if (p_err.error == Variant::CallError::CALL_ERROR_TOO_FEW_ARGUMENTS) {
+ } else if (p_err.error == Callable::CallError::CALL_ERROR_TOO_FEW_ARGUMENTS) {
err_text = "Invalid call to " + p_where + ". Expected " + itos(p_err.argument) + " arguments.";
- } else if (p_err.error == Variant::CallError::CALL_ERROR_INVALID_METHOD) {
+ } else if (p_err.error == Callable::CallError::CALL_ERROR_INVALID_METHOD) {
err_text = "Invalid call. Nonexistent " + p_where + ".";
- } else if (p_err.error == Variant::CallError::CALL_ERROR_INSTANCE_IS_NULL) {
+ } else if (p_err.error == Callable::CallError::CALL_ERROR_INSTANCE_IS_NULL) {
err_text = "Attempt to call " + p_where + " on a null instance.";
} else {
err_text = "Bug, call error: #" + itos(p_err.error);
@@ -257,7 +258,7 @@ String GDScriptFunction::_get_call_error(const Variant::CallError &p_err, const
#define OPCODE_OUT break
#endif
-Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_args, int p_argcount, Variant::CallError &r_err, CallState *p_state) {
+Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_args, int p_argcount, Callable::CallError &r_err, CallState *p_state) {
OPCODES_TABLE;
@@ -266,9 +267,10 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a
return Variant();
}
- r_err.error = Variant::CallError::CALL_OK;
+ r_err.error = Callable::CallError::CALL_OK;
Variant self;
+ Variant static_ref;
Variant retvalue;
Variant *stack = NULL;
Variant **call_args;
@@ -304,13 +306,13 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a
if (p_argcount > _argument_count) {
- r_err.error = Variant::CallError::CALL_ERROR_TOO_MANY_ARGUMENTS;
+ r_err.error = Callable::CallError::CALL_ERROR_TOO_MANY_ARGUMENTS;
r_err.argument = _argument_count;
return Variant();
} else if (p_argcount < _argument_count - _default_arg_count) {
- r_err.error = Variant::CallError::CALL_ERROR_TOO_FEW_ARGUMENTS;
+ r_err.error = Callable::CallError::CALL_ERROR_TOO_FEW_ARGUMENTS;
r_err.argument = _argument_count - _default_arg_count;
return Variant();
} else {
@@ -339,7 +341,7 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a
memnew_placement(&stack[i], Variant);
continue;
} else {
- r_err.error = Variant::CallError::CALL_ERROR_INVALID_ARGUMENT;
+ r_err.error = Callable::CallError::CALL_ERROR_INVALID_ARGUMENT;
r_err.argument = i;
r_err.expected = argument_types[i].kind == GDScriptDataType::BUILTIN ? argument_types[i].builtin_type : Variant::OBJECT;
return Variant();
@@ -403,10 +405,10 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a
#define CHECK_SPACE(m_space) \
GD_ERR_BREAK((ip + m_space) > _code_size)
-#define GET_VARIANT_PTR(m_v, m_code_ofs) \
- Variant *m_v; \
- m_v = _get_variant(_code_ptr[ip + m_code_ofs], p_instance, script, self, stack, err_text); \
- if (unlikely(!m_v)) \
+#define GET_VARIANT_PTR(m_v, m_code_ofs) \
+ Variant *m_v; \
+ m_v = _get_variant(_code_ptr[ip + m_code_ofs], p_instance, script, self, static_ref, stack, err_text); \
+ if (unlikely(!m_v)) \
OPCODE_BREAK;
#else
@@ -414,7 +416,7 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a
#define CHECK_SPACE(m_space)
#define GET_VARIANT_PTR(m_v, m_code_ofs) \
Variant *m_v; \
- m_v = _get_variant(_code_ptr[ip + m_code_ofs], p_instance, script, self, stack, err_text);
+ m_v = _get_variant(_code_ptr[ip + m_code_ofs], p_instance, script, self, static_ref, stack, err_text);
#endif
@@ -497,14 +499,26 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a
bool extends_ok = false;
if (a->get_type() == Variant::OBJECT && a->operator Object *() != NULL) {
- Object *obj_A = *a;
- Object *obj_B = *b;
#ifdef DEBUG_ENABLED
- if (!ObjectDB::instance_validate(obj_A)) {
- err_text = "Left operand of 'is' was already freed.";
+ bool was_freed;
+ Object *obj_A = a->get_validated_object_with_check(was_freed);
+
+ if (was_freed) {
+ err_text = "Left operand of 'is' is a previously freed instance.";
+ OPCODE_BREAK;
+ }
+
+ Object *obj_B = b->get_validated_object_with_check(was_freed);
+
+ if (was_freed) {
+ err_text = "Right operand of 'is' is a previously freed instance.";
OPCODE_BREAK;
}
+#else
+
+ Object *obj_A = *a;
+ Object *obj_B = *b;
#endif // DEBUG_ENABLED
GDScript *scr_B = Object::cast_to<GDScript>(obj_B);
@@ -778,7 +792,7 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a
#ifdef DEBUG_ENABLED
if (Variant::can_convert_strict(src->get_type(), var_type)) {
#endif // DEBUG_ENABLED
- Variant::CallError ce;
+ Callable::CallError ce;
*dst = Variant::construct(var_type, const_cast<const Variant **>(&src), 1, ce);
} else {
#ifdef DEBUG_ENABLED
@@ -884,11 +898,11 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a
GD_ERR_BREAK(to_type < 0 || to_type >= Variant::VARIANT_MAX);
- Variant::CallError err;
+ Callable::CallError err;
*dst = Variant::construct(to_type, (const Variant **)&src, 1, err);
#ifdef DEBUG_ENABLED
- if (err.error != Variant::CallError::CALL_OK) {
+ if (err.error != Callable::CallError::CALL_OK) {
err_text = "Invalid cast: could not convert value to '" + Variant::get_type_name(to_type) + "'.";
OPCODE_BREAK;
}
@@ -987,11 +1001,11 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a
}
GET_VARIANT_PTR(dst, 3 + argc);
- Variant::CallError err;
+ Callable::CallError err;
*dst = Variant::construct(t, (const Variant **)argptrs, argc, err);
#ifdef DEBUG_ENABLED
- if (err.error != Variant::CallError::CALL_OK) {
+ if (err.error != Callable::CallError::CALL_OK) {
err_text = _get_call_error(err, "'" + Variant::get_type_name(t) + "' constructor", (const Variant **)argptrs);
OPCODE_BREAK;
@@ -1078,7 +1092,7 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a
}
#endif
- Variant::CallError err;
+ Callable::CallError err;
if (call_ret) {
GET_VARIANT_PTR(ret, argc);
@@ -1092,7 +1106,7 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a
function_call_time += OS::get_singleton()->get_ticks_usec() - call_time;
}
- if (err.error != Variant::CallError::CALL_OK) {
+ if (err.error != Callable::CallError::CALL_OK) {
String methodstr = *methodname;
String basestr = _get_var_type(base);
@@ -1100,13 +1114,13 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a
if (methodstr == "call") {
if (argc >= 1) {
methodstr = String(*argptrs[0]) + " (via call)";
- if (err.error == Variant::CallError::CALL_ERROR_INVALID_ARGUMENT) {
+ if (err.error == Callable::CallError::CALL_ERROR_INVALID_ARGUMENT) {
err.argument += 1;
}
}
} else if (methodstr == "free") {
- if (err.error == Variant::CallError::CALL_ERROR_INVALID_METHOD) {
+ if (err.error == Callable::CallError::CALL_ERROR_INVALID_METHOD) {
if (base->is_ref()) {
err_text = "Attempted to free a reference.";
@@ -1147,12 +1161,12 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a
GET_VARIANT_PTR(dst, argc);
- Variant::CallError err;
+ Callable::CallError err;
GDScriptFunctions::call(func, (const Variant **)argptrs, argc, *dst, err);
#ifdef DEBUG_ENABLED
- if (err.error != Variant::CallError::CALL_OK) {
+ if (err.error != Callable::CallError::CALL_OK) {
String methodstr = GDScriptFunctions::get_func_name(func);
if (dst->get_type() == Variant::STRING) {
@@ -1210,7 +1224,7 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a
break;
}
- Variant::CallError err;
+ Callable::CallError err;
if (E) {
@@ -1221,23 +1235,23 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a
MethodBind *mb = ClassDB::get_method(gds->native->get_name(), *methodname);
if (!mb) {
- err.error = Variant::CallError::CALL_ERROR_INVALID_METHOD;
+ err.error = Callable::CallError::CALL_ERROR_INVALID_METHOD;
} else {
*dst = mb->call(p_instance->owner, (const Variant **)argptrs, argc, err);
}
} else {
- err.error = Variant::CallError::CALL_OK;
+ err.error = Callable::CallError::CALL_OK;
}
} else {
if (*methodname != GDScriptLanguage::get_singleton()->strings._init) {
- err.error = Variant::CallError::CALL_ERROR_INVALID_METHOD;
+ err.error = Callable::CallError::CALL_ERROR_INVALID_METHOD;
} else {
- err.error = Variant::CallError::CALL_OK;
+ err.error = Callable::CallError::CALL_OK;
}
}
- if (err.error != Variant::CallError::CALL_OK) {
+ if (err.error != Callable::CallError::CALL_OK) {
String methodstr = *methodname;
err_text = _get_call_error(err, "function '" + methodstr + "'", (const Variant **)argptrs);
@@ -1274,7 +1288,7 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a
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;
+ gdfs->state.instance_id = (p_instance && p_instance->get_owner()) ? p_instance->get_owner()->get_instance_id() : ObjectID();
//gdfs->state.result_pos=ip+ipofs-1;
gdfs->state.defarg = defarg;
gdfs->state.instance = p_instance;
@@ -1298,33 +1312,36 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a
}
#endif
- Object *obj = argobj->operator Object *();
+#ifdef DEBUG_ENABLED
+ bool was_freed;
+ Object *obj = argobj->get_validated_object_with_check(was_freed);
String signal = argname->operator String();
-#ifdef DEBUG_ENABLED
+ if (was_freed) {
+ err_text = "First argument of yield() is a previously freed instance.";
+ OPCODE_BREAK;
+ }
+
if (!obj) {
err_text = "First argument of yield() is null.";
OPCODE_BREAK;
}
- if (ScriptDebugger::get_singleton()) {
- if (!ObjectDB::instance_validate(obj)) {
- err_text = "First argument of yield() is a previously freed instance.";
- OPCODE_BREAK;
- }
- }
if (signal.length() == 0) {
err_text = "Second argument of yield() is an empty string (for signal name).";
OPCODE_BREAK;
}
- Error err = obj->connect(signal, gdfs.ptr(), "_signal_callback", varray(gdfs), Object::CONNECT_ONESHOT);
+ Error err = obj->connect_compat(signal, gdfs.ptr(), "_signal_callback", varray(gdfs), Object::CONNECT_ONESHOT);
if (err != OK) {
err_text = "Error connecting to signal: " + signal + " during yield().";
OPCODE_BREAK;
}
#else
- obj->connect(signal, gdfs.ptr(), "_signal_callback", varray(gdfs), Object::CONNECT_ONESHOT);
+ Object *obj = argobj->operator Object *();
+ String signal = argname->operator String();
+
+ obj->connect_compat(signal, gdfs.ptr(), "_signal_callback", varray(gdfs), Object::CONNECT_ONESHOT);
#endif
}
@@ -1565,14 +1582,14 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a
//error
// function, file, line, error, explanation
String err_file;
- if (p_instance && ObjectDB::instance_validate(p_instance->owner) && p_instance->script->is_valid() && p_instance->script->path != "")
+ if (p_instance && ObjectDB::get_instance(p_instance->owner_id) != nullptr && p_instance->script->is_valid() && p_instance->script->path != "")
err_file = p_instance->script->path;
else if (script)
err_file = script->path;
if (err_file == "")
err_file = "<built-in>";
String err_func = name;
- if (p_instance && ObjectDB::instance_validate(p_instance->owner) && p_instance->script->is_valid() && p_instance->script->name != "")
+ if (p_instance && ObjectDB::get_instance(p_instance->owner_id) != nullptr && p_instance->script->is_valid() && p_instance->script->name != "")
err_func = p_instance->script->name + "." + err_func;
int err_line = line;
if (err_text == "") {
@@ -1752,13 +1769,10 @@ GDScriptFunction::GDScriptFunction() :
#ifdef DEBUG_ENABLED
_func_cname = NULL;
- if (GDScriptLanguage::get_singleton()->lock) {
- GDScriptLanguage::get_singleton()->lock->lock();
- }
- GDScriptLanguage::get_singleton()->function_list.add(&function_list);
+ {
+ MutexLock lock(GDScriptLanguage::get_singleton()->lock);
- if (GDScriptLanguage::get_singleton()->lock) {
- GDScriptLanguage::get_singleton()->lock->unlock();
+ GDScriptLanguage::get_singleton()->function_list.add(&function_list);
}
profile.call_count = 0;
@@ -1776,26 +1790,22 @@ GDScriptFunction::GDScriptFunction() :
GDScriptFunction::~GDScriptFunction() {
#ifdef DEBUG_ENABLED
- if (GDScriptLanguage::get_singleton()->lock) {
- GDScriptLanguage::get_singleton()->lock->lock();
- }
- GDScriptLanguage::get_singleton()->function_list.remove(&function_list);
- if (GDScriptLanguage::get_singleton()->lock) {
- GDScriptLanguage::get_singleton()->lock->unlock();
- }
+ MutexLock lock(GDScriptLanguage::get_singleton()->lock);
+
+ GDScriptLanguage::get_singleton()->function_list.remove(&function_list);
#endif
}
/////////////////////
-Variant GDScriptFunctionState::_signal_callback(const Variant **p_args, int p_argcount, Variant::CallError &r_error) {
+Variant GDScriptFunctionState::_signal_callback(const Variant **p_args, int p_argcount, Callable::CallError &r_error) {
Variant arg;
- r_error.error = Variant::CallError::CALL_OK;
+ r_error.error = Callable::CallError::CALL_OK;
if (p_argcount == 0) {
- r_error.error = Variant::CallError::CALL_ERROR_TOO_FEW_ARGUMENTS;
+ r_error.error = Callable::CallError::CALL_ERROR_TOO_FEW_ARGUMENTS;
r_error.argument = 1;
return Variant();
} else if (p_argcount == 1) {
@@ -1813,7 +1823,7 @@ Variant GDScriptFunctionState::_signal_callback(const Variant **p_args, int p_ar
Ref<GDScriptFunctionState> self = *p_args[p_argcount - 1];
if (self.is_null()) {
- r_error.error = Variant::CallError::CALL_ERROR_INVALID_ARGUMENT;
+ r_error.error = Callable::CallError::CALL_ERROR_INVALID_ARGUMENT;
r_error.argument = p_argcount - 1;
r_error.expected = Variant::OBJECT;
return Variant();
@@ -1829,7 +1839,7 @@ bool GDScriptFunctionState::is_valid(bool p_extended_check) const {
if (p_extended_check) {
//class instance gone?
- if (state.instance_id && !ObjectDB::get_instance(state.instance_id))
+ if (state.instance_id.is_valid() && !ObjectDB::get_instance(state.instance_id))
return false;
}
@@ -1839,7 +1849,7 @@ bool GDScriptFunctionState::is_valid(bool p_extended_check) const {
Variant GDScriptFunctionState::resume(const Variant &p_arg) {
ERR_FAIL_COND_V(!function, Variant());
- if (state.instance_id && !ObjectDB::get_instance(state.instance_id)) {
+ if (state.instance_id.is_valid() && !ObjectDB::get_instance(state.instance_id)) {
#ifdef DEBUG_ENABLED
ERR_FAIL_V_MSG(Variant(), "Resumed function '" + String(function->get_name()) + "()' after yield, but class instance is gone. At script: " + state.script->get_path() + ":" + itos(state.line));
#else
@@ -1848,7 +1858,7 @@ Variant GDScriptFunctionState::resume(const Variant &p_arg) {
}
state.result = p_arg;
- Variant::CallError err;
+ Callable::CallError err;
Variant ret = function->call(NULL, NULL, 0, err, &state);
bool completed = true;
diff --git a/modules/gdscript/gdscript_function.h b/modules/gdscript/gdscript_function.h
index ad95ebc543..34019e563d 100644
--- a/modules/gdscript/gdscript_function.h
+++ b/modules/gdscript/gdscript_function.h
@@ -77,8 +77,8 @@ struct GDScriptDataType {
return false;
}
- Object *obj = p_variant.operator Object *();
- if (!obj || !ObjectDB::instance_validate(obj)) {
+ Object *obj = p_variant.get_validated_object();
+ if (!obj) {
return false;
}
@@ -100,8 +100,8 @@ struct GDScriptDataType {
return false;
}
- Object *obj = p_variant.operator Object *();
- if (!obj || !ObjectDB::instance_validate(obj)) {
+ Object *obj = p_variant.get_validated_object();
+ if (!obj) {
return false;
}
@@ -265,8 +265,8 @@ private:
List<StackDebug> stack_debug;
- _FORCE_INLINE_ Variant *_get_variant(int p_address, GDScriptInstance *p_instance, GDScript *p_script, Variant &self, Variant *p_stack, String &r_error) const;
- _FORCE_INLINE_ String _get_call_error(const Variant::CallError &p_err, const String &p_where, const Variant **argptrs) const;
+ _FORCE_INLINE_ Variant *_get_variant(int p_address, GDScriptInstance *p_instance, GDScript *p_script, Variant &self, Variant &static_ref, Variant *p_stack, String &r_error) const;
+ _FORCE_INLINE_ String _get_call_error(const Callable::CallError &p_err, const String &p_where, const Variant **argptrs) const;
friend class GDScriptLanguage;
@@ -339,7 +339,7 @@ public:
return default_arguments[p_idx];
}
- Variant call(GDScriptInstance *p_instance, const Variant **p_args, int p_argcount, Variant::CallError &r_err, CallState *p_state = NULL);
+ Variant call(GDScriptInstance *p_instance, const Variant **p_args, int p_argcount, Callable::CallError &r_err, CallState *p_state = NULL);
_FORCE_INLINE_ MultiplayerAPI::RPCMode get_rpc_mode() const { return rpc_mode; }
GDScriptFunction();
@@ -352,7 +352,7 @@ class GDScriptFunctionState : public Reference {
friend class GDScriptFunction;
GDScriptFunction *function;
GDScriptFunction::CallState state;
- Variant _signal_callback(const Variant **p_args, int p_argcount, Variant::CallError &r_error);
+ Variant _signal_callback(const Variant **p_args, int p_argcount, Callable::CallError &r_error);
Ref<GDScriptFunctionState> first_state;
protected:
diff --git a/modules/gdscript/gdscript_functions.cpp b/modules/gdscript/gdscript_functions.cpp
index 01d62a1c62..aaa308f40f 100644
--- a/modules/gdscript/gdscript_functions.cpp
+++ b/modules/gdscript/gdscript_functions.cpp
@@ -72,7 +72,6 @@ const char *GDScriptFunctions::get_func_name(Function p_func) {
"is_equal_approx",
"is_zero_approx",
"ease",
- "decimals",
"step_decimals",
"stepify",
"lerp",
@@ -140,32 +139,32 @@ const char *GDScriptFunctions::get_func_name(Function p_func) {
return _names[p_func];
}
-void GDScriptFunctions::call(Function p_func, const Variant **p_args, int p_arg_count, Variant &r_ret, Variant::CallError &r_error) {
+void GDScriptFunctions::call(Function p_func, const Variant **p_args, int p_arg_count, Variant &r_ret, Callable::CallError &r_error) {
- r_error.error = Variant::CallError::CALL_OK;
+ r_error.error = Callable::CallError::CALL_OK;
#ifdef DEBUG_ENABLED
-#define VALIDATE_ARG_COUNT(m_count) \
- if (p_arg_count < m_count) { \
- r_error.error = Variant::CallError::CALL_ERROR_TOO_FEW_ARGUMENTS; \
- r_error.argument = m_count; \
- r_ret = Variant(); \
- return; \
- } \
- if (p_arg_count > m_count) { \
- r_error.error = Variant::CallError::CALL_ERROR_TOO_MANY_ARGUMENTS; \
- r_error.argument = m_count; \
- r_ret = Variant(); \
- return; \
+#define VALIDATE_ARG_COUNT(m_count) \
+ if (p_arg_count < m_count) { \
+ r_error.error = Callable::CallError::CALL_ERROR_TOO_FEW_ARGUMENTS; \
+ r_error.argument = m_count; \
+ r_ret = Variant(); \
+ return; \
+ } \
+ if (p_arg_count > m_count) { \
+ r_error.error = Callable::CallError::CALL_ERROR_TOO_MANY_ARGUMENTS; \
+ r_error.argument = m_count; \
+ r_ret = Variant(); \
+ return; \
}
-#define VALIDATE_ARG_NUM(m_arg) \
- if (!p_args[m_arg]->is_num()) { \
- r_error.error = Variant::CallError::CALL_ERROR_INVALID_ARGUMENT; \
- r_error.argument = m_arg; \
- r_error.expected = Variant::REAL; \
- r_ret = Variant(); \
- return; \
+#define VALIDATE_ARG_NUM(m_arg) \
+ if (!p_args[m_arg]->is_num()) { \
+ r_error.error = Callable::CallError::CALL_ERROR_INVALID_ARGUMENT; \
+ r_error.argument = m_arg; \
+ r_error.expected = Variant::FLOAT; \
+ r_ret = Variant(); \
+ return; \
}
#else
@@ -273,15 +272,15 @@ void GDScriptFunctions::call(Function p_func, const Variant **p_args, int p_arg_
int64_t i = *p_args[0];
r_ret = ABS(i);
- } else if (p_args[0]->get_type() == Variant::REAL) {
+ } else if (p_args[0]->get_type() == Variant::FLOAT) {
double r = *p_args[0];
r_ret = Math::abs(r);
} else {
- r_error.error = Variant::CallError::CALL_ERROR_INVALID_ARGUMENT;
+ r_error.error = Callable::CallError::CALL_ERROR_INVALID_ARGUMENT;
r_error.argument = 0;
- r_error.expected = Variant::REAL;
+ r_error.expected = Variant::FLOAT;
r_ret = Variant();
}
} break;
@@ -291,15 +290,15 @@ void GDScriptFunctions::call(Function p_func, const Variant **p_args, int p_arg_
int64_t i = *p_args[0];
r_ret = i < 0 ? -1 : (i > 0 ? +1 : 0);
- } else if (p_args[0]->get_type() == Variant::REAL) {
+ } else if (p_args[0]->get_type() == Variant::FLOAT) {
real_t r = *p_args[0];
r_ret = r < 0.0 ? -1.0 : (r > 0.0 ? +1.0 : 0.0);
} else {
- r_error.error = Variant::CallError::CALL_ERROR_INVALID_ARGUMENT;
+ r_error.error = Callable::CallError::CALL_ERROR_INVALID_ARGUMENT;
r_error.argument = 0;
- r_error.expected = Variant::REAL;
+ r_error.expected = Variant::FLOAT;
r_ret = Variant();
}
} break;
@@ -346,12 +345,6 @@ void GDScriptFunctions::call(Function p_func, const Variant **p_args, int p_arg_
VALIDATE_ARG_NUM(1);
r_ret = Math::ease((double)*p_args[0], (double)*p_args[1]);
} break;
- case MATH_DECIMALS: {
- VALIDATE_ARG_COUNT(1);
- VALIDATE_ARG_NUM(0);
- r_ret = Math::step_decimals((double)*p_args[0]);
- WARN_DEPRECATED_MSG("GDScript method 'decimals' is deprecated and has been renamed to 'step_decimals', please update your code accordingly.");
- } break;
case MATH_STEP_DECIMALS: {
VALIDATE_ARG_COUNT(1);
VALIDATE_ARG_NUM(0);
@@ -367,12 +360,12 @@ void GDScriptFunctions::call(Function p_func, const Variant **p_args, int p_arg_
VALIDATE_ARG_COUNT(3);
VALIDATE_ARG_NUM(2);
const double t = (double)*p_args[2];
- switch (p_args[0]->get_type() == p_args[1]->get_type() ? p_args[0]->get_type() : Variant::REAL) {
+ switch (p_args[0]->get_type() == p_args[1]->get_type() ? p_args[0]->get_type() : Variant::FLOAT) {
case Variant::VECTOR2: {
r_ret = ((Vector2)*p_args[0]).linear_interpolate((Vector2)*p_args[1], t);
} break;
case Variant::VECTOR3: {
- r_ret = ((Vector3)*p_args[0]).linear_interpolate((Vector3)*p_args[1], t);
+ r_ret = (p_args[0]->operator Vector3()).linear_interpolate(p_args[1]->operator Vector3(), t);
} break;
case Variant::COLOR: {
r_ret = ((Color)*p_args[0]).linear_interpolate((Color)*p_args[1], t);
@@ -592,7 +585,7 @@ void GDScriptFunctions::call(Function p_func, const Variant **p_args, int p_arg_
Ref<WeakRef> wref = memnew(WeakRef);
r_ret = wref;
} else {
- r_error.error = Variant::CallError::CALL_ERROR_INVALID_ARGUMENT;
+ r_error.error = Callable::CallError::CALL_ERROR_INVALID_ARGUMENT;
r_error.argument = 0;
r_error.expected = Variant::OBJECT;
r_ret = Variant();
@@ -603,7 +596,7 @@ void GDScriptFunctions::call(Function p_func, const Variant **p_args, int p_arg_
VALIDATE_ARG_COUNT(2);
if (p_args[0]->get_type() != Variant::OBJECT) {
- r_error.error = Variant::CallError::CALL_ERROR_INVALID_ARGUMENT;
+ r_error.error = Callable::CallError::CALL_ERROR_INVALID_ARGUMENT;
r_error.argument = 0;
r_error.expected = Variant::OBJECT;
r_ret = Variant();
@@ -611,7 +604,7 @@ void GDScriptFunctions::call(Function p_func, const Variant **p_args, int p_arg_
}
if (p_args[1]->get_type() != Variant::STRING && p_args[1]->get_type() != Variant::NODE_PATH) {
- r_error.error = Variant::CallError::CALL_ERROR_INVALID_ARGUMENT;
+ r_error.error = Callable::CallError::CALL_ERROR_INVALID_ARGUMENT;
r_error.argument = 1;
r_error.expected = Variant::STRING;
r_ret = Variant();
@@ -633,7 +626,7 @@ void GDScriptFunctions::call(Function p_func, const Variant **p_args, int p_arg_
if (type < 0 || type >= Variant::VARIANT_MAX) {
r_ret = RTR("Invalid type argument to convert(), use TYPE_* constants.");
- r_error.error = Variant::CallError::CALL_ERROR_INVALID_ARGUMENT;
+ r_error.error = Callable::CallError::CALL_ERROR_INVALID_ARGUMENT;
r_error.argument = 0;
r_error.expected = Variant::INT;
return;
@@ -667,7 +660,7 @@ void GDScriptFunctions::call(Function p_func, const Variant **p_args, int p_arg_
if (p_args[0]->get_type() != Variant::STRING) {
- r_error.error = Variant::CallError::CALL_ERROR_INVALID_ARGUMENT;
+ r_error.error = Callable::CallError::CALL_ERROR_INVALID_ARGUMENT;
r_error.argument = 0;
r_error.expected = Variant::STRING;
r_ret = Variant();
@@ -678,7 +671,7 @@ void GDScriptFunctions::call(Function p_func, const Variant **p_args, int p_arg_
if (str.length() != 1) {
- r_error.error = Variant::CallError::CALL_ERROR_INVALID_ARGUMENT;
+ r_error.error = Callable::CallError::CALL_ERROR_INVALID_ARGUMENT;
r_error.argument = 0;
r_error.expected = Variant::STRING;
r_ret = RTR("Expected a string of length 1 (a character).");
@@ -690,7 +683,7 @@ void GDScriptFunctions::call(Function p_func, const Variant **p_args, int p_arg_
} break;
case TEXT_STR: {
if (p_arg_count < 1) {
- r_error.error = Variant::CallError::CALL_ERROR_TOO_FEW_ARGUMENTS;
+ r_error.error = Callable::CallError::CALL_ERROR_TOO_FEW_ARGUMENTS;
r_error.argument = 1;
r_ret = Variant();
@@ -792,7 +785,7 @@ void GDScriptFunctions::call(Function p_func, const Variant **p_args, int p_arg_
case PUSH_ERROR: {
VALIDATE_ARG_COUNT(1);
if (p_args[0]->get_type() != Variant::STRING) {
- r_error.error = Variant::CallError::CALL_ERROR_INVALID_ARGUMENT;
+ r_error.error = Callable::CallError::CALL_ERROR_INVALID_ARGUMENT;
r_error.argument = 0;
r_error.expected = Variant::STRING;
r_ret = Variant();
@@ -800,13 +793,13 @@ void GDScriptFunctions::call(Function p_func, const Variant **p_args, int p_arg_
}
String message = *p_args[0];
- ERR_PRINTS(message);
+ ERR_PRINT(message);
r_ret = Variant();
} break;
case PUSH_WARNING: {
VALIDATE_ARG_COUNT(1);
if (p_args[0]->get_type() != Variant::STRING) {
- r_error.error = Variant::CallError::CALL_ERROR_INVALID_ARGUMENT;
+ r_error.error = Callable::CallError::CALL_ERROR_INVALID_ARGUMENT;
r_error.argument = 0;
r_error.expected = Variant::STRING;
r_ret = Variant();
@@ -814,7 +807,7 @@ void GDScriptFunctions::call(Function p_func, const Variant **p_args, int p_arg_
}
String message = *p_args[0];
- WARN_PRINTS(message);
+ WARN_PRINT(message);
r_ret = Variant();
} break;
case VAR_TO_STR: {
@@ -826,7 +819,7 @@ void GDScriptFunctions::call(Function p_func, const Variant **p_args, int p_arg_
case STR_TO_VAR: {
VALIDATE_ARG_COUNT(1);
if (p_args[0]->get_type() != Variant::STRING) {
- r_error.error = Variant::CallError::CALL_ERROR_INVALID_ARGUMENT;
+ r_error.error = Callable::CallError::CALL_ERROR_INVALID_ARGUMENT;
r_error.argument = 0;
r_error.expected = Variant::STRING;
r_ret = Variant();
@@ -844,17 +837,17 @@ void GDScriptFunctions::call(Function p_func, const Variant **p_args, int p_arg_
case VAR_TO_BYTES: {
bool full_objects = false;
if (p_arg_count < 1) {
- r_error.error = Variant::CallError::CALL_ERROR_TOO_FEW_ARGUMENTS;
+ r_error.error = Callable::CallError::CALL_ERROR_TOO_FEW_ARGUMENTS;
r_error.argument = 1;
r_ret = Variant();
return;
} else if (p_arg_count > 2) {
- r_error.error = Variant::CallError::CALL_ERROR_TOO_MANY_ARGUMENTS;
+ r_error.error = Callable::CallError::CALL_ERROR_TOO_MANY_ARGUMENTS;
r_error.argument = 2;
r_ret = Variant();
} else if (p_arg_count == 2) {
if (p_args[1]->get_type() != Variant::BOOL) {
- r_error.error = Variant::CallError::CALL_ERROR_INVALID_ARGUMENT;
+ r_error.error = Callable::CallError::CALL_ERROR_INVALID_ARGUMENT;
r_error.argument = 1;
r_error.expected = Variant::BOOL;
r_ret = Variant();
@@ -863,11 +856,11 @@ void GDScriptFunctions::call(Function p_func, const Variant **p_args, int p_arg_
full_objects = *p_args[1];
}
- PoolByteArray barr;
+ PackedByteArray barr;
int len;
Error err = encode_variant(*p_args[0], NULL, len, full_objects);
if (err) {
- r_error.error = Variant::CallError::CALL_ERROR_INVALID_ARGUMENT;
+ r_error.error = Callable::CallError::CALL_ERROR_INVALID_ARGUMENT;
r_error.argument = 0;
r_error.expected = Variant::NIL;
r_ret = "Unexpected error encoding variable to bytes, likely unserializable type found (Object or RID).";
@@ -876,25 +869,25 @@ void GDScriptFunctions::call(Function p_func, const Variant **p_args, int p_arg_
barr.resize(len);
{
- PoolByteArray::Write w = barr.write();
- encode_variant(*p_args[0], w.ptr(), len, full_objects);
+ uint8_t *w = barr.ptrw();
+ encode_variant(*p_args[0], w, len, full_objects);
}
r_ret = barr;
} break;
case BYTES_TO_VAR: {
bool allow_objects = false;
if (p_arg_count < 1) {
- r_error.error = Variant::CallError::CALL_ERROR_TOO_FEW_ARGUMENTS;
+ r_error.error = Callable::CallError::CALL_ERROR_TOO_FEW_ARGUMENTS;
r_error.argument = 1;
r_ret = Variant();
return;
} else if (p_arg_count > 2) {
- r_error.error = Variant::CallError::CALL_ERROR_TOO_MANY_ARGUMENTS;
+ r_error.error = Callable::CallError::CALL_ERROR_TOO_MANY_ARGUMENTS;
r_error.argument = 2;
r_ret = Variant();
} else if (p_arg_count == 2) {
if (p_args[1]->get_type() != Variant::BOOL) {
- r_error.error = Variant::CallError::CALL_ERROR_INVALID_ARGUMENT;
+ r_error.error = Callable::CallError::CALL_ERROR_INVALID_ARGUMENT;
r_error.argument = 1;
r_error.expected = Variant::BOOL;
r_ret = Variant();
@@ -903,24 +896,24 @@ void GDScriptFunctions::call(Function p_func, const Variant **p_args, int p_arg_
allow_objects = *p_args[1];
}
- if (p_args[0]->get_type() != Variant::POOL_BYTE_ARRAY) {
- r_error.error = Variant::CallError::CALL_ERROR_INVALID_ARGUMENT;
+ if (p_args[0]->get_type() != Variant::PACKED_BYTE_ARRAY) {
+ r_error.error = Callable::CallError::CALL_ERROR_INVALID_ARGUMENT;
r_error.argument = 1;
- r_error.expected = Variant::POOL_BYTE_ARRAY;
+ r_error.expected = Variant::PACKED_BYTE_ARRAY;
r_ret = Variant();
return;
}
- PoolByteArray varr = *p_args[0];
+ PackedByteArray varr = *p_args[0];
Variant ret;
{
- PoolByteArray::Read r = varr.read();
- Error err = decode_variant(ret, r.ptr(), varr.size(), NULL, allow_objects);
+ const uint8_t *r = varr.ptr();
+ Error err = decode_variant(ret, r, varr.size(), NULL, allow_objects);
if (err != OK) {
r_ret = RTR("Not enough bytes for decoding bytes, or invalid format.");
- r_error.error = Variant::CallError::CALL_ERROR_INVALID_ARGUMENT;
+ r_error.error = Callable::CallError::CALL_ERROR_INVALID_ARGUMENT;
r_error.argument = 0;
- r_error.expected = Variant::POOL_BYTE_ARRAY;
+ r_error.expected = Variant::PACKED_BYTE_ARRAY;
return;
}
}
@@ -934,7 +927,7 @@ void GDScriptFunctions::call(Function p_func, const Variant **p_args, int p_arg_
case 0: {
- r_error.error = Variant::CallError::CALL_ERROR_TOO_FEW_ARGUMENTS;
+ r_error.error = Callable::CallError::CALL_ERROR_TOO_FEW_ARGUMENTS;
r_error.argument = 1;
r_ret = Variant();
@@ -950,7 +943,7 @@ void GDScriptFunctions::call(Function p_func, const Variant **p_args, int p_arg_
}
Error err = arr.resize(count);
if (err != OK) {
- r_error.error = Variant::CallError::CALL_ERROR_INVALID_METHOD;
+ r_error.error = Callable::CallError::CALL_ERROR_INVALID_METHOD;
r_ret = Variant();
return;
}
@@ -976,7 +969,7 @@ void GDScriptFunctions::call(Function p_func, const Variant **p_args, int p_arg_
}
Error err = arr.resize(to - from);
if (err != OK) {
- r_error.error = Variant::CallError::CALL_ERROR_INVALID_METHOD;
+ r_error.error = Callable::CallError::CALL_ERROR_INVALID_METHOD;
r_ret = Variant();
return;
}
@@ -996,7 +989,7 @@ void GDScriptFunctions::call(Function p_func, const Variant **p_args, int p_arg_
if (incr == 0) {
r_ret = RTR("Step argument is zero!");
- r_error.error = Variant::CallError::CALL_ERROR_INVALID_METHOD;
+ r_error.error = Callable::CallError::CALL_ERROR_INVALID_METHOD;
return;
}
@@ -1023,7 +1016,7 @@ void GDScriptFunctions::call(Function p_func, const Variant **p_args, int p_arg_
Error err = arr.resize(count);
if (err != OK) {
- r_error.error = Variant::CallError::CALL_ERROR_INVALID_METHOD;
+ r_error.error = Callable::CallError::CALL_ERROR_INVALID_METHOD;
r_ret = Variant();
return;
}
@@ -1045,7 +1038,7 @@ void GDScriptFunctions::call(Function p_func, const Variant **p_args, int p_arg_
} break;
default: {
- r_error.error = Variant::CallError::CALL_ERROR_TOO_MANY_ARGUMENTS;
+ r_error.error = Callable::CallError::CALL_ERROR_TOO_MANY_ARGUMENTS;
r_error.argument = 3;
r_ret = Variant();
@@ -1056,7 +1049,7 @@ void GDScriptFunctions::call(Function p_func, const Variant **p_args, int p_arg_
case RESOURCE_LOAD: {
VALIDATE_ARG_COUNT(1);
if (p_args[0]->get_type() != Variant::STRING) {
- r_error.error = Variant::CallError::CALL_ERROR_INVALID_ARGUMENT;
+ r_error.error = Callable::CallError::CALL_ERROR_INVALID_ARGUMENT;
r_error.argument = 0;
r_error.expected = Variant::STRING;
r_ret = Variant();
@@ -1072,7 +1065,7 @@ void GDScriptFunctions::call(Function p_func, const Variant **p_args, int p_arg_
if (p_args[0]->get_type() == Variant::NIL) {
r_ret = Variant();
} else if (p_args[0]->get_type() != Variant::OBJECT) {
- r_error.error = Variant::CallError::CALL_ERROR_INVALID_ARGUMENT;
+ r_error.error = Callable::CallError::CALL_ERROR_INVALID_ARGUMENT;
r_error.argument = 0;
r_ret = Variant();
} else {
@@ -1083,7 +1076,7 @@ void GDScriptFunctions::call(Function p_func, const Variant **p_args, int p_arg_
} else if (!obj->get_script_instance() || obj->get_script_instance()->get_language() != GDScriptLanguage::get_singleton()) {
- r_error.error = Variant::CallError::CALL_ERROR_INVALID_ARGUMENT;
+ r_error.error = Callable::CallError::CALL_ERROR_INVALID_ARGUMENT;
r_error.argument = 0;
r_error.expected = Variant::DICTIONARY;
r_ret = RTR("Not a script with an instance");
@@ -1094,7 +1087,7 @@ void GDScriptFunctions::call(Function p_func, const Variant **p_args, int p_arg_
Ref<GDScript> base = ins->get_script();
if (base.is_null()) {
- r_error.error = Variant::CallError::CALL_ERROR_INVALID_ARGUMENT;
+ r_error.error = Callable::CallError::CALL_ERROR_INVALID_ARGUMENT;
r_error.argument = 0;
r_error.expected = Variant::DICTIONARY;
r_ret = RTR("Not based on a script");
@@ -1112,7 +1105,7 @@ void GDScriptFunctions::call(Function p_func, const Variant **p_args, int p_arg_
sname.invert();
if (!p->path.is_resource_file()) {
- r_error.error = Variant::CallError::CALL_ERROR_INVALID_ARGUMENT;
+ r_error.error = Callable::CallError::CALL_ERROR_INVALID_ARGUMENT;
r_error.argument = 0;
r_error.expected = Variant::DICTIONARY;
r_ret = Variant();
@@ -1144,7 +1137,7 @@ void GDScriptFunctions::call(Function p_func, const Variant **p_args, int p_arg_
if (p_args[0]->get_type() != Variant::DICTIONARY) {
- r_error.error = Variant::CallError::CALL_ERROR_INVALID_ARGUMENT;
+ r_error.error = Callable::CallError::CALL_ERROR_INVALID_ARGUMENT;
r_error.argument = 0;
r_error.expected = Variant::DICTIONARY;
r_ret = Variant();
@@ -1156,7 +1149,7 @@ void GDScriptFunctions::call(Function p_func, const Variant **p_args, int p_arg_
if (!d.has("@path")) {
- r_error.error = Variant::CallError::CALL_ERROR_INVALID_ARGUMENT;
+ r_error.error = Callable::CallError::CALL_ERROR_INVALID_ARGUMENT;
r_error.argument = 0;
r_error.expected = Variant::OBJECT;
r_ret = RTR("Invalid instance dictionary format (missing @path)");
@@ -1167,7 +1160,7 @@ void GDScriptFunctions::call(Function p_func, const Variant **p_args, int p_arg_
Ref<Script> scr = ResourceLoader::load(d["@path"]);
if (!scr.is_valid()) {
- r_error.error = Variant::CallError::CALL_ERROR_INVALID_ARGUMENT;
+ r_error.error = Callable::CallError::CALL_ERROR_INVALID_ARGUMENT;
r_error.argument = 0;
r_error.expected = Variant::OBJECT;
r_ret = RTR("Invalid instance dictionary format (can't load script at @path)");
@@ -1178,7 +1171,7 @@ void GDScriptFunctions::call(Function p_func, const Variant **p_args, int p_arg_
if (!gdscr.is_valid()) {
- r_error.error = Variant::CallError::CALL_ERROR_INVALID_ARGUMENT;
+ r_error.error = Callable::CallError::CALL_ERROR_INVALID_ARGUMENT;
r_error.argument = 0;
r_error.expected = Variant::OBJECT;
r_ret = Variant();
@@ -1196,7 +1189,7 @@ void GDScriptFunctions::call(Function p_func, const Variant **p_args, int p_arg_
gdscr = gdscr->subclasses[sub.get_name(i)];
if (!gdscr.is_valid()) {
- r_error.error = Variant::CallError::CALL_ERROR_INVALID_ARGUMENT;
+ r_error.error = Callable::CallError::CALL_ERROR_INVALID_ARGUMENT;
r_error.argument = 0;
r_error.expected = Variant::OBJECT;
r_ret = Variant();
@@ -1222,7 +1215,7 @@ void GDScriptFunctions::call(Function p_func, const Variant **p_args, int p_arg_
VALIDATE_ARG_COUNT(1);
if (p_args[0]->get_type() != Variant::STRING) {
- r_error.error = Variant::CallError::CALL_ERROR_INVALID_ARGUMENT;
+ r_error.error = Callable::CallError::CALL_ERROR_INVALID_ARGUMENT;
r_error.argument = 0;
r_error.expected = Variant::STRING;
r_ret = Variant();
@@ -1246,7 +1239,7 @@ void GDScriptFunctions::call(Function p_func, const Variant **p_args, int p_arg_
VALIDATE_ARG_COUNT(1);
if (p_args[0]->get_type() != Variant::STRING) {
- r_error.error = Variant::CallError::CALL_ERROR_INVALID_ARGUMENT;
+ r_error.error = Callable::CallError::CALL_ERROR_INVALID_ARGUMENT;
r_error.argument = 0;
r_error.expected = Variant::STRING;
r_ret = Variant();
@@ -1260,7 +1253,7 @@ void GDScriptFunctions::call(Function p_func, const Variant **p_args, int p_arg_
if (err != OK) {
r_ret = Variant();
- ERR_PRINTS(vformat("Error parsing JSON at line %s: %s", errl, errs));
+ ERR_PRINT(vformat("Error parsing JSON at line %s: %s", errl, errs));
}
} break;
@@ -1278,14 +1271,14 @@ void GDScriptFunctions::call(Function p_func, const Variant **p_args, int p_arg_
case COLOR8: {
if (p_arg_count < 3) {
- r_error.error = Variant::CallError::CALL_ERROR_TOO_FEW_ARGUMENTS;
+ r_error.error = Callable::CallError::CALL_ERROR_TOO_FEW_ARGUMENTS;
r_error.argument = 3;
r_ret = Variant();
return;
}
if (p_arg_count > 4) {
- r_error.error = Variant::CallError::CALL_ERROR_TOO_MANY_ARGUMENTS;
+ r_error.error = Callable::CallError::CALL_ERROR_TOO_MANY_ARGUMENTS;
r_error.argument = 4;
r_ret = Variant();
@@ -1309,21 +1302,21 @@ void GDScriptFunctions::call(Function p_func, const Variant **p_args, int p_arg_
case COLORN: {
if (p_arg_count < 1) {
- r_error.error = Variant::CallError::CALL_ERROR_TOO_FEW_ARGUMENTS;
+ r_error.error = Callable::CallError::CALL_ERROR_TOO_FEW_ARGUMENTS;
r_error.argument = 1;
r_ret = Variant();
return;
}
if (p_arg_count > 2) {
- r_error.error = Variant::CallError::CALL_ERROR_TOO_MANY_ARGUMENTS;
+ r_error.error = Callable::CallError::CALL_ERROR_TOO_MANY_ARGUMENTS;
r_error.argument = 2;
r_ret = Variant();
return;
}
if (p_args[0]->get_type() != Variant::STRING) {
- r_error.error = Variant::CallError::CALL_ERROR_INVALID_ARGUMENT;
+ r_error.error = Callable::CallError::CALL_ERROR_INVALID_ARGUMENT;
r_error.argument = 0;
r_ret = Variant();
} else {
@@ -1366,15 +1359,15 @@ void GDScriptFunctions::call(Function p_func, const Variant **p_args, int p_arg_
case INSTANCE_FROM_ID: {
VALIDATE_ARG_COUNT(1);
- if (p_args[0]->get_type() != Variant::INT && p_args[0]->get_type() != Variant::REAL) {
- r_error.error = Variant::CallError::CALL_ERROR_INVALID_ARGUMENT;
+ if (p_args[0]->get_type() != Variant::INT && p_args[0]->get_type() != Variant::FLOAT) {
+ r_error.error = Callable::CallError::CALL_ERROR_INVALID_ARGUMENT;
r_error.argument = 0;
r_error.expected = Variant::INT;
r_ret = Variant();
break;
}
- uint32_t id = *p_args[0];
+ ObjectID id = *p_args[0];
r_ret = ObjectDB::get_instance(id);
} break;
@@ -1397,43 +1390,53 @@ void GDScriptFunctions::call(Function p_func, const Variant **p_args, int p_arg_
Array d = *p_args[0];
r_ret = d.size();
} break;
- case Variant::POOL_BYTE_ARRAY: {
+ case Variant::PACKED_BYTE_ARRAY: {
+
+ Vector<uint8_t> d = *p_args[0];
+ r_ret = d.size();
+ } break;
+ case Variant::PACKED_INT32_ARRAY: {
- PoolVector<uint8_t> d = *p_args[0];
+ Vector<int32_t> d = *p_args[0];
r_ret = d.size();
} break;
- case Variant::POOL_INT_ARRAY: {
+ case Variant::PACKED_INT64_ARRAY: {
- PoolVector<int> d = *p_args[0];
+ Vector<int64_t> d = *p_args[0];
r_ret = d.size();
} break;
- case Variant::POOL_REAL_ARRAY: {
+ case Variant::PACKED_FLOAT32_ARRAY: {
- PoolVector<real_t> d = *p_args[0];
+ Vector<float> d = *p_args[0];
r_ret = d.size();
} break;
- case Variant::POOL_STRING_ARRAY: {
+ case Variant::PACKED_FLOAT64_ARRAY: {
- PoolVector<String> d = *p_args[0];
+ Vector<double> d = *p_args[0];
r_ret = d.size();
} break;
- case Variant::POOL_VECTOR2_ARRAY: {
+ case Variant::PACKED_STRING_ARRAY: {
- PoolVector<Vector2> d = *p_args[0];
+ Vector<String> d = *p_args[0];
r_ret = d.size();
} break;
- case Variant::POOL_VECTOR3_ARRAY: {
+ case Variant::PACKED_VECTOR2_ARRAY: {
- PoolVector<Vector3> d = *p_args[0];
+ Vector<Vector2> d = *p_args[0];
r_ret = d.size();
} break;
- case Variant::POOL_COLOR_ARRAY: {
+ case Variant::PACKED_VECTOR3_ARRAY: {
- PoolVector<Color> d = *p_args[0];
+ Vector<Vector3> d = *p_args[0];
+ r_ret = d.size();
+ } break;
+ case Variant::PACKED_COLOR_ARRAY: {
+
+ Vector<Color> d = *p_args[0];
r_ret = d.size();
} break;
default: {
- r_error.error = Variant::CallError::CALL_ERROR_INVALID_ARGUMENT;
+ r_error.error = Callable::CallError::CALL_ERROR_INVALID_ARGUMENT;
r_error.argument = 0;
r_error.expected = Variant::OBJECT;
r_ret = Variant();
@@ -1448,8 +1451,8 @@ void GDScriptFunctions::call(Function p_func, const Variant **p_args, int p_arg_
if (p_args[0]->get_type() != Variant::OBJECT) {
r_ret = false;
} else {
- Object *obj = *p_args[0];
- r_ret = ObjectDB::instance_validate(obj);
+ Object *obj = p_args[0]->get_validated_object();
+ r_ret = obj != nullptr;
}
} break;
@@ -1492,7 +1495,6 @@ bool GDScriptFunctions::is_deterministic(Function p_func) {
case MATH_ISNAN:
case MATH_ISINF:
case MATH_EASE:
- case MATH_DECIMALS:
case MATH_STEP_DECIMALS:
case MATH_STEPIFY:
case MATH_LERP:
@@ -1538,69 +1540,69 @@ MethodInfo GDScriptFunctions::get_info(Function p_func) {
switch (p_func) {
case MATH_SIN: {
- MethodInfo mi("sin", PropertyInfo(Variant::REAL, "s"));
- mi.return_val.type = Variant::REAL;
+ MethodInfo mi("sin", PropertyInfo(Variant::FLOAT, "s"));
+ mi.return_val.type = Variant::FLOAT;
return mi;
} break;
case MATH_COS: {
- MethodInfo mi("cos", PropertyInfo(Variant::REAL, "s"));
- mi.return_val.type = Variant::REAL;
+ MethodInfo mi("cos", PropertyInfo(Variant::FLOAT, "s"));
+ mi.return_val.type = Variant::FLOAT;
return mi;
} break;
case MATH_TAN: {
- MethodInfo mi("tan", PropertyInfo(Variant::REAL, "s"));
- mi.return_val.type = Variant::REAL;
+ MethodInfo mi("tan", PropertyInfo(Variant::FLOAT, "s"));
+ mi.return_val.type = Variant::FLOAT;
return mi;
} break;
case MATH_SINH: {
- MethodInfo mi("sinh", PropertyInfo(Variant::REAL, "s"));
- mi.return_val.type = Variant::REAL;
+ MethodInfo mi("sinh", PropertyInfo(Variant::FLOAT, "s"));
+ mi.return_val.type = Variant::FLOAT;
return mi;
} break;
case MATH_COSH: {
- MethodInfo mi("cosh", PropertyInfo(Variant::REAL, "s"));
- mi.return_val.type = Variant::REAL;
+ MethodInfo mi("cosh", PropertyInfo(Variant::FLOAT, "s"));
+ mi.return_val.type = Variant::FLOAT;
return mi;
} break;
case MATH_TANH: {
- MethodInfo mi("tanh", PropertyInfo(Variant::REAL, "s"));
- mi.return_val.type = Variant::REAL;
+ MethodInfo mi("tanh", PropertyInfo(Variant::FLOAT, "s"));
+ mi.return_val.type = Variant::FLOAT;
return mi;
} break;
case MATH_ASIN: {
- MethodInfo mi("asin", PropertyInfo(Variant::REAL, "s"));
- mi.return_val.type = Variant::REAL;
+ MethodInfo mi("asin", PropertyInfo(Variant::FLOAT, "s"));
+ mi.return_val.type = Variant::FLOAT;
return mi;
} break;
case MATH_ACOS: {
- MethodInfo mi("acos", PropertyInfo(Variant::REAL, "s"));
- mi.return_val.type = Variant::REAL;
+ MethodInfo mi("acos", PropertyInfo(Variant::FLOAT, "s"));
+ mi.return_val.type = Variant::FLOAT;
return mi;
} break;
case MATH_ATAN: {
- MethodInfo mi("atan", PropertyInfo(Variant::REAL, "s"));
- mi.return_val.type = Variant::REAL;
+ MethodInfo mi("atan", PropertyInfo(Variant::FLOAT, "s"));
+ mi.return_val.type = Variant::FLOAT;
return mi;
} break;
case MATH_ATAN2: {
- MethodInfo mi("atan2", PropertyInfo(Variant::REAL, "y"), PropertyInfo(Variant::REAL, "x"));
- mi.return_val.type = Variant::REAL;
+ MethodInfo mi("atan2", PropertyInfo(Variant::FLOAT, "y"), PropertyInfo(Variant::FLOAT, "x"));
+ mi.return_val.type = Variant::FLOAT;
return mi;
} break;
case MATH_SQRT: {
- MethodInfo mi("sqrt", PropertyInfo(Variant::REAL, "s"));
- mi.return_val.type = Variant::REAL;
+ MethodInfo mi("sqrt", PropertyInfo(Variant::FLOAT, "s"));
+ mi.return_val.type = Variant::FLOAT;
return mi;
} break;
case MATH_FMOD: {
- MethodInfo mi("fmod", PropertyInfo(Variant::REAL, "a"), PropertyInfo(Variant::REAL, "b"));
- mi.return_val.type = Variant::REAL;
+ MethodInfo mi("fmod", PropertyInfo(Variant::FLOAT, "a"), PropertyInfo(Variant::FLOAT, "b"));
+ mi.return_val.type = Variant::FLOAT;
return mi;
} break;
case MATH_FPOSMOD: {
- MethodInfo mi("fposmod", PropertyInfo(Variant::REAL, "a"), PropertyInfo(Variant::REAL, "b"));
- mi.return_val.type = Variant::REAL;
+ MethodInfo mi("fposmod", PropertyInfo(Variant::FLOAT, "a"), PropertyInfo(Variant::FLOAT, "b"));
+ mi.return_val.type = Variant::FLOAT;
return mi;
} break;
case MATH_POSMOD: {
@@ -1609,119 +1611,114 @@ MethodInfo GDScriptFunctions::get_info(Function p_func) {
return mi;
} break;
case MATH_FLOOR: {
- MethodInfo mi("floor", PropertyInfo(Variant::REAL, "s"));
- mi.return_val.type = Variant::REAL;
+ MethodInfo mi("floor", PropertyInfo(Variant::FLOAT, "s"));
+ mi.return_val.type = Variant::FLOAT;
return mi;
} break;
case MATH_CEIL: {
- MethodInfo mi("ceil", PropertyInfo(Variant::REAL, "s"));
- mi.return_val.type = Variant::REAL;
+ MethodInfo mi("ceil", PropertyInfo(Variant::FLOAT, "s"));
+ mi.return_val.type = Variant::FLOAT;
return mi;
} break;
case MATH_ROUND: {
- MethodInfo mi("round", PropertyInfo(Variant::REAL, "s"));
- mi.return_val.type = Variant::REAL;
+ MethodInfo mi("round", PropertyInfo(Variant::FLOAT, "s"));
+ mi.return_val.type = Variant::FLOAT;
return mi;
} break;
case MATH_ABS: {
- MethodInfo mi("abs", PropertyInfo(Variant::REAL, "s"));
- mi.return_val.type = Variant::REAL;
+ MethodInfo mi("abs", PropertyInfo(Variant::FLOAT, "s"));
+ mi.return_val.type = Variant::FLOAT;
return mi;
} break;
case MATH_SIGN: {
- MethodInfo mi("sign", PropertyInfo(Variant::REAL, "s"));
- mi.return_val.type = Variant::REAL;
+ MethodInfo mi("sign", PropertyInfo(Variant::FLOAT, "s"));
+ mi.return_val.type = Variant::FLOAT;
return mi;
} break;
case MATH_POW: {
- MethodInfo mi("pow", PropertyInfo(Variant::REAL, "base"), PropertyInfo(Variant::REAL, "exp"));
- mi.return_val.type = Variant::REAL;
+ MethodInfo mi("pow", PropertyInfo(Variant::FLOAT, "base"), PropertyInfo(Variant::FLOAT, "exp"));
+ mi.return_val.type = Variant::FLOAT;
return mi;
} break;
case MATH_LOG: {
- MethodInfo mi("log", PropertyInfo(Variant::REAL, "s"));
- mi.return_val.type = Variant::REAL;
+ MethodInfo mi("log", PropertyInfo(Variant::FLOAT, "s"));
+ mi.return_val.type = Variant::FLOAT;
return mi;
} break;
case MATH_EXP: {
- MethodInfo mi("exp", PropertyInfo(Variant::REAL, "s"));
- mi.return_val.type = Variant::REAL;
+ MethodInfo mi("exp", PropertyInfo(Variant::FLOAT, "s"));
+ mi.return_val.type = Variant::FLOAT;
return mi;
} break;
case MATH_ISNAN: {
- MethodInfo mi("is_nan", PropertyInfo(Variant::REAL, "s"));
+ MethodInfo mi("is_nan", PropertyInfo(Variant::FLOAT, "s"));
mi.return_val.type = Variant::BOOL;
return mi;
} break;
case MATH_ISINF: {
- MethodInfo mi("is_inf", PropertyInfo(Variant::REAL, "s"));
+ MethodInfo mi("is_inf", PropertyInfo(Variant::FLOAT, "s"));
mi.return_val.type = Variant::BOOL;
return mi;
} break;
case MATH_ISEQUALAPPROX: {
- MethodInfo mi("is_equal_approx", PropertyInfo(Variant::REAL, "a"), PropertyInfo(Variant::REAL, "b"));
+ MethodInfo mi("is_equal_approx", PropertyInfo(Variant::FLOAT, "a"), PropertyInfo(Variant::FLOAT, "b"));
mi.return_val.type = Variant::BOOL;
return mi;
} break;
case MATH_ISZEROAPPROX: {
- MethodInfo mi("is_zero_approx", PropertyInfo(Variant::REAL, "s"));
+ MethodInfo mi("is_zero_approx", PropertyInfo(Variant::FLOAT, "s"));
mi.return_val.type = Variant::BOOL;
return mi;
} break;
case MATH_EASE: {
- MethodInfo mi("ease", PropertyInfo(Variant::REAL, "s"), PropertyInfo(Variant::REAL, "curve"));
- mi.return_val.type = Variant::REAL;
- return mi;
- } break;
- case MATH_DECIMALS: {
- MethodInfo mi("decimals", PropertyInfo(Variant::REAL, "step"));
- mi.return_val.type = Variant::INT;
+ MethodInfo mi("ease", PropertyInfo(Variant::FLOAT, "s"), PropertyInfo(Variant::FLOAT, "curve"));
+ mi.return_val.type = Variant::FLOAT;
return mi;
} break;
case MATH_STEP_DECIMALS: {
- MethodInfo mi("step_decimals", PropertyInfo(Variant::REAL, "step"));
+ MethodInfo mi("step_decimals", PropertyInfo(Variant::FLOAT, "step"));
mi.return_val.type = Variant::INT;
return mi;
} break;
case MATH_STEPIFY: {
- MethodInfo mi("stepify", PropertyInfo(Variant::REAL, "s"), PropertyInfo(Variant::REAL, "step"));
- mi.return_val.type = Variant::REAL;
+ MethodInfo mi("stepify", PropertyInfo(Variant::FLOAT, "s"), PropertyInfo(Variant::FLOAT, "step"));
+ mi.return_val.type = Variant::FLOAT;
return mi;
} break;
case MATH_LERP: {
- MethodInfo mi("lerp", PropertyInfo(Variant::NIL, "from"), PropertyInfo(Variant::NIL, "to"), PropertyInfo(Variant::REAL, "weight"));
+ MethodInfo mi("lerp", PropertyInfo(Variant::NIL, "from"), PropertyInfo(Variant::NIL, "to"), PropertyInfo(Variant::FLOAT, "weight"));
mi.return_val.type = Variant::NIL;
mi.return_val.usage |= PROPERTY_USAGE_NIL_IS_VARIANT;
return mi;
} break;
case MATH_LERP_ANGLE: {
- MethodInfo mi("lerp_angle", PropertyInfo(Variant::REAL, "from"), PropertyInfo(Variant::REAL, "to"), PropertyInfo(Variant::REAL, "weight"));
- mi.return_val.type = Variant::REAL;
+ MethodInfo mi("lerp_angle", PropertyInfo(Variant::FLOAT, "from"), PropertyInfo(Variant::FLOAT, "to"), PropertyInfo(Variant::FLOAT, "weight"));
+ mi.return_val.type = Variant::FLOAT;
return mi;
} break;
case MATH_INVERSE_LERP: {
- MethodInfo mi("inverse_lerp", PropertyInfo(Variant::REAL, "from"), PropertyInfo(Variant::REAL, "to"), PropertyInfo(Variant::REAL, "weight"));
- mi.return_val.type = Variant::REAL;
+ MethodInfo mi("inverse_lerp", PropertyInfo(Variant::FLOAT, "from"), PropertyInfo(Variant::FLOAT, "to"), PropertyInfo(Variant::FLOAT, "weight"));
+ mi.return_val.type = Variant::FLOAT;
return mi;
} break;
case MATH_RANGE_LERP: {
- MethodInfo mi("range_lerp", PropertyInfo(Variant::REAL, "value"), PropertyInfo(Variant::REAL, "istart"), PropertyInfo(Variant::REAL, "istop"), PropertyInfo(Variant::REAL, "ostart"), PropertyInfo(Variant::REAL, "ostop"));
- mi.return_val.type = Variant::REAL;
+ MethodInfo mi("range_lerp", PropertyInfo(Variant::FLOAT, "value"), PropertyInfo(Variant::FLOAT, "istart"), PropertyInfo(Variant::FLOAT, "istop"), PropertyInfo(Variant::FLOAT, "ostart"), PropertyInfo(Variant::FLOAT, "ostop"));
+ mi.return_val.type = Variant::FLOAT;
return mi;
} break;
case MATH_SMOOTHSTEP: {
- MethodInfo mi("smoothstep", PropertyInfo(Variant::REAL, "from"), PropertyInfo(Variant::REAL, "to"), PropertyInfo(Variant::REAL, "weight"));
- mi.return_val.type = Variant::REAL;
+ MethodInfo mi("smoothstep", PropertyInfo(Variant::FLOAT, "from"), PropertyInfo(Variant::FLOAT, "to"), PropertyInfo(Variant::FLOAT, "weight"));
+ mi.return_val.type = Variant::FLOAT;
return mi;
} break;
case MATH_MOVE_TOWARD: {
- MethodInfo mi("move_toward", PropertyInfo(Variant::REAL, "from"), PropertyInfo(Variant::REAL, "to"), PropertyInfo(Variant::REAL, "delta"));
- mi.return_val.type = Variant::REAL;
+ MethodInfo mi("move_toward", PropertyInfo(Variant::FLOAT, "from"), PropertyInfo(Variant::FLOAT, "to"), PropertyInfo(Variant::FLOAT, "delta"));
+ mi.return_val.type = Variant::FLOAT;
return mi;
} break;
case MATH_DECTIME: {
- MethodInfo mi("dectime", PropertyInfo(Variant::REAL, "value"), PropertyInfo(Variant::REAL, "amount"), PropertyInfo(Variant::REAL, "step"));
- mi.return_val.type = Variant::REAL;
+ MethodInfo mi("dectime", PropertyInfo(Variant::FLOAT, "value"), PropertyInfo(Variant::FLOAT, "amount"), PropertyInfo(Variant::FLOAT, "step"));
+ mi.return_val.type = Variant::FLOAT;
return mi;
} break;
case MATH_RANDOMIZE: {
@@ -1736,12 +1733,12 @@ MethodInfo GDScriptFunctions::get_info(Function p_func) {
} break;
case MATH_RANDF: {
MethodInfo mi("randf");
- mi.return_val.type = Variant::REAL;
+ mi.return_val.type = Variant::FLOAT;
return mi;
} break;
case MATH_RANDOM: {
- MethodInfo mi("rand_range", PropertyInfo(Variant::REAL, "from"), PropertyInfo(Variant::REAL, "to"));
- mi.return_val.type = Variant::REAL;
+ MethodInfo mi("rand_range", PropertyInfo(Variant::FLOAT, "from"), PropertyInfo(Variant::FLOAT, "to"));
+ mi.return_val.type = Variant::FLOAT;
return mi;
} break;
case MATH_SEED: {
@@ -1755,32 +1752,32 @@ MethodInfo GDScriptFunctions::get_info(Function p_func) {
return mi;
} break;
case MATH_DEG2RAD: {
- MethodInfo mi("deg2rad", PropertyInfo(Variant::REAL, "deg"));
- mi.return_val.type = Variant::REAL;
+ MethodInfo mi("deg2rad", PropertyInfo(Variant::FLOAT, "deg"));
+ mi.return_val.type = Variant::FLOAT;
return mi;
} break;
case MATH_RAD2DEG: {
- MethodInfo mi("rad2deg", PropertyInfo(Variant::REAL, "rad"));
- mi.return_val.type = Variant::REAL;
+ MethodInfo mi("rad2deg", PropertyInfo(Variant::FLOAT, "rad"));
+ mi.return_val.type = Variant::FLOAT;
return mi;
} break;
case MATH_LINEAR2DB: {
- MethodInfo mi("linear2db", PropertyInfo(Variant::REAL, "nrg"));
- mi.return_val.type = Variant::REAL;
+ MethodInfo mi("linear2db", PropertyInfo(Variant::FLOAT, "nrg"));
+ mi.return_val.type = Variant::FLOAT;
return mi;
} break;
case MATH_DB2LINEAR: {
- MethodInfo mi("db2linear", PropertyInfo(Variant::REAL, "db"));
- mi.return_val.type = Variant::REAL;
+ MethodInfo mi("db2linear", PropertyInfo(Variant::FLOAT, "db"));
+ mi.return_val.type = Variant::FLOAT;
return mi;
} break;
case MATH_POLAR2CARTESIAN: {
- MethodInfo mi("polar2cartesian", PropertyInfo(Variant::REAL, "r"), PropertyInfo(Variant::REAL, "th"));
+ MethodInfo mi("polar2cartesian", PropertyInfo(Variant::FLOAT, "r"), PropertyInfo(Variant::FLOAT, "th"));
mi.return_val.type = Variant::VECTOR2;
return mi;
} break;
case MATH_CARTESIAN2POLAR: {
- MethodInfo mi("cartesian2polar", PropertyInfo(Variant::REAL, "x"), PropertyInfo(Variant::REAL, "y"));
+ MethodInfo mi("cartesian2polar", PropertyInfo(Variant::FLOAT, "x"), PropertyInfo(Variant::FLOAT, "y"));
mi.return_val.type = Variant::VECTOR2;
return mi;
} break;
@@ -1790,24 +1787,24 @@ MethodInfo GDScriptFunctions::get_info(Function p_func) {
return mi;
} break;
case MATH_WRAPF: {
- MethodInfo mi("wrapf", PropertyInfo(Variant::REAL, "value"), PropertyInfo(Variant::REAL, "min"), PropertyInfo(Variant::REAL, "max"));
- mi.return_val.type = Variant::REAL;
+ MethodInfo mi("wrapf", PropertyInfo(Variant::FLOAT, "value"), PropertyInfo(Variant::FLOAT, "min"), PropertyInfo(Variant::FLOAT, "max"));
+ mi.return_val.type = Variant::FLOAT;
return mi;
} break;
case LOGIC_MAX: {
- MethodInfo mi("max", PropertyInfo(Variant::REAL, "a"), PropertyInfo(Variant::REAL, "b"));
- mi.return_val.type = Variant::REAL;
+ MethodInfo mi("max", PropertyInfo(Variant::FLOAT, "a"), PropertyInfo(Variant::FLOAT, "b"));
+ mi.return_val.type = Variant::FLOAT;
return mi;
} break;
case LOGIC_MIN: {
- MethodInfo mi("min", PropertyInfo(Variant::REAL, "a"), PropertyInfo(Variant::REAL, "b"));
- mi.return_val.type = Variant::REAL;
+ MethodInfo mi("min", PropertyInfo(Variant::FLOAT, "a"), PropertyInfo(Variant::FLOAT, "b"));
+ mi.return_val.type = Variant::FLOAT;
return mi;
} break;
case LOGIC_CLAMP: {
- MethodInfo mi("clamp", PropertyInfo(Variant::REAL, "value"), PropertyInfo(Variant::REAL, "min"), PropertyInfo(Variant::REAL, "max"));
- mi.return_val.type = Variant::REAL;
+ MethodInfo mi("clamp", PropertyInfo(Variant::FLOAT, "value"), PropertyInfo(Variant::FLOAT, "min"), PropertyInfo(Variant::FLOAT, "max"));
+ mi.return_val.type = Variant::FLOAT;
return mi;
} break;
case LOGIC_NEAREST_PO2: {
@@ -1954,12 +1951,12 @@ MethodInfo GDScriptFunctions::get_info(Function p_func) {
MethodInfo mi("var2bytes", PropertyInfo(Variant::NIL, "var", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_NIL_IS_VARIANT), PropertyInfo(Variant::BOOL, "full_objects"));
mi.default_arguments.push_back(false);
- mi.return_val.type = Variant::POOL_BYTE_ARRAY;
+ mi.return_val.type = Variant::PACKED_BYTE_ARRAY;
return mi;
} break;
case BYTES_TO_VAR: {
- MethodInfo mi(Variant::NIL, "bytes2var", PropertyInfo(Variant::POOL_BYTE_ARRAY, "bytes"), PropertyInfo(Variant::BOOL, "allow_objects"));
+ MethodInfo mi(Variant::NIL, "bytes2var", PropertyInfo(Variant::PACKED_BYTE_ARRAY, "bytes"), PropertyInfo(Variant::BOOL, "allow_objects"));
mi.default_arguments.push_back(false);
mi.return_val.type = Variant::NIL;
mi.return_val.usage |= PROPERTY_USAGE_NIL_IS_VARIANT;
@@ -2025,7 +2022,7 @@ MethodInfo GDScriptFunctions::get_info(Function p_func) {
} break;
case COLORN: {
- MethodInfo mi("ColorN", PropertyInfo(Variant::STRING, "name"), PropertyInfo(Variant::REAL, "alpha"));
+ MethodInfo mi("ColorN", PropertyInfo(Variant::STRING, "name"), PropertyInfo(Variant::FLOAT, "alpha"));
mi.default_arguments.push_back(1.0f);
mi.return_val.type = Variant::COLOR;
return mi;
diff --git a/modules/gdscript/gdscript_functions.h b/modules/gdscript/gdscript_functions.h
index 1812ddf121..2c6dc02913 100644
--- a/modules/gdscript/gdscript_functions.h
+++ b/modules/gdscript/gdscript_functions.h
@@ -63,7 +63,6 @@ public:
MATH_ISEQUALAPPROX,
MATH_ISZEROAPPROX,
MATH_EASE,
- MATH_DECIMALS,
MATH_STEP_DECIMALS,
MATH_STEPIFY,
MATH_LERP,
@@ -130,7 +129,7 @@ public:
};
static const char *get_func_name(Function p_func);
- static void call(Function p_func, const Variant **p_args, int p_arg_count, Variant &r_ret, Variant::CallError &r_error);
+ static void call(Function p_func, const Variant **p_args, int p_arg_count, Variant &r_ret, Callable::CallError &r_error);
static bool is_deterministic(Function p_func);
static MethodInfo get_info(Function p_func);
};
diff --git a/modules/gdscript/gdscript_parser.cpp b/modules/gdscript/gdscript_parser.cpp
index d125da5b79..0382944efd 100644
--- a/modules/gdscript/gdscript_parser.cpp
+++ b/modules/gdscript/gdscript_parser.cpp
@@ -793,7 +793,7 @@ GDScriptParser::Node *GDScriptParser::_parse_expression(Node *p_parent, bool p_s
}
_add_warning(GDScriptWarning::UNASSIGNED_VARIABLE_OP_ASSIGN, -1, identifier.operator String());
}
- FALLTHROUGH;
+ [[fallthrough]];
}
case GDScriptTokenizer::TK_OP_ASSIGN: {
lv->assignments += 1;
@@ -1739,7 +1739,7 @@ GDScriptParser::Node *GDScriptParser::_reduce_expression(Node *p_node, bool p_to
vptr = (const Variant **)&ptrs[0];
}
- Variant::CallError ce;
+ Callable::CallError ce;
Variant v;
if (op->arguments[0]->type == Node::TYPE_TYPE) {
@@ -1751,7 +1751,7 @@ GDScriptParser::Node *GDScriptParser::_reduce_expression(Node *p_node, bool p_to
GDScriptFunctions::call(func, vptr, ptrs.size(), v, ce);
}
- if (ce.error != Variant::CallError::CALL_OK) {
+ if (ce.error != Callable::CallError::CALL_OK) {
String errwhere;
if (op->arguments[0]->type == Node::TYPE_TYPE) {
@@ -1765,16 +1765,16 @@ GDScriptParser::Node *GDScriptParser::_reduce_expression(Node *p_node, bool p_to
switch (ce.error) {
- case Variant::CallError::CALL_ERROR_INVALID_ARGUMENT: {
+ case Callable::CallError::CALL_ERROR_INVALID_ARGUMENT: {
_set_error("Invalid argument (#" + itos(ce.argument + 1) + ") for " + errwhere + ".");
} break;
- case Variant::CallError::CALL_ERROR_TOO_MANY_ARGUMENTS: {
+ case Callable::CallError::CALL_ERROR_TOO_MANY_ARGUMENTS: {
_set_error("Too many arguments for " + errwhere + ".");
} break;
- case Variant::CallError::CALL_ERROR_TOO_FEW_ARGUMENTS: {
+ case Callable::CallError::CALL_ERROR_TOO_FEW_ARGUMENTS: {
_set_error("Too few arguments for " + errwhere + ".");
} break;
@@ -2766,13 +2766,12 @@ void GDScriptParser::_parse_block(BlockNode *p_block, bool p_static) {
}
#endif // DEBUG_ENABLED
switch (token) {
- case GDScriptTokenizer::TK_EOF:
+ case GDScriptTokenizer::TK_EOF: {
p_block->end_line = tokenizer->get_token_line();
+ return; // End of file!
+ } break;
case GDScriptTokenizer::TK_ERROR: {
- return; //go back
-
- //end of file!
-
+ return;
} break;
case GDScriptTokenizer::TK_NEWLINE: {
@@ -3109,7 +3108,7 @@ void GDScriptParser::_parse_block(BlockNode *p_block, bool p_static) {
args.push_back(op->arguments[i]);
if (constant && op->arguments[i]->type == Node::TYPE_CONSTANT) {
ConstantNode *c = static_cast<ConstantNode *>(op->arguments[i]);
- if (c->value.get_type() == Variant::REAL || c->value.get_type() == Variant::INT) {
+ if (c->value.get_type() == Variant::FLOAT || c->value.get_type() == Variant::INT) {
constants.push_back(c->value);
constant = true;
}
@@ -3525,11 +3524,12 @@ void GDScriptParser::_parse_class(ClassNode *p_class) {
case GDScriptTokenizer::TK_CURSOR: {
tokenizer->advance();
} break;
- case GDScriptTokenizer::TK_EOF:
+ case GDScriptTokenizer::TK_EOF: {
p_class->end_line = tokenizer->get_token_line();
+ return; // End of file!
+ } break;
case GDScriptTokenizer::TK_ERROR: {
- return; //go back
- //end of file!
+ return; // Go back.
} break;
case GDScriptTokenizer::TK_NEWLINE: {
if (!_parse_newline()) {
@@ -3719,7 +3719,7 @@ void GDScriptParser::_parse_class(ClassNode *p_class) {
return;
}
- FALLTHROUGH;
+ [[fallthrough]];
}
case GDScriptTokenizer::TK_PR_FUNCTION: {
@@ -4099,10 +4099,6 @@ void GDScriptParser::_parse_class(ClassNode *p_class) {
_ADVANCE_AND_CONSUME_NEWLINES;
- if (tokenizer->get_token() == GDScriptTokenizer::TK_PARENTHESIS_CLOSE) {
- WARN_DEPRECATED_MSG("Exporting bit flags hint requires string constants.");
- break;
- }
if (tokenizer->get_token() != GDScriptTokenizer::TK_COMMA) {
_set_error("Expected \",\" in the bit flags hint.");
return;
@@ -4224,9 +4220,9 @@ void GDScriptParser::_parse_class(ClassNode *p_class) {
break;
}
- FALLTHROUGH;
+ [[fallthrough]];
}
- case Variant::REAL: {
+ case Variant::FLOAT: {
if (tokenizer->get_token() == GDScriptTokenizer::TK_IDENTIFIER && tokenizer->get_token_identifier() == "EASE") {
current_export.hint = PROPERTY_HINT_EXP_EASING;
@@ -4588,10 +4584,10 @@ void GDScriptParser::_parse_class(ClassNode *p_class) {
#undef _ADVANCE_AND_CONSUME_NEWLINES
}
- if (tokenizer->get_token() != GDScriptTokenizer::TK_PR_VAR && tokenizer->get_token() != GDScriptTokenizer::TK_PR_ONREADY && tokenizer->get_token() != GDScriptTokenizer::TK_PR_REMOTE && tokenizer->get_token() != GDScriptTokenizer::TK_PR_MASTER && tokenizer->get_token() != GDScriptTokenizer::TK_PR_PUPPET && tokenizer->get_token() != GDScriptTokenizer::TK_PR_SYNC && tokenizer->get_token() != GDScriptTokenizer::TK_PR_REMOTESYNC && tokenizer->get_token() != GDScriptTokenizer::TK_PR_MASTERSYNC && tokenizer->get_token() != GDScriptTokenizer::TK_PR_PUPPETSYNC && tokenizer->get_token() != GDScriptTokenizer::TK_PR_SLAVE) {
+ if (tokenizer->get_token() != GDScriptTokenizer::TK_PR_VAR && tokenizer->get_token() != GDScriptTokenizer::TK_PR_ONREADY && tokenizer->get_token() != GDScriptTokenizer::TK_PR_REMOTE && tokenizer->get_token() != GDScriptTokenizer::TK_PR_MASTER && tokenizer->get_token() != GDScriptTokenizer::TK_PR_PUPPET && tokenizer->get_token() != GDScriptTokenizer::TK_PR_REMOTESYNC && tokenizer->get_token() != GDScriptTokenizer::TK_PR_MASTERSYNC && tokenizer->get_token() != GDScriptTokenizer::TK_PR_PUPPETSYNC) {
current_export = PropertyInfo();
- _set_error("Expected \"var\", \"onready\", \"remote\", \"master\", \"puppet\", \"sync\", \"remotesync\", \"mastersync\", \"puppetsync\".");
+ _set_error("Expected \"var\", \"onready\", \"remote\", \"master\", \"puppet\", \"remotesync\", \"mastersync\", \"puppetsync\".");
return;
}
@@ -4648,11 +4644,6 @@ void GDScriptParser::_parse_class(ClassNode *p_class) {
rpc_mode = MultiplayerAPI::RPC_MODE_MASTER;
continue;
} break;
- case GDScriptTokenizer::TK_PR_SLAVE:
-#ifdef DEBUG_ENABLED
- _add_warning(GDScriptWarning::DEPRECATED_KEYWORD, tokenizer->get_token_line(), "slave", "puppet");
-#endif
- FALLTHROUGH;
case GDScriptTokenizer::TK_PR_PUPPET: {
//may be fallthrough from export, ignore if so
@@ -4673,8 +4664,7 @@ void GDScriptParser::_parse_class(ClassNode *p_class) {
rpc_mode = MultiplayerAPI::RPC_MODE_PUPPET;
continue;
} break;
- case GDScriptTokenizer::TK_PR_REMOTESYNC:
- case GDScriptTokenizer::TK_PR_SYNC: {
+ case GDScriptTokenizer::TK_PR_REMOTESYNC: {
//may be fallthrough from export, ignore if so
tokenizer->advance();
@@ -4819,7 +4809,7 @@ void GDScriptParser::_parse_class(ClassNode *p_class) {
}
#ifdef TOOLS_ENABLED
- Variant::CallError ce;
+ Callable::CallError ce;
member.default_value = Variant::construct(member._export.type, NULL, 0, ce);
#endif
@@ -4888,7 +4878,7 @@ void GDScriptParser::_parse_class(ClassNode *p_class) {
if (cn->value.get_type() != Variant::NIL) {
if (member._export.type != Variant::NIL && cn->value.get_type() != member._export.type) {
if (Variant::can_convert(cn->value.get_type(), member._export.type)) {
- Variant::CallError err;
+ Callable::CallError err;
const Variant *args = &cn->value;
cn->value = Variant::construct(member._export.type, &args, 1, err);
} else {
@@ -5499,7 +5489,7 @@ String GDScriptParser::DataType::to_string() const {
if (!gds_class.empty()) {
return gds_class;
}
- FALLTHROUGH;
+ [[fallthrough]];
}
case SCRIPT: {
if (is_meta_type) {
@@ -5943,9 +5933,9 @@ GDScriptParser::DataType GDScriptParser::_get_operation_type(const Variant::Oper
a_ref.instance();
a = a_ref;
} else {
- Variant::CallError err;
+ Callable::CallError err;
a = Variant::construct(a_type, NULL, 0, err);
- if (err.error != Variant::CallError::CALL_OK) {
+ if (err.error != Callable::CallError::CALL_OK) {
r_valid = false;
return DataType();
}
@@ -5956,19 +5946,19 @@ GDScriptParser::DataType GDScriptParser::_get_operation_type(const Variant::Oper
b_ref.instance();
b = b_ref;
} else {
- Variant::CallError err;
+ Callable::CallError err;
b = Variant::construct(b_type, NULL, 0, err);
- if (err.error != Variant::CallError::CALL_OK) {
+ if (err.error != Callable::CallError::CALL_OK) {
r_valid = false;
return DataType();
}
}
// Avoid division by zero
- if (a_type == Variant::INT || a_type == Variant::REAL) {
+ if (a_type == Variant::INT || a_type == Variant::FLOAT) {
Variant::evaluate(Variant::OP_ADD, a, 1, a, r_valid);
}
- if (b_type == Variant::INT || b_type == Variant::REAL) {
+ if (b_type == Variant::INT || b_type == Variant::FLOAT) {
Variant::evaluate(Variant::OP_ADD, b, 1, b, r_valid);
}
if (a_type == Variant::STRING && b_type != Variant::ARRAY) {
@@ -6228,7 +6218,7 @@ GDScriptParser::Node *GDScriptParser::_get_default_value_for_type(const DataType
result = alloc_node<DictionaryNode>();
} else {
ConstantNode *c = alloc_node<ConstantNode>();
- Variant::CallError err;
+ Callable::CallError err;
c->value = Variant::construct(p_type.builtin_type, NULL, 0, err);
result = c;
}
@@ -6541,7 +6531,7 @@ GDScriptParser::DataType GDScriptParser::_reduce_node_type(Node *p_node) {
result.has_type = false;
} break;
default: {
- Variant::CallError err;
+ Callable::CallError err;
Variant temp = Variant::construct(base_type.builtin_type, NULL, 0, err);
bool valid = false;
@@ -6606,16 +6596,18 @@ GDScriptParser::DataType GDScriptParser::_reduce_node_type(Node *p_node) {
if (!error) {
switch (base_type.builtin_type) {
// Expect int or real as index
- case Variant::POOL_BYTE_ARRAY:
- case Variant::POOL_COLOR_ARRAY:
- case Variant::POOL_INT_ARRAY:
- case Variant::POOL_REAL_ARRAY:
- case Variant::POOL_STRING_ARRAY:
- case Variant::POOL_VECTOR2_ARRAY:
- case Variant::POOL_VECTOR3_ARRAY:
+ case Variant::PACKED_BYTE_ARRAY:
+ case Variant::PACKED_COLOR_ARRAY:
+ case Variant::PACKED_INT32_ARRAY:
+ case Variant::PACKED_INT64_ARRAY:
+ case Variant::PACKED_FLOAT32_ARRAY:
+ case Variant::PACKED_FLOAT64_ARRAY:
+ case Variant::PACKED_STRING_ARRAY:
+ case Variant::PACKED_VECTOR2_ARRAY:
+ case Variant::PACKED_VECTOR3_ARRAY:
case Variant::ARRAY:
case Variant::STRING: {
- error = index_type.builtin_type != Variant::INT && index_type.builtin_type != Variant::REAL;
+ error = index_type.builtin_type != Variant::INT && index_type.builtin_type != Variant::FLOAT;
} break;
// Expect String only
case Variant::RECT2:
@@ -6631,7 +6623,7 @@ GDScriptParser::DataType GDScriptParser::_reduce_node_type(Node *p_node) {
case Variant::TRANSFORM2D:
case Variant::BASIS:
case Variant::TRANSFORM: {
- error = index_type.builtin_type != Variant::INT && index_type.builtin_type != Variant::REAL &&
+ error = index_type.builtin_type != Variant::INT && index_type.builtin_type != Variant::FLOAT &&
index_type.builtin_type != Variant::STRING;
} break;
// Expect String or int
@@ -6656,17 +6648,19 @@ GDScriptParser::DataType GDScriptParser::_reduce_node_type(Node *p_node) {
case Variant::STRING:
case Variant::ARRAY:
case Variant::DICTIONARY:
- case Variant::POOL_BYTE_ARRAY:
- case Variant::POOL_COLOR_ARRAY:
- case Variant::POOL_INT_ARRAY:
- case Variant::POOL_REAL_ARRAY:
- case Variant::POOL_STRING_ARRAY:
- case Variant::POOL_VECTOR2_ARRAY:
- case Variant::POOL_VECTOR3_ARRAY: {
+ case Variant::PACKED_BYTE_ARRAY:
+ case Variant::PACKED_COLOR_ARRAY:
+ case Variant::PACKED_INT32_ARRAY:
+ case Variant::PACKED_INT64_ARRAY:
+ case Variant::PACKED_FLOAT32_ARRAY:
+ case Variant::PACKED_FLOAT64_ARRAY:
+ case Variant::PACKED_STRING_ARRAY:
+ case Variant::PACKED_VECTOR2_ARRAY:
+ case Variant::PACKED_VECTOR3_ARRAY: {
break;
}
default: {
- Variant::CallError err;
+ Callable::CallError err;
Variant temp = Variant::construct(base_type.builtin_type, NULL, 0, err);
bool valid = false;
@@ -6701,41 +6695,43 @@ GDScriptParser::DataType GDScriptParser::_reduce_node_type(Node *p_node) {
case Variant::NIL:
case Variant::BOOL:
case Variant::INT:
- case Variant::REAL:
+ case Variant::FLOAT:
case Variant::NODE_PATH:
case Variant::_RID: {
_set_error("Can't index on a value of type \"" + base_type.to_string() + "\".", op->line);
return DataType();
} break;
// Return int
- case Variant::POOL_BYTE_ARRAY:
- case Variant::POOL_INT_ARRAY: {
+ case Variant::PACKED_BYTE_ARRAY:
+ case Variant::PACKED_INT32_ARRAY:
+ case Variant::PACKED_INT64_ARRAY: {
result.builtin_type = Variant::INT;
} break;
// Return real
- case Variant::POOL_REAL_ARRAY:
+ case Variant::PACKED_FLOAT32_ARRAY:
+ case Variant::PACKED_FLOAT64_ARRAY:
case Variant::VECTOR2:
case Variant::VECTOR3:
case Variant::QUAT: {
- result.builtin_type = Variant::REAL;
+ result.builtin_type = Variant::FLOAT;
} break;
// Return color
- case Variant::POOL_COLOR_ARRAY: {
+ case Variant::PACKED_COLOR_ARRAY: {
result.builtin_type = Variant::COLOR;
} break;
// Return string
- case Variant::POOL_STRING_ARRAY:
+ case Variant::PACKED_STRING_ARRAY:
case Variant::STRING: {
result.builtin_type = Variant::STRING;
} break;
// Return Vector2
- case Variant::POOL_VECTOR2_ARRAY:
+ case Variant::PACKED_VECTOR2_ARRAY:
case Variant::TRANSFORM2D:
case Variant::RECT2: {
result.builtin_type = Variant::VECTOR2;
} break;
// Return Vector3
- case Variant::POOL_VECTOR3_ARRAY:
+ case Variant::PACKED_VECTOR3_ARRAY:
case Variant::AABB:
case Variant::BASIS: {
result.builtin_type = Variant::VECTOR3;
@@ -7012,7 +7008,7 @@ GDScriptParser::DataType GDScriptParser::_reduce_function_call_type(const Operat
break;
} else {
#ifdef DEBUG_ENABLED
- if (arg_type.kind == DataType::BUILTIN && arg_type.builtin_type == Variant::INT && par_types[i].kind == DataType::BUILTIN && par_types[i].builtin_type == Variant::REAL) {
+ if (arg_type.kind == DataType::BUILTIN && arg_type.builtin_type == Variant::INT && par_types[i].kind == DataType::BUILTIN && par_types[i].builtin_type == Variant::FLOAT) {
_add_warning(GDScriptWarning::NARROWING_CONVERSION, p_call->line, Variant::get_type_name(tn->vtype));
}
if (par_types[i].may_yield && p_call->arguments[i + 1]->type == Node::TYPE_OPERATOR) {
@@ -7105,7 +7101,7 @@ GDScriptParser::DataType GDScriptParser::_reduce_function_call_type(const Operat
}
if (base_type.kind == DataType::BUILTIN) {
- Variant::CallError err;
+ Callable::CallError err;
Variant tmp = Variant::construct(base_type.builtin_type, NULL, 0, err);
if (check_types) {
@@ -7255,7 +7251,7 @@ GDScriptParser::DataType GDScriptParser::_reduce_function_call_type(const Operat
_mark_line_as_unsafe(p_call->line);
}
} else {
- if (arg_type.kind == DataType::BUILTIN && arg_type.builtin_type == Variant::INT && par_type.kind == DataType::BUILTIN && par_type.builtin_type == Variant::REAL) {
+ if (arg_type.kind == DataType::BUILTIN && arg_type.builtin_type == Variant::INT && par_type.kind == DataType::BUILTIN && par_type.builtin_type == Variant::FLOAT) {
_add_warning(GDScriptWarning::NARROWING_CONVERSION, p_call->line, callee_name);
}
}
@@ -8113,7 +8109,7 @@ void GDScriptParser::_check_block_types(BlockNode *p_block) {
lv->assign = convert_call;
lv->assign_op->arguments.write[1] = convert_call;
#ifdef DEBUG_ENABLED
- if (lv->datatype.builtin_type == Variant::INT && assign_type.builtin_type == Variant::REAL) {
+ if (lv->datatype.builtin_type == Variant::INT && assign_type.builtin_type == Variant::FLOAT) {
_add_warning(GDScriptWarning::NARROWING_CONVERSION, lv->line);
}
#endif // DEBUG_ENABLED
@@ -8250,7 +8246,7 @@ void GDScriptParser::_check_block_types(BlockNode *p_block) {
type_match = true; // Since we are converting, the type is matching
}
#ifdef DEBUG_ENABLED
- if (lh_type.builtin_type == Variant::INT && rh_type.builtin_type == Variant::REAL) {
+ if (lh_type.builtin_type == Variant::INT && rh_type.builtin_type == Variant::FLOAT) {
_add_warning(GDScriptWarning::NARROWING_CONVERSION, op->line);
}
#endif // DEBUG_ENABLED
@@ -8355,7 +8351,7 @@ void GDScriptParser::_check_block_types(BlockNode *p_block) {
if (cn->value.get_type() == Variant::STRING) {
break;
}
- FALLTHROUGH;
+ [[fallthrough]];
}
default: {
_mark_line_as_safe(statement->line);
diff --git a/modules/gdscript/gdscript_tokenizer.cpp b/modules/gdscript/gdscript_tokenizer.cpp
index 11ffa22906..9064998d32 100644
--- a/modules/gdscript/gdscript_tokenizer.cpp
+++ b/modules/gdscript/gdscript_tokenizer.cpp
@@ -106,11 +106,9 @@ const char *GDScriptTokenizer::token_names[TK_MAX] = {
"yield",
"signal",
"breakpoint",
- "rpc",
- "sync",
+ "remote",
"master",
"puppet",
- "slave",
"remotesync",
"mastersync",
"puppetsync",
@@ -148,12 +146,15 @@ static const _bit _type_list[] = {
//types
{ Variant::BOOL, "bool" },
{ Variant::INT, "int" },
- { Variant::REAL, "float" },
+ { Variant::FLOAT, "float" },
{ Variant::STRING, "String" },
{ Variant::VECTOR2, "Vector2" },
+ { Variant::VECTOR2I, "Vector2i" },
{ Variant::RECT2, "Rect2" },
+ { Variant::RECT2I, "Rect2i" },
{ Variant::TRANSFORM2D, "Transform2D" },
{ Variant::VECTOR3, "Vector3" },
+ { Variant::VECTOR3I, "Vector3i" },
{ Variant::AABB, "AABB" },
{ Variant::PLANE, "Plane" },
{ Variant::QUAT, "Quat" },
@@ -162,16 +163,21 @@ static const _bit _type_list[] = {
{ Variant::COLOR, "Color" },
{ Variant::_RID, "RID" },
{ Variant::OBJECT, "Object" },
+ { Variant::STRING_NAME, "StringName" },
{ Variant::NODE_PATH, "NodePath" },
{ Variant::DICTIONARY, "Dictionary" },
+ { Variant::CALLABLE, "Callable" },
+ { Variant::SIGNAL, "Signal" },
{ Variant::ARRAY, "Array" },
- { Variant::POOL_BYTE_ARRAY, "PoolByteArray" },
- { Variant::POOL_INT_ARRAY, "PoolIntArray" },
- { Variant::POOL_REAL_ARRAY, "PoolRealArray" },
- { Variant::POOL_STRING_ARRAY, "PoolStringArray" },
- { Variant::POOL_VECTOR2_ARRAY, "PoolVector2Array" },
- { Variant::POOL_VECTOR3_ARRAY, "PoolVector3Array" },
- { Variant::POOL_COLOR_ARRAY, "PoolColorArray" },
+ { Variant::PACKED_BYTE_ARRAY, "PackedByteArray" },
+ { Variant::PACKED_INT32_ARRAY, "PackedInt32Array" },
+ { Variant::PACKED_INT64_ARRAY, "PackedInt64Array" },
+ { Variant::PACKED_FLOAT32_ARRAY, "PackedFloat32Array" },
+ { Variant::PACKED_FLOAT64_ARRAY, "PackedFloat64Array" },
+ { Variant::PACKED_STRING_ARRAY, "PackedStringArray" },
+ { Variant::PACKED_VECTOR2_ARRAY, "PackedVector2Array" },
+ { Variant::PACKED_VECTOR3_ARRAY, "PackedVector3Array" },
+ { Variant::PACKED_COLOR_ARRAY, "PackedColorArray" },
{ Variant::VARIANT_MAX, NULL },
};
@@ -207,9 +213,7 @@ static const _kws _keyword_list[] = {
{ GDScriptTokenizer::TK_PR_BREAKPOINT, "breakpoint" },
{ GDScriptTokenizer::TK_PR_REMOTE, "remote" },
{ GDScriptTokenizer::TK_PR_MASTER, "master" },
- { GDScriptTokenizer::TK_PR_SLAVE, "slave" },
{ GDScriptTokenizer::TK_PR_PUPPET, "puppet" },
- { GDScriptTokenizer::TK_PR_SYNC, "sync" },
{ GDScriptTokenizer::TK_PR_REMOTESYNC, "remotesync" },
{ GDScriptTokenizer::TK_PR_MASTERSYNC, "mastersync" },
{ GDScriptTokenizer::TK_PR_PUPPETSYNC, "puppetsync" },
@@ -255,7 +259,6 @@ bool GDScriptTokenizer::is_token_literal(int p_offset, bool variable_safe) const
case TK_PR_REMOTE:
case TK_PR_MASTER:
case TK_PR_PUPPET:
- case TK_PR_SYNC:
case TK_PR_REMOTESYNC:
case TK_PR_MASTERSYNC:
case TK_PR_PUPPETSYNC:
@@ -342,7 +345,7 @@ StringName GDScriptTokenizer::get_token_literal(int p_offset) const {
default: {
}
}
- }
+ } break;
case TK_OP_AND:
case TK_OP_OR:
break; // Don't get into default, since they can be non-literal
@@ -480,7 +483,7 @@ void GDScriptTokenizerText::_advance() {
}
while (true) {
- bool is_node_path = false;
+ bool is_string_name = false;
StringMode string_mode = STRING_DOUBLE_QUOTE;
switch (GETCHAR(0)) {
@@ -538,7 +541,7 @@ void GDScriptTokenizerText::_advance() {
ignore_warnings = true;
}
#endif // DEBUG_ENABLED
- FALLTHROUGH;
+ [[fallthrough]];
}
case '\n': {
line++;
@@ -754,8 +757,8 @@ void GDScriptTokenizerText::_advance() {
return;
}
INCPOS(1);
- is_node_path = true;
- FALLTHROUGH;
+ is_string_name = true;
+ [[fallthrough]];
case '\'':
case '"': {
@@ -815,7 +818,7 @@ void GDScriptTokenizerText::_advance() {
break; //wtf
case 'u': {
- //hexnumbarh - oct is deprecated
+ // hex number
i += 1;
for (int j = 0; j < 4; j++) {
CharType c = GETCHAR(i + j);
@@ -865,8 +868,8 @@ void GDScriptTokenizerText::_advance() {
}
INCPOS(i);
- if (is_node_path) {
- _make_constant(NodePath(str));
+ if (is_string_name) {
+ _make_constant(StringName(str));
} else {
_make_constant(str);
}
diff --git a/modules/gdscript/gdscript_tokenizer.h b/modules/gdscript/gdscript_tokenizer.h
index 0efc8551cb..3694825d80 100644
--- a/modules/gdscript/gdscript_tokenizer.h
+++ b/modules/gdscript/gdscript_tokenizer.h
@@ -113,9 +113,7 @@ public:
TK_PR_SIGNAL,
TK_PR_BREAKPOINT,
TK_PR_REMOTE,
- TK_PR_SYNC,
TK_PR_MASTER,
- TK_PR_SLAVE, // Deprecated by TK_PR_PUPPET, to remove in 4.0
TK_PR_PUPPET,
TK_PR_REMOTESYNC,
TK_PR_MASTERSYNC,
diff --git a/modules/gdscript/language_server/gdscript_language_protocol.cpp b/modules/gdscript/language_server/gdscript_language_protocol.cpp
index 7133c6b4be..2243a7b81d 100644
--- a/modules/gdscript/language_server/gdscript_language_protocol.cpp
+++ b/modules/gdscript/language_server/gdscript_language_protocol.cpp
@@ -32,32 +32,107 @@
#include "core/io/json.h"
#include "core/os/copymem.h"
#include "core/project_settings.h"
+#include "editor/editor_log.h"
#include "editor/editor_node.h"
GDScriptLanguageProtocol *GDScriptLanguageProtocol::singleton = NULL;
-void GDScriptLanguageProtocol::on_data_received(int p_id) {
- lastest_client_id = p_id;
- Ref<WebSocketPeer> peer = server->get_peer(p_id);
- PoolByteArray data;
- if (OK == peer->get_packet_buffer(data)) {
- String message;
- message.parse_utf8((const char *)data.read().ptr(), data.size());
- if (message.begins_with("Content-Length:")) return;
- String output = process_message(message);
+Error GDScriptLanguageProtocol::LSPeer::handle_data() {
+ int read = 0;
+ // Read headers
+ if (!has_header) {
+ while (true) {
+ if (req_pos >= LSP_MAX_BUFFER_SIZE) {
+ req_pos = 0;
+ ERR_FAIL_COND_V_MSG(true, ERR_OUT_OF_MEMORY, "Response header too big");
+ }
+ Error err = connection->get_partial_data(&req_buf[req_pos], 1, read);
+ if (err != OK)
+ return FAILED;
+ else if (read != 1) // Busy, wait until next poll
+ return ERR_BUSY;
+ char *r = (char *)req_buf;
+ int l = req_pos;
+
+ // End of headers
+ if (l > 3 && r[l] == '\n' && r[l - 1] == '\r' && r[l - 2] == '\n' && r[l - 3] == '\r') {
+ r[l - 3] = '\0'; // Null terminate to read string
+ String header;
+ header.parse_utf8(r);
+ content_length = header.substr(16).to_int();
+ has_header = true;
+ req_pos = 0;
+ break;
+ }
+ req_pos++;
+ }
+ }
+ if (has_header) {
+ while (req_pos < content_length) {
+ if (req_pos >= LSP_MAX_BUFFER_SIZE) {
+ req_pos = 0;
+ has_header = false;
+ ERR_FAIL_COND_V_MSG(req_pos >= LSP_MAX_BUFFER_SIZE, ERR_OUT_OF_MEMORY, "Response content too big");
+ }
+ Error err = connection->get_partial_data(&req_buf[req_pos], 1, read);
+ if (err != OK)
+ return FAILED;
+ else if (read != 1)
+ return ERR_BUSY;
+ req_pos++;
+ }
+
+ // Parse data
+ String msg;
+ msg.parse_utf8((const char *)req_buf, req_pos);
+
+ // Reset to read again
+ req_pos = 0;
+ has_header = false;
+
+ // Response
+ String output = GDScriptLanguageProtocol::get_singleton()->process_message(msg);
if (!output.empty()) {
- CharString charstr = output.utf8();
- peer->put_packet((const uint8_t *)charstr.ptr(), charstr.length());
+ res_queue.push_back(output.utf8());
}
}
+ return OK;
}
-void GDScriptLanguageProtocol::on_client_connected(int p_id, const String &p_protocal) {
- clients.set(p_id, server->get_peer(p_id));
+Error GDScriptLanguageProtocol::LSPeer::send_data() {
+ int sent = 0;
+ if (!res_queue.empty()) {
+ CharString c_res = res_queue[0];
+ if (res_sent < c_res.size()) {
+ Error err = connection->put_partial_data((const uint8_t *)c_res.get_data() + res_sent, c_res.size() - res_sent - 1, sent);
+ if (err != OK) {
+ return err;
+ }
+ res_sent += sent;
+ }
+ // Response sent
+ if (res_sent >= c_res.size() - 1) {
+ res_sent = 0;
+ res_queue.remove(0);
+ }
+ }
+ return OK;
+}
+
+Error GDScriptLanguageProtocol::on_client_connected() {
+ Ref<StreamPeerTCP> tcp_peer = server->take_connection();
+ ERR_FAIL_COND_V_MSG(clients.size() >= LSP_MAX_CLIENTS, FAILED, "Max client limits reached");
+ Ref<LSPeer> peer = memnew(LSPeer);
+ peer->connection = tcp_peer;
+ clients.set(next_client_id, peer);
+ next_client_id++;
+ EditorNode::get_log()->add_message("Connection Taken", EditorLog::MSG_TYPE_EDITOR);
+ return OK;
}
-void GDScriptLanguageProtocol::on_client_disconnected(int p_id, bool p_was_clean_close) {
- clients.erase(p_id);
+void GDScriptLanguageProtocol::on_client_disconnected(const int &p_client_id) {
+ clients.erase(p_client_id);
+ EditorNode::get_log()->add_message("Disconnected", EditorLog::MSG_TYPE_EDITOR);
}
String GDScriptLanguageProtocol::process_message(const String &p_text) {
@@ -83,11 +158,9 @@ String GDScriptLanguageProtocol::format_output(const String &p_text) {
void GDScriptLanguageProtocol::_bind_methods() {
ClassDB::bind_method(D_METHOD("initialize", "params"), &GDScriptLanguageProtocol::initialize);
ClassDB::bind_method(D_METHOD("initialized", "params"), &GDScriptLanguageProtocol::initialized);
- ClassDB::bind_method(D_METHOD("on_data_received"), &GDScriptLanguageProtocol::on_data_received);
ClassDB::bind_method(D_METHOD("on_client_connected"), &GDScriptLanguageProtocol::on_client_connected);
ClassDB::bind_method(D_METHOD("on_client_disconnected"), &GDScriptLanguageProtocol::on_client_disconnected);
- ClassDB::bind_method(D_METHOD("notify_all_clients", "p_method", "p_params"), &GDScriptLanguageProtocol::notify_all_clients, DEFVAL(Variant()));
- ClassDB::bind_method(D_METHOD("notify_client", "p_method", "p_params", "p_client"), &GDScriptLanguageProtocol::notify_client, DEFVAL(Variant()), DEFVAL(-1));
+ ClassDB::bind_method(D_METHOD("notify_client", "p_method", "p_params"), &GDScriptLanguageProtocol::notify_client, DEFVAL(Variant()), DEFVAL(-1));
ClassDB::bind_method(D_METHOD("is_smart_resolve_enabled"), &GDScriptLanguageProtocol::is_smart_resolve_enabled);
ClassDB::bind_method(D_METHOD("get_text_document"), &GDScriptLanguageProtocol::get_text_document);
ClassDB::bind_method(D_METHOD("get_workspace"), &GDScriptLanguageProtocol::get_workspace);
@@ -116,11 +189,12 @@ Dictionary GDScriptLanguageProtocol::initialize(const Dictionary &p_params) {
Dictionary params;
params["path"] = workspace->root;
Dictionary request = make_notification("gdscrip_client/changeWorkspace", params);
- if (Ref<WebSocketPeer> *peer = clients.getptr(lastest_client_id)) {
+
+ Ref<LSPeer> peer = clients.get(latest_client_id);
+ if (peer != NULL) {
String msg = JSON::print(request);
msg = format_output(msg);
- CharString charstr = msg.utf8();
- (*peer)->put_packet((const uint8_t *)charstr.ptr(), charstr.length());
+ (*peer)->res_queue.push_back(msg.utf8());
}
}
@@ -153,61 +227,59 @@ void GDScriptLanguageProtocol::initialized(const Variant &p_params) {
}
void GDScriptLanguageProtocol::poll() {
- server->poll();
+ if (server->is_connection_available()) {
+ on_client_connected();
+ }
+ const int *id = NULL;
+ while ((id = clients.next(id))) {
+ Ref<LSPeer> peer = clients.get(*id);
+ StreamPeerTCP::Status status = peer->connection->get_status();
+ if (status == StreamPeerTCP::STATUS_NONE || status == StreamPeerTCP::STATUS_ERROR) {
+ on_client_disconnected(*id);
+ id = NULL;
+ } else {
+ if (peer->connection->get_available_bytes() > 0) {
+ latest_client_id = *id;
+ Error err = peer->handle_data();
+ if (err != OK && err != ERR_BUSY) {
+ on_client_disconnected(*id);
+ id = NULL;
+ }
+ }
+ Error err = peer->send_data();
+ if (err != OK && err != ERR_BUSY) {
+ on_client_disconnected(*id);
+ id = NULL;
+ }
+ }
+ }
}
Error GDScriptLanguageProtocol::start(int p_port, const IP_Address &p_bind_ip) {
- if (server == NULL) {
- server = dynamic_cast<WebSocketServer *>(ClassDB::instance("WebSocketServer"));
- ERR_FAIL_COND_V(!server, FAILED);
- server->set_buffers(8192, 1024, 8192, 1024); // 8mb should be way more than enough
- server->connect("data_received", this, "on_data_received");
- server->connect("client_connected", this, "on_client_connected");
- server->connect("client_disconnected", this, "on_client_disconnected");
- }
- server->set_bind_ip(p_bind_ip);
- return server->listen(p_port);
+ return server->listen(p_port, p_bind_ip);
}
void GDScriptLanguageProtocol::stop() {
- const int *ptr = clients.next(NULL);
- while (ptr) {
- clients.get(*ptr)->close();
- ptr = clients.next(ptr);
+ const int *id = NULL;
+ while ((id = clients.next(id))) {
+ Ref<LSPeer> peer = clients.get(*id);
+ peer->connection->disconnect_from_host();
}
- server->stop();
- clients.clear();
-}
-
-void GDScriptLanguageProtocol::notify_all_clients(const String &p_method, const Variant &p_params) {
- Dictionary message = make_notification(p_method, p_params);
- String msg = JSON::print(message);
- msg = format_output(msg);
- CharString charstr = msg.utf8();
- const int *p_id = clients.next(NULL);
- while (p_id != NULL) {
- Ref<WebSocketPeer> peer = clients.get(*p_id);
- (*peer)->put_packet((const uint8_t *)charstr.ptr(), charstr.length());
- p_id = clients.next(p_id);
- }
+ server->stop();
}
-void GDScriptLanguageProtocol::notify_client(const String &p_method, const Variant &p_params, int p_client) {
-
- if (p_client == -1) {
- p_client = lastest_client_id;
+void GDScriptLanguageProtocol::notify_client(const String &p_method, const Variant &p_params, int p_client_id) {
+ if (p_client_id == -1) {
+ p_client_id = latest_client_id;
}
-
- Ref<WebSocketPeer> *peer = clients.getptr(p_client);
+ Ref<LSPeer> peer = clients.get(p_client_id);
ERR_FAIL_COND(peer == NULL);
Dictionary message = make_notification(p_method, p_params);
String msg = JSON::print(message);
msg = format_output(msg);
- CharString charstr = msg.utf8();
-
- (*peer)->put_packet((const uint8_t *)charstr.ptr(), charstr.length());
+ peer->res_queue.push_back(msg.utf8());
}
bool GDScriptLanguageProtocol::is_smart_resolve_enabled() const {
@@ -219,7 +291,7 @@ bool GDScriptLanguageProtocol::is_goto_native_symbols_enabled() const {
}
GDScriptLanguageProtocol::GDScriptLanguageProtocol() {
- server = NULL;
+ server.instance();
singleton = this;
_initialized = false;
workspace.instance();
@@ -228,9 +300,6 @@ GDScriptLanguageProtocol::GDScriptLanguageProtocol() {
set_scope("completionItem", text_document.ptr());
set_scope("workspace", workspace.ptr());
workspace->root = ProjectSettings::get_singleton()->get_resource_path();
-}
-
-GDScriptLanguageProtocol::~GDScriptLanguageProtocol() {
- memdelete(server);
- server = NULL;
+ latest_client_id = 0;
+ next_client_id = 0;
}
diff --git a/modules/gdscript/language_server/gdscript_language_protocol.h b/modules/gdscript/language_server/gdscript_language_protocol.h
index 52c680ab19..3f0ae36af2 100644
--- a/modules/gdscript/language_server/gdscript_language_protocol.h
+++ b/modules/gdscript/language_server/gdscript_language_protocol.h
@@ -31,16 +31,36 @@
#ifndef GDSCRIPT_PROTOCAL_SERVER_H
#define GDSCRIPT_PROTOCAL_SERVER_H
+#include "core/io/stream_peer.h"
+#include "core/io/stream_peer_tcp.h"
+#include "core/io/tcp_server.h"
#include "gdscript_text_document.h"
#include "gdscript_workspace.h"
#include "lsp.hpp"
#include "modules/jsonrpc/jsonrpc.h"
-#include "modules/websocket/websocket_peer.h"
-#include "modules/websocket/websocket_server.h"
+
+#define LSP_MAX_BUFFER_SIZE 4194304
+#define LSP_MAX_CLIENTS 8
class GDScriptLanguageProtocol : public JSONRPC {
GDCLASS(GDScriptLanguageProtocol, JSONRPC)
+private:
+ struct LSPeer : Reference {
+ Ref<StreamPeerTCP> connection;
+
+ uint8_t req_buf[LSP_MAX_BUFFER_SIZE];
+ int req_pos = 0;
+ bool has_header = false;
+ bool has_content = false;
+ int content_length = 0;
+ Vector<CharString> res_queue;
+ int res_sent = 0;
+
+ Error handle_data();
+ Error send_data();
+ };
+
enum LSPErrorCode {
RequestCancelled = -32800,
ContentModified = -32801,
@@ -48,16 +68,16 @@ class GDScriptLanguageProtocol : public JSONRPC {
static GDScriptLanguageProtocol *singleton;
- HashMap<int, Ref<WebSocketPeer> > clients;
- WebSocketServer *server;
- int lastest_client_id;
+ HashMap<int, Ref<LSPeer> > clients;
+ Ref<TCP_Server> server;
+ int latest_client_id;
+ int next_client_id;
Ref<GDScriptTextDocument> text_document;
Ref<GDScriptWorkspace> workspace;
- void on_data_received(int p_id);
- void on_client_connected(int p_id, const String &p_protocal);
- void on_client_disconnected(int p_id, bool p_was_clean_close);
+ Error on_client_connected();
+ void on_client_disconnected(const int &p_client_id);
String process_message(const String &p_text);
String format_output(const String &p_text);
@@ -80,14 +100,12 @@ public:
Error start(int p_port, const IP_Address &p_bind_ip);
void stop();
- void notify_all_clients(const String &p_method, const Variant &p_params = Variant());
- void notify_client(const String &p_method, const Variant &p_params = Variant(), int p_client = -1);
+ void notify_client(const String &p_method, const Variant &p_params = Variant(), int p_client_id = -1);
bool is_smart_resolve_enabled() const;
bool is_goto_native_symbols_enabled() const;
GDScriptLanguageProtocol();
- ~GDScriptLanguageProtocol();
};
#endif
diff --git a/modules/gdscript/language_server/gdscript_text_document.cpp b/modules/gdscript/language_server/gdscript_text_document.cpp
index 0572c5f746..d5723fd20f 100644
--- a/modules/gdscript/language_server/gdscript_text_document.cpp
+++ b/modules/gdscript/language_server/gdscript_text_document.cpp
@@ -321,6 +321,8 @@ Variant GDScriptTextDocument::hover(const Dictionary &p_params) {
lsp::Hover hover;
hover.contents = symbol->render();
+ hover.range.start = params.position;
+ hover.range.end = params.position;
return hover.to_json();
} else if (GDScriptLanguageProtocol::get_singleton()->is_smart_resolve_enabled()) {
diff --git a/modules/gdscript/language_server/gdscript_workspace.cpp b/modules/gdscript/language_server/gdscript_workspace.cpp
index 1c0590cff1..ea54784f96 100644
--- a/modules/gdscript/language_server/gdscript_workspace.cpp
+++ b/modules/gdscript/language_server/gdscript_workspace.cpp
@@ -33,8 +33,11 @@
#include "../gdscript_parser.h"
#include "core/project_settings.h"
#include "core/script_language.h"
+#include "editor/editor_file_system.h"
#include "editor/editor_help.h"
+#include "editor/editor_node.h"
#include "gdscript_language_protocol.h"
+#include "scene/resources/packed_scene.h"
void GDScriptWorkspace::_bind_methods() {
ClassDB::bind_method(D_METHOD("symbol"), &GDScriptWorkspace::symbol);
@@ -373,6 +376,46 @@ void GDScriptWorkspace::publish_diagnostics(const String &p_path) {
GDScriptLanguageProtocol::get_singleton()->notify_client("textDocument/publishDiagnostics", params);
}
+void GDScriptWorkspace::_get_owners(EditorFileSystemDirectory *efsd, String p_path, List<String> &owners) {
+ if (!efsd)
+ return;
+
+ for (int i = 0; i < efsd->get_subdir_count(); i++) {
+ _get_owners(efsd->get_subdir(i), p_path, owners);
+ }
+
+ for (int i = 0; i < efsd->get_file_count(); i++) {
+
+ Vector<String> deps = efsd->get_file_deps(i);
+ bool found = false;
+ for (int j = 0; j < deps.size(); j++) {
+ if (deps[j] == p_path) {
+ found = true;
+ break;
+ }
+ }
+ if (!found)
+ continue;
+
+ owners.push_back(efsd->get_file_path(i));
+ }
+}
+
+Node *GDScriptWorkspace::_get_owner_node(String p_path) {
+ Node *owner_node = NULL;
+ List<String> owners;
+
+ _get_owners(EditorFileSystem::get_singleton()->get_filesystem(), p_path, owners);
+
+ if (owners.size() > 0) {
+ NodePath owner_path = owners[0];
+ Ref<PackedScene> owner_res = ResourceLoader::load(owner_path);
+ owner_node = owner_res->instance(PackedScene::GEN_EDIT_STATE_DISABLED);
+ }
+
+ return owner_node;
+}
+
void GDScriptWorkspace::completion(const lsp::CompletionParams &p_params, List<ScriptCodeCompletionOption> *r_options) {
String path = get_file_path(p_params.textDocument.uri);
@@ -380,8 +423,12 @@ void GDScriptWorkspace::completion(const lsp::CompletionParams &p_params, List<S
bool forced = false;
if (const ExtendGDScriptParser *parser = get_parse_result(path)) {
+ Node *owner_node = _get_owner_node(path);
String code = parser->get_text_for_completion(p_params.position);
- GDScriptLanguage::get_singleton()->complete_code(code, path, NULL, r_options, forced, call_hint);
+ GDScriptLanguage::get_singleton()->complete_code(code, path, owner_node, r_options, forced, call_hint);
+ if (owner_node) {
+ memdelete(owner_node);
+ }
}
}
diff --git a/modules/gdscript/language_server/gdscript_workspace.h b/modules/gdscript/language_server/gdscript_workspace.h
index 146a5cb7c9..8b46d345d9 100644
--- a/modules/gdscript/language_server/gdscript_workspace.h
+++ b/modules/gdscript/language_server/gdscript_workspace.h
@@ -33,12 +33,17 @@
#include "../gdscript_parser.h"
#include "core/variant.h"
+#include "editor/editor_file_system.h"
#include "gdscript_extend_parser.h"
#include "lsp.hpp"
class GDScriptWorkspace : public Reference {
GDCLASS(GDScriptWorkspace, Reference);
+private:
+ void _get_owners(EditorFileSystemDirectory *efsd, String p_path, List<String> &owners);
+ Node *_get_owner_node(String p_path);
+
protected:
static void _bind_methods();
void remove_cache_parser(const String &p_path);