summaryrefslogtreecommitdiff
path: root/modules/mono/csharp_script.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'modules/mono/csharp_script.cpp')
-rw-r--r--modules/mono/csharp_script.cpp271
1 files changed, 132 insertions, 139 deletions
diff --git a/modules/mono/csharp_script.cpp b/modules/mono/csharp_script.cpp
index 0ceb45d425..c7279be97f 100644
--- a/modules/mono/csharp_script.cpp
+++ b/modules/mono/csharp_script.cpp
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -45,16 +45,17 @@
#ifdef TOOLS_ENABLED
#include "core/os/keyboard.h"
#include "editor/bindings_generator.h"
+#include "editor/editor_internal_calls.h"
#include "editor/editor_node.h"
#include "editor/editor_settings.h"
#include "editor/node_dock.h"
+#include "editor/script_templates/templates.gen.h"
#endif
#ifdef DEBUG_METHODS_ENABLED
#include "class_db_api_json.h"
#endif
-#include "editor/editor_internal_calls.h"
#include "godotsharp_dirs.h"
#include "mono_gd/gd_mono_cache.h"
#include "mono_gd/gd_mono_class.h"
@@ -351,57 +352,35 @@ static String get_base_class_name(const String &p_base_class_name, const String
return base_class;
}
-Ref<Script> CSharpLanguage::get_template(const String &p_class_name, const String &p_base_class_name) const {
- String script_template = "using " BINDINGS_NAMESPACE ";\n"
- "using System;\n"
- "\n"
- "public partial class %CLASS% : %BASE%\n"
- "{\n"
- " // Declare member variables here. Examples:\n"
- " // private int a = 2;\n"
- " // private string b = \"text\";\n"
- "\n"
- " // Called when the node enters the scene tree for the first time.\n"
- " public override void _Ready()\n"
- " {\n"
- " \n"
- " }\n"
- "\n"
- "// // Called every frame. 'delta' is the elapsed time since the previous frame.\n"
- "// public override void _Process(float delta)\n"
- "// {\n"
- "// \n"
- "// }\n"
- "}\n";
-
- // Replaces all spaces in p_class_name with underscores to prevent
- // invalid C# Script templates from being generated when the object name
- // has spaces in it.
- String class_name_no_spaces = p_class_name.replace(" ", "_");
- String base_class_name = get_base_class_name(p_base_class_name, class_name_no_spaces);
- script_template = script_template.replace("%BASE%", base_class_name)
- .replace("%CLASS%", class_name_no_spaces);
+bool CSharpLanguage::is_using_templates() {
+ return true;
+}
+Ref<Script> CSharpLanguage::make_template(const String &p_template, const String &p_class_name, const String &p_base_class_name) const {
Ref<CSharpScript> script;
script.instantiate();
- script->set_source_code(script_template);
- script->set_name(class_name_no_spaces);
+ String class_name_no_spaces = p_class_name.replace(" ", "_");
+ String base_class_name = get_base_class_name(p_base_class_name, class_name_no_spaces);
+ String processed_template = p_template;
+ processed_template = processed_template.replace("_BINDINGS_NAMESPACE_", BINDINGS_NAMESPACE)
+ .replace("_BASE_", base_class_name)
+ .replace("_CLASS_", class_name_no_spaces)
+ .replace("_TS_", _get_indentation());
+ script->set_source_code(processed_template);
return script;
}
-bool CSharpLanguage::is_using_templates() {
- return true;
-}
-
-void CSharpLanguage::make_template(const String &p_class_name, const String &p_base_class_name, Ref<Script> &p_script) {
- String src = p_script->get_source_code();
- String class_name_no_spaces = p_class_name.replace(" ", "_");
- String base_class_name = get_base_class_name(p_base_class_name, class_name_no_spaces);
- src = src.replace("%BASE%", base_class_name)
- .replace("%CLASS%", class_name_no_spaces)
- .replace("%TS%", _get_indentation());
- p_script->set_source_code(src);
+Vector<ScriptLanguage::ScriptTemplate> CSharpLanguage::get_built_in_templates(StringName p_object) {
+ Vector<ScriptLanguage::ScriptTemplate> templates;
+#ifdef TOOLS_ENABLED
+ for (int i = 0; i < TEMPLATES_ARRAY_SIZE; i++) {
+ if (TEMPLATES[i].inherit == p_object) {
+ templates.append(TEMPLATES[i]);
+ }
+ }
+#endif
+ return templates;
}
String CSharpLanguage::validate_path(const String &p_path) const {
@@ -409,7 +388,7 @@ String CSharpLanguage::validate_path(const String &p_path) const {
List<String> keywords;
get_reserved_words(&keywords);
if (keywords.find(class_name)) {
- return TTR("Class name can't be a reserved keyword");
+ return RTR("Class name can't be a reserved keyword");
}
return "";
}
@@ -502,11 +481,14 @@ static String variant_type_to_managed_name(const String &p_var_type_name) {
Variant::VECTOR3,
Variant::VECTOR3I,
Variant::TRANSFORM2D,
+ Variant::VECTOR4,
+ Variant::VECTOR4I,
Variant::PLANE,
Variant::QUATERNION,
Variant::AABB,
Variant::BASIS,
Variant::TRANSFORM3D,
+ Variant::PROJECTION,
Variant::COLOR,
Variant::STRING_NAME,
Variant::NODE_PATH,
@@ -550,10 +532,10 @@ String CSharpLanguage::make_function(const String &, const String &, const Packe
String CSharpLanguage::_get_indentation() const {
#ifdef TOOLS_ENABLED
if (Engine::get_singleton()->is_editor_hint()) {
- bool use_space_indentation = EDITOR_DEF("text_editor/behavior/indent/type", 0);
+ bool use_space_indentation = EDITOR_GET("text_editor/behavior/indent/type");
if (use_space_indentation) {
- int indent_size = EDITOR_DEF("text_editor/behavior/indent/size", 4);
+ int indent_size = EDITOR_GET("text_editor/behavior/indent/size");
String space_indent = "";
for (int i = 0; i < indent_size; i++) {
@@ -707,10 +689,10 @@ void CSharpLanguage::pre_unsafe_unreference(Object *p_obj) {
#ifdef DEBUG_ENABLED
MutexLock lock(unsafe_object_references_lock);
ObjectID id = p_obj->get_instance_id();
- Map<ObjectID, int>::Element *elem = unsafe_object_references.find(id);
+ HashMap<ObjectID, int>::Iterator elem = unsafe_object_references.find(id);
ERR_FAIL_NULL(elem);
- if (--elem->value() == 0) {
- unsafe_object_references.erase(elem);
+ if (--elem->value == 0) {
+ unsafe_object_references.remove(elem);
}
#endif
}
@@ -896,7 +878,7 @@ void CSharpLanguage::reload_assemblies(bool p_soft_reload) {
// Script::instances are deleted during managed object disposal, which happens on domain finalize.
// Only placeholders are kept. Therefore we need to keep a copy before that happens.
- for (Object *&obj : script->instances) {
+ for (Object *obj : script->instances) {
script->pending_reload_instances.insert(obj->get_instance_id());
RefCounted *rc = Object::cast_to<RefCounted>(obj);
@@ -906,7 +888,7 @@ void CSharpLanguage::reload_assemblies(bool p_soft_reload) {
}
#ifdef TOOLS_ENABLED
- for (PlaceHolderScriptInstance *&script_instance : script->placeholders) {
+ for (PlaceHolderScriptInstance *script_instance : script->placeholders) {
Object *obj = script_instance->get_owner();
script->pending_reload_instances.insert(obj->get_instance_id());
@@ -918,9 +900,9 @@ void CSharpLanguage::reload_assemblies(bool p_soft_reload) {
#endif
// Save state and remove script from instances
- Map<ObjectID, CSharpScript::StateBackup> &owners_map = script->pending_reload_state;
+ RBMap<ObjectID, CSharpScript::StateBackup> &owners_map = script->pending_reload_state;
- for (Object *&obj : script->instances) {
+ for (Object *obj : script->instances) {
ERR_CONTINUE(!obj->get_script_instance());
CSharpInstance *csi = static_cast<CSharpInstance *>(obj->get_script_instance());
@@ -943,9 +925,9 @@ void CSharpLanguage::reload_assemblies(bool p_soft_reload) {
// After the state of all instances is saved, clear scripts and script instances
for (Ref<CSharpScript> &script : scripts) {
- while (script->instances.front()) {
- Object *obj = script->instances.front()->get();
- obj->set_script(REF()); // Remove script and existing script instances (placeholder are not removed before domain reload)
+ while (script->instances.begin()) {
+ Object *obj = *script->instances.begin();
+ obj->set_script(Ref<RefCounted>()); // Remove script and existing script instances (placeholder are not removed before domain reload)
}
script->_clear();
@@ -1120,14 +1102,14 @@ void CSharpLanguage::reload_assemblies(bool p_soft_reload) {
const StringName &name = G.first;
const Array &serialized_data = G.second;
- Map<StringName, CSharpScript::EventSignal>::Element *match = script->event_signals.find(name);
+ HashMap<StringName, CSharpScript::EventSignal>::Iterator match = script->event_signals.find(name);
if (!match) {
// The event or its signal attribute were removed
continue;
}
- const CSharpScript::EventSignal &event_signal = match->value();
+ const CSharpScript::EventSignal &event_signal = match->value;
MonoObject *managed_serialized_data = GDMonoMarshal::variant_to_mono_object(serialized_data);
MonoDelegate *delegate = nullptr;
@@ -1191,8 +1173,8 @@ void CSharpLanguage::reload_assemblies(bool p_soft_reload) {
#ifdef TOOLS_ENABLED
// FIXME: Hack to refresh editor in order to display new properties and signals. See if there is a better alternative.
if (Engine::get_singleton()->is_editor_hint()) {
- EditorNode::get_singleton()->get_inspector()->update_tree();
- NodeDock::singleton->update_lists();
+ InspectorDock::get_inspector_singleton()->update_tree();
+ NodeDock::get_singleton()->update_lists();
}
#endif
}
@@ -1449,7 +1431,7 @@ bool CSharpLanguage::setup_csharp_script_binding(CSharpScriptBinding &r_script_b
return true;
}
-Map<Object *, CSharpScriptBinding>::Element *CSharpLanguage::insert_script_binding(Object *p_object, const CSharpScriptBinding &p_script_binding) {
+RBMap<Object *, CSharpScriptBinding>::Element *CSharpLanguage::insert_script_binding(Object *p_object, const CSharpScriptBinding &p_script_binding) {
return script_bindings.insert(p_object, p_script_binding);
}
@@ -1458,7 +1440,7 @@ void *CSharpLanguage::_instance_binding_create_callback(void *, void *p_instance
MutexLock lock(csharp_lang->language_bind_mutex);
- Map<Object *, CSharpScriptBinding>::Element *match = csharp_lang->script_bindings.find((Object *)p_instance);
+ RBMap<Object *, CSharpScriptBinding>::Element *match = csharp_lang->script_bindings.find((Object *)p_instance);
if (match) {
return (void *)match;
}
@@ -1488,7 +1470,7 @@ void CSharpLanguage::_instance_binding_free_callback(void *, void *, void *p_bin
{
MutexLock lock(csharp_lang->language_bind_mutex);
- Map<Object *, CSharpScriptBinding>::Element *data = (Map<Object *, CSharpScriptBinding>::Element *)p_binding;
+ RBMap<Object *, CSharpScriptBinding>::Element *data = (RBMap<Object *, CSharpScriptBinding>::Element *)p_binding;
CSharpScriptBinding &script_binding = data->value();
@@ -1509,7 +1491,7 @@ void CSharpLanguage::_instance_binding_free_callback(void *, void *, void *p_bin
GDNativeBool CSharpLanguage::_instance_binding_reference_callback(void *p_token, void *p_binding, GDNativeBool p_reference) {
CRASH_COND(!p_binding);
- CSharpScriptBinding &script_binding = ((Map<Object *, CSharpScriptBinding>::Element *)p_binding)->get();
+ CSharpScriptBinding &script_binding = ((RBMap<Object *, CSharpScriptBinding>::Element *)p_binding)->get();
RefCounted *rc_owner = Object::cast_to<RefCounted>(script_binding.owner);
@@ -1579,7 +1561,7 @@ void *CSharpLanguage::get_instance_binding(Object *p_object) {
// `setup_csharp_script_binding` may call `reference()`. It was moved here outside to fix that.
if (binding) {
- CSharpScriptBinding &script_binding = ((Map<Object *, CSharpScriptBinding>::Element *)binding)->value();
+ CSharpScriptBinding &script_binding = ((RBMap<Object *, CSharpScriptBinding>::Element *)binding)->value();
if (!script_binding.inited) {
MutexLock lock(CSharpLanguage::get_singleton()->get_language_bind_mutex());
@@ -1762,7 +1744,16 @@ void CSharpInstance::get_properties_state_for_reloading(List<Pair<StringName, Va
ManagedType managedType;
- GDMonoField *field = script->script_class->get_field(state_pair.first);
+ GDMonoField *field = nullptr;
+ GDMonoClass *top = script->script_class;
+ while (top && top != script->native) {
+ field = top->get_field(state_pair.first);
+ if (field) {
+ break;
+ }
+
+ top = top->get_parent_class();
+ }
if (!field) {
continue; // Properties ignored. We get the property baking fields instead.
}
@@ -1810,8 +1801,8 @@ void CSharpInstance::get_event_signals_state_for_reloading(List<Pair<StringName,
void CSharpInstance::get_property_list(List<PropertyInfo> *p_properties) const {
List<PropertyInfo> props;
- for (OrderedHashMap<StringName, PropertyInfo>::ConstElement E = script->member_info.front(); E; E = E.next()) {
- props.push_front(E.value());
+ for (const KeyValue<StringName, PropertyInfo> &E : script->member_info) {
+ props.push_front(E.value);
}
// Call _get_property_list
@@ -1907,7 +1898,7 @@ bool CSharpInstance::has_method(const StringName &p_method) const {
return false;
}
-Variant CSharpInstance::call(const StringName &p_method, const Variant **p_args, int p_argcount, Callable::CallError &r_error) {
+Variant CSharpInstance::callp(const StringName &p_method, const Variant **p_args, int p_argcount, Callable::CallError &r_error) {
ERR_FAIL_COND_V(!script.is_valid(), Variant());
GD_MONO_SCOPE_THREAD_ATTACH;
@@ -2150,8 +2141,8 @@ bool CSharpInstance::refcount_decremented() {
return ref_dying;
}
-const Vector<Multiplayer::RPCConfig> CSharpInstance::get_rpc_methods() const {
- return script->get_rpc_methods();
+const Variant CSharpInstance::get_rpc_config() const {
+ return script->get_rpc_config();
}
void CSharpInstance::notification(int p_notification) {
@@ -2313,7 +2304,7 @@ CSharpInstance::~CSharpInstance() {
void *data = CSharpLanguage::get_instance_binding(owner);
CRASH_COND(data == nullptr);
- CSharpScriptBinding &script_binding = ((Map<Object *, CSharpScriptBinding>::Element *)data)->get();
+ CSharpScriptBinding &script_binding = ((RBMap<Object *, CSharpScriptBinding>::Element *)data)->get();
CRASH_COND(!script_binding.inited);
#ifdef DEBUG_ENABLED
@@ -2327,9 +2318,9 @@ CSharpInstance::~CSharpInstance() {
#ifdef DEBUG_ENABLED
// CSharpInstance must not be created unless it's going to be added to the list for sure
- Set<Object *>::Element *match = script->instances.find(owner);
+ HashSet<Object *>::Iterator match = script->instances.find(owner);
CRASH_COND(!match);
- script->instances.erase(match);
+ script->instances.remove(match);
#else
script->instances.erase(owner);
#endif
@@ -2343,7 +2334,7 @@ void CSharpScript::_placeholder_erased(PlaceHolderScriptInstance *p_placeholder)
#endif
#ifdef TOOLS_ENABLED
-void CSharpScript::_update_exports_values(Map<StringName, Variant> &values, List<PropertyInfo> &propnames) {
+void CSharpScript::_update_exports_values(HashMap<StringName, Variant> &values, List<PropertyInfo> &propnames) {
if (base_cache.is_valid()) {
base_cache->_update_exports_values(values, propnames);
}
@@ -2579,12 +2570,12 @@ bool CSharpScript::_update_exports(PlaceHolderScriptInstance *p_instance_to_upda
if ((changed || p_instance_to_update) && placeholders.size()) {
// Update placeholders if any
- Map<StringName, Variant> values;
+ HashMap<StringName, Variant> values;
List<PropertyInfo> propnames;
_update_exports_values(values, propnames);
if (changed) {
- for (PlaceHolderScriptInstance *&script_instance : placeholders) {
+ for (PlaceHolderScriptInstance *script_instance : placeholders) {
script_instance->update(propnames, values);
}
} else {
@@ -2819,7 +2810,8 @@ int CSharpScript::_try_get_member_export_hint(IMonoClassMember *p_member, Manage
GD_MONO_ASSERT_THREAD_ATTACHED;
if (p_variant_type == Variant::INT && p_type.type_encoding == MONO_TYPE_VALUETYPE && mono_class_is_enum(p_type.type_class->get_mono_ptr())) {
- r_hint = PROPERTY_HINT_ENUM;
+ MonoReflectionType *reftype = mono_type_get_object(mono_domain_get(), p_type.type_class->get_mono_type());
+ r_hint = GDMonoUtils::Marshal::type_has_flags_attribute(reftype) ? PROPERTY_HINT_FLAGS : PROPERTY_HINT_ENUM;
Vector<MonoClassField *> fields = p_type.type_class->get_enum_fields();
@@ -2856,7 +2848,8 @@ int CSharpScript::_try_get_member_export_hint(IMonoClassMember *p_member, Manage
uint64_t val = GDMonoUtils::unbox_enum_value(val_obj, enum_basetype, r_error);
ERR_FAIL_COND_V_MSG(r_error, -1, "Failed to unbox '" + enum_field_name + "' constant enum value.");
- if (val != (unsigned int)i) {
+ unsigned int expected_val = r_hint == PROPERTY_HINT_FLAGS ? 1 << i : i;
+ if (val != expected_val) {
uses_default_values = false;
}
@@ -2876,6 +2869,12 @@ int CSharpScript::_try_get_member_export_hint(IMonoClassMember *p_member, Manage
r_hint = PROPERTY_HINT_RESOURCE_TYPE;
r_hint_string = String(NATIVE_GDMONOCLASS_NAME(field_native_class));
+ } else if (p_variant_type == Variant::OBJECT && CACHED_CLASS(Node)->is_assignable_from(p_type.type_class)) {
+ GDMonoClass *field_native_class = GDMonoUtils::get_class_native_base(p_type.type_class);
+ CRASH_COND(field_native_class == nullptr);
+
+ r_hint = PROPERTY_HINT_NODE_TYPE;
+ r_hint_string = String(NATIVE_GDMONOCLASS_NAME(field_native_class));
} else if (p_allow_generics && p_variant_type == Variant::ARRAY) {
// Nested arrays are not supported in the inspector
@@ -2922,7 +2921,7 @@ int CSharpScript::_try_get_member_export_hint(IMonoClassMember *p_member, Manage
}
#endif
-Variant CSharpScript::call(const StringName &p_method, const Variant **p_args, int p_argcount, Callable::CallError &r_error) {
+Variant CSharpScript::callp(const StringName &p_method, const Variant **p_args, int p_argcount, Callable::CallError &r_error) {
if (unlikely(GDMono::get_singleton() == nullptr)) {
// Probably not the best error but eh.
r_error.error = Callable::CallError::CALL_ERROR_INSTANCE_IS_NULL;
@@ -2950,7 +2949,7 @@ Variant CSharpScript::call(const StringName &p_method, const Variant **p_args, i
}
// No static method found. Try regular instance calls
- return Script::call(p_method, p_args, p_argcount, r_error);
+ return Script::callp(p_method, p_args, p_argcount, r_error);
}
void CSharpScript::_resource_path_changed() {
@@ -3009,6 +3008,7 @@ void CSharpScript::initialize_for_managed_type(Ref<CSharpScript> p_script, GDMon
CRASH_COND(p_script->native == nullptr);
p_script->valid = true;
+ p_script->reload_invalidated = false;
update_script_class_info(p_script);
@@ -3060,7 +3060,7 @@ void CSharpScript::update_script_class_info(Ref<CSharpScript> p_script) {
p_script->script_class->fetch_methods_with_godot_api_checks(p_script->native);
- p_script->rpc_functions.clear();
+ p_script->rpc_config.clear();
GDMonoClass *top = p_script->script_class;
while (top && top != p_script->native) {
@@ -3072,17 +3072,9 @@ void CSharpScript::update_script_class_info(Ref<CSharpScript> p_script) {
Vector<GDMonoMethod *> methods = top->get_all_methods();
for (int i = 0; i < methods.size(); i++) {
if (!methods[i]->is_static()) {
- Multiplayer::RPCMode mode = p_script->_member_get_rpc_mode(methods[i]);
- if (Multiplayer::RPC_MODE_DISABLED != mode) {
- Multiplayer::RPCConfig nd;
- nd.name = methods[i]->get_name();
- nd.rpc_mode = mode;
- // TODO Transfer mode, channel
- nd.transfer_mode = Multiplayer::TRANSFER_MODE_RELIABLE;
- nd.channel = 0;
- if (-1 == p_script->rpc_functions.find(nd)) {
- p_script->rpc_functions.push_back(nd);
- }
+ const Variant rpc_config = p_script->_member_get_rpc_config(methods[i]);
+ if (rpc_config.get_type() != Variant::NIL) {
+ p_script->rpc_config[methods[i]->get_name()] = rpc_config;
}
}
}
@@ -3091,9 +3083,6 @@ void CSharpScript::update_script_class_info(Ref<CSharpScript> p_script) {
top = top->get_parent_class();
}
- // Sort so we are 100% that they are always the same.
- p_script->rpc_functions.sort_custom<Multiplayer::SortRPCConfig>();
-
p_script->load_script_signals(p_script->script_class, p_script->native);
}
@@ -3155,7 +3144,7 @@ CSharpInstance *CSharpScript::_create_instance(const Variant **p_args, int p_arg
void *data = CSharpLanguage::get_existing_instance_binding(p_owner);
CRASH_COND(data == nullptr);
- CSharpScriptBinding &script_binding = ((Map<Object *, CSharpScriptBinding>::Element *)data)->get();
+ CSharpScriptBinding &script_binding = ((RBMap<Object *, CSharpScriptBinding>::Element *)data)->get();
if (script_binding.inited && !script_binding.gchandle.is_released()) {
MonoObject *mono_object = script_binding.gchandle.get_target();
if (mono_object) {
@@ -3232,10 +3221,10 @@ Variant CSharpScript::_new(const Variant **p_args, int p_argcount, Callable::Cal
Object *owner = ClassDB::instantiate(NATIVE_GDMONOCLASS_NAME(native));
- REF ref;
+ Ref<RefCounted> ref;
RefCounted *r = Object::cast_to<RefCounted>(owner);
if (r) {
- ref = REF(r);
+ ref = Ref<RefCounted>(r);
}
CSharpInstance *instance = _create_instance(p_args, p_argcount, owner, r != nullptr, r_error);
@@ -3258,6 +3247,8 @@ ScriptInstance *CSharpScript::instance_create(Object *p_this) {
CRASH_COND(!valid);
#endif
+ GD_MONO_SCOPE_THREAD_ATTACH;
+
if (native) {
StringName native_name = NATIVE_GDMONOCLASS_NAME(native);
if (!ClassDB::is_parent_class(p_this->get_class_name(), native_name)) {
@@ -3270,8 +3261,6 @@ ScriptInstance *CSharpScript::instance_create(Object *p_this) {
}
}
- GD_MONO_SCOPE_THREAD_ATTACH;
-
Callable::CallError unchecked_error;
return _create_instance(nullptr, 0, p_this, Object::cast_to<RefCounted>(p_this) != nullptr, unchecked_error);
}
@@ -3365,13 +3354,13 @@ MethodInfo CSharpScript::get_method_info(const StringName &p_method) const {
}
Error CSharpScript::reload(bool p_keep_state) {
- bool has_instances;
- {
- MutexLock lock(CSharpLanguage::get_singleton()->script_instances_mutex);
- has_instances = instances.size();
+ if (!reload_invalidated) {
+ return OK;
}
- ERR_FAIL_COND_V(!p_keep_state && has_instances, ERR_ALREADY_IN_USE);
+ // In the case of C#, reload doesn't really do any script reloading.
+ // That's done separately via domain reloading.
+ reload_invalidated = false;
GD_MONO_SCOPE_THREAD_ATTACH;
@@ -3412,9 +3401,9 @@ ScriptLanguage *CSharpScript::get_language() const {
bool CSharpScript::get_property_default_value(const StringName &p_property, Variant &r_value) const {
#ifdef TOOLS_ENABLED
- const Map<StringName, Variant>::Element *E = exported_members_defval_cache.find(p_property);
+ HashMap<StringName, Variant>::ConstIterator E = exported_members_defval_cache.find(p_property);
if (E) {
- r_value = E->get();
+ r_value = E->value;
return true;
}
@@ -3502,8 +3491,8 @@ Ref<Script> CSharpScript::get_base_script() const {
void CSharpScript::get_script_property_list(List<PropertyInfo> *r_list) const {
List<PropertyInfo> props;
- for (OrderedHashMap<StringName, PropertyInfo>::ConstElement E = member_info.front(); E; E = E.next()) {
- props.push_front(E.value());
+ for (const KeyValue<StringName, PropertyInfo> &E : member_info) {
+ props.push_front(E.value);
}
for (const PropertyInfo &prop : props) {
@@ -3516,19 +3505,24 @@ int CSharpScript::get_member_line(const StringName &p_member) const {
return -1;
}
-Multiplayer::RPCMode CSharpScript::_member_get_rpc_mode(IMonoClassMember *p_member) const {
- if (p_member->has_attribute(CACHED_CLASS(AnyPeerAttribute))) {
- return Multiplayer::RPC_MODE_ANY_PEER;
- }
- if (p_member->has_attribute(CACHED_CLASS(AuthorityAttribute))) {
- return Multiplayer::RPC_MODE_AUTHORITY;
+Variant CSharpScript::_member_get_rpc_config(IMonoClassMember *p_member) const {
+ Variant out;
+
+ MonoObject *rpc_attribute = p_member->get_attribute(CACHED_CLASS(RPCAttribute));
+ if (rpc_attribute != nullptr) {
+ Dictionary rpc_config;
+ rpc_config["rpc_mode"] = CACHED_PROPERTY(RPCAttribute, Mode)->get_int_value(rpc_attribute);
+ rpc_config["call_local"] = CACHED_PROPERTY(RPCAttribute, CallLocal)->get_bool_value(rpc_attribute);
+ rpc_config["transfer_mode"] = CACHED_PROPERTY(RPCAttribute, TransferMode)->get_int_value(rpc_attribute);
+ rpc_config["channel"] = CACHED_PROPERTY(RPCAttribute, TransferChannel)->get_int_value(rpc_attribute);
+ out = rpc_config;
}
- return Multiplayer::RPC_MODE_DISABLED;
+ return out;
}
-const Vector<Multiplayer::RPCConfig> CSharpScript::get_rpc_methods() const {
- return rpc_functions;
+const Variant CSharpScript::get_rpc_config() const {
+ return rpc_config;
}
Error CSharpScript::load_source_code(const String &p_path) {
@@ -3558,6 +3552,7 @@ void CSharpScript::_update_name() {
void CSharpScript::_clear() {
tool = false;
valid = false;
+ reload_invalidated = true;
base = nullptr;
native = nullptr;
@@ -3584,7 +3579,7 @@ CSharpScript::~CSharpScript() {
#endif
}
-void CSharpScript::get_members(Set<StringName> *p_members) {
+void CSharpScript::get_members(HashSet<StringName> *p_members) {
#if defined(TOOLS_ENABLED) || defined(DEBUG_ENABLED)
if (p_members) {
for (const StringName &member_name : exported_members_names) {
@@ -3596,7 +3591,7 @@ void CSharpScript::get_members(Set<StringName> *p_members) {
/*************** RESOURCE ***************/
-RES ResourceFormatLoaderCSharpScript::load(const String &p_path, const String &p_original_path, Error *r_error, bool p_use_sub_threads, float *r_progress, CacheMode p_cache_mode) {
+Ref<Resource> ResourceFormatLoaderCSharpScript::load(const String &p_path, const String &p_original_path, Error *r_error, bool p_use_sub_threads, float *r_progress, CacheMode p_cache_mode) {
if (r_error) {
*r_error = ERR_FILE_CANT_OPEN;
}
@@ -3609,7 +3604,7 @@ RES ResourceFormatLoaderCSharpScript::load(const String &p_path, const String &p
#if defined(DEBUG_ENABLED) || defined(TOOLS_ENABLED)
Error err = script->load_source_code(p_path);
- ERR_FAIL_COND_V_MSG(err != OK, RES(), "Cannot load C# script file '" + p_path + "'.");
+ ERR_FAIL_COND_V_MSG(err != OK, Ref<Resource>(), "Cannot load C# script file '" + p_path + "'.");
#endif
script->set_path(p_original_path);
@@ -3635,7 +3630,7 @@ String ResourceFormatLoaderCSharpScript::get_resource_type(const String &p_path)
return p_path.get_extension().to_lower() == "cs" ? CSharpLanguage::get_singleton()->get_type() : "";
}
-Error ResourceFormatSaverCSharpScript::save(const String &p_path, const RES &p_resource, uint32_t p_flags) {
+Error ResourceFormatSaverCSharpScript::save(const Ref<Resource> &p_resource, const String &p_path, uint32_t p_flags) {
Ref<CSharpScript> sqscr = p_resource;
ERR_FAIL_COND_V(sqscr.is_null(), ERR_INVALID_PARAMETER);
@@ -3651,20 +3646,18 @@ Error ResourceFormatSaverCSharpScript::save(const String &p_path, const RES &p_r
}
#endif
- Error err;
- FileAccess *file = FileAccess::open(p_path, FileAccess::WRITE, &err);
- ERR_FAIL_COND_V_MSG(err != OK, err, "Cannot save C# script file '" + p_path + "'.");
+ {
+ Error err;
+ Ref<FileAccess> file = FileAccess::open(p_path, FileAccess::WRITE, &err);
+ ERR_FAIL_COND_V_MSG(err != OK, err, "Cannot save C# script file '" + p_path + "'.");
- file->store_string(source);
+ file->store_string(source);
- if (file->get_error() != OK && file->get_error() != ERR_FILE_EOF) {
- memdelete(file);
- return ERR_CANT_CREATE;
+ if (file->get_error() != OK && file->get_error() != ERR_FILE_EOF) {
+ return ERR_CANT_CREATE;
+ }
}
- file->close();
- memdelete(file);
-
#ifdef TOOLS_ENABLED
if (ScriptServer::is_reload_scripts_on_save_enabled()) {
CSharpLanguage::get_singleton()->reload_tool_script(p_resource, false);
@@ -3674,13 +3667,13 @@ Error ResourceFormatSaverCSharpScript::save(const String &p_path, const RES &p_r
return OK;
}
-void ResourceFormatSaverCSharpScript::get_recognized_extensions(const RES &p_resource, List<String> *p_extensions) const {
+void ResourceFormatSaverCSharpScript::get_recognized_extensions(const Ref<Resource> &p_resource, List<String> *p_extensions) const {
if (Object::cast_to<CSharpScript>(p_resource.ptr())) {
p_extensions->push_back("cs");
}
}
-bool ResourceFormatSaverCSharpScript::recognize(const RES &p_resource) const {
+bool ResourceFormatSaverCSharpScript::recognize(const Ref<Resource> &p_resource) const {
return Object::cast_to<CSharpScript>(p_resource.ptr()) != nullptr;
}