diff options
Diffstat (limited to 'modules')
48 files changed, 1088 insertions, 561 deletions
diff --git a/modules/gdscript/gdscript.cpp b/modules/gdscript/gdscript.cpp index bd6cef0b6e..60230257e0 100644 --- a/modules/gdscript/gdscript.cpp +++ b/modules/gdscript/gdscript.cpp @@ -808,6 +808,11 @@ String GDScript::_get_debug_path() const { } Error GDScript::reload(bool p_keep_state) { + if (reloading) { + return OK; + } + reloading = true; + bool has_instances; { MutexLock lock(GDScriptLanguage::singleton->mutex); @@ -830,6 +835,7 @@ Error GDScript::reload(bool p_keep_state) { // Loading a template, don't parse. #ifdef TOOLS_ENABLED if (EditorPaths::get_singleton() && basedir.begins_with(EditorPaths::get_singleton()->get_project_script_templates_dir())) { + reloading = false; return OK; } #endif @@ -839,11 +845,10 @@ Error GDScript::reload(bool p_keep_state) { if (source_path.is_empty()) { source_path = get_path(); } - if (!source_path.is_empty()) { - MutexLock lock(GDScriptCache::singleton->lock); - if (!GDScriptCache::singleton->shallow_gdscript_cache.has(source_path)) { - GDScriptCache::singleton->shallow_gdscript_cache[source_path] = this; - } + Ref<GDScript> cached_script = GDScriptCache::get_cached_script(source_path); + if (!source_path.is_empty() && cached_script.is_null()) { + MutexLock lock(GDScriptCache::singleton->mutex); + GDScriptCache::singleton->shallow_gdscript_cache[source_path] = Ref<GDScript>(this); } } @@ -856,6 +861,7 @@ Error GDScript::reload(bool p_keep_state) { } // TODO: Show all error messages. _err_print_error("GDScript::reload", path.is_empty() ? "built-in" : (const char *)path.utf8().get_data(), parser.get_errors().front()->get().line, ("Parse Error: " + parser.get_errors().front()->get().message).utf8().get_data(), false, ERR_HANDLER_SCRIPT); + reloading = false; return ERR_PARSE_ERROR; } @@ -872,6 +878,7 @@ Error GDScript::reload(bool p_keep_state) { _err_print_error("GDScript::reload", path.is_empty() ? "built-in" : (const char *)path.utf8().get_data(), e->get().line, ("Parse Error: " + e->get().message).utf8().get_data(), false, ERR_HANDLER_SCRIPT); e = e->next(); } + reloading = false; return ERR_PARSE_ERROR; } @@ -886,8 +893,10 @@ Error GDScript::reload(bool p_keep_state) { GDScriptLanguage::get_singleton()->debug_break_parse(_get_debug_path(), compiler.get_error_line(), "Parser Error: " + compiler.get_error()); } _err_print_error("GDScript::reload", path.is_empty() ? "built-in" : (const char *)path.utf8().get_data(), compiler.get_error_line(), ("Compile Error: " + compiler.get_error()).utf8().get_data(), false, ERR_HANDLER_SCRIPT); + reloading = false; return ERR_COMPILATION_FAILED; } else { + reloading = false; return err; } } @@ -900,6 +909,7 @@ Error GDScript::reload(bool p_keep_state) { } #endif + reloading = false; return OK; } @@ -1006,16 +1016,22 @@ Error GDScript::load_byte_code(const String &p_path) { } void GDScript::set_path(const String &p_path, bool p_take_over) { + String old_path = path; if (is_root_script()) { Script::set_path(p_path, p_take_over); } this->path = p_path; + GDScriptCache::move_script(old_path, p_path); for (KeyValue<StringName, Ref<GDScript>> &kv : subclasses) { kv.value->set_path(p_path, p_take_over); } } Error GDScript::load_source_code(const String &p_path) { + if (p_path.is_empty() || ResourceLoader::get_resource_type(p_path.get_slice("::", 0)) == "PackedScene") { + return OK; + } + Vector<uint8_t> sourcef; Error err; Ref<FileAccess> f = FileAccess::open(p_path, FileAccess::READ, &err); @@ -1133,6 +1149,78 @@ GDScript *GDScript::get_root_script() { return result; } +RBSet<GDScript *> GDScript::get_dependencies() { + RBSet<GDScript *> dependencies; + + _get_dependencies(dependencies, this); + dependencies.erase(this); + + return dependencies; +} + +RBSet<GDScript *> GDScript::get_inverted_dependencies() { + RBSet<GDScript *> inverted_dependencies; + + List<GDScript *> scripts; + { + MutexLock lock(GDScriptLanguage::singleton->mutex); + + SelfList<GDScript> *elem = GDScriptLanguage::singleton->script_list.first(); + while (elem) { + scripts.push_back(elem->self()); + elem = elem->next(); + } + } + + for (GDScript *scr : scripts) { + if (scr == nullptr || scr == this || scr->destructing) { + continue; + } + + RBSet<GDScript *> scr_dependencies = scr->get_dependencies(); + if (scr_dependencies.has(this)) { + inverted_dependencies.insert(scr); + } + } + + return inverted_dependencies; +} + +RBSet<GDScript *> GDScript::get_must_clear_dependencies() { + RBSet<GDScript *> dependencies = get_dependencies(); + RBSet<GDScript *> must_clear_dependencies; + HashMap<GDScript *, RBSet<GDScript *>> inverted_dependencies; + + for (GDScript *E : dependencies) { + inverted_dependencies.insert(E, E->get_inverted_dependencies()); + } + + RBSet<GDScript *> cant_clear; + for (KeyValue<GDScript *, RBSet<GDScript *>> &E : inverted_dependencies) { + for (GDScript *F : E.value) { + if (!dependencies.has(F)) { + cant_clear.insert(E.key); + for (GDScript *G : E.key->get_dependencies()) { + cant_clear.insert(G); + } + break; + } + } + } + + for (KeyValue<GDScript *, RBSet<GDScript *>> &E : inverted_dependencies) { + if (cant_clear.has(E.key) || ScriptServer::is_global_class(E.key->get_fully_qualified_name())) { + continue; + } + must_clear_dependencies.insert(E.key); + } + + cant_clear.clear(); + dependencies.clear(); + inverted_dependencies.clear(); + return must_clear_dependencies; +} + bool GDScript::has_script_signal(const StringName &p_signal) const { if (_signals.has(p_signal)) { return true; @@ -1194,6 +1282,69 @@ String GDScript::_get_gdscript_reference_class_name(const GDScript *p_gdscript) return class_name; } +GDScript *GDScript::_get_gdscript_from_variant(const Variant &p_variant) { + Variant::Type type = p_variant.get_type(); + if (type != Variant::Type::OBJECT) + return nullptr; + + Object *obj = p_variant; + if (obj == nullptr) { + return nullptr; + } + + return Object::cast_to<GDScript>(obj); +} + +void GDScript::_get_dependencies(RBSet<GDScript *> &p_dependencies, const GDScript *p_except) { + if (skip_dependencies || p_dependencies.has(this)) { + return; + } + p_dependencies.insert(this); + + for (const KeyValue<StringName, GDScriptFunction *> &E : member_functions) { + if (E.value == nullptr) { + continue; + } + for (const Variant &V : E.value->constants) { + GDScript *scr = _get_gdscript_from_variant(V); + if (scr != nullptr && scr != p_except) { + scr->_get_dependencies(p_dependencies, p_except); + } + } + } + + if (implicit_initializer) { + for (const Variant &V : implicit_initializer->constants) { + GDScript *scr = _get_gdscript_from_variant(V); + if (scr != nullptr && scr != p_except) { + scr->_get_dependencies(p_dependencies, p_except); + } + } + } + + if (implicit_ready) { + for (const Variant &V : implicit_ready->constants) { + GDScript *scr = _get_gdscript_from_variant(V); + if (scr != nullptr && scr != p_except) { + scr->_get_dependencies(p_dependencies, p_except); + } + } + } + + for (KeyValue<StringName, Ref<GDScript>> &E : subclasses) { + if (E.value != p_except) { + E.value->_get_dependencies(p_dependencies, p_except); + } + } + + for (const KeyValue<StringName, Variant> &E : constants) { + GDScript *scr = _get_gdscript_from_variant(E.value); + if (scr != nullptr && scr != p_except) { + scr->_get_dependencies(p_dependencies, p_except); + } + } +} + GDScript::GDScript() : script_list(this) { #ifdef DEBUG_ENABLED @@ -1253,33 +1404,58 @@ void GDScript::_init_rpc_methods_properties() { } } -GDScript::~GDScript() { - { - MutexLock lock(GDScriptLanguage::get_singleton()->mutex); +void GDScript::clear() { + if (clearing) { + return; + } + clearing = true; - while (SelfList<GDScriptFunctionState> *E = pending_func_states.first()) { - // Order matters since clearing the stack may already cause - // the GDSCriptFunctionState to be destroyed and thus removed from the list. - pending_func_states.remove(E); - E->self()->_clear_stack(); + RBSet<GDScript *> must_clear_dependencies = get_must_clear_dependencies(); + HashMap<GDScript *, ObjectID> must_clear_dependencies_objectids; + + // Log the objectids before clearing, as a cascade of clear could + // remove instances that are still in the clear loop + for (GDScript *E : must_clear_dependencies) { + must_clear_dependencies_objectids.insert(E, E->get_instance_id()); + } + + for (GDScript *E : must_clear_dependencies) { + Object *obj = ObjectDB::get_instance(must_clear_dependencies_objectids[E]); + if (obj == nullptr) { + continue; } + + E->skip_dependencies = true; + E->clear(); + E->skip_dependencies = false; + GDScriptCache::remove_script(E->get_path()); } + RBSet<StringName> member_function_names; for (const KeyValue<StringName, GDScriptFunction *> &E : member_functions) { - memdelete(E.value); + member_function_names.insert(E.key); + } + for (const StringName &E : member_function_names) { + if (member_functions.has(E)) { + memdelete(member_functions[E]); + } + } + member_function_names.clear(); + member_functions.clear(); + + for (KeyValue<StringName, GDScript::MemberInfo> &E : member_indices) { + E.value.data_type.script_type_ref = Ref<Script>(); } if (implicit_initializer) { memdelete(implicit_initializer); } + implicit_initializer = nullptr; if (implicit_ready) { memdelete(implicit_ready); } - - if (GDScriptCache::singleton) { // Cache may have been already destroyed at engine shutdown. - GDScriptCache::remove_script(get_path()); - } + implicit_ready = nullptr; _save_orphaned_subclasses(); @@ -1289,6 +1465,27 @@ GDScript::~GDScript() { _clear_doc(); } #endif + clearing = false; +} + +GDScript::~GDScript() { + if (destructing) { + return; + } + destructing = true; + + clear(); + + { + MutexLock lock(GDScriptLanguage::get_singleton()->mutex); + + while (SelfList<GDScriptFunctionState> *E = pending_func_states.first()) { + // Order matters since clearing the stack may already cause + // the GDScriptFunctionState to be destroyed and thus removed from the list. + pending_func_states.remove(E); + E->self()->_clear_stack(); + } + } #ifdef DEBUG_ENABLED { @@ -1297,6 +1494,10 @@ GDScript::~GDScript() { GDScriptLanguage::get_singleton()->script_list.remove(&script_list); } #endif + + if (GDScriptCache::singleton) { // Cache may have been already destroyed at engine shutdown. + GDScriptCache::remove_script(get_path()); + } } ////////////////////////////// @@ -2336,26 +2537,27 @@ GDScriptLanguage::~GDScriptLanguage() { // Clear dependencies between scripts, to ensure cyclic references are broken (to avoid leaks at exit). SelfList<GDScript> *s = script_list.first(); while (s) { - GDScript *scr = s->self(); // This ensures the current script is not released before we can check what's the next one // in the list (we can't get the next upfront because we don't know if the reference breaking // will cause it -or any other after it, for that matter- to be released so the next one // is not the same as before). - scr->reference(); - - for (KeyValue<StringName, GDScriptFunction *> &E : scr->member_functions) { - GDScriptFunction *func = E.value; - for (int i = 0; i < func->argument_types.size(); i++) { - func->argument_types.write[i].script_type_ref = Ref<Script>(); + Ref<GDScript> scr = s->self(); + if (scr.is_valid()) { + for (KeyValue<StringName, GDScriptFunction *> &E : scr->member_functions) { + GDScriptFunction *func = E.value; + for (int i = 0; i < func->argument_types.size(); i++) { + func->argument_types.write[i].script_type_ref = Ref<Script>(); + } + func->return_type.script_type_ref = Ref<Script>(); + } + for (KeyValue<StringName, GDScript::MemberInfo> &E : scr->member_indices) { + E.value.data_type.script_type_ref = Ref<Script>(); } - func->return_type.script_type_ref = Ref<Script>(); - } - for (KeyValue<StringName, GDScript::MemberInfo> &E : scr->member_indices) { - E.value.data_type.script_type_ref = Ref<Script>(); - } + // Clear backup for scripts that could slip out of the cyclic reference check + scr->clear(); + } s = s->next(); - scr->unreference(); } singleton = nullptr; @@ -2379,6 +2581,27 @@ Ref<GDScript> GDScriptLanguage::get_orphan_subclass(const String &p_qualified_na return Ref<GDScript>(Object::cast_to<GDScript>(obj)); } +Ref<GDScript> GDScriptLanguage::get_script_by_fully_qualified_name(const String &p_name) { + { + MutexLock lock(mutex); + + SelfList<GDScript> *elem = script_list.first(); + while (elem) { + GDScript *scr = elem->self(); + scr = scr->find_class(p_name); + if (scr != nullptr) { + return scr; + } + elem = elem->next(); + } + } + + Ref<GDScript> scr; + scr.instantiate(); + scr->fully_qualified_name = p_name; + return scr; +} + /*************** RESOURCE ***************/ Ref<Resource> ResourceFormatLoaderGDScript::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) { diff --git a/modules/gdscript/gdscript.h b/modules/gdscript/gdscript.h index 61600b1258..2df89d812c 100644 --- a/modules/gdscript/gdscript.h +++ b/modules/gdscript/gdscript.h @@ -61,6 +61,8 @@ class GDScript : public Script { GDCLASS(GDScript, Script); bool tool = false; bool valid = false; + bool reloading = false; + bool skip_dependencies = false; struct MemberInfo { int index = 0; @@ -124,6 +126,8 @@ class GDScript : public Script { int subclass_count = 0; RBSet<Object *> instances; + bool destructing = false; + bool clearing = false; //exported members String source; String path; @@ -163,6 +167,9 @@ class GDScript : public Script { // This method will map the class name from "RefCounted" to "MyClass.InnerClass". static String _get_gdscript_reference_class_name(const GDScript *p_gdscript); + GDScript *_get_gdscript_from_variant(const Variant &p_variant); + void _get_dependencies(RBSet<GDScript *> &p_dependencies, const GDScript *p_except); + protected: bool _get(const StringName &p_name, Variant &r_ret) const; bool _set(const StringName &p_name, const Variant &p_value); @@ -173,6 +180,8 @@ protected: static void _bind_methods(); public: + void clear(); + virtual bool is_valid() const override { return valid; } bool inherits_script(const Ref<Script> &p_script) const override; @@ -193,6 +202,10 @@ public: const Ref<GDScriptNativeClass> &get_native() const { return native; } const String &get_script_class_name() const { return name; } + RBSet<GDScript *> get_dependencies(); + RBSet<GDScript *> get_inverted_dependencies(); + RBSet<GDScript *> get_must_clear_dependencies(); + virtual bool has_script_signal(const StringName &p_signal) const override; virtual void get_script_signal_list(List<MethodInfo> *r_signals) const override; @@ -270,6 +283,7 @@ class GDScriptInstance : public ScriptInstance { friend class GDScriptLambdaCallable; friend class GDScriptLambdaSelfCallable; friend class GDScriptCompiler; + friend class GDScriptCache; friend struct GDScriptUtilityFunctionsDefinitions; ObjectID owner_id; @@ -518,6 +532,8 @@ public: void add_orphan_subclass(const String &p_qualified_name, const ObjectID &p_subclass); Ref<GDScript> get_orphan_subclass(const String &p_qualified_name); + Ref<GDScript> get_script_by_fully_qualified_name(const String &p_name); + GDScriptLanguage(); ~GDScriptLanguage(); }; diff --git a/modules/gdscript/gdscript_analyzer.cpp b/modules/gdscript/gdscript_analyzer.cpp index 8da77b9e5b..8b0b7a5102 100644 --- a/modules/gdscript/gdscript_analyzer.cpp +++ b/modules/gdscript/gdscript_analyzer.cpp @@ -32,6 +32,7 @@ #include "core/config/engine.h" #include "core/config/project_settings.h" +#include "core/core_string_names.h" #include "core/io/file_access.h" #include "core/io/resource_loader.h" #include "core/object/class_db.h" @@ -39,6 +40,7 @@ #include "core/templates/hash_map.h" #include "gdscript.h" #include "gdscript_utility_functions.h" +#include "scene/resources/packed_scene.h" static MethodInfo info_from_utility_func(const StringName &p_function) { ERR_FAIL_COND_V(!Variant::has_utility_function(p_function), MethodInfo()); @@ -132,7 +134,7 @@ static GDScriptParser::DataType make_builtin_meta_type(Variant::Type p_type) { return type; } -bool GDScriptAnalyzer::has_member_name_conflict_in_script_class(const StringName &p_member_name, const GDScriptParser::ClassNode *p_class) { +bool GDScriptAnalyzer::has_member_name_conflict_in_script_class(const StringName &p_member_name, const GDScriptParser::ClassNode *p_class, const GDScriptParser::Node *p_member) { if (p_class->members_indices.has(p_member_name)) { int index = p_class->members_indices[p_member_name]; const GDScriptParser::ClassNode::Member *member = &p_class->members[index]; @@ -145,6 +147,9 @@ bool GDScriptAnalyzer::has_member_name_conflict_in_script_class(const StringName member->type == GDScriptParser::ClassNode::Member::SIGNAL) { return true; } + if (p_member->type != GDScriptParser::Node::FUNCTION && member->type == GDScriptParser::ClassNode::Member::FUNCTION) { + return true; + } } return false; @@ -160,6 +165,9 @@ bool GDScriptAnalyzer::has_member_name_conflict_in_native_type(const StringName if (ClassDB::has_integer_constant(p_native_type_string, p_member_name)) { return true; } + if (p_member_name == CoreStringNames::get_singleton()->_script) { + return true; + } return false; } @@ -187,14 +195,15 @@ Error GDScriptAnalyzer::check_class_member_name_conflict(const GDScriptParser::C const GDScriptParser::DataType *current_data_type = &p_class_node->base_type; while (current_data_type && current_data_type->kind == GDScriptParser::DataType::Kind::CLASS) { GDScriptParser::ClassNode *current_class_node = current_data_type->class_type; - if (has_member_name_conflict_in_script_class(p_member_name, current_class_node)) { - push_error(vformat(R"(The member "%s" already exists in a parent class.)", p_member_name), + if (has_member_name_conflict_in_script_class(p_member_name, current_class_node, p_member_node)) { + push_error(vformat(R"(The member "%s" already exists in parent class %s.)", p_member_name, current_class_node->identifier->name), p_member_node); return ERR_PARSE_ERROR; } current_data_type = ¤t_class_node->base_type; } + // No need for native class recursion because Node exposes all Object's properties. if (current_data_type && current_data_type->kind == GDScriptParser::DataType::Kind::NATIVE) { if (current_data_type->native_type != StringName()) { return check_native_member_name_conflict( @@ -2912,7 +2921,7 @@ void GDScriptAnalyzer::reduce_identifier_from_base(GDScriptParser::IdentifierNod base_class = base_class->base_type.class_type; } - // Check native members. + // Check native members. No need for native class recursion because Node exposes all Object's properties. const StringName &native = base.native_type; if (class_exists(native)) { @@ -3103,7 +3112,7 @@ void GDScriptAnalyzer::reduce_identifier(GDScriptParser::IdentifierNode *p_ident GDScriptParser::DataType result; result.kind = GDScriptParser::DataType::NATIVE; result.type_source = GDScriptParser::DataType::ANNOTATED_EXPLICIT; - if (autoload.path.to_lower().ends_with(GDScriptLanguage::get_singleton()->get_extension())) { + if (ResourceLoader::get_resource_type(autoload.path) == "GDScript") { Ref<GDScriptParserRef> singl_parser = get_parser_for(autoload.path); if (singl_parser.is_valid()) { Error err = singl_parser->raise_status(GDScriptParserRef::INTERFACE_SOLVED); @@ -3111,6 +3120,34 @@ void GDScriptAnalyzer::reduce_identifier(GDScriptParser::IdentifierNode *p_ident result = type_from_metatype(singl_parser->get_parser()->head->get_datatype()); } } + } else if (ResourceLoader::get_resource_type(autoload.path) == "PackedScene") { + Error err = OK; + Ref<PackedScene> scene = GDScriptCache::get_packed_scene(autoload.path, err); + if (err == OK && scene->get_state().is_valid()) { + Ref<SceneState> state = scene->get_state(); + if (state->get_node_count() > 0) { + const int ROOT_NODE = 0; + for (int i = 0; i < state->get_node_property_count(ROOT_NODE); i++) { + if (state->get_node_property_name(ROOT_NODE, i) != SNAME("script")) { + continue; + } + + Ref<GDScript> scr = state->get_node_property_value(ROOT_NODE, i); + if (scr.is_null()) { + continue; + } + + Ref<GDScriptParserRef> singl_parser = get_parser_for(scr->get_path()); + if (singl_parser.is_valid()) { + err = singl_parser->raise_status(GDScriptParserRef::INTERFACE_SOLVED); + if (err == OK) { + result = type_from_metatype(singl_parser->get_parser()->head->get_datatype()); + } + } + break; + } + } + } } result.is_constant = true; p_identifier->set_datatype(result); @@ -3236,9 +3273,28 @@ void GDScriptAnalyzer::reduce_preload(GDScriptParser::PreloadNode *p_preload) { } } else { // TODO: Don't load if validating: use completion cache. - p_preload->resource = ResourceLoader::load(p_preload->resolved_path); - if (p_preload->resource.is_null()) { - push_error(vformat(R"(Could not preload resource file "%s".)", p_preload->resolved_path), p_preload->path); + + // Must load GDScript and PackedScenes separately to permit cyclic references + // as ResourceLoader::load() detect and reject those. + if (ResourceLoader::get_resource_type(p_preload->resolved_path) == "GDScript") { + Error err = OK; + Ref<GDScript> res = GDScriptCache::get_shallow_script(p_preload->resolved_path, err, parser->script_path); + p_preload->resource = res; + if (err != OK) { + push_error(vformat(R"(Could not preload resource script "%s".)", p_preload->resolved_path), p_preload->path); + } + } else if (ResourceLoader::get_resource_type(p_preload->resolved_path) == "PackedScene") { + Error err = OK; + Ref<PackedScene> res = GDScriptCache::get_packed_scene(p_preload->resolved_path, err, parser->script_path); + p_preload->resource = res; + if (err != OK) { + push_error(vformat(R"(Could not preload resource scene "%s".)", p_preload->resolved_path), p_preload->path); + } + } else { + p_preload->resource = ResourceLoader::load(p_preload->resolved_path); + if (p_preload->resource.is_null()) { + push_error(vformat(R"(Could not preload resource file "%s".)", p_preload->resolved_path), p_preload->path); + } } } } @@ -3280,6 +3336,17 @@ void GDScriptAnalyzer::reduce_subscript(GDScriptParser::SubscriptNode *p_subscri // Just try to get it. bool valid = false; Variant value = p_subscript->base->reduced_value.get_named(p_subscript->attribute->name, valid); + + // If it's a GDScript instance, try to get the full script. Maybe it's not still completely loaded. + Ref<GDScript> gdscr = Ref<GDScript>(p_subscript->base->reduced_value); + if (!valid && gdscr.is_valid()) { + Error err = OK; + GDScriptCache::get_full_script(gdscr->get_path(), err); + if (err == OK) { + value = p_subscript->base->reduced_value.get_named(p_subscript->attribute->name, valid); + } + } + if (!valid) { push_error(vformat(R"(Cannot get member "%s" from "%s".)", p_subscript->attribute->name, p_subscript->base->reduced_value), p_subscript->index); result_type.kind = GDScriptParser::DataType::VARIANT; @@ -3662,50 +3729,43 @@ GDScriptParser::DataType GDScriptAnalyzer::type_from_variant(const Variant &p_va scr = obj->get_script(); } if (scr.is_valid()) { - if (scr->is_valid()) { - result.script_type = scr; - result.script_path = scr->get_path(); - Ref<GDScript> gds = scr; - if (gds.is_valid()) { - result.kind = GDScriptParser::DataType::CLASS; - // This might be an inner class, so we want to get the parser for the root. - // But still get the inner class from that tree. - GDScript *current = gds.ptr(); - List<StringName> class_chain; - while (current->_owner) { - // Push to front so it's in reverse. - class_chain.push_front(current->name); - current = current->_owner; - } - - Ref<GDScriptParserRef> ref = get_parser_for(current->get_path()); - if (ref.is_null()) { - push_error("Could not find script in path.", p_source); - GDScriptParser::DataType error_type; - error_type.kind = GDScriptParser::DataType::VARIANT; - return error_type; - } - ref->raise_status(GDScriptParserRef::INTERFACE_SOLVED); + result.script_type = scr; + result.script_path = scr->get_path(); + Ref<GDScript> gds = scr; + if (gds.is_valid()) { + result.kind = GDScriptParser::DataType::CLASS; + // This might be an inner class, so we want to get the parser for the root. + // But still get the inner class from that tree. + GDScript *current = gds.ptr(); + List<StringName> class_chain; + while (current->_owner) { + // Push to front so it's in reverse. + class_chain.push_front(current->name); + current = current->_owner; + } - GDScriptParser::ClassNode *found = ref->get_parser()->head; + Ref<GDScriptParserRef> ref = get_parser_for(current->get_path()); + if (ref.is_null()) { + push_error("Could not find script in path.", p_source); + GDScriptParser::DataType error_type; + error_type.kind = GDScriptParser::DataType::VARIANT; + return error_type; + } + ref->raise_status(GDScriptParserRef::INTERFACE_SOLVED); - // It should be okay to assume this exists, since we have a complete script already. - for (const StringName &E : class_chain) { - found = found->get_member(E).m_class; - } + GDScriptParser::ClassNode *found = ref->get_parser()->head; - result.class_type = found; - result.script_path = ref->get_parser()->script_path; - } else { - result.kind = GDScriptParser::DataType::SCRIPT; + // It should be okay to assume this exists, since we have a complete script already. + for (const StringName &E : class_chain) { + found = found->get_member(E).m_class; } - result.native_type = scr->get_instance_base_type(); + + result.class_type = found; + result.script_path = ref->get_parser()->script_path; } else { - push_error(vformat(R"(Constant value uses script from "%s" which is loaded but not compiled.)", scr->get_path()), p_source); - result.kind = GDScriptParser::DataType::VARIANT; - result.type_source = GDScriptParser::DataType::UNDETECTED; - result.is_meta_type = false; + result.kind = GDScriptParser::DataType::SCRIPT; } + result.native_type = scr->get_instance_base_type(); } else { result.kind = GDScriptParser::DataType::NATIVE; if (result.native_type == GDScriptNativeClass::get_class_static()) { diff --git a/modules/gdscript/gdscript_analyzer.h b/modules/gdscript/gdscript_analyzer.h index 217a856ce0..23a3ad39a5 100644 --- a/modules/gdscript/gdscript_analyzer.h +++ b/modules/gdscript/gdscript_analyzer.h @@ -45,7 +45,7 @@ class GDScriptAnalyzer { List<GDScriptParser::LambdaNode *> lambda_stack; // Tests for detecting invalid overloading of script members - static _FORCE_INLINE_ bool has_member_name_conflict_in_script_class(const StringName &p_name, const GDScriptParser::ClassNode *p_current_class_node); + static _FORCE_INLINE_ bool has_member_name_conflict_in_script_class(const StringName &p_name, const GDScriptParser::ClassNode *p_current_class_node, const GDScriptParser::Node *p_member); static _FORCE_INLINE_ bool has_member_name_conflict_in_native_type(const StringName &p_name, const StringName &p_native_type_string); Error check_native_member_name_conflict(const StringName &p_member_name, const GDScriptParser::Node *p_member_node, const StringName &p_native_type_string); Error check_class_member_name_conflict(const GDScriptParser::ClassNode *p_class_node, const StringName &p_member_name, const GDScriptParser::Node *p_member_node); diff --git a/modules/gdscript/gdscript_cache.cpp b/modules/gdscript/gdscript_cache.cpp index 03a101b9fc..40681d9771 100644 --- a/modules/gdscript/gdscript_cache.cpp +++ b/modules/gdscript/gdscript_cache.cpp @@ -36,6 +36,7 @@ #include "gdscript_analyzer.h" #include "gdscript_compiler.h" #include "gdscript_parser.h" +#include "scene/resources/packed_scene.h" bool GDScriptParserRef::is_valid() const { return parser != nullptr; @@ -96,27 +97,88 @@ Error GDScriptParserRef::raise_status(Status p_new_status) { return result; } -GDScriptParserRef::~GDScriptParserRef() { +void GDScriptParserRef::clear() { + if (cleared) { + return; + } + cleared = true; + if (parser != nullptr) { memdelete(parser); } + if (analyzer != nullptr) { memdelete(analyzer); } - MutexLock lock(GDScriptCache::singleton->lock); +} + +GDScriptParserRef::~GDScriptParserRef() { + clear(); + + MutexLock lock(GDScriptCache::singleton->mutex); GDScriptCache::singleton->parser_map.erase(path); } GDScriptCache *GDScriptCache::singleton = nullptr; +void GDScriptCache::move_script(const String &p_from, const String &p_to) { + if (singleton == nullptr) { + return; + } + + MutexLock lock(singleton->mutex); + + for (KeyValue<String, HashSet<String>> &E : singleton->packed_scene_dependencies) { + if (E.value.has(p_from)) { + E.value.insert(p_to); + E.value.erase(p_from); + } + } + + if (singleton->parser_map.has(p_from) && !p_from.is_empty()) { + singleton->parser_map[p_to] = singleton->parser_map[p_from]; + } + singleton->parser_map.erase(p_from); + + if (singleton->shallow_gdscript_cache.has(p_from) && !p_from.is_empty()) { + singleton->shallow_gdscript_cache[p_to] = singleton->shallow_gdscript_cache[p_from]; + } + singleton->shallow_gdscript_cache.erase(p_from); + + if (singleton->full_gdscript_cache.has(p_from) && !p_from.is_empty()) { + singleton->full_gdscript_cache[p_to] = singleton->full_gdscript_cache[p_from]; + } + singleton->full_gdscript_cache.erase(p_from); +} + void GDScriptCache::remove_script(const String &p_path) { - MutexLock lock(singleton->lock); + if (singleton == nullptr) { + return; + } + + MutexLock lock(singleton->mutex); + + for (KeyValue<String, HashSet<String>> &E : singleton->packed_scene_dependencies) { + if (!E.value.has(p_path)) { + continue; + } + E.value.erase(p_path); + } + + GDScriptCache::clear_unreferenced_packed_scenes(); + + if (singleton->parser_map.has(p_path)) { + singleton->parser_map[p_path]->clear(); + singleton->parser_map.erase(p_path); + } + + singleton->dependencies.erase(p_path); singleton->shallow_gdscript_cache.erase(p_path); singleton->full_gdscript_cache.erase(p_path); } Ref<GDScriptParserRef> GDScriptCache::get_parser(const String &p_path, GDScriptParserRef::Status p_status, Error &r_error, const String &p_owner) { - MutexLock lock(singleton->lock); + MutexLock lock(singleton->mutex); Ref<GDScriptParserRef> ref; if (!p_owner.is_empty()) { singleton->dependencies[p_owner].insert(p_path); @@ -163,7 +225,7 @@ String GDScriptCache::get_source_code(const String &p_path) { } Ref<GDScript> GDScriptCache::get_shallow_script(const String &p_path, Error &r_error, const String &p_owner) { - MutexLock lock(singleton->lock); + MutexLock lock(singleton->mutex); if (!p_owner.is_empty()) { singleton->dependencies[p_owner].insert(p_path); } @@ -185,12 +247,12 @@ Ref<GDScript> GDScriptCache::get_shallow_script(const String &p_path, Error &r_e script->load_source_code(p_path); GDScriptCompiler::make_scripts(script.ptr(), parser_ref->get_parser()->get_tree(), true); - singleton->shallow_gdscript_cache[p_path] = script.ptr(); + singleton->shallow_gdscript_cache[p_path] = script; return script; } Ref<GDScript> GDScriptCache::get_full_script(const String &p_path, Error &r_error, const String &p_owner, bool p_update_from_disk) { - MutexLock lock(singleton->lock); + MutexLock lock(singleton->mutex); if (!p_owner.is_empty()) { singleton->dependencies[p_owner].insert(p_path); @@ -220,19 +282,21 @@ Ref<GDScript> GDScriptCache::get_full_script(const String &p_path, Error &r_erro return script; } + singleton->full_gdscript_cache[p_path] = script; + singleton->shallow_gdscript_cache.erase(p_path); + r_error = script->reload(true); if (r_error) { + singleton->shallow_gdscript_cache[p_path] = script; + singleton->full_gdscript_cache.erase(p_path); return script; } - singleton->full_gdscript_cache[p_path] = script.ptr(); - singleton->shallow_gdscript_cache.erase(p_path); - return script; } Ref<GDScript> GDScriptCache::get_cached_script(const String &p_path) { - MutexLock lock(singleton->lock); + MutexLock lock(singleton->mutex); if (singleton->full_gdscript_cache.has(p_path)) { return singleton->full_gdscript_cache[p_path]; @@ -246,11 +310,11 @@ Ref<GDScript> GDScriptCache::get_cached_script(const String &p_path) { } Error GDScriptCache::finish_compiling(const String &p_owner) { - MutexLock lock(singleton->lock); + MutexLock lock(singleton->mutex); // Mark this as compiled. Ref<GDScript> script = get_cached_script(p_owner); - singleton->full_gdscript_cache[p_owner] = script.ptr(); + singleton->full_gdscript_cache[p_owner] = script; singleton->shallow_gdscript_cache.erase(p_owner); HashSet<String> depends = singleton->dependencies[p_owner]; @@ -271,13 +335,73 @@ Error GDScriptCache::finish_compiling(const String &p_owner) { return err; } +Ref<PackedScene> GDScriptCache::get_packed_scene(const String &p_path, Error &r_error, const String &p_owner) { + MutexLock lock(singleton->mutex); + + if (singleton->packed_scene_cache.has(p_path)) { + singleton->packed_scene_dependencies[p_path].insert(p_owner); + return singleton->packed_scene_cache[p_path]; + } + + Ref<PackedScene> scene; + scene.instantiate(); + + r_error = OK; + if (p_path.is_empty()) { + r_error = ERR_FILE_BAD_PATH; + return scene; + } + + scene->set_path(p_path); + singleton->packed_scene_cache[p_path] = scene; + singleton->packed_scene_dependencies[p_path].insert(p_owner); + + scene->recreate_state(); + scene->reload_from_file(); + return scene; +} + +void GDScriptCache::clear_unreferenced_packed_scenes() { + if (singleton == nullptr) { + return; + } + + MutexLock lock(singleton->mutex); + + for (KeyValue<String, HashSet<String>> &E : singleton->packed_scene_dependencies) { + if (E.value.size() > 0 || !ResourceLoader::is_imported(E.key)) { + continue; + } + + singleton->packed_scene_dependencies.erase(E.key); + singleton->packed_scene_cache.erase(E.key); + } +} + GDScriptCache::GDScriptCache() { singleton = this; } GDScriptCache::~GDScriptCache() { + destructing = true; + + RBSet<Ref<GDScriptParserRef>> parser_map_refs; + for (KeyValue<String, GDScriptParserRef *> &E : parser_map) { + parser_map_refs.insert(E.value); + } + + for (Ref<GDScriptParserRef> &E : parser_map_refs) { + if (E.is_valid()) + E->clear(); + } + + parser_map_refs.clear(); parser_map.clear(); shallow_gdscript_cache.clear(); full_gdscript_cache.clear(); + + packed_scene_cache.clear(); + packed_scene_dependencies.clear(); + singleton = nullptr; } diff --git a/modules/gdscript/gdscript_cache.h b/modules/gdscript/gdscript_cache.h index fcd240ba8d..2195932aa3 100644 --- a/modules/gdscript/gdscript_cache.h +++ b/modules/gdscript/gdscript_cache.h @@ -36,6 +36,7 @@ #include "core/templates/hash_map.h" #include "core/templates/hash_set.h" #include "gdscript.h" +#include "scene/resources/packed_scene.h" class GDScriptAnalyzer; class GDScriptParser; @@ -56,6 +57,7 @@ private: Status status = EMPTY; Error result = OK; String path; + bool cleared = false; friend class GDScriptCache; @@ -64,6 +66,7 @@ public: Status get_status() const; GDScriptParser *get_parser() const; Error raise_status(Status p_new_status); + void clear(); GDScriptParserRef() {} ~GDScriptParserRef(); @@ -72,19 +75,25 @@ public: class GDScriptCache { // String key is full path. HashMap<String, GDScriptParserRef *> parser_map; - HashMap<String, GDScript *> shallow_gdscript_cache; - HashMap<String, GDScript *> full_gdscript_cache; + HashMap<String, Ref<GDScript>> shallow_gdscript_cache; + HashMap<String, Ref<GDScript>> full_gdscript_cache; HashMap<String, HashSet<String>> dependencies; + HashMap<String, Ref<PackedScene>> packed_scene_cache; + HashMap<String, HashSet<String>> packed_scene_dependencies; friend class GDScript; friend class GDScriptParserRef; + friend class GDScriptInstance; static GDScriptCache *singleton; - Mutex lock; - static void remove_script(const String &p_path); + bool destructing = false; + + Mutex mutex; public: + static void move_script(const String &p_from, const String &p_to); + static void remove_script(const String &p_path); static Ref<GDScriptParserRef> get_parser(const String &p_path, GDScriptParserRef::Status status, Error &r_error, const String &p_owner = String()); static String get_source_code(const String &p_path); static Ref<GDScript> get_shallow_script(const String &p_path, Error &r_error, const String &p_owner = String()); @@ -92,6 +101,16 @@ public: static Ref<GDScript> get_cached_script(const String &p_path); static Error finish_compiling(const String &p_owner); + static Ref<PackedScene> get_packed_scene(const String &p_path, Error &r_error, const String &p_owner = ""); + static void clear_unreferenced_packed_scenes(); + + static bool is_destructing() { + if (singleton == nullptr) { + return true; + } + return singleton->destructing; + }; + GDScriptCache(); ~GDScriptCache(); }; diff --git a/modules/gdscript/gdscript_compiler.cpp b/modules/gdscript/gdscript_compiler.cpp index 824625b745..f0ceb42f89 100644 --- a/modules/gdscript/gdscript_compiler.cpp +++ b/modules/gdscript/gdscript_compiler.cpp @@ -141,6 +141,7 @@ GDScriptDataType GDScriptCompiler::_gdtype_from_datatype(const GDScriptParser::D result.script_type_ref = script; } result.script_type = script.ptr(); + result.native_type = p_datatype.native_type; } } break; case GDScriptParser::DataType::ENUM: @@ -354,11 +355,22 @@ GDScriptCodeGenerator::Address GDScriptCompiler::_parse_expression(CodeGen &code if (class_node->identifier && class_node->identifier->name == identifier) { res = Ref<GDScript>(main_script); } else { - res = ResourceLoader::load(ScriptServer::get_global_class_path(identifier)); - if (res.is_null()) { - _set_error("Can't load global class " + String(identifier) + ", cyclic reference?", p_expression); - r_error = ERR_COMPILATION_FAILED; - return GDScriptCodeGenerator::Address(); + String global_class_path = ScriptServer::get_global_class_path(identifier); + if (ResourceLoader::get_resource_type(global_class_path) == "GDScript") { + Error err = OK; + res = GDScriptCache::get_full_script(global_class_path, err); + if (err != OK) { + _set_error("Can't load global class " + String(identifier), p_expression); + r_error = ERR_COMPILATION_FAILED; + return GDScriptCodeGenerator::Address(); + } + } else { + res = ResourceLoader::load(global_class_path); + if (res.is_null()) { + _set_error("Can't load global class " + String(identifier) + ", cyclic reference?", p_expression); + r_error = ERR_COMPILATION_FAILED; + return GDScriptCodeGenerator::Address(); + } } } @@ -2172,6 +2184,7 @@ Error GDScriptCompiler::_populate_class_members(GDScript *p_script, const GDScri parsing_classes.insert(p_script); + p_script->clearing = true; #ifdef TOOLS_ENABLED p_script->doc_functions.clear(); p_script->doc_variables.clear(); @@ -2194,10 +2207,24 @@ Error GDScriptCompiler::_populate_class_members(GDScript *p_script, const GDScri p_script->base = Ref<GDScript>(); p_script->_base = nullptr; p_script->members.clear(); + + // This makes possible to clear script constants and member_functions without heap-use-after-free errors. + HashMap<StringName, Variant> constants; + for (const KeyValue<StringName, Variant> &E : p_script->constants) { + constants.insert(E.key, E.value); + } p_script->constants.clear(); + constants.clear(); + HashMap<StringName, GDScriptFunction *> member_functions; for (const KeyValue<StringName, GDScriptFunction *> &E : p_script->member_functions) { + member_functions.insert(E.key, E.value); + } + p_script->member_functions.clear(); + for (const KeyValue<StringName, GDScriptFunction *> &E : member_functions) { memdelete(E.value); } + member_functions.clear(); + if (p_script->implicit_initializer) { memdelete(p_script->implicit_initializer); } @@ -2212,6 +2239,8 @@ Error GDScriptCompiler::_populate_class_members(GDScript *p_script, const GDScri p_script->implicit_initializer = nullptr; p_script->implicit_ready = nullptr; + p_script->clearing = false; + p_script->tool = parser->is_tool(); if (!p_script->name.is_empty()) { @@ -2454,10 +2483,8 @@ Error GDScriptCompiler::_populate_class_members(GDScript *p_script, const GDScri } #ifdef TOOLS_ENABLED - p_script->member_lines[name] = inner_class->start_line; #endif - p_script->constants.insert(name, subclass); //once parsed, goes to the list of constants } diff --git a/modules/gdscript/gdscript_function.cpp b/modules/gdscript/gdscript_function.cpp index 98b3e40f1b..24a614b1ad 100644 --- a/modules/gdscript/gdscript_function.cpp +++ b/modules/gdscript/gdscript_function.cpp @@ -149,10 +149,17 @@ GDScriptFunction::GDScriptFunction() { } GDScriptFunction::~GDScriptFunction() { + get_script()->member_functions.erase(name); + for (int i = 0; i < lambdas.size(); i++) { memdelete(lambdas[i]); } + for (int i = 0; i < argument_types.size(); i++) { + argument_types.write[i].script_type_ref = Ref<Script>(); + } + return_type.script_type_ref = Ref<Script>(); + #ifdef DEBUG_ENABLED MutexLock lock(GDScriptLanguage::get_singleton()->mutex); diff --git a/modules/gdscript/gdscript_function.h b/modules/gdscript/gdscript_function.h index e44038d6da..6e5f7a8520 100644 --- a/modules/gdscript/gdscript_function.h +++ b/modules/gdscript/gdscript_function.h @@ -430,6 +430,7 @@ public: }; private: + friend class GDScript; friend class GDScriptCompiler; friend class GDScriptByteCodeGenerator; diff --git a/modules/gdscript/gdscript_parser.cpp b/modules/gdscript/gdscript_parser.cpp index 053d81893d..6fd1362e68 100644 --- a/modules/gdscript/gdscript_parser.cpp +++ b/modules/gdscript/gdscript_parser.cpp @@ -648,7 +648,13 @@ GDScriptParser::ClassNode *GDScriptParser::parse_class() { if (consume(GDScriptTokenizer::Token::IDENTIFIER, R"(Expected identifier for the class name after "class".)")) { n_class->identifier = parse_identifier(); if (n_class->outer) { - n_class->fqcn = n_class->outer->fqcn + "::" + n_class->identifier->name; + String fqcn = n_class->outer->fqcn; + if (fqcn.is_empty()) { + fqcn = script_path; + } + n_class->fqcn = fqcn + "::" + n_class->identifier->name; + } else { + n_class->fqcn = n_class->identifier->name; } } @@ -1535,7 +1541,7 @@ GDScriptParser::SuiteNode *GDScriptParser::parse_suite(const String &p_context, VariableNode *variable = static_cast<VariableNode *>(statement); const SuiteNode::Local &local = current_suite->get_local(variable->identifier->name); if (local.type != SuiteNode::Local::UNDEFINED) { - push_error(vformat(R"(There is already a %s named "%s" declared in this scope.)", local.get_name(), variable->identifier->name)); + push_error(vformat(R"(There is already a %s named "%s" declared in this scope.)", local.get_name(), variable->identifier->name), variable->identifier); } current_suite->add_local(variable, current_function); break; @@ -1550,7 +1556,7 @@ GDScriptParser::SuiteNode *GDScriptParser::parse_suite(const String &p_context, } else { name = "variable"; } - push_error(vformat(R"(There is already a %s named "%s" declared in this scope.)", name, constant->identifier->name)); + push_error(vformat(R"(There is already a %s named "%s" declared in this scope.)", name, constant->identifier->name), constant->identifier); } current_suite->add_local(constant, current_function); break; diff --git a/modules/gdscript/tests/gdscript_test_runner.cpp b/modules/gdscript/tests/gdscript_test_runner.cpp index 1ccbf9d150..7f42643c8f 100644 --- a/modules/gdscript/tests/gdscript_test_runner.cpp +++ b/modules/gdscript/tests/gdscript_test_runner.cpp @@ -251,7 +251,10 @@ bool GDScriptTestRunner::make_tests_for_dir(const String &p_dir) { return false; } } else { - if (next.get_extension().to_lower() == "gd") { + if (next.ends_with(".notest.gd")) { + next = dir->get_next(); + continue; + } else if (next.get_extension().to_lower() == "gd") { #ifndef DEBUG_ENABLED // On release builds, skip tests marked as debug only. Error open_err = OK; @@ -597,6 +600,9 @@ GDScriptTest::TestResult GDScriptTest::execute_test_code(bool p_is_generating) { } enable_stdout(); + + GDScriptCache::remove_script(script->get_path()); + return result; } diff --git a/modules/gdscript/tests/scripts/analyzer/errors/overload_script_variable.gd b/modules/gdscript/tests/scripts/analyzer/errors/overload_script_variable.gd new file mode 100644 index 0000000000..5c8b9fa4ae --- /dev/null +++ b/modules/gdscript/tests/scripts/analyzer/errors/overload_script_variable.gd @@ -0,0 +1,6 @@ +extends Node + +var script: int + +func test(): + pass diff --git a/modules/gdscript/tests/scripts/analyzer/errors/overload_script_variable.out b/modules/gdscript/tests/scripts/analyzer/errors/overload_script_variable.out new file mode 100644 index 0000000000..8454aaa404 --- /dev/null +++ b/modules/gdscript/tests/scripts/analyzer/errors/overload_script_variable.out @@ -0,0 +1,2 @@ +GDTEST_ANALYZER_ERROR +Member "script" redefined (original in native class 'Node') diff --git a/modules/gdscript/tests/scripts/analyzer/errors/variable_overloads_superclass_function.gd b/modules/gdscript/tests/scripts/analyzer/errors/variable_overloads_superclass_function.gd new file mode 100644 index 0000000000..28561ff94b --- /dev/null +++ b/modules/gdscript/tests/scripts/analyzer/errors/variable_overloads_superclass_function.gd @@ -0,0 +1,9 @@ +func test(): + pass + +class A: + func overload_me(): + pass + +class B extends A: + var overload_me diff --git a/modules/gdscript/tests/scripts/analyzer/errors/variable_overloads_superclass_function.out b/modules/gdscript/tests/scripts/analyzer/errors/variable_overloads_superclass_function.out new file mode 100644 index 0000000000..32357f9f6a --- /dev/null +++ b/modules/gdscript/tests/scripts/analyzer/errors/variable_overloads_superclass_function.out @@ -0,0 +1,2 @@ +GDTEST_ANALYZER_ERROR +The member "overload_me" already exists in parent class A. diff --git a/modules/gdscript/tests/scripts/analyzer/features/gdscript_to_preload.gd b/modules/gdscript/tests/scripts/analyzer/features/gdscript_to_preload.notest.gd index ea744e3027..c3fc176679 100644 --- a/modules/gdscript/tests/scripts/analyzer/features/gdscript_to_preload.gd +++ b/modules/gdscript/tests/scripts/analyzer/features/gdscript_to_preload.notest.gd @@ -1,7 +1,4 @@ const A := 42 -func test(): - pass - func something(): return "OK" diff --git a/modules/gdscript/tests/scripts/analyzer/features/preload_constant_types_are_inferred.gd b/modules/gdscript/tests/scripts/analyzer/features/preload_constant_types_are_inferred.gd index 276875dd5a..9d0324ead8 100644 --- a/modules/gdscript/tests/scripts/analyzer/features/preload_constant_types_are_inferred.gd +++ b/modules/gdscript/tests/scripts/analyzer/features/preload_constant_types_are_inferred.gd @@ -1,4 +1,4 @@ -const Constants = preload("gdscript_to_preload.gd") +const Constants = preload("gdscript_to_preload.notest.gd") func test(): var a := Constants.A diff --git a/modules/gdscript/tests/scripts/analyzer/features/preload_cyclic_reference.gd b/modules/gdscript/tests/scripts/analyzer/features/preload_cyclic_reference.gd new file mode 100644 index 0000000000..b730453a8a --- /dev/null +++ b/modules/gdscript/tests/scripts/analyzer/features/preload_cyclic_reference.gd @@ -0,0 +1,4 @@ +const A = preload("preload_cyclic_reference_a.notest.gd") + +func test(): + A.test_cyclic_reference() diff --git a/modules/gdscript/tests/scripts/analyzer/features/gdscript_to_preload.out b/modules/gdscript/tests/scripts/analyzer/features/preload_cyclic_reference.out index d73c5eb7cd..14bb971221 100644 --- a/modules/gdscript/tests/scripts/analyzer/features/gdscript_to_preload.out +++ b/modules/gdscript/tests/scripts/analyzer/features/preload_cyclic_reference.out @@ -1 +1,2 @@ GDTEST_OK +godot diff --git a/modules/gdscript/tests/scripts/analyzer/features/preload_cyclic_reference_a.notest.gd b/modules/gdscript/tests/scripts/analyzer/features/preload_cyclic_reference_a.notest.gd new file mode 100644 index 0000000000..7a6035ded1 --- /dev/null +++ b/modules/gdscript/tests/scripts/analyzer/features/preload_cyclic_reference_a.notest.gd @@ -0,0 +1,12 @@ +const B = preload("preload_cyclic_reference_b.notest.gd") + +const WAITING_FOR = "godot" + +static func test_cyclic_reference(): + B.test_cyclic_reference() + +static func test_cyclic_reference_2(): + B.test_cyclic_reference_2() + +static func test_cyclic_reference_3(): + B.test_cyclic_reference_3() diff --git a/modules/gdscript/tests/scripts/analyzer/features/preload_cyclic_reference_b.notest.gd b/modules/gdscript/tests/scripts/analyzer/features/preload_cyclic_reference_b.notest.gd new file mode 100644 index 0000000000..3ea5b01156 --- /dev/null +++ b/modules/gdscript/tests/scripts/analyzer/features/preload_cyclic_reference_b.notest.gd @@ -0,0 +1,10 @@ +const A = preload("preload_cyclic_reference_a.notest.gd") + +static func test_cyclic_reference(): + A.test_cyclic_reference_2() + +static func test_cyclic_reference_2(): + A.test_cyclic_reference_3() + +static func test_cyclic_reference_3(): + print(A.WAITING_FOR) diff --git a/modules/gdscript/tests/scripts/analyzer/features/use_preload_script_as_type.gd b/modules/gdscript/tests/scripts/analyzer/features/use_preload_script_as_type.gd index 5f73064cc0..beabf3d2e5 100644 --- a/modules/gdscript/tests/scripts/analyzer/features/use_preload_script_as_type.gd +++ b/modules/gdscript/tests/scripts/analyzer/features/use_preload_script_as_type.gd @@ -1,4 +1,4 @@ -const preloaded : GDScript = preload("gdscript_to_preload.gd") +const preloaded : GDScript = preload("gdscript_to_preload.notest.gd") func test(): var preloaded_instance: preloaded = preloaded.new() diff --git a/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/GodotMemberData.cs b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/GodotMemberData.cs index db395e21cb..abd8079922 100644 --- a/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/GodotMemberData.cs +++ b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/GodotMemberData.cs @@ -3,7 +3,7 @@ using Microsoft.CodeAnalysis; namespace Godot.SourceGenerators { - public struct GodotMethodData + public readonly struct GodotMethodData { public GodotMethodData(IMethodSymbol method, ImmutableArray<MarshalType> paramTypes, ImmutableArray<ITypeSymbol> paramTypeSymbols, MarshalType? retType, ITypeSymbol? retSymbol) @@ -22,7 +22,7 @@ namespace Godot.SourceGenerators public ITypeSymbol? RetSymbol { get; } } - public struct GodotSignalDelegateData + public readonly struct GodotSignalDelegateData { public GodotSignalDelegateData(string name, INamedTypeSymbol delegateSymbol, GodotMethodData invokeMethodData) { @@ -36,7 +36,7 @@ namespace Godot.SourceGenerators public GodotMethodData InvokeMethodData { get; } } - public struct GodotPropertyData + public readonly struct GodotPropertyData { public GodotPropertyData(IPropertySymbol propertySymbol, MarshalType type) { @@ -48,7 +48,7 @@ namespace Godot.SourceGenerators public MarshalType Type { get; } } - public struct GodotFieldData + public readonly struct GodotFieldData { public GodotFieldData(IFieldSymbol fieldSymbol, MarshalType type) { diff --git a/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/MethodInfo.cs b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/MethodInfo.cs index 81c6f2b7d5..bb9be862c4 100644 --- a/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/MethodInfo.cs +++ b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/MethodInfo.cs @@ -2,7 +2,7 @@ using System.Collections.Generic; namespace Godot.SourceGenerators { - internal struct MethodInfo + internal readonly struct MethodInfo { public MethodInfo(string name, PropertyInfo returnVal, MethodFlags flags, List<PropertyInfo>? arguments, diff --git a/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/PropertyInfo.cs b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/PropertyInfo.cs index b345f5f84d..2b89633ef6 100644 --- a/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/PropertyInfo.cs +++ b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/PropertyInfo.cs @@ -1,6 +1,6 @@ namespace Godot.SourceGenerators { - internal struct PropertyInfo + internal readonly struct PropertyInfo { public PropertyInfo(VariantType type, string name, PropertyHint hint, string? hintString, PropertyUsageFlags usage, bool exported) diff --git a/modules/mono/editor/GodotTools/GodotTools.IdeMessaging/Utils/SemaphoreExtensions.cs b/modules/mono/editor/GodotTools/GodotTools.IdeMessaging/Utils/SemaphoreExtensions.cs index 9d593fbf8a..ab21527344 100644 --- a/modules/mono/editor/GodotTools/GodotTools.IdeMessaging/Utils/SemaphoreExtensions.cs +++ b/modules/mono/editor/GodotTools/GodotTools.IdeMessaging/Utils/SemaphoreExtensions.cs @@ -13,7 +13,7 @@ namespace GodotTools.IdeMessaging.Utils return waitAsyncTask.ContinueWith<IDisposable>(t => wrapper, cancellationToken).ConfigureAwait(false); } - private struct SemaphoreSlimWaitReleaseWrapper : IDisposable + private readonly struct SemaphoreSlimWaitReleaseWrapper : IDisposable { private readonly SemaphoreSlim semaphoreSlim; diff --git a/modules/mono/editor/GodotTools/GodotTools/Export/AotBuilder.cs b/modules/mono/editor/GodotTools/GodotTools/Export/AotBuilder.cs index 2184cae6d6..94efcba3f1 100644 --- a/modules/mono/editor/GodotTools/GodotTools/Export/AotBuilder.cs +++ b/modules/mono/editor/GodotTools/GodotTools/Export/AotBuilder.cs @@ -22,7 +22,7 @@ namespace GodotTools.Export public bool FullAot; private bool _useInterpreter; - public bool UseInterpreter { get => _useInterpreter && !LLVMOnly; set => _useInterpreter = value; } + public bool UseInterpreter { readonly get => _useInterpreter && !LLVMOnly; set => _useInterpreter = value; } public string[] ExtraAotOptions; public string[] ExtraOptimizerOptions; diff --git a/modules/mono/editor/GodotTools/GodotTools/PlaySettings.cs b/modules/mono/editor/GodotTools/GodotTools/PlaySettings.cs index 820d0c0b83..9a8fdcc7c5 100644 --- a/modules/mono/editor/GodotTools/GodotTools/PlaySettings.cs +++ b/modules/mono/editor/GodotTools/GodotTools/PlaySettings.cs @@ -1,6 +1,6 @@ namespace GodotTools { - public struct PlaySettings + public readonly struct PlaySettings { public bool HasDebugger { get; } public string DebuggerHost { get; } diff --git a/modules/mono/glue/GodotSharp/Godot.SourceGenerators.Internal/CallbacksInfo.cs b/modules/mono/glue/GodotSharp/Godot.SourceGenerators.Internal/CallbacksInfo.cs index 686023a077..ae51c07386 100644 --- a/modules/mono/glue/GodotSharp/Godot.SourceGenerators.Internal/CallbacksInfo.cs +++ b/modules/mono/glue/GodotSharp/Godot.SourceGenerators.Internal/CallbacksInfo.cs @@ -4,7 +4,7 @@ using Microsoft.CodeAnalysis; namespace Godot.SourceGenerators.Internal; -internal struct CallbacksData +internal readonly struct CallbacksData { public CallbacksData(INamedTypeSymbol nativeTypeSymbol, INamedTypeSymbol funcStructSymbol) { diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/AABB.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/AABB.cs index d8a6644a66..a2916d4ae8 100644 --- a/modules/mono/glue/GodotSharp/GodotSharp/Core/AABB.cs +++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/AABB.cs @@ -20,7 +20,7 @@ namespace Godot /// <value>Directly uses a private field.</value> public Vector3 Position { - get { return _position; } + readonly get { return _position; } set { _position = value; } } @@ -31,7 +31,7 @@ namespace Godot /// <value>Directly uses a private field.</value> public Vector3 Size { - get { return _size; } + readonly get { return _size; } set { _size = value; } } @@ -45,7 +45,7 @@ namespace Godot /// </value> public Vector3 End { - get { return _position + _size; } + readonly get { return _position + _size; } set { _size = value - _position; } } @@ -54,7 +54,7 @@ namespace Godot /// the most-negative corner is the origin and the size is positive. /// </summary> /// <returns>The modified <see cref="AABB"/>.</returns> - public AABB Abs() + public readonly AABB Abs() { Vector3 end = End; Vector3 topLeft = new Vector3(Mathf.Min(_position.x, end.x), Mathf.Min(_position.y, end.y), Mathf.Min(_position.z, end.z)); @@ -66,7 +66,7 @@ namespace Godot /// to <see cref="Position"/> + (<see cref="Size"/> / 2). /// </summary> /// <returns>The center.</returns> - public Vector3 GetCenter() + public readonly Vector3 GetCenter() { return _position + (_size * 0.5f); } @@ -78,7 +78,7 @@ namespace Godot /// <returns> /// A <see langword="bool"/> for whether or not this <see cref="AABB"/> encloses <paramref name="with"/>. /// </returns> - public bool Encloses(AABB with) + public readonly bool Encloses(AABB with) { Vector3 srcMin = _position; Vector3 srcMax = _position + _size; @@ -98,7 +98,7 @@ namespace Godot /// </summary> /// <param name="point">The point to include.</param> /// <returns>The expanded <see cref="AABB"/>.</returns> - public AABB Expand(Vector3 point) + public readonly AABB Expand(Vector3 point) { Vector3 begin = _position; Vector3 end = _position + _size; @@ -140,7 +140,7 @@ namespace Godot /// <paramref name="idx"/> is less than 0 or greater than 7. /// </exception> /// <returns>An endpoint of the <see cref="AABB"/>.</returns> - public Vector3 GetEndpoint(int idx) + public readonly Vector3 GetEndpoint(int idx) { switch (idx) { @@ -172,7 +172,7 @@ namespace Godot /// Returns the normalized longest axis of the <see cref="AABB"/>. /// </summary> /// <returns>A vector representing the normalized longest axis of the <see cref="AABB"/>.</returns> - public Vector3 GetLongestAxis() + public readonly Vector3 GetLongestAxis() { var axis = new Vector3(1f, 0f, 0f); real_t maxSize = _size.x; @@ -195,7 +195,7 @@ namespace Godot /// Returns the <see cref="Vector3.Axis"/> index of the longest axis of the <see cref="AABB"/>. /// </summary> /// <returns>A <see cref="Vector3.Axis"/> index for which axis is longest.</returns> - public Vector3.Axis GetLongestAxisIndex() + public readonly Vector3.Axis GetLongestAxisIndex() { var axis = Vector3.Axis.X; real_t maxSize = _size.x; @@ -218,7 +218,7 @@ namespace Godot /// Returns the scalar length of the longest axis of the <see cref="AABB"/>. /// </summary> /// <returns>The scalar length of the longest axis of the <see cref="AABB"/>.</returns> - public real_t GetLongestAxisSize() + public readonly real_t GetLongestAxisSize() { real_t maxSize = _size.x; @@ -235,7 +235,7 @@ namespace Godot /// Returns the normalized shortest axis of the <see cref="AABB"/>. /// </summary> /// <returns>A vector representing the normalized shortest axis of the <see cref="AABB"/>.</returns> - public Vector3 GetShortestAxis() + public readonly Vector3 GetShortestAxis() { var axis = new Vector3(1f, 0f, 0f); real_t maxSize = _size.x; @@ -258,7 +258,7 @@ namespace Godot /// Returns the <see cref="Vector3.Axis"/> index of the shortest axis of the <see cref="AABB"/>. /// </summary> /// <returns>A <see cref="Vector3.Axis"/> index for which axis is shortest.</returns> - public Vector3.Axis GetShortestAxisIndex() + public readonly Vector3.Axis GetShortestAxisIndex() { var axis = Vector3.Axis.X; real_t maxSize = _size.x; @@ -281,7 +281,7 @@ namespace Godot /// Returns the scalar length of the shortest axis of the <see cref="AABB"/>. /// </summary> /// <returns>The scalar length of the shortest axis of the <see cref="AABB"/>.</returns> - public real_t GetShortestAxisSize() + public readonly real_t GetShortestAxisSize() { real_t maxSize = _size.x; @@ -300,7 +300,7 @@ namespace Godot /// </summary> /// <param name="dir">The direction to find support for.</param> /// <returns>A vector representing the support.</returns> - public Vector3 GetSupport(Vector3 dir) + public readonly Vector3 GetSupport(Vector3 dir) { Vector3 halfExtents = _size * 0.5f; Vector3 ofs = _position + halfExtents; @@ -315,7 +315,7 @@ namespace Godot /// Returns the volume of the <see cref="AABB"/>. /// </summary> /// <returns>The volume.</returns> - public real_t GetVolume() + public readonly real_t GetVolume() { return _size.x * _size.y * _size.z; } @@ -325,7 +325,7 @@ namespace Godot /// </summary> /// <param name="by">The amount to grow by.</param> /// <returns>The grown <see cref="AABB"/>.</returns> - public AABB Grow(real_t by) + public readonly AABB Grow(real_t by) { AABB res = this; @@ -347,7 +347,7 @@ namespace Godot /// <returns> /// A <see langword="bool"/> for whether or not the <see cref="AABB"/> contains <paramref name="point"/>. /// </returns> - public bool HasPoint(Vector3 point) + public readonly bool HasPoint(Vector3 point) { if (point.x < _position.x) return false; @@ -374,7 +374,7 @@ namespace Godot /// <returns> /// A <see langword="bool"/> for whether or not the <see cref="AABB"/> has surface. /// </returns> - public bool HasSurface() + public readonly bool HasSurface() { return _size.x > 0.0f || _size.y > 0.0f || _size.z > 0.0f; } @@ -388,7 +388,7 @@ namespace Godot /// <returns> /// A <see langword="bool"/> for whether or not the <see cref="AABB"/> has volume. /// </returns> - public bool HasVolume() + public readonly bool HasVolume() { return _size.x > 0.0f && _size.y > 0.0f && _size.z > 0.0f; } @@ -398,7 +398,7 @@ namespace Godot /// </summary> /// <param name="with">The other <see cref="AABB"/>.</param> /// <returns>The clipped <see cref="AABB"/>.</returns> - public AABB Intersection(AABB with) + public readonly AABB Intersection(AABB with) { Vector3 srcMin = _position; Vector3 srcMax = _position + _size; @@ -447,7 +447,7 @@ namespace Godot /// <returns> /// A <see langword="bool"/> for whether or not they are intersecting. /// </returns> - public bool Intersects(AABB with, bool includeBorders = false) + public readonly bool Intersects(AABB with, bool includeBorders = false) { if (includeBorders) { @@ -490,7 +490,7 @@ namespace Godot /// <returns> /// A <see langword="bool"/> for whether or not the <see cref="AABB"/> intersects the <see cref="Plane"/>. /// </returns> - public bool IntersectsPlane(Plane plane) + public readonly bool IntersectsPlane(Plane plane) { Vector3[] points = { @@ -531,7 +531,7 @@ namespace Godot /// <returns> /// A <see langword="bool"/> for whether or not the <see cref="AABB"/> intersects the line segment. /// </returns> - public bool IntersectsSegment(Vector3 from, Vector3 to) + public readonly bool IntersectsSegment(Vector3 from, Vector3 to) { real_t min = 0f; real_t max = 1f; @@ -590,7 +590,7 @@ namespace Godot /// </summary> /// <param name="with">The other <see cref="AABB"/>.</param> /// <returns>The merged <see cref="AABB"/>.</returns> - public AABB Merge(AABB with) + public readonly AABB Merge(AABB with) { Vector3 beg1 = _position; Vector3 beg2 = with._position; @@ -702,7 +702,7 @@ namespace Godot /// </summary> /// <param name="obj">The object to compare with.</param> /// <returns>Whether or not the AABB and the object are equal.</returns> - public override bool Equals(object obj) + public override readonly bool Equals(object obj) { return obj is AABB other && Equals(other); } @@ -714,7 +714,7 @@ namespace Godot /// </summary> /// <param name="other">The other AABB.</param> /// <returns>Whether or not the AABBs are exactly equal.</returns> - public bool Equals(AABB other) + public readonly bool Equals(AABB other) { return _position == other._position && _size == other._size; } @@ -725,7 +725,7 @@ namespace Godot /// </summary> /// <param name="other">The other AABB to compare.</param> /// <returns>Whether or not the AABBs structures are approximately equal.</returns> - public bool IsEqualApprox(AABB other) + public readonly bool IsEqualApprox(AABB other) { return _position.IsEqualApprox(other._position) && _size.IsEqualApprox(other._size); } @@ -734,7 +734,7 @@ namespace Godot /// Serves as the hash function for <see cref="AABB"/>. /// </summary> /// <returns>A hash code for this AABB.</returns> - public override int GetHashCode() + public override readonly int GetHashCode() { return _position.GetHashCode() ^ _size.GetHashCode(); } @@ -743,7 +743,7 @@ namespace Godot /// Converts this <see cref="AABB"/> to a string. /// </summary> /// <returns>A string representation of this AABB.</returns> - public override string ToString() + public override readonly string ToString() { return $"{_position}, {_size}"; } @@ -752,7 +752,7 @@ namespace Godot /// Converts this <see cref="AABB"/> to a string with the given <paramref name="format"/>. /// </summary> /// <returns>A string representation of this AABB.</returns> - public string ToString(string format) + public readonly string ToString(string format) { return $"{_position.ToString(format)}, {_size.ToString(format)}"; } diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Basis.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Basis.cs index bb1d6e1661..5d390a298d 100644 --- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Basis.cs +++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Basis.cs @@ -29,7 +29,7 @@ namespace Godot /// <value>Equivalent to <see cref="Column0"/> and array index <c>[0]</c>.</value> public Vector3 x { - get => Column0; + readonly get => Column0; set => Column0 = value; } @@ -39,7 +39,7 @@ namespace Godot /// <value>Equivalent to <see cref="Column1"/> and array index <c>[1]</c>.</value> public Vector3 y { - get => Column1; + readonly get => Column1; set => Column1 = value; } @@ -49,7 +49,7 @@ namespace Godot /// <value>Equivalent to <see cref="Column2"/> and array index <c>[2]</c>.</value> public Vector3 z { - get => Column2; + readonly get => Column2; set => Column2 = value; } @@ -80,7 +80,7 @@ namespace Godot /// <value>Equivalent to <see cref="x"/> and array index <c>[0]</c>.</value> public Vector3 Column0 { - get => new Vector3(Row0.x, Row1.x, Row2.x); + readonly get => new Vector3(Row0.x, Row1.x, Row2.x); set { Row0.x = value.x; @@ -95,7 +95,7 @@ namespace Godot /// <value>Equivalent to <see cref="y"/> and array index <c>[1]</c>.</value> public Vector3 Column1 { - get => new Vector3(Row0.y, Row1.y, Row2.y); + readonly get => new Vector3(Row0.y, Row1.y, Row2.y); set { Row0.y = value.x; @@ -110,7 +110,7 @@ namespace Godot /// <value>Equivalent to <see cref="z"/> and array index <c>[2]</c>.</value> public Vector3 Column2 { - get => new Vector3(Row0.z, Row1.z, Row2.z); + readonly get => new Vector3(Row0.z, Row1.z, Row2.z); set { Row0.z = value.x; @@ -125,7 +125,7 @@ namespace Godot /// <value>Equivalent to the lengths of each column vector, but negative if the determinant is negative.</value> public Vector3 Scale { - get + readonly get { real_t detSign = Mathf.Sign(Determinant()); return detSign * new Vector3 @@ -154,7 +154,7 @@ namespace Godot /// <value>The basis column.</value> public Vector3 this[int column] { - get + readonly get { switch (column) { @@ -195,7 +195,7 @@ namespace Godot /// <value>The matrix element.</value> public real_t this[int column, int row] { - get + readonly get { return this[column][row]; } @@ -234,7 +234,7 @@ namespace Godot /// and is usually considered invalid. /// </summary> /// <returns>The determinant of the basis matrix.</returns> - public real_t Determinant() + public readonly real_t Determinant() { real_t cofac00 = Row1[1] * Row2[2] - Row1[2] * Row2[1]; real_t cofac10 = Row1[2] * Row2[0] - Row1[0] * Row2[2]; @@ -255,7 +255,7 @@ namespace Godot /// </summary> /// <param name="order">The Euler order to use. By default, use YXZ order (most common).</param> /// <returns>A <see cref="Vector3"/> representing the basis rotation in Euler angles.</returns> - public Vector3 GetEuler(EulerOrder order = EulerOrder.Yxz) + public readonly Vector3 GetEuler(EulerOrder order = EulerOrder.Yxz) { switch (order) { @@ -499,7 +499,7 @@ namespace Godot /// mind that quaternions should generally be preferred to Euler angles. /// </summary> /// <returns>A <see cref="Quaternion"/> representing the basis's rotation.</returns> - internal Quaternion GetQuaternion() + internal readonly Quaternion GetQuaternion() { real_t trace = Row0[0] + Row1[1] + Row2[2]; @@ -558,7 +558,7 @@ namespace Godot /// be preferred to Euler angles. /// </summary> /// <returns>The basis rotation.</returns> - public Quaternion GetRotationQuaternion() + public readonly Quaternion GetRotationQuaternion() { Basis orthonormalizedBasis = Orthonormalized(); real_t det = orthonormalizedBasis.Determinant(); @@ -581,7 +581,7 @@ namespace Godot /// <paramref name="index"/> is not 0, 1 or 2. /// </exception> /// <returns>One of <c>Row0</c>, <c>Row1</c>, or <c>Row2</c>.</returns> - public Vector3 GetRow(int index) + public readonly Vector3 GetRow(int index) { switch (index) { @@ -633,7 +633,7 @@ namespace Godot /// For further details, refer to the Godot source code. /// </summary> /// <returns>The orthogonal index.</returns> - public int GetOrthogonalIndex() + public readonly int GetOrthogonalIndex() { var orth = this; @@ -679,7 +679,7 @@ namespace Godot /// Returns the inverse of the matrix. /// </summary> /// <returns>The inverse matrix.</returns> - public Basis Inverse() + public readonly Basis Inverse() { real_t cofac00 = Row1[1] * Row2[2] - Row1[2] * Row2[1]; real_t cofac10 = Row1[2] * Row2[0] - Row1[0] * Row2[2]; @@ -709,7 +709,7 @@ namespace Godot ); } - internal Basis Lerp(Basis to, real_t weight) + internal readonly Basis Lerp(Basis to, real_t weight) { Basis b = this; b.Row0 = Row0.Lerp(to.Row0, weight); @@ -724,7 +724,7 @@ namespace Godot /// This performs a Gram-Schmidt orthonormalization on the basis of the matrix. /// </summary> /// <returns>An orthonormalized basis matrix.</returns> - public Basis Orthonormalized() + public readonly Basis Orthonormalized() { Vector3 column0 = this[0]; Vector3 column1 = this[1]; @@ -746,7 +746,7 @@ namespace Godot /// <param name="axis">The axis to rotate around. Must be normalized.</param> /// <param name="angle">The angle to rotate, in radians.</param> /// <returns>The rotated basis matrix.</returns> - public Basis Rotated(Vector3 axis, real_t angle) + public readonly Basis Rotated(Vector3 axis, real_t angle) { return new Basis(axis, angle) * this; } @@ -756,7 +756,7 @@ namespace Godot /// </summary> /// <param name="scale">The scale to introduce.</param> /// <returns>The scaled basis matrix.</returns> - public Basis Scaled(Vector3 scale) + public readonly Basis Scaled(Vector3 scale) { Basis b = this; b.Row0 *= scale.x; @@ -772,7 +772,7 @@ namespace Godot /// <param name="target">The destination basis for interpolation.</param> /// <param name="weight">A value on the range of 0.0 to 1.0, representing the amount of interpolation.</param> /// <returns>The resulting basis matrix of the interpolation.</returns> - public Basis Slerp(Basis target, real_t weight) + public readonly Basis Slerp(Basis target, real_t weight) { Quaternion from = new Quaternion(this); Quaternion to = new Quaternion(target); @@ -790,7 +790,7 @@ namespace Godot /// </summary> /// <param name="with">A vector to calculate the dot product with.</param> /// <returns>The resulting dot product.</returns> - public real_t Tdotx(Vector3 with) + public readonly real_t Tdotx(Vector3 with) { return Row0[0] * with[0] + Row1[0] * with[1] + Row2[0] * with[2]; } @@ -800,7 +800,7 @@ namespace Godot /// </summary> /// <param name="with">A vector to calculate the dot product with.</param> /// <returns>The resulting dot product.</returns> - public real_t Tdoty(Vector3 with) + public readonly real_t Tdoty(Vector3 with) { return Row0[1] * with[0] + Row1[1] * with[1] + Row2[1] * with[2]; } @@ -810,7 +810,7 @@ namespace Godot /// </summary> /// <param name="with">A vector to calculate the dot product with.</param> /// <returns>The resulting dot product.</returns> - public real_t Tdotz(Vector3 with) + public readonly real_t Tdotz(Vector3 with) { return Row0[2] * with[0] + Row1[2] * with[1] + Row2[2] * with[2]; } @@ -819,21 +819,18 @@ namespace Godot /// Returns the transposed version of the basis matrix. /// </summary> /// <returns>The transposed basis matrix.</returns> - public Basis Transposed() + public readonly Basis Transposed() { Basis tr = this; - real_t temp = tr.Row0[1]; - tr.Row0[1] = tr.Row1[0]; - tr.Row1[0] = temp; + tr.Row0[1] = Row1[0]; + tr.Row1[0] = Row0[1]; - temp = tr.Row0[2]; - tr.Row0[2] = tr.Row2[0]; - tr.Row2[0] = temp; + tr.Row0[2] = Row2[0]; + tr.Row2[0] = Row0[2]; - temp = tr.Row1[2]; - tr.Row1[2] = tr.Row2[1]; - tr.Row2[1] = temp; + tr.Row1[2] = Row2[1]; + tr.Row2[1] = Row1[2]; return tr; } @@ -1121,7 +1118,7 @@ namespace Godot /// </summary> /// <param name="obj">The object to compare with.</param> /// <returns>Whether or not the basis matrix and the object are exactly equal.</returns> - public override bool Equals(object obj) + public override readonly bool Equals(object obj) { return obj is Basis other && Equals(other); } @@ -1133,7 +1130,7 @@ namespace Godot /// </summary> /// <param name="other">The other basis.</param> /// <returns>Whether or not the basis matrices are exactly equal.</returns> - public bool Equals(Basis other) + public readonly bool Equals(Basis other) { return Row0.Equals(other.Row0) && Row1.Equals(other.Row1) && Row2.Equals(other.Row2); } @@ -1144,7 +1141,7 @@ namespace Godot /// </summary> /// <param name="other">The other basis to compare.</param> /// <returns>Whether or not the bases are approximately equal.</returns> - public bool IsEqualApprox(Basis other) + public readonly bool IsEqualApprox(Basis other) { return Row0.IsEqualApprox(other.Row0) && Row1.IsEqualApprox(other.Row1) && Row2.IsEqualApprox(other.Row2); } @@ -1153,7 +1150,7 @@ namespace Godot /// Serves as the hash function for <see cref="Basis"/>. /// </summary> /// <returns>A hash code for this basis.</returns> - public override int GetHashCode() + public override readonly int GetHashCode() { return Row0.GetHashCode() ^ Row1.GetHashCode() ^ Row2.GetHashCode(); } @@ -1162,7 +1159,7 @@ namespace Godot /// Converts this <see cref="Basis"/> to a string. /// </summary> /// <returns>A string representation of this basis.</returns> - public override string ToString() + public override readonly string ToString() { return $"[X: {x}, Y: {y}, Z: {z}]"; } @@ -1171,7 +1168,7 @@ namespace Godot /// Converts this <see cref="Basis"/> to a string with the given <paramref name="format"/>. /// </summary> /// <returns>A string representation of this basis.</returns> - public string ToString(string format) + public readonly string ToString(string format) { return $"[X: {x.ToString(format)}, Y: {y.ToString(format)}, Z: {z.ToString(format)}]"; } diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Bridge/MethodInfo.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Bridge/MethodInfo.cs index 647ae436ff..85d38f9727 100644 --- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Bridge/MethodInfo.cs +++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Bridge/MethodInfo.cs @@ -4,7 +4,7 @@ namespace Godot.Bridge; #nullable enable -public struct MethodInfo +public readonly struct MethodInfo { public StringName Name { get; init; } public PropertyInfo ReturnVal { get; init; } diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Bridge/PropertyInfo.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Bridge/PropertyInfo.cs index 80d6f7b4a5..0f447b93c8 100644 --- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Bridge/PropertyInfo.cs +++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Bridge/PropertyInfo.cs @@ -2,7 +2,7 @@ namespace Godot.Bridge; #nullable enable -public struct PropertyInfo +public readonly struct PropertyInfo { public Variant.Type Type { get; init; } public StringName Name { get; init; } diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Color.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Color.cs index ee9e59f9fa..f49023555b 100644 --- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Color.cs +++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Color.cs @@ -43,7 +43,7 @@ namespace Godot /// <value>Getting is equivalent to multiplying by 255 and rounding. Setting is equivalent to dividing by 255.</value> public int r8 { - get + readonly get { return (int)Math.Round(r * 255.0f); } @@ -59,7 +59,7 @@ namespace Godot /// <value>Getting is equivalent to multiplying by 255 and rounding. Setting is equivalent to dividing by 255.</value> public int g8 { - get + readonly get { return (int)Math.Round(g * 255.0f); } @@ -75,7 +75,7 @@ namespace Godot /// <value>Getting is equivalent to multiplying by 255 and rounding. Setting is equivalent to dividing by 255.</value> public int b8 { - get + readonly get { return (int)Math.Round(b * 255.0f); } @@ -91,7 +91,7 @@ namespace Godot /// <value>Getting is equivalent to multiplying by 255 and rounding. Setting is equivalent to dividing by 255.</value> public int a8 { - get + readonly get { return (int)Math.Round(a * 255.0f); } @@ -107,7 +107,7 @@ namespace Godot /// <value>Getting is a long process, refer to the source code for details. Setting uses <see cref="FromHSV"/>.</value> public float h { - get + readonly get { float max = Math.Max(r, Math.Max(g, b)); float min = Math.Min(r, Math.Min(g, b)); @@ -155,7 +155,7 @@ namespace Godot /// <value>Getting is equivalent to the ratio between the min and max RGB value. Setting uses <see cref="FromHSV"/>.</value> public float s { - get + readonly get { float max = Math.Max(r, Math.Max(g, b)); float min = Math.Min(r, Math.Min(g, b)); @@ -176,7 +176,7 @@ namespace Godot /// <value>Getting is equivalent to using <see cref="Math.Max(float, float)"/> on the RGB components. Setting uses <see cref="FromHSV"/>.</value> public float v { - get + readonly get { return Math.Max(r, Math.Max(g, b)); } @@ -197,7 +197,7 @@ namespace Godot /// </value> public float this[int index] { - get + readonly get { switch (index) { @@ -242,7 +242,7 @@ namespace Godot /// </summary> /// <param name="over">The color to blend over.</param> /// <returns>This color blended over <paramref name="over"/>.</returns> - public Color Blend(Color over) + public readonly Color Blend(Color over) { Color res; @@ -269,7 +269,7 @@ namespace Godot /// <param name="min">The color with minimum allowed values.</param> /// <param name="max">The color with maximum allowed values.</param> /// <returns>The color with all components clamped.</returns> - public Color Clamp(Color? min = null, Color? max = null) + public readonly Color Clamp(Color? min = null, Color? max = null) { Color minimum = min ?? new Color(0, 0, 0, 0); Color maximum = max ?? new Color(1, 1, 1, 1); @@ -288,7 +288,7 @@ namespace Godot /// </summary> /// <param name="amount">The ratio to darken by.</param> /// <returns>The darkened color.</returns> - public Color Darkened(float amount) + public readonly Color Darkened(float amount) { Color res = this; res.r *= 1.0f - amount; @@ -301,7 +301,7 @@ namespace Godot /// Returns the inverted color: <c>(1 - r, 1 - g, 1 - b, a)</c>. /// </summary> /// <returns>The inverted color.</returns> - public Color Inverted() + public readonly Color Inverted() { return new Color( 1.0f - r, @@ -317,7 +317,7 @@ namespace Godot /// </summary> /// <param name="amount">The ratio to lighten by.</param> /// <returns>The darkened color.</returns> - public Color Lightened(float amount) + public readonly Color Lightened(float amount) { Color res = this; res.r += (1.0f - res.r) * amount; @@ -333,7 +333,7 @@ namespace Godot /// <param name="to">The destination color for interpolation.</param> /// <param name="weight">A value on the range of 0.0 to 1.0, representing the amount of interpolation.</param> /// <returns>The resulting color of the interpolation.</returns> - public Color Lerp(Color to, real_t weight) + public readonly Color Lerp(Color to, real_t weight) { return new Color ( @@ -351,7 +351,7 @@ namespace Godot /// <param name="to">The destination color for interpolation.</param> /// <param name="weight">A color with components on the range of 0.0 to 1.0, representing the amount of interpolation.</param> /// <returns>The resulting color of the interpolation.</returns> - public Color Lerp(Color to, Color weight) + public readonly Color Lerp(Color to, Color weight) { return new Color ( @@ -368,7 +368,7 @@ namespace Godot /// ABGR is the reversed version of the default format. /// </summary> /// <returns>A <see langword="uint"/> representing this color in ABGR32 format.</returns> - public uint ToAbgr32() + public readonly uint ToAbgr32() { uint c = (byte)Math.Round(a * 255); c <<= 8; @@ -387,7 +387,7 @@ namespace Godot /// ABGR is the reversed version of the default format. /// </summary> /// <returns>A <see langword="ulong"/> representing this color in ABGR64 format.</returns> - public ulong ToAbgr64() + public readonly ulong ToAbgr64() { ulong c = (ushort)Math.Round(a * 65535); c <<= 16; @@ -406,7 +406,7 @@ namespace Godot /// ARGB is more compatible with DirectX, but not used much in Godot. /// </summary> /// <returns>A <see langword="uint"/> representing this color in ARGB32 format.</returns> - public uint ToArgb32() + public readonly uint ToArgb32() { uint c = (byte)Math.Round(a * 255); c <<= 8; @@ -425,7 +425,7 @@ namespace Godot /// ARGB is more compatible with DirectX, but not used much in Godot. /// </summary> /// <returns>A <see langword="ulong"/> representing this color in ARGB64 format.</returns> - public ulong ToArgb64() + public readonly ulong ToArgb64() { ulong c = (ushort)Math.Round(a * 65535); c <<= 16; @@ -444,7 +444,7 @@ namespace Godot /// RGBA is Godot's default and recommended format. /// </summary> /// <returns>A <see langword="uint"/> representing this color in RGBA32 format.</returns> - public uint ToRgba32() + public readonly uint ToRgba32() { uint c = (byte)Math.Round(r * 255); c <<= 8; @@ -463,7 +463,7 @@ namespace Godot /// RGBA is Godot's default and recommended format. /// </summary> /// <returns>A <see langword="ulong"/> representing this color in RGBA64 format.</returns> - public ulong ToRgba64() + public readonly ulong ToRgba64() { ulong c = (ushort)Math.Round(r * 65535); c <<= 16; @@ -483,7 +483,7 @@ namespace Godot /// Whether or not to include alpha. If <see langword="false"/>, the color is RGB instead of RGBA. /// </param> /// <returns>A string for the HTML hexadecimal representation of this color.</returns> - public string ToHTML(bool includeAlpha = true) + public readonly string ToHTML(bool includeAlpha = true) { string txt = string.Empty; @@ -777,7 +777,7 @@ namespace Godot /// <param name="hue">Output parameter for the HSV hue.</param> /// <param name="saturation">Output parameter for the HSV saturation.</param> /// <param name="value">Output parameter for the HSV value.</param> - public void ToHSV(out float hue, out float saturation, out float value) + public readonly void ToHSV(out float hue, out float saturation, out float value) { float max = (float)Mathf.Max(r, Mathf.Max(g, b)); float min = (float)Mathf.Min(r, Mathf.Min(g, b)); @@ -1149,7 +1149,7 @@ namespace Godot /// </summary> /// <param name="obj">The other object to compare.</param> /// <returns>Whether or not the color and the other object are equal.</returns> - public override bool Equals(object obj) + public override readonly bool Equals(object obj) { return obj is Color other && Equals(other); } @@ -1161,7 +1161,7 @@ namespace Godot /// </summary> /// <param name="other">The other color.</param> /// <returns>Whether or not the colors are equal.</returns> - public bool Equals(Color other) + public readonly bool Equals(Color other) { return r == other.r && g == other.g && b == other.b && a == other.a; } @@ -1172,7 +1172,7 @@ namespace Godot /// </summary> /// <param name="other">The other color to compare.</param> /// <returns>Whether or not the colors are approximately equal.</returns> - public bool IsEqualApprox(Color other) + public readonly bool IsEqualApprox(Color other) { return Mathf.IsEqualApprox(r, other.r) && Mathf.IsEqualApprox(g, other.g) && Mathf.IsEqualApprox(b, other.b) && Mathf.IsEqualApprox(a, other.a); } @@ -1181,7 +1181,7 @@ namespace Godot /// Serves as the hash function for <see cref="Color"/>. /// </summary> /// <returns>A hash code for this color.</returns> - public override int GetHashCode() + public override readonly int GetHashCode() { return r.GetHashCode() ^ g.GetHashCode() ^ b.GetHashCode() ^ a.GetHashCode(); } @@ -1190,7 +1190,7 @@ namespace Godot /// Converts this <see cref="Color"/> to a string. /// </summary> /// <returns>A string representation of this color.</returns> - public override string ToString() + public override readonly string ToString() { return $"({r}, {g}, {b}, {a})"; } @@ -1199,7 +1199,7 @@ namespace Godot /// Converts this <see cref="Color"/> to a string with the given <paramref name="format"/>. /// </summary> /// <returns>A string representation of this color.</returns> - public string ToString(string format) + public readonly string ToString(string format) { return $"({r.ToString(format)}, {g.ToString(format)}, {b.ToString(format)}, {a.ToString(format)})"; } diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Plane.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Plane.cs index 664b2e0f34..42c6b0a37e 100644 --- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Plane.cs +++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Plane.cs @@ -22,7 +22,7 @@ namespace Godot /// <value>Equivalent to <see cref="x"/>, <see cref="y"/>, and <see cref="z"/>.</value> public Vector3 Normal { - get { return _normal; } + readonly get { return _normal; } set { _normal = value; } } @@ -32,7 +32,7 @@ namespace Godot /// <value>Equivalent to <see cref="Normal"/>'s X value.</value> public real_t x { - get + readonly get { return _normal.x; } @@ -48,7 +48,7 @@ namespace Godot /// <value>Equivalent to <see cref="Normal"/>'s Y value.</value> public real_t y { - get + readonly get { return _normal.y; } @@ -64,7 +64,7 @@ namespace Godot /// <value>Equivalent to <see cref="Normal"/>'s Z value.</value> public real_t z { - get + readonly get { return _normal.z; } @@ -90,7 +90,7 @@ namespace Godot /// <value>Equivalent to <see cref="Normal"/> multiplied by <see cref="D"/>.</value> public Vector3 Center { - get + readonly get { return _normal * D; } @@ -106,7 +106,7 @@ namespace Godot /// </summary> /// <param name="point">The position to use for the calculation.</param> /// <returns>The shortest distance.</returns> - public real_t DistanceTo(Vector3 point) + public readonly real_t DistanceTo(Vector3 point) { return _normal.Dot(point) - D; } @@ -118,7 +118,7 @@ namespace Godot /// <param name="point">The point to check.</param> /// <param name="tolerance">The tolerance threshold.</param> /// <returns>A <see langword="bool"/> for whether or not the plane has the point.</returns> - public bool HasPoint(Vector3 point, real_t tolerance = Mathf.Epsilon) + public readonly bool HasPoint(Vector3 point, real_t tolerance = Mathf.Epsilon) { real_t dist = _normal.Dot(point) - D; return Mathf.Abs(dist) <= tolerance; @@ -131,7 +131,7 @@ namespace Godot /// <param name="b">One of the three planes to use in the calculation.</param> /// <param name="c">One of the three planes to use in the calculation.</param> /// <returns>The intersection, or <see langword="null"/> if none is found.</returns> - public Vector3? Intersect3(Plane b, Plane c) + public readonly Vector3? Intersect3(Plane b, Plane c) { real_t denom = _normal.Cross(b._normal).Dot(c._normal); @@ -155,7 +155,7 @@ namespace Godot /// <param name="from">The start of the ray.</param> /// <param name="dir">The direction of the ray, normalized.</param> /// <returns>The intersection, or <see langword="null"/> if none is found.</returns> - public Vector3? IntersectRay(Vector3 from, Vector3 dir) + public readonly Vector3? IntersectRay(Vector3 from, Vector3 dir) { real_t den = _normal.Dot(dir); @@ -183,7 +183,7 @@ namespace Godot /// <param name="begin">The start of the line segment.</param> /// <param name="end">The end of the line segment.</param> /// <returns>The intersection, or <see langword="null"/> if none is found.</returns> - public Vector3? IntersectSegment(Vector3 begin, Vector3 end) + public readonly Vector3? IntersectSegment(Vector3 begin, Vector3 end) { Vector3 segment = begin - end; real_t den = _normal.Dot(segment); @@ -209,7 +209,7 @@ namespace Godot /// </summary> /// <param name="point">The point to check.</param> /// <returns>A <see langword="bool"/> for whether or not the point is above the plane.</returns> - public bool IsPointOver(Vector3 point) + public readonly bool IsPointOver(Vector3 point) { return _normal.Dot(point) > D; } @@ -218,7 +218,7 @@ namespace Godot /// Returns the plane scaled to unit length. /// </summary> /// <returns>A normalized version of the plane.</returns> - public Plane Normalized() + public readonly Plane Normalized() { real_t len = _normal.Length(); @@ -235,7 +235,7 @@ namespace Godot /// </summary> /// <param name="point">The point to project.</param> /// <returns>The projected point.</returns> - public Vector3 Project(Vector3 point) + public readonly Vector3 Project(Vector3 point) { return point - (_normal * DistanceTo(point)); } @@ -363,7 +363,7 @@ namespace Godot /// </summary> /// <param name="obj">The other object to compare.</param> /// <returns>Whether or not the plane and the other object are exactly equal.</returns> - public override bool Equals(object obj) + public override readonly bool Equals(object obj) { return obj is Plane other && Equals(other); } @@ -373,7 +373,7 @@ namespace Godot /// </summary> /// <param name="other">The other plane to compare.</param> /// <returns>Whether or not the planes are exactly equal.</returns> - public bool Equals(Plane other) + public readonly bool Equals(Plane other) { return _normal == other._normal && D == other.D; } @@ -384,7 +384,7 @@ namespace Godot /// </summary> /// <param name="other">The other plane to compare.</param> /// <returns>Whether or not the planes are approximately equal.</returns> - public bool IsEqualApprox(Plane other) + public readonly bool IsEqualApprox(Plane other) { return _normal.IsEqualApprox(other._normal) && Mathf.IsEqualApprox(D, other.D); } @@ -393,7 +393,7 @@ namespace Godot /// Serves as the hash function for <see cref="Plane"/>. /// </summary> /// <returns>A hash code for this plane.</returns> - public override int GetHashCode() + public override readonly int GetHashCode() { return _normal.GetHashCode() ^ D.GetHashCode(); } @@ -402,7 +402,7 @@ namespace Godot /// Converts this <see cref="Plane"/> to a string. /// </summary> /// <returns>A string representation of this plane.</returns> - public override string ToString() + public override readonly string ToString() { return $"{_normal}, {D}"; } @@ -411,7 +411,7 @@ namespace Godot /// Converts this <see cref="Plane"/> to a string with the given <paramref name="format"/>. /// </summary> /// <returns>A string representation of this plane.</returns> - public string ToString(string format) + public readonly string ToString(string format) { return $"{_normal.ToString(format)}, {D.ToString(format)}"; } diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Projection.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Projection.cs index da895fd121..371729ebec 100644 --- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Projection.cs +++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Projection.cs @@ -286,7 +286,7 @@ namespace Godot return proj * cm; } - public real_t Determinant() + public readonly real_t Determinant() { return x.w * y.z * z.y * w.x - x.z * y.w * z.y * w.x - x.w * y.y * z.z * w.x + x.y * y.w * z.z * w.x + @@ -302,13 +302,13 @@ namespace Godot x.y * y.x * z.z * w.w + x.x * y.y * z.z * w.w; } - public real_t GetAspect() + public readonly real_t GetAspect() { Vector2 vpHe = GetViewportHalfExtents(); return vpHe.x / vpHe.y; } - public real_t GetFov() + public readonly real_t GetFov() { Plane rightPlane = new Plane(x.w - x.x, y.w - y.x, z.w - z.x, -w.w + w.x).Normalized(); if (z.x == 0 && z.y == 0) @@ -327,7 +327,7 @@ namespace Godot return Mathf.RadToDeg(Mathf.Atan(aspect * Mathf.Tan(Mathf.DegToRad(fovx) * (real_t)0.5)) * (real_t)2.0); } - public real_t GetLodMultiplier() + public readonly real_t GetLodMultiplier() { if (IsOrthogonal()) { @@ -341,14 +341,14 @@ namespace Godot } } - public int GetPixelsPerMeter(int forPixelWidth) + public readonly int GetPixelsPerMeter(int forPixelWidth) { Vector3 result = this * new Vector3(1, 0, -1); return (int)((result.x * (real_t)0.5 + (real_t)0.5) * forPixelWidth); } - public Plane GetProjectionPlane(Planes plane) + public readonly Plane GetProjectionPlane(Planes plane) { Plane newPlane = plane switch { @@ -364,36 +364,36 @@ namespace Godot return newPlane.Normalized(); } - public Vector2 GetFarPlaneHalfExtents() + public readonly Vector2 GetFarPlaneHalfExtents() { var res = GetProjectionPlane(Planes.Far).Intersect3(GetProjectionPlane(Planes.Right), GetProjectionPlane(Planes.Top)); return new Vector2(res.Value.x, res.Value.y); } - public Vector2 GetViewportHalfExtents() + public readonly Vector2 GetViewportHalfExtents() { var res = GetProjectionPlane(Planes.Near).Intersect3(GetProjectionPlane(Planes.Right), GetProjectionPlane(Planes.Top)); return new Vector2(res.Value.x, res.Value.y); } - public real_t GetZFar() + public readonly real_t GetZFar() { return GetProjectionPlane(Planes.Far).D; } - public real_t GetZNear() + public readonly real_t GetZNear() { return -GetProjectionPlane(Planes.Near).D; } - public Projection FlippedY() + public readonly Projection FlippedY() { Projection proj = this; proj.y = -proj.y; return proj; } - public Projection PerspectiveZNearAdjusted(real_t newZNear) + public readonly Projection PerspectiveZNearAdjusted(real_t newZNear) { Projection proj = this; real_t zFar = GetZFar(); @@ -404,7 +404,7 @@ namespace Godot return proj; } - public Projection JitterOffseted(Vector2 offset) + public readonly Projection JitterOffseted(Vector2 offset) { Projection proj = this; proj.w.x += offset.x; @@ -412,7 +412,7 @@ namespace Godot return proj; } - public Projection Inverse() + public readonly Projection Inverse() { Projection proj = this; int i, j, k; @@ -535,7 +535,7 @@ namespace Godot return proj; } - public bool IsOrthogonal() + public readonly bool IsOrthogonal() { return w.w == (real_t)1.0; } @@ -654,7 +654,7 @@ namespace Godot /// </exception> public Vector4 this[int column] { - get + readonly get { switch (column) { @@ -702,7 +702,7 @@ namespace Godot /// </exception> public real_t this[int column, int row] { - get + readonly get { switch (column) { @@ -772,7 +772,7 @@ namespace Godot /// Serves as the hash function for <see cref="Projection"/>. /// </summary> /// <returns>A hash code for this projection.</returns> - public override int GetHashCode() + public override readonly int GetHashCode() { return y.GetHashCode() ^ x.GetHashCode() ^ z.GetHashCode() ^ w.GetHashCode(); } @@ -781,7 +781,7 @@ namespace Godot /// Converts this <see cref="Projection"/> to a string. /// </summary> /// <returns>A string representation of this projection.</returns> - public override string ToString() + public override readonly string ToString() { return $"{x.x}, {x.y}, {x.z}, {x.w}\n{y.x}, {y.y}, {y.z}, {y.w}\n{z.x}, {z.y}, {z.z}, {z.w}\n{w.x}, {w.y}, {w.z}, {w.w}\n"; } @@ -790,7 +790,7 @@ namespace Godot /// Converts this <see cref="Projection"/> to a string with the given <paramref name="format"/>. /// </summary> /// <returns>A string representation of this projection.</returns> - public string ToString(string format) + public readonly string ToString(string format) { return $"{x.x.ToString(format)}, {x.y.ToString(format)}, {x.z.ToString(format)}, {x.w.ToString(format)}\n" + $"{y.x.ToString(format)}, {y.y.ToString(format)}, {y.z.ToString(format)}, {y.w.ToString(format)}\n" + @@ -804,7 +804,7 @@ namespace Godot /// </summary> /// <param name="obj">The object to compare with.</param> /// <returns>Whether or not the vector and the object are equal.</returns> - public override bool Equals(object obj) + public override readonly bool Equals(object obj) { return obj is Projection other && Equals(other); } @@ -814,7 +814,7 @@ namespace Godot /// </summary> /// <param name="other">The other projection.</param> /// <returns>Whether or not the projections are exactly equal.</returns> - public bool Equals(Projection other) + public readonly bool Equals(Projection other) { return x == other.x && y == other.y && z == other.z && w == other.w; } diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Quaternion.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Quaternion.cs index f01f0be985..c55003586b 100644 --- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Quaternion.cs +++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Quaternion.cs @@ -58,7 +58,7 @@ namespace Godot /// </value> public real_t this[int index] { - get + readonly get { switch (index) { @@ -101,7 +101,7 @@ namespace Godot /// </summary> /// <seealso cref="LengthSquared"/> /// <value>Equivalent to <c>Mathf.Sqrt(LengthSquared)</c>.</value> - public real_t Length + public readonly real_t Length { get { return Mathf.Sqrt(LengthSquared); } } @@ -112,7 +112,7 @@ namespace Godot /// you need to compare quaternions or need the squared length for some formula. /// </summary> /// <value>Equivalent to <c>Dot(this)</c>.</value> - public real_t LengthSquared + public readonly real_t LengthSquared { get { return Dot(this); } } @@ -128,7 +128,7 @@ namespace Godot /// </summary> /// <param name="to">The other quaternion.</param> /// <returns>The angle between the quaternions.</returns> - public real_t AngleTo(Quaternion to) + public readonly real_t AngleTo(Quaternion to) { real_t dot = Dot(to); return Mathf.Acos(Mathf.Clamp(dot * dot * 2 - 1, -1, 1)); @@ -143,7 +143,7 @@ namespace Godot /// <param name="postB">A quaternion after <paramref name="b"/>.</param> /// <param name="weight">A value on the range of 0.0 to 1.0, representing the amount of interpolation.</param> /// <returns>The interpolated quaternion.</returns> - public Quaternion SphericalCubicInterpolate(Quaternion b, Quaternion preA, Quaternion postB, real_t weight) + public readonly Quaternion SphericalCubicInterpolate(Quaternion b, Quaternion preA, Quaternion postB, real_t weight) { #if DEBUG if (!IsNormalized()) @@ -212,7 +212,7 @@ namespace Godot /// <param name="preAT"></param> /// <param name="postBT"></param> /// <returns>The interpolated quaternion.</returns> - public Quaternion SphericalCubicInterpolateInTime(Quaternion b, Quaternion preA, Quaternion postB, real_t weight, real_t bT, real_t preAT, real_t postBT) + public readonly Quaternion SphericalCubicInterpolateInTime(Quaternion b, Quaternion preA, Quaternion postB, real_t weight, real_t bT, real_t preAT, real_t postBT) { #if DEBUG if (!IsNormalized()) @@ -272,12 +272,12 @@ namespace Godot /// </summary> /// <param name="b">The other quaternion.</param> /// <returns>The dot product.</returns> - public real_t Dot(Quaternion b) + public readonly real_t Dot(Quaternion b) { return (x * b.x) + (y * b.y) + (z * b.z) + (w * b.w); } - public Quaternion Exp() + public readonly Quaternion Exp() { Vector3 v = new Vector3(x, y, z); real_t theta = v.Length(); @@ -289,12 +289,12 @@ namespace Godot return new Quaternion(v, theta); } - public real_t GetAngle() + public readonly real_t GetAngle() { return 2 * Mathf.Acos(w); } - public Vector3 GetAxis() + public readonly Vector3 GetAxis() { if (Mathf.Abs(w) > 1 - Mathf.Epsilon) { @@ -312,7 +312,7 @@ namespace Godot /// the rotation angles in the format (X angle, Y angle, Z angle). /// </summary> /// <returns>The Euler angle representation of this quaternion.</returns> - public Vector3 GetEuler(EulerOrder order = EulerOrder.Yxz) + public readonly Vector3 GetEuler(EulerOrder order = EulerOrder.Yxz) { #if DEBUG if (!IsNormalized()) @@ -328,7 +328,7 @@ namespace Godot /// Returns the inverse of the quaternion. /// </summary> /// <returns>The inverse quaternion.</returns> - public Quaternion Inverse() + public readonly Quaternion Inverse() { #if DEBUG if (!IsNormalized()) @@ -343,12 +343,12 @@ namespace Godot /// Returns whether the quaternion is normalized or not. /// </summary> /// <returns>A <see langword="bool"/> for whether the quaternion is normalized or not.</returns> - public bool IsNormalized() + public readonly bool IsNormalized() { return Mathf.Abs(LengthSquared - 1) <= Mathf.Epsilon; } - public Quaternion Log() + public readonly Quaternion Log() { Vector3 v = GetAxis() * GetAngle(); return new Quaternion(v.x, v.y, v.z, 0); @@ -358,7 +358,7 @@ namespace Godot /// Returns a copy of the quaternion, normalized to unit length. /// </summary> /// <returns>The normalized quaternion.</returns> - public Quaternion Normalized() + public readonly Quaternion Normalized() { return this / Length; } @@ -372,7 +372,7 @@ namespace Godot /// <param name="to">The destination quaternion for interpolation. Must be normalized.</param> /// <param name="weight">A value on the range of 0.0 to 1.0, representing the amount of interpolation.</param> /// <returns>The resulting quaternion of the interpolation.</returns> - public Quaternion Slerp(Quaternion to, real_t weight) + public readonly Quaternion Slerp(Quaternion to, real_t weight) { #if DEBUG if (!IsNormalized()) @@ -437,7 +437,7 @@ namespace Godot /// <param name="to">The destination quaternion for interpolation. Must be normalized.</param> /// <param name="weight">A value on the range of 0.0 to 1.0, representing the amount of interpolation.</param> /// <returns>The resulting quaternion of the interpolation.</returns> - public Quaternion Slerpni(Quaternion to, real_t weight) + public readonly Quaternion Slerpni(Quaternion to, real_t weight) { #if DEBUG if (!IsNormalized()) @@ -762,7 +762,7 @@ namespace Godot /// </summary> /// <param name="obj">The other object to compare.</param> /// <returns>Whether or not the quaternion and the other object are exactly equal.</returns> - public override bool Equals(object obj) + public override readonly bool Equals(object obj) { return obj is Quaternion other && Equals(other); } @@ -772,7 +772,7 @@ namespace Godot /// </summary> /// <param name="other">The other quaternion to compare.</param> /// <returns>Whether or not the quaternions are exactly equal.</returns> - public bool Equals(Quaternion other) + public readonly bool Equals(Quaternion other) { return x == other.x && y == other.y && z == other.z && w == other.w; } @@ -783,7 +783,7 @@ namespace Godot /// </summary> /// <param name="other">The other quaternion to compare.</param> /// <returns>Whether or not the quaternions are approximately equal.</returns> - public bool IsEqualApprox(Quaternion other) + public readonly bool IsEqualApprox(Quaternion other) { return Mathf.IsEqualApprox(x, other.x) && Mathf.IsEqualApprox(y, other.y) && Mathf.IsEqualApprox(z, other.z) && Mathf.IsEqualApprox(w, other.w); } @@ -792,7 +792,7 @@ namespace Godot /// Serves as the hash function for <see cref="Quaternion"/>. /// </summary> /// <returns>A hash code for this quaternion.</returns> - public override int GetHashCode() + public override readonly int GetHashCode() { return y.GetHashCode() ^ x.GetHashCode() ^ z.GetHashCode() ^ w.GetHashCode(); } @@ -801,7 +801,7 @@ namespace Godot /// Converts this <see cref="Quaternion"/> to a string. /// </summary> /// <returns>A string representation of this quaternion.</returns> - public override string ToString() + public override readonly string ToString() { return $"({x}, {y}, {z}, {w})"; } @@ -810,7 +810,7 @@ namespace Godot /// Converts this <see cref="Quaternion"/> to a string with the given <paramref name="format"/>. /// </summary> /// <returns>A string representation of this quaternion.</returns> - public string ToString(string format) + public readonly string ToString(string format) { return $"({x.ToString(format)}, {y.ToString(format)}, {z.ToString(format)}, {w.ToString(format)})"; } diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/RID.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/RID.cs index a31fef8360..59b9faf16c 100644 --- a/modules/mono/glue/GodotSharp/GodotSharp/Core/RID.cs +++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/RID.cs @@ -12,9 +12,9 @@ namespace Godot /// classes such as <see cref="RenderingServer"/>. /// </summary> [StructLayout(LayoutKind.Sequential)] - public struct RID + public readonly struct RID { - private ulong _id; // Default is 0 + private readonly ulong _id; // Default is 0 internal RID(ulong id) { diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Rect2.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Rect2.cs index e80d75dacf..b0e0e75a34 100644 --- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Rect2.cs +++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Rect2.cs @@ -20,7 +20,7 @@ namespace Godot /// <value>Directly uses a private field.</value> public Vector2 Position { - get { return _position; } + readonly get { return _position; } set { _position = value; } } @@ -31,7 +31,7 @@ namespace Godot /// <value>Directly uses a private field.</value> public Vector2 Size { - get { return _size; } + readonly get { return _size; } set { _size = value; } } @@ -45,7 +45,7 @@ namespace Godot /// </value> public Vector2 End { - get { return _position + _size; } + readonly get { return _position + _size; } set { _size = value - _position; } } @@ -53,7 +53,7 @@ namespace Godot /// The area of this <see cref="Rect2"/>. /// </summary> /// <value>Equivalent to <see cref="GetArea()"/>.</value> - public real_t Area + public readonly real_t Area { get { return GetArea(); } } @@ -63,7 +63,7 @@ namespace Godot /// the top-left corner is the origin and width and height are positive. /// </summary> /// <returns>The modified <see cref="Rect2"/>.</returns> - public Rect2 Abs() + public readonly Rect2 Abs() { Vector2 end = End; Vector2 topLeft = new Vector2(Mathf.Min(_position.x, end.x), Mathf.Min(_position.y, end.y)); @@ -79,7 +79,7 @@ namespace Godot /// The intersection of this <see cref="Rect2"/> and <paramref name="b"/>, /// or an empty <see cref="Rect2"/> if they do not intersect. /// </returns> - public Rect2 Intersection(Rect2 b) + public readonly Rect2 Intersection(Rect2 b) { Rect2 newRect = b; @@ -107,7 +107,7 @@ namespace Godot /// <returns> /// A <see langword="bool"/> for whether or not this <see cref="Rect2"/> encloses <paramref name="b"/>. /// </returns> - public bool Encloses(Rect2 b) + public readonly bool Encloses(Rect2 b) { return b._position.x >= _position.x && b._position.y >= _position.y && b._position.x + b._size.x < _position.x + _size.x && @@ -119,7 +119,7 @@ namespace Godot /// </summary> /// <param name="to">The point to include.</param> /// <returns>The expanded <see cref="Rect2"/>.</returns> - public Rect2 Expand(Vector2 to) + public readonly Rect2 Expand(Vector2 to) { Rect2 expanded = this; @@ -154,7 +154,7 @@ namespace Godot /// Returns the area of the <see cref="Rect2"/>. /// </summary> /// <returns>The area.</returns> - public real_t GetArea() + public readonly real_t GetArea() { return _size.x * _size.y; } @@ -164,7 +164,7 @@ namespace Godot /// to <see cref="Position"/> + (<see cref="Size"/> / 2). /// </summary> /// <returns>The center.</returns> - public Vector2 GetCenter() + public readonly Vector2 GetCenter() { return _position + (_size * 0.5f); } @@ -177,7 +177,7 @@ namespace Godot /// <seealso cref="GrowSide(Side, real_t)"/> /// <param name="by">The amount to grow by.</param> /// <returns>The grown <see cref="Rect2"/>.</returns> - public Rect2 Grow(real_t by) + public readonly Rect2 Grow(real_t by) { Rect2 g = this; @@ -200,7 +200,7 @@ namespace Godot /// <param name="right">The amount to grow by on the right side.</param> /// <param name="bottom">The amount to grow by on the bottom side.</param> /// <returns>The grown <see cref="Rect2"/>.</returns> - public Rect2 GrowIndividual(real_t left, real_t top, real_t right, real_t bottom) + public readonly Rect2 GrowIndividual(real_t left, real_t top, real_t right, real_t bottom) { Rect2 g = this; @@ -221,7 +221,7 @@ namespace Godot /// <param name="side">The side to grow.</param> /// <param name="by">The amount to grow by.</param> /// <returns>The grown <see cref="Rect2"/>.</returns> - public Rect2 GrowSide(Side side, real_t by) + public readonly Rect2 GrowSide(Side side, real_t by) { Rect2 g = this; @@ -242,7 +242,7 @@ namespace Godot /// <returns> /// A <see langword="bool"/> for whether or not the <see cref="Rect2"/> has area. /// </returns> - public bool HasArea() + public readonly bool HasArea() { return _size.x > 0.0f && _size.y > 0.0f; } @@ -255,7 +255,7 @@ namespace Godot /// <returns> /// A <see langword="bool"/> for whether or not the <see cref="Rect2"/> contains <paramref name="point"/>. /// </returns> - public bool HasPoint(Vector2 point) + public readonly bool HasPoint(Vector2 point) { if (point.x < _position.x) return false; @@ -281,7 +281,7 @@ namespace Godot /// <param name="b">The other <see cref="Rect2"/> to check for intersections with.</param> /// <param name="includeBorders">Whether or not to consider borders.</param> /// <returns>A <see langword="bool"/> for whether or not they are intersecting.</returns> - public bool Intersects(Rect2 b, bool includeBorders = false) + public readonly bool Intersects(Rect2 b, bool includeBorders = false) { if (includeBorders) { @@ -330,7 +330,7 @@ namespace Godot /// </summary> /// <param name="b">The other <see cref="Rect2"/>.</param> /// <returns>The merged <see cref="Rect2"/>.</returns> - public Rect2 Merge(Rect2 b) + public readonly Rect2 Merge(Rect2 b) { Rect2 newRect; @@ -426,7 +426,7 @@ namespace Godot /// </summary> /// <param name="obj">The other object to compare.</param> /// <returns>Whether or not the rect and the other object are exactly equal.</returns> - public override bool Equals(object obj) + public override readonly bool Equals(object obj) { return obj is Rect2 other && Equals(other); } @@ -436,7 +436,7 @@ namespace Godot /// </summary> /// <param name="other">The other rect to compare.</param> /// <returns>Whether or not the rects are exactly equal.</returns> - public bool Equals(Rect2 other) + public readonly bool Equals(Rect2 other) { return _position.Equals(other._position) && _size.Equals(other._size); } @@ -447,7 +447,7 @@ namespace Godot /// </summary> /// <param name="other">The other rect to compare.</param> /// <returns>Whether or not the rects are approximately equal.</returns> - public bool IsEqualApprox(Rect2 other) + public readonly bool IsEqualApprox(Rect2 other) { return _position.IsEqualApprox(other._position) && _size.IsEqualApprox(other.Size); } @@ -456,7 +456,7 @@ namespace Godot /// Serves as the hash function for <see cref="Rect2"/>. /// </summary> /// <returns>A hash code for this rect.</returns> - public override int GetHashCode() + public override readonly int GetHashCode() { return _position.GetHashCode() ^ _size.GetHashCode(); } @@ -465,7 +465,7 @@ namespace Godot /// Converts this <see cref="Rect2"/> to a string. /// </summary> /// <returns>A string representation of this rect.</returns> - public override string ToString() + public override readonly string ToString() { return $"{_position}, {_size}"; } @@ -474,7 +474,7 @@ namespace Godot /// Converts this <see cref="Rect2"/> to a string with the given <paramref name="format"/>. /// </summary> /// <returns>A string representation of this rect.</returns> - public string ToString(string format) + public readonly string ToString(string format) { return $"{_position.ToString(format)}, {_size.ToString(format)}"; } diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Rect2i.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Rect2i.cs index b2768476cc..faee81a98a 100644 --- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Rect2i.cs +++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Rect2i.cs @@ -20,7 +20,7 @@ namespace Godot /// <value>Directly uses a private field.</value> public Vector2i Position { - get { return _position; } + readonly get { return _position; } set { _position = value; } } @@ -31,7 +31,7 @@ namespace Godot /// <value>Directly uses a private field.</value> public Vector2i Size { - get { return _size; } + readonly get { return _size; } set { _size = value; } } @@ -45,7 +45,7 @@ namespace Godot /// </value> public Vector2i End { - get { return _position + _size; } + readonly get { return _position + _size; } set { _size = value - _position; } } @@ -53,7 +53,7 @@ namespace Godot /// The area of this <see cref="Rect2i"/>. /// </summary> /// <value>Equivalent to <see cref="GetArea()"/>.</value> - public int Area + public readonly int Area { get { return GetArea(); } } @@ -63,7 +63,7 @@ namespace Godot /// the top-left corner is the origin and width and height are positive. /// </summary> /// <returns>The modified <see cref="Rect2i"/>.</returns> - public Rect2i Abs() + public readonly Rect2i Abs() { Vector2i end = End; Vector2i topLeft = new Vector2i(Mathf.Min(_position.x, end.x), Mathf.Min(_position.y, end.y)); @@ -79,7 +79,7 @@ namespace Godot /// The intersection of this <see cref="Rect2i"/> and <paramref name="b"/>, /// or an empty <see cref="Rect2i"/> if they do not intersect. /// </returns> - public Rect2i Intersection(Rect2i b) + public readonly Rect2i Intersection(Rect2i b) { Rect2i newRect = b; @@ -107,7 +107,7 @@ namespace Godot /// <returns> /// A <see langword="bool"/> for whether or not this <see cref="Rect2i"/> encloses <paramref name="b"/>. /// </returns> - public bool Encloses(Rect2i b) + public readonly bool Encloses(Rect2i b) { return b._position.x >= _position.x && b._position.y >= _position.y && b._position.x + b._size.x < _position.x + _size.x && @@ -119,7 +119,7 @@ namespace Godot /// </summary> /// <param name="to">The point to include.</param> /// <returns>The expanded <see cref="Rect2i"/>.</returns> - public Rect2i Expand(Vector2i to) + public readonly Rect2i Expand(Vector2i to) { Rect2i expanded = this; @@ -154,7 +154,7 @@ namespace Godot /// Returns the area of the <see cref="Rect2i"/>. /// </summary> /// <returns>The area.</returns> - public int GetArea() + public readonly int GetArea() { return _size.x * _size.y; } @@ -166,7 +166,7 @@ namespace Godot /// value will be rounded towards <see cref="Position"/>. /// </summary> /// <returns>The center.</returns> - public Vector2i GetCenter() + public readonly Vector2i GetCenter() { return _position + (_size / 2); } @@ -179,7 +179,7 @@ namespace Godot /// <seealso cref="GrowSide(Side, int)"/> /// <param name="by">The amount to grow by.</param> /// <returns>The grown <see cref="Rect2i"/>.</returns> - public Rect2i Grow(int by) + public readonly Rect2i Grow(int by) { Rect2i g = this; @@ -202,7 +202,7 @@ namespace Godot /// <param name="right">The amount to grow by on the right side.</param> /// <param name="bottom">The amount to grow by on the bottom side.</param> /// <returns>The grown <see cref="Rect2i"/>.</returns> - public Rect2i GrowIndividual(int left, int top, int right, int bottom) + public readonly Rect2i GrowIndividual(int left, int top, int right, int bottom) { Rect2i g = this; @@ -223,7 +223,7 @@ namespace Godot /// <param name="side">The side to grow.</param> /// <param name="by">The amount to grow by.</param> /// <returns>The grown <see cref="Rect2i"/>.</returns> - public Rect2i GrowSide(Side side, int by) + public readonly Rect2i GrowSide(Side side, int by) { Rect2i g = this; @@ -244,7 +244,7 @@ namespace Godot /// <returns> /// A <see langword="bool"/> for whether or not the <see cref="Rect2i"/> has area. /// </returns> - public bool HasArea() + public readonly bool HasArea() { return _size.x > 0 && _size.y > 0; } @@ -257,7 +257,7 @@ namespace Godot /// <returns> /// A <see langword="bool"/> for whether or not the <see cref="Rect2i"/> contains <paramref name="point"/>. /// </returns> - public bool HasPoint(Vector2i point) + public readonly bool HasPoint(Vector2i point) { if (point.x < _position.x) return false; @@ -283,7 +283,7 @@ namespace Godot /// <param name="b">The other <see cref="Rect2i"/> to check for intersections with.</param> /// <param name="includeBorders">Whether or not to consider borders.</param> /// <returns>A <see langword="bool"/> for whether or not they are intersecting.</returns> - public bool Intersects(Rect2i b, bool includeBorders = false) + public readonly bool Intersects(Rect2i b, bool includeBorders = false) { if (includeBorders) { @@ -316,7 +316,7 @@ namespace Godot /// </summary> /// <param name="b">The other <see cref="Rect2i"/>.</param> /// <returns>The merged <see cref="Rect2i"/>.</returns> - public Rect2i Merge(Rect2i b) + public readonly Rect2i Merge(Rect2i b) { Rect2i newRect; @@ -426,7 +426,7 @@ namespace Godot /// </summary> /// <param name="obj">The other object to compare.</param> /// <returns>Whether or not the rect and the other object are equal.</returns> - public override bool Equals(object obj) + public override readonly bool Equals(object obj) { return obj is Rect2i other && Equals(other); } @@ -436,7 +436,7 @@ namespace Godot /// </summary> /// <param name="other">The other rect to compare.</param> /// <returns>Whether or not the rects are equal.</returns> - public bool Equals(Rect2i other) + public readonly bool Equals(Rect2i other) { return _position.Equals(other._position) && _size.Equals(other._size); } @@ -445,7 +445,7 @@ namespace Godot /// Serves as the hash function for <see cref="Rect2i"/>. /// </summary> /// <returns>A hash code for this rect.</returns> - public override int GetHashCode() + public override readonly int GetHashCode() { return _position.GetHashCode() ^ _size.GetHashCode(); } @@ -454,7 +454,7 @@ namespace Godot /// Converts this <see cref="Rect2i"/> to a string. /// </summary> /// <returns>A string representation of this rect.</returns> - public override string ToString() + public override readonly string ToString() { return $"{_position}, {_size}"; } @@ -463,7 +463,7 @@ namespace Godot /// Converts this <see cref="Rect2i"/> to a string with the given <paramref name="format"/>. /// </summary> /// <returns>A string representation of this rect.</returns> - public string ToString(string format) + public readonly string ToString(string format) { return $"{_position.ToString(format)}, {_size.ToString(format)}"; } diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Transform2D.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Transform2D.cs index 894667db76..756f71e5b2 100644 --- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Transform2D.cs +++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Transform2D.cs @@ -37,7 +37,7 @@ namespace Godot /// <value>Getting is equivalent to calling <see cref="Mathf.Atan2(real_t, real_t)"/> with the values of <see cref="x"/>.</value> public real_t Rotation { - get + readonly get { return Mathf.Atan2(x.y, x.x); } @@ -57,7 +57,7 @@ namespace Godot /// <value>Equivalent to the lengths of each column vector, but Y is negative if the determinant is negative.</value> public Vector2 Scale { - get + readonly get { real_t detSign = Mathf.Sign(BasisDeterminant()); return new Vector2(x.Length(), detSign * y.Length()); @@ -80,7 +80,7 @@ namespace Godot /// </exception> public Vector2 this[int column] { - get + readonly get { switch (column) { @@ -121,7 +121,7 @@ namespace Godot /// <param name="row">Which row, the matrix vertical position.</param> public real_t this[int column, int row] { - get + readonly get { return this[column][row]; } @@ -139,7 +139,7 @@ namespace Godot /// </summary> /// <seealso cref="Inverse"/> /// <returns>The inverse transformation matrix.</returns> - public Transform2D AffineInverse() + public readonly Transform2D AffineInverse() { real_t det = BasisDeterminant(); @@ -148,9 +148,8 @@ namespace Godot Transform2D inv = this; - real_t temp = inv[0, 0]; - inv[0, 0] = inv[1, 1]; - inv[1, 1] = temp; + inv[0, 0] = this[1, 1]; + inv[1, 1] = this[0, 0]; real_t detInv = 1.0f / det; @@ -171,7 +170,7 @@ namespace Godot /// and is usually considered invalid. /// </summary> /// <returns>The determinant of the basis matrix.</returns> - private real_t BasisDeterminant() + private readonly real_t BasisDeterminant() { return (x.x * y.y) - (x.y * y.x); } @@ -183,7 +182,7 @@ namespace Godot /// <seealso cref="BasisXformInv(Vector2)"/> /// <param name="v">A vector to transform.</param> /// <returns>The transformed vector.</returns> - public Vector2 BasisXform(Vector2 v) + public readonly Vector2 BasisXform(Vector2 v) { return new Vector2(Tdotx(v), Tdoty(v)); } @@ -198,7 +197,7 @@ namespace Godot /// <seealso cref="BasisXform(Vector2)"/> /// <param name="v">A vector to inversely transform.</param> /// <returns>The inversely transformed vector.</returns> - public Vector2 BasisXformInv(Vector2 v) + public readonly Vector2 BasisXformInv(Vector2 v) { return new Vector2(x.Dot(v), y.Dot(v)); } @@ -209,7 +208,7 @@ namespace Godot /// <param name="transform">The other transform.</param> /// <param name="weight">A value on the range of 0.0 to 1.0, representing the amount of interpolation.</param> /// <returns>The interpolated transform.</returns> - public Transform2D InterpolateWith(Transform2D transform, real_t weight) + public readonly Transform2D InterpolateWith(Transform2D transform, real_t weight) { real_t r1 = Rotation; real_t r2 = transform.Rotation; @@ -258,14 +257,13 @@ namespace Godot /// (no scaling, use <see cref="AffineInverse"/> for transforms with scaling). /// </summary> /// <returns>The inverse matrix.</returns> - public Transform2D Inverse() + public readonly Transform2D Inverse() { Transform2D inv = this; // Swap - real_t temp = inv.x.y; - inv.x.y = inv.y.x; - inv.y.x = temp; + inv.x.y = y.x; + inv.y.x = x.y; inv.origin = inv.BasisXform(-inv.origin); @@ -277,7 +275,7 @@ namespace Godot /// and normalized axis vectors (scale of 1 or -1). /// </summary> /// <returns>The orthonormalized transform.</returns> - public Transform2D Orthonormalized() + public readonly Transform2D Orthonormalized() { Transform2D on = this; @@ -301,7 +299,7 @@ namespace Godot /// </summary> /// <param name="angle">The angle to rotate, in radians.</param> /// <returns>The rotated transformation matrix.</returns> - public Transform2D Rotated(real_t angle) + public readonly Transform2D Rotated(real_t angle) { return this * new Transform2D(angle, new Vector2()); } @@ -313,7 +311,7 @@ namespace Godot /// </summary> /// <param name="angle">The angle to rotate, in radians.</param> /// <returns>The rotated transformation matrix.</returns> - public Transform2D RotatedLocal(real_t angle) + public readonly Transform2D RotatedLocal(real_t angle) { return new Transform2D(angle, new Vector2()) * this; } @@ -325,7 +323,7 @@ namespace Godot /// </summary> /// <param name="scale">The scale to introduce.</param> /// <returns>The scaled transformation matrix.</returns> - public Transform2D Scaled(Vector2 scale) + public readonly Transform2D Scaled(Vector2 scale) { Transform2D copy = this; copy.x *= scale; @@ -341,7 +339,7 @@ namespace Godot /// </summary> /// <param name="scale">The scale to introduce.</param> /// <returns>The scaled transformation matrix.</returns> - public Transform2D ScaledLocal(Vector2 scale) + public readonly Transform2D ScaledLocal(Vector2 scale) { Transform2D copy = this; copy.x *= scale; @@ -349,12 +347,12 @@ namespace Godot return copy; } - private real_t Tdotx(Vector2 with) + private readonly real_t Tdotx(Vector2 with) { return (this[0, 0] * with[0]) + (this[1, 0] * with[1]); } - private real_t Tdoty(Vector2 with) + private readonly real_t Tdoty(Vector2 with) { return (this[0, 1] * with[0]) + (this[1, 1] * with[1]); } @@ -366,7 +364,7 @@ namespace Godot /// </summary> /// <param name="offset">The offset to translate by.</param> /// <returns>The translated matrix.</returns> - public Transform2D Translated(Vector2 offset) + public readonly Transform2D Translated(Vector2 offset) { Transform2D copy = this; copy.origin += offset; @@ -380,7 +378,7 @@ namespace Godot /// </summary> /// <param name="offset">The offset to translate by.</param> /// <returns>The translated matrix.</returns> - public Transform2D TranslatedLocal(Vector2 offset) + public readonly Transform2D TranslatedLocal(Vector2 offset) { Transform2D copy = this; copy.origin += copy.BasisXform(offset); @@ -603,7 +601,7 @@ namespace Godot /// </summary> /// <param name="obj">The object to compare with.</param> /// <returns>Whether or not the transform and the object are exactly equal.</returns> - public override bool Equals(object obj) + public override readonly bool Equals(object obj) { return obj is Transform2D other && Equals(other); } @@ -615,7 +613,7 @@ namespace Godot /// </summary> /// <param name="other">The other transform to compare.</param> /// <returns>Whether or not the matrices are exactly equal.</returns> - public bool Equals(Transform2D other) + public readonly bool Equals(Transform2D other) { return x.Equals(other.x) && y.Equals(other.y) && origin.Equals(other.origin); } @@ -626,7 +624,7 @@ namespace Godot /// </summary> /// <param name="other">The other transform to compare.</param> /// <returns>Whether or not the matrices are approximately equal.</returns> - public bool IsEqualApprox(Transform2D other) + public readonly bool IsEqualApprox(Transform2D other) { return x.IsEqualApprox(other.x) && y.IsEqualApprox(other.y) && origin.IsEqualApprox(other.origin); } @@ -635,7 +633,7 @@ namespace Godot /// Serves as the hash function for <see cref="Transform2D"/>. /// </summary> /// <returns>A hash code for this transform.</returns> - public override int GetHashCode() + public override readonly int GetHashCode() { return x.GetHashCode() ^ y.GetHashCode() ^ origin.GetHashCode(); } @@ -644,7 +642,7 @@ namespace Godot /// Converts this <see cref="Transform2D"/> to a string. /// </summary> /// <returns>A string representation of this transform.</returns> - public override string ToString() + public override readonly string ToString() { return $"[X: {x}, Y: {y}, O: {origin}]"; } @@ -653,7 +651,7 @@ namespace Godot /// Converts this <see cref="Transform2D"/> to a string with the given <paramref name="format"/>. /// </summary> /// <returns>A string representation of this transform.</returns> - public string ToString(string format) + public readonly string ToString(string format) { return $"[X: {x.ToString(format)}, Y: {y.ToString(format)}, O: {origin.ToString(format)}]"; } diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Transform3D.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Transform3D.cs index 2f7891e7ef..39167bd116 100644 --- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Transform3D.cs +++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Transform3D.cs @@ -37,7 +37,7 @@ namespace Godot /// </exception> public Vector3 this[int column] { - get + readonly get { switch (column) { @@ -83,7 +83,7 @@ namespace Godot /// <param name="row">Which row, the matrix vertical position.</param> public real_t this[int column, int row] { - get + readonly get { if (column == 3) { @@ -108,7 +108,7 @@ namespace Godot /// </summary> /// <seealso cref="Inverse"/> /// <returns>The inverse transformation matrix.</returns> - public Transform3D AffineInverse() + public readonly Transform3D AffineInverse() { Basis basisInv = basis.Inverse(); return new Transform3D(basisInv, basisInv * -origin); @@ -120,7 +120,7 @@ namespace Godot /// <param name="transform">The other transform.</param> /// <param name="weight">A value on the range of 0.0 to 1.0, representing the amount of interpolation.</param> /// <returns>The interpolated transform.</returns> - public Transform3D InterpolateWith(Transform3D transform, real_t weight) + public readonly Transform3D InterpolateWith(Transform3D transform, real_t weight) { Basis retBasis = basis.Lerp(transform.basis, weight); Vector3 retOrigin = origin.Lerp(transform.origin, weight); @@ -133,7 +133,7 @@ namespace Godot /// (no scaling, use <see cref="AffineInverse"/> for transforms with scaling). /// </summary> /// <returns>The inverse matrix.</returns> - public Transform3D Inverse() + public readonly Transform3D Inverse() { Basis basisTr = basis.Transposed(); return new Transform3D(basisTr, basisTr * -origin); @@ -164,7 +164,7 @@ namespace Godot /// and normalized axis vectors (scale of 1 or -1). /// </summary> /// <returns>The orthonormalized transform.</returns> - public Transform3D Orthonormalized() + public readonly Transform3D Orthonormalized() { return new Transform3D(basis.Orthonormalized(), origin); } @@ -192,7 +192,7 @@ namespace Godot /// <param name="axis">The axis to rotate around. Must be normalized.</param> /// <param name="angle">The angle to rotate, in radians.</param> /// <returns>The rotated transformation matrix.</returns> - public Transform3D RotatedLocal(Vector3 axis, real_t angle) + public readonly Transform3D RotatedLocal(Vector3 axis, real_t angle) { Basis tmpBasis = new Basis(axis, angle); return new Transform3D(basis * tmpBasis, origin); @@ -205,7 +205,7 @@ namespace Godot /// </summary> /// <param name="scale">The scale to introduce.</param> /// <returns>The scaled transformation matrix.</returns> - public Transform3D Scaled(Vector3 scale) + public readonly Transform3D Scaled(Vector3 scale) { return new Transform3D(basis.Scaled(scale), origin * scale); } @@ -217,7 +217,7 @@ namespace Godot /// </summary> /// <param name="scale">The scale to introduce.</param> /// <returns>The scaled transformation matrix.</returns> - public Transform3D ScaledLocal(Vector3 scale) + public readonly Transform3D ScaledLocal(Vector3 scale) { Basis tmpBasis = Basis.FromScale(scale); return new Transform3D(basis * tmpBasis, origin); @@ -230,7 +230,7 @@ namespace Godot /// <param name="transform">The other transform.</param> /// <param name="weight">A value on the range of 0.0 to 1.0, representing the amount of interpolation.</param> /// <returns>The interpolated transform.</returns> - public Transform3D SphericalInterpolateWith(Transform3D transform, real_t weight) + public readonly Transform3D SphericalInterpolateWith(Transform3D transform, real_t weight) { /* not sure if very "efficient" but good enough? */ @@ -281,7 +281,7 @@ namespace Godot /// </summary> /// <param name="offset">The offset to translate by.</param> /// <returns>The translated matrix.</returns> - public Transform3D Translated(Vector3 offset) + public readonly Transform3D Translated(Vector3 offset) { return new Transform3D(basis, origin + offset); } @@ -293,7 +293,7 @@ namespace Godot /// </summary> /// <param name="offset">The offset to translate by.</param> /// <returns>The translated matrix.</returns> - public Transform3D TranslatedLocal(Vector3 offset) + public readonly Transform3D TranslatedLocal(Vector3 offset) { return new Transform3D(basis, new Vector3 ( @@ -617,7 +617,7 @@ namespace Godot /// </summary> /// <param name="other">The other transform to compare.</param> /// <returns>Whether or not the matrices are approximately equal.</returns> - public bool IsEqualApprox(Transform3D other) + public readonly bool IsEqualApprox(Transform3D other) { return basis.IsEqualApprox(other.basis) && origin.IsEqualApprox(other.origin); } @@ -626,7 +626,7 @@ namespace Godot /// Serves as the hash function for <see cref="Transform3D"/>. /// </summary> /// <returns>A hash code for this transform.</returns> - public override int GetHashCode() + public override readonly int GetHashCode() { return basis.GetHashCode() ^ origin.GetHashCode(); } @@ -635,7 +635,7 @@ namespace Godot /// Converts this <see cref="Transform3D"/> to a string. /// </summary> /// <returns>A string representation of this transform.</returns> - public override string ToString() + public override readonly string ToString() { return $"[X: {basis.x}, Y: {basis.y}, Z: {basis.z}, O: {origin}]"; } @@ -644,7 +644,7 @@ namespace Godot /// Converts this <see cref="Transform3D"/> to a string with the given <paramref name="format"/>. /// </summary> /// <returns>A string representation of this transform.</returns> - public string ToString(string format) + public readonly string ToString(string format) { return $"[X: {basis.x.ToString(format)}, Y: {basis.y.ToString(format)}, Z: {basis.z.ToString(format)}, O: {origin.ToString(format)}]"; } diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector2.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector2.cs index 87f397891e..535391f447 100644 --- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector2.cs +++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector2.cs @@ -48,7 +48,7 @@ namespace Godot /// </value> public real_t this[int index] { - get + readonly get { switch (index) { @@ -79,7 +79,7 @@ namespace Godot /// <summary> /// Helper method for deconstruction into a tuple. /// </summary> - public void Deconstruct(out real_t x, out real_t y) + public readonly void Deconstruct(out real_t x, out real_t y) { x = this.x; y = this.y; @@ -105,7 +105,7 @@ namespace Godot /// Returns a new vector with all components in absolute values (i.e. positive). /// </summary> /// <returns>A vector with <see cref="Mathf.Abs(real_t)"/> called on each component.</returns> - public Vector2 Abs() + public readonly Vector2 Abs() { return new Vector2(Mathf.Abs(x), Mathf.Abs(y)); } @@ -117,7 +117,7 @@ namespace Godot /// called with the vector's <see cref="y"/> and <see cref="x"/> as parameters: <c>Mathf.Atan2(v.y, v.x)</c>. /// </summary> /// <returns>The angle of this vector, in radians.</returns> - public real_t Angle() + public readonly real_t Angle() { return Mathf.Atan2(y, x); } @@ -127,7 +127,7 @@ namespace Godot /// </summary> /// <param name="to">The other vector to compare this vector to.</param> /// <returns>The angle between the two vectors, in radians.</returns> - public real_t AngleTo(Vector2 to) + public readonly real_t AngleTo(Vector2 to) { return Mathf.Atan2(Cross(to), Dot(to)); } @@ -137,7 +137,7 @@ namespace Godot /// </summary> /// <param name="to">The other vector to compare this vector to.</param> /// <returns>The angle between the two vectors, in radians.</returns> - public real_t AngleToPoint(Vector2 to) + public readonly real_t AngleToPoint(Vector2 to) { return Mathf.Atan2(y - to.y, x - to.x); } @@ -146,7 +146,7 @@ namespace Godot /// Returns the aspect ratio of this vector, the ratio of <see cref="x"/> to <see cref="y"/>. /// </summary> /// <returns>The <see cref="x"/> component divided by the <see cref="y"/> component.</returns> - public real_t Aspect() + public readonly real_t Aspect() { return x / y; } @@ -156,7 +156,7 @@ namespace Godot /// </summary> /// <param name="normal">The normal vector defining the plane to bounce off. Must be normalized.</param> /// <returns>The bounced vector.</returns> - public Vector2 Bounce(Vector2 normal) + public readonly Vector2 Bounce(Vector2 normal) { return -Reflect(normal); } @@ -165,7 +165,7 @@ namespace Godot /// Returns a new vector with all components rounded up (towards positive infinity). /// </summary> /// <returns>A vector with <see cref="Mathf.Ceil"/> called on each component.</returns> - public Vector2 Ceil() + public readonly Vector2 Ceil() { return new Vector2(Mathf.Ceil(x), Mathf.Ceil(y)); } @@ -178,7 +178,7 @@ namespace Godot /// <param name="min">The vector with minimum allowed values.</param> /// <param name="max">The vector with maximum allowed values.</param> /// <returns>The vector with all components clamped.</returns> - public Vector2 Clamp(Vector2 min, Vector2 max) + public readonly Vector2 Clamp(Vector2 min, Vector2 max) { return new Vector2 ( @@ -192,7 +192,7 @@ namespace Godot /// </summary> /// <param name="with">The other vector.</param> /// <returns>The cross product value.</returns> - public real_t Cross(Vector2 with) + public readonly real_t Cross(Vector2 with) { return (x * with.y) - (y * with.x); } @@ -206,7 +206,7 @@ namespace Godot /// <param name="postB">A vector after <paramref name="b"/>.</param> /// <param name="weight">A value on the range of 0.0 to 1.0, representing the amount of interpolation.</param> /// <returns>The interpolated vector.</returns> - public Vector2 CubicInterpolate(Vector2 b, Vector2 preA, Vector2 postB, real_t weight) + public readonly Vector2 CubicInterpolate(Vector2 b, Vector2 preA, Vector2 postB, real_t weight) { return new Vector2 ( @@ -229,7 +229,7 @@ namespace Godot /// <param name="preAT"></param> /// <param name="postBT"></param> /// <returns>The interpolated vector.</returns> - public Vector2 CubicInterpolateInTime(Vector2 b, Vector2 preA, Vector2 postB, real_t weight, real_t t, real_t preAT, real_t postBT) + public readonly Vector2 CubicInterpolateInTime(Vector2 b, Vector2 preA, Vector2 postB, real_t weight, real_t t, real_t preAT, real_t postBT) { return new Vector2 ( @@ -247,7 +247,7 @@ namespace Godot /// <param name="end">The destination vector.</param> /// <param name="t">A value on the range of 0.0 to 1.0, representing the amount of interpolation.</param> /// <returns>The interpolated vector.</returns> - public Vector2 BezierInterpolate(Vector2 control1, Vector2 control2, Vector2 end, real_t t) + public readonly Vector2 BezierInterpolate(Vector2 control1, Vector2 control2, Vector2 end, real_t t) { // Formula from Wikipedia article on Bezier curves real_t omt = 1 - t; @@ -264,7 +264,7 @@ namespace Godot /// </summary> /// <param name="to">The other vector to point towards.</param> /// <returns>The direction from this vector to <paramref name="to"/>.</returns> - public Vector2 DirectionTo(Vector2 to) + public readonly Vector2 DirectionTo(Vector2 to) { return new Vector2(to.x - x, to.y - y).Normalized(); } @@ -276,7 +276,7 @@ namespace Godot /// </summary> /// <param name="to">The other vector to use.</param> /// <returns>The squared distance between the two vectors.</returns> - public real_t DistanceSquaredTo(Vector2 to) + public readonly real_t DistanceSquaredTo(Vector2 to) { return (x - to.x) * (x - to.x) + (y - to.y) * (y - to.y); } @@ -286,7 +286,7 @@ namespace Godot /// </summary> /// <param name="to">The other vector to use.</param> /// <returns>The distance between the two vectors.</returns> - public real_t DistanceTo(Vector2 to) + public readonly real_t DistanceTo(Vector2 to) { return Mathf.Sqrt((x - to.x) * (x - to.x) + (y - to.y) * (y - to.y)); } @@ -296,7 +296,7 @@ namespace Godot /// </summary> /// <param name="with">The other vector to use.</param> /// <returns>The dot product of the two vectors.</returns> - public real_t Dot(Vector2 with) + public readonly real_t Dot(Vector2 with) { return (x * with.x) + (y * with.y); } @@ -305,7 +305,7 @@ namespace Godot /// Returns a new vector with all components rounded down (towards negative infinity). /// </summary> /// <returns>A vector with <see cref="Mathf.Floor"/> called on each component.</returns> - public Vector2 Floor() + public readonly Vector2 Floor() { return new Vector2(Mathf.Floor(x), Mathf.Floor(y)); } @@ -314,7 +314,7 @@ namespace Godot /// Returns the inverse of this vector. This is the same as <c>new Vector2(1 / v.x, 1 / v.y)</c>. /// </summary> /// <returns>The inverse of this vector.</returns> - public Vector2 Inverse() + public readonly Vector2 Inverse() { return new Vector2(1 / x, 1 / y); } @@ -323,7 +323,7 @@ namespace Godot /// Returns <see langword="true"/> if the vector is normalized, and <see langword="false"/> otherwise. /// </summary> /// <returns>A <see langword="bool"/> indicating whether or not the vector is normalized.</returns> - public bool IsNormalized() + public readonly bool IsNormalized() { return Mathf.Abs(LengthSquared() - 1.0f) < Mathf.Epsilon; } @@ -333,7 +333,7 @@ namespace Godot /// </summary> /// <seealso cref="LengthSquared"/> /// <returns>The length of this vector.</returns> - public real_t Length() + public readonly real_t Length() { return Mathf.Sqrt((x * x) + (y * y)); } @@ -344,7 +344,7 @@ namespace Godot /// you need to compare vectors or need the squared length for some formula. /// </summary> /// <returns>The squared length of this vector.</returns> - public real_t LengthSquared() + public readonly real_t LengthSquared() { return (x * x) + (y * y); } @@ -356,7 +356,7 @@ namespace Godot /// <param name="to">The destination vector for interpolation.</param> /// <param name="weight">A value on the range of 0.0 to 1.0, representing the amount of interpolation.</param> /// <returns>The resulting vector of the interpolation.</returns> - public Vector2 Lerp(Vector2 to, real_t weight) + public readonly Vector2 Lerp(Vector2 to, real_t weight) { return new Vector2 ( @@ -374,7 +374,7 @@ namespace Godot /// A vector with components on the range of 0.0 to 1.0, representing the amount of interpolation. /// </param> /// <returns>The resulting vector of the interpolation.</returns> - public Vector2 Lerp(Vector2 to, Vector2 weight) + public readonly Vector2 Lerp(Vector2 to, Vector2 weight) { return new Vector2 ( @@ -388,7 +388,7 @@ namespace Godot /// </summary> /// <param name="length">The length to limit to.</param> /// <returns>The vector with its length limited.</returns> - public Vector2 LimitLength(real_t length = 1.0f) + public readonly Vector2 LimitLength(real_t length = 1.0f) { Vector2 v = this; real_t l = Length(); @@ -407,7 +407,7 @@ namespace Godot /// If both components are equal, this method returns <see cref="Axis.X"/>. /// </summary> /// <returns>The index of the highest axis.</returns> - public Axis MaxAxisIndex() + public readonly Axis MaxAxisIndex() { return x < y ? Axis.Y : Axis.X; } @@ -417,7 +417,7 @@ namespace Godot /// If both components are equal, this method returns <see cref="Axis.Y"/>. /// </summary> /// <returns>The index of the lowest axis.</returns> - public Axis MinAxisIndex() + public readonly Axis MinAxisIndex() { return x < y ? Axis.X : Axis.Y; } @@ -428,7 +428,7 @@ namespace Godot /// <param name="to">The vector to move towards.</param> /// <param name="delta">The amount to move towards by.</param> /// <returns>The resulting vector.</returns> - public Vector2 MoveToward(Vector2 to, real_t delta) + public readonly Vector2 MoveToward(Vector2 to, real_t delta) { Vector2 v = this; Vector2 vd = to - v; @@ -443,7 +443,7 @@ namespace Godot /// Returns the vector scaled to unit length. Equivalent to <c>v / v.Length()</c>. /// </summary> /// <returns>A normalized version of the vector.</returns> - public Vector2 Normalized() + public readonly Vector2 Normalized() { Vector2 v = this; v.Normalize(); @@ -458,7 +458,7 @@ namespace Godot /// <returns> /// A vector with each component <see cref="Mathf.PosMod(real_t, real_t)"/> by <paramref name="mod"/>. /// </returns> - public Vector2 PosMod(real_t mod) + public readonly Vector2 PosMod(real_t mod) { Vector2 v; v.x = Mathf.PosMod(x, mod); @@ -474,7 +474,7 @@ namespace Godot /// <returns> /// A vector with each component <see cref="Mathf.PosMod(real_t, real_t)"/> by <paramref name="modv"/>'s components. /// </returns> - public Vector2 PosMod(Vector2 modv) + public readonly Vector2 PosMod(Vector2 modv) { Vector2 v; v.x = Mathf.PosMod(x, modv.x); @@ -487,7 +487,7 @@ namespace Godot /// </summary> /// <param name="onNormal">The vector to project onto.</param> /// <returns>The projected vector.</returns> - public Vector2 Project(Vector2 onNormal) + public readonly Vector2 Project(Vector2 onNormal) { return onNormal * (Dot(onNormal) / onNormal.LengthSquared()); } @@ -497,7 +497,7 @@ namespace Godot /// </summary> /// <param name="normal">The normal vector defining the plane to reflect from. Must be normalized.</param> /// <returns>The reflected vector.</returns> - public Vector2 Reflect(Vector2 normal) + public readonly Vector2 Reflect(Vector2 normal) { #if DEBUG if (!normal.IsNormalized()) @@ -513,7 +513,7 @@ namespace Godot /// </summary> /// <param name="angle">The angle to rotate by, in radians.</param> /// <returns>The rotated vector.</returns> - public Vector2 Rotated(real_t angle) + public readonly Vector2 Rotated(real_t angle) { real_t sine = Mathf.Sin(angle); real_t cosi = Mathf.Cos(angle); @@ -527,7 +527,7 @@ namespace Godot /// with halfway cases rounded towards the nearest multiple of two. /// </summary> /// <returns>The rounded vector.</returns> - public Vector2 Round() + public readonly Vector2 Round() { return new Vector2(Mathf.Round(x), Mathf.Round(y)); } @@ -538,7 +538,7 @@ namespace Godot /// by calling <see cref="Mathf.Sign(real_t)"/> on each component. /// </summary> /// <returns>A vector with all components as either <c>1</c>, <c>-1</c>, or <c>0</c>.</returns> - public Vector2 Sign() + public readonly Vector2 Sign() { Vector2 v; v.x = Mathf.Sign(x); @@ -557,7 +557,7 @@ namespace Godot /// <param name="to">The destination vector for interpolation.</param> /// <param name="weight">A value on the range of 0.0 to 1.0, representing the amount of interpolation.</param> /// <returns>The resulting vector of the interpolation.</returns> - public Vector2 Slerp(Vector2 to, real_t weight) + public readonly Vector2 Slerp(Vector2 to, real_t weight) { real_t startLengthSquared = LengthSquared(); real_t endLengthSquared = to.LengthSquared(); @@ -577,7 +577,7 @@ namespace Godot /// </summary> /// <param name="normal">The normal vector defining the plane to slide on.</param> /// <returns>The slid vector.</returns> - public Vector2 Slide(Vector2 normal) + public readonly Vector2 Slide(Vector2 normal) { return this - (normal * Dot(normal)); } @@ -588,7 +588,7 @@ namespace Godot /// </summary> /// <param name="step">A vector value representing the step size to snap to.</param> /// <returns>The snapped vector.</returns> - public Vector2 Snapped(Vector2 step) + public readonly Vector2 Snapped(Vector2 step) { return new Vector2(Mathf.Snapped(x, step.x), Mathf.Snapped(y, step.y)); } @@ -598,7 +598,7 @@ namespace Godot /// compared to the original, with the same length. /// </summary> /// <returns>The perpendicular vector.</returns> - public Vector2 Orthogonal() + public readonly Vector2 Orthogonal() { return new Vector2(y, -x); } @@ -946,7 +946,7 @@ namespace Godot /// </summary> /// <param name="obj">The object to compare with.</param> /// <returns>Whether or not the vector and the object are equal.</returns> - public override bool Equals(object obj) + public override readonly bool Equals(object obj) { return obj is Vector2 other && Equals(other); } @@ -958,7 +958,7 @@ namespace Godot /// </summary> /// <param name="other">The other vector.</param> /// <returns>Whether or not the vectors are exactly equal.</returns> - public bool Equals(Vector2 other) + public readonly bool Equals(Vector2 other) { return x == other.x && y == other.y; } @@ -969,7 +969,7 @@ namespace Godot /// </summary> /// <param name="other">The other vector to compare.</param> /// <returns>Whether or not the vectors are approximately equal.</returns> - public bool IsEqualApprox(Vector2 other) + public readonly bool IsEqualApprox(Vector2 other) { return Mathf.IsEqualApprox(x, other.x) && Mathf.IsEqualApprox(y, other.y); } @@ -978,7 +978,7 @@ namespace Godot /// Serves as the hash function for <see cref="Vector2"/>. /// </summary> /// <returns>A hash code for this vector.</returns> - public override int GetHashCode() + public override readonly int GetHashCode() { return y.GetHashCode() ^ x.GetHashCode(); } @@ -987,7 +987,7 @@ namespace Godot /// Converts this <see cref="Vector2"/> to a string. /// </summary> /// <returns>A string representation of this vector.</returns> - public override string ToString() + public override readonly string ToString() { return $"({x}, {y})"; } @@ -996,7 +996,7 @@ namespace Godot /// Converts this <see cref="Vector2"/> to a string with the given <paramref name="format"/>. /// </summary> /// <returns>A string representation of this vector.</returns> - public string ToString(string format) + public readonly string ToString(string format) { return $"({x.ToString(format)}, {y.ToString(format)})"; } diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector2i.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector2i.cs index bdadf696e3..08f2a3a8af 100644 --- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector2i.cs +++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector2i.cs @@ -48,7 +48,7 @@ namespace Godot /// </value> public int this[int index] { - get + readonly get { switch (index) { @@ -79,7 +79,7 @@ namespace Godot /// <summary> /// Helper method for deconstruction into a tuple. /// </summary> - public void Deconstruct(out int x, out int y) + public readonly void Deconstruct(out int x, out int y) { x = this.x; y = this.y; @@ -89,7 +89,7 @@ namespace Godot /// Returns a new vector with all components in absolute values (i.e. positive). /// </summary> /// <returns>A vector with <see cref="Mathf.Abs(int)"/> called on each component.</returns> - public Vector2i Abs() + public readonly Vector2i Abs() { return new Vector2i(Mathf.Abs(x), Mathf.Abs(y)); } @@ -101,7 +101,7 @@ namespace Godot /// called with the vector's <see cref="y"/> and <see cref="x"/> as parameters: <c>Mathf.Atan2(v.y, v.x)</c>. /// </summary> /// <returns>The angle of this vector, in radians.</returns> - public real_t Angle() + public readonly real_t Angle() { return Mathf.Atan2(y, x); } @@ -111,7 +111,7 @@ namespace Godot /// </summary> /// <param name="to">The other vector to compare this vector to.</param> /// <returns>The angle between the two vectors, in radians.</returns> - public real_t AngleTo(Vector2i to) + public readonly real_t AngleTo(Vector2i to) { return Mathf.Atan2(Cross(to), Dot(to)); } @@ -121,7 +121,7 @@ namespace Godot /// </summary> /// <param name="to">The other vector to compare this vector to.</param> /// <returns>The angle between the two vectors, in radians.</returns> - public real_t AngleToPoint(Vector2i to) + public readonly real_t AngleToPoint(Vector2i to) { return Mathf.Atan2(y - to.y, x - to.x); } @@ -130,7 +130,7 @@ namespace Godot /// Returns the aspect ratio of this vector, the ratio of <see cref="x"/> to <see cref="y"/>. /// </summary> /// <returns>The <see cref="x"/> component divided by the <see cref="y"/> component.</returns> - public real_t Aspect() + public readonly real_t Aspect() { return x / (real_t)y; } @@ -143,7 +143,7 @@ namespace Godot /// <param name="min">The vector with minimum allowed values.</param> /// <param name="max">The vector with maximum allowed values.</param> /// <returns>The vector with all components clamped.</returns> - public Vector2i Clamp(Vector2i min, Vector2i max) + public readonly Vector2i Clamp(Vector2i min, Vector2i max) { return new Vector2i ( @@ -157,7 +157,7 @@ namespace Godot /// </summary> /// <param name="with">The other vector.</param> /// <returns>The cross product vector.</returns> - public int Cross(Vector2i with) + public readonly int Cross(Vector2i with) { return x * with.y - y * with.x; } @@ -169,7 +169,7 @@ namespace Godot /// </summary> /// <param name="to">The other vector to use.</param> /// <returns>The squared distance between the two vectors.</returns> - public int DistanceSquaredTo(Vector2i to) + public readonly int DistanceSquaredTo(Vector2i to) { return (to - this).LengthSquared(); } @@ -179,7 +179,7 @@ namespace Godot /// </summary> /// <param name="to">The other vector to use.</param> /// <returns>The distance between the two vectors.</returns> - public real_t DistanceTo(Vector2i to) + public readonly real_t DistanceTo(Vector2i to) { return (to - this).Length(); } @@ -189,7 +189,7 @@ namespace Godot /// </summary> /// <param name="with">The other vector to use.</param> /// <returns>The dot product of the two vectors.</returns> - public int Dot(Vector2i with) + public readonly int Dot(Vector2i with) { return x * with.x + y * with.y; } @@ -199,7 +199,7 @@ namespace Godot /// </summary> /// <seealso cref="LengthSquared"/> /// <returns>The length of this vector.</returns> - public real_t Length() + public readonly real_t Length() { int x2 = x * x; int y2 = y * y; @@ -213,7 +213,7 @@ namespace Godot /// you need to compare vectors or need the squared length for some formula. /// </summary> /// <returns>The squared length of this vector.</returns> - public int LengthSquared() + public readonly int LengthSquared() { int x2 = x * x; int y2 = y * y; @@ -226,7 +226,7 @@ namespace Godot /// If both components are equal, this method returns <see cref="Axis.X"/>. /// </summary> /// <returns>The index of the highest axis.</returns> - public Axis MaxAxisIndex() + public readonly Axis MaxAxisIndex() { return x < y ? Axis.Y : Axis.X; } @@ -236,7 +236,7 @@ namespace Godot /// If both components are equal, this method returns <see cref="Axis.Y"/>. /// </summary> /// <returns>The index of the lowest axis.</returns> - public Axis MinAxisIndex() + public readonly Axis MinAxisIndex() { return x < y ? Axis.X : Axis.Y; } @@ -249,7 +249,7 @@ namespace Godot /// <returns> /// A vector with each component <see cref="Mathf.PosMod(int, int)"/> by <paramref name="mod"/>. /// </returns> - public Vector2i PosMod(int mod) + public readonly Vector2i PosMod(int mod) { Vector2i v = this; v.x = Mathf.PosMod(v.x, mod); @@ -265,7 +265,7 @@ namespace Godot /// <returns> /// A vector with each component <see cref="Mathf.PosMod(int, int)"/> by <paramref name="modv"/>'s components. /// </returns> - public Vector2i PosMod(Vector2i modv) + public readonly Vector2i PosMod(Vector2i modv) { Vector2i v = this; v.x = Mathf.PosMod(v.x, modv.x); @@ -279,7 +279,7 @@ namespace Godot /// by calling <see cref="Mathf.Sign(int)"/> on each component. /// </summary> /// <returns>A vector with all components as either <c>1</c>, <c>-1</c>, or <c>0</c>.</returns> - public Vector2i Sign() + public readonly Vector2i Sign() { Vector2i v = this; v.x = Mathf.Sign(v.x); @@ -292,7 +292,7 @@ namespace Godot /// compared to the original, with the same length. /// </summary> /// <returns>The perpendicular vector.</returns> - public Vector2i Orthogonal() + public readonly Vector2i Orthogonal() { return new Vector2i(y, -x); } @@ -665,7 +665,7 @@ namespace Godot /// </summary> /// <param name="obj">The object to compare with.</param> /// <returns>Whether or not the vector and the object are equal.</returns> - public override bool Equals(object obj) + public override readonly bool Equals(object obj) { return obj is Vector2i other && Equals(other); } @@ -675,7 +675,7 @@ namespace Godot /// </summary> /// <param name="other">The other vector.</param> /// <returns>Whether or not the vectors are equal.</returns> - public bool Equals(Vector2i other) + public readonly bool Equals(Vector2i other) { return x == other.x && y == other.y; } @@ -684,7 +684,7 @@ namespace Godot /// Serves as the hash function for <see cref="Vector2i"/>. /// </summary> /// <returns>A hash code for this vector.</returns> - public override int GetHashCode() + public override readonly int GetHashCode() { return y.GetHashCode() ^ x.GetHashCode(); } @@ -693,7 +693,7 @@ namespace Godot /// Converts this <see cref="Vector2i"/> to a string. /// </summary> /// <returns>A string representation of this vector.</returns> - public override string ToString() + public override readonly string ToString() { return $"({x}, {y})"; } @@ -702,7 +702,7 @@ namespace Godot /// Converts this <see cref="Vector2i"/> to a string with the given <paramref name="format"/>. /// </summary> /// <returns>A string representation of this vector.</returns> - public string ToString(string format) + public readonly string ToString(string format) { return $"({x.ToString(format)}, {y.ToString(format)})"; } diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector3.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector3.cs index 6649f3b784..53bd0b0908 100644 --- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector3.cs +++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector3.cs @@ -58,7 +58,7 @@ namespace Godot /// </value> public real_t this[int index] { - get + readonly get { switch (index) { @@ -94,7 +94,7 @@ namespace Godot /// <summary> /// Helper method for deconstruction into a tuple. /// </summary> - public void Deconstruct(out real_t x, out real_t y, out real_t z) + public readonly void Deconstruct(out real_t x, out real_t y, out real_t z) { x = this.x; y = this.y; @@ -122,7 +122,7 @@ namespace Godot /// Returns a new vector with all components in absolute values (i.e. positive). /// </summary> /// <returns>A vector with <see cref="Mathf.Abs(real_t)"/> called on each component.</returns> - public Vector3 Abs() + public readonly Vector3 Abs() { return new Vector3(Mathf.Abs(x), Mathf.Abs(y), Mathf.Abs(z)); } @@ -132,7 +132,7 @@ namespace Godot /// </summary> /// <param name="to">The other vector to compare this vector to.</param> /// <returns>The unsigned angle between the two vectors, in radians.</returns> - public real_t AngleTo(Vector3 to) + public readonly real_t AngleTo(Vector3 to) { return Mathf.Atan2(Cross(to).Length(), Dot(to)); } @@ -142,7 +142,7 @@ namespace Godot /// </summary> /// <param name="normal">The normal vector defining the plane to bounce off. Must be normalized.</param> /// <returns>The bounced vector.</returns> - public Vector3 Bounce(Vector3 normal) + public readonly Vector3 Bounce(Vector3 normal) { return -Reflect(normal); } @@ -151,7 +151,7 @@ namespace Godot /// Returns a new vector with all components rounded up (towards positive infinity). /// </summary> /// <returns>A vector with <see cref="Mathf.Ceil"/> called on each component.</returns> - public Vector3 Ceil() + public readonly Vector3 Ceil() { return new Vector3(Mathf.Ceil(x), Mathf.Ceil(y), Mathf.Ceil(z)); } @@ -164,7 +164,7 @@ namespace Godot /// <param name="min">The vector with minimum allowed values.</param> /// <param name="max">The vector with maximum allowed values.</param> /// <returns>The vector with all components clamped.</returns> - public Vector3 Clamp(Vector3 min, Vector3 max) + public readonly Vector3 Clamp(Vector3 min, Vector3 max) { return new Vector3 ( @@ -179,7 +179,7 @@ namespace Godot /// </summary> /// <param name="with">The other vector.</param> /// <returns>The cross product vector.</returns> - public Vector3 Cross(Vector3 with) + public readonly Vector3 Cross(Vector3 with) { return new Vector3 ( @@ -198,7 +198,7 @@ namespace Godot /// <param name="postB">A vector after <paramref name="b"/>.</param> /// <param name="weight">A value on the range of 0.0 to 1.0, representing the amount of interpolation.</param> /// <returns>The interpolated vector.</returns> - public Vector3 CubicInterpolate(Vector3 b, Vector3 preA, Vector3 postB, real_t weight) + public readonly Vector3 CubicInterpolate(Vector3 b, Vector3 preA, Vector3 postB, real_t weight) { return new Vector3 ( @@ -222,7 +222,7 @@ namespace Godot /// <param name="preAT"></param> /// <param name="postBT"></param> /// <returns>The interpolated vector.</returns> - public Vector3 CubicInterpolateInTime(Vector3 b, Vector3 preA, Vector3 postB, real_t weight, real_t t, real_t preAT, real_t postBT) + public readonly Vector3 CubicInterpolateInTime(Vector3 b, Vector3 preA, Vector3 postB, real_t weight, real_t t, real_t preAT, real_t postBT) { return new Vector3 ( @@ -241,7 +241,7 @@ namespace Godot /// <param name="end">The destination vector.</param> /// <param name="t">A value on the range of 0.0 to 1.0, representing the amount of interpolation.</param> /// <returns>The interpolated vector.</returns> - public Vector3 BezierInterpolate(Vector3 control1, Vector3 control2, Vector3 end, real_t t) + public readonly Vector3 BezierInterpolate(Vector3 control1, Vector3 control2, Vector3 end, real_t t) { // Formula from Wikipedia article on Bezier curves real_t omt = 1 - t; @@ -258,7 +258,7 @@ namespace Godot /// </summary> /// <param name="to">The other vector to point towards.</param> /// <returns>The direction from this vector to <paramref name="to"/>.</returns> - public Vector3 DirectionTo(Vector3 to) + public readonly Vector3 DirectionTo(Vector3 to) { return new Vector3(to.x - x, to.y - y, to.z - z).Normalized(); } @@ -270,7 +270,7 @@ namespace Godot /// </summary> /// <param name="to">The other vector to use.</param> /// <returns>The squared distance between the two vectors.</returns> - public real_t DistanceSquaredTo(Vector3 to) + public readonly real_t DistanceSquaredTo(Vector3 to) { return (to - this).LengthSquared(); } @@ -281,7 +281,7 @@ namespace Godot /// <seealso cref="DistanceSquaredTo(Vector3)"/> /// <param name="to">The other vector to use.</param> /// <returns>The distance between the two vectors.</returns> - public real_t DistanceTo(Vector3 to) + public readonly real_t DistanceTo(Vector3 to) { return (to - this).Length(); } @@ -291,7 +291,7 @@ namespace Godot /// </summary> /// <param name="with">The other vector to use.</param> /// <returns>The dot product of the two vectors.</returns> - public real_t Dot(Vector3 with) + public readonly real_t Dot(Vector3 with) { return (x * with.x) + (y * with.y) + (z * with.z); } @@ -300,7 +300,7 @@ namespace Godot /// Returns a new vector with all components rounded down (towards negative infinity). /// </summary> /// <returns>A vector with <see cref="Mathf.Floor"/> called on each component.</returns> - public Vector3 Floor() + public readonly Vector3 Floor() { return new Vector3(Mathf.Floor(x), Mathf.Floor(y), Mathf.Floor(z)); } @@ -309,7 +309,7 @@ namespace Godot /// Returns the inverse of this vector. This is the same as <c>new Vector3(1 / v.x, 1 / v.y, 1 / v.z)</c>. /// </summary> /// <returns>The inverse of this vector.</returns> - public Vector3 Inverse() + public readonly Vector3 Inverse() { return new Vector3(1 / x, 1 / y, 1 / z); } @@ -318,7 +318,7 @@ namespace Godot /// Returns <see langword="true"/> if the vector is normalized, and <see langword="false"/> otherwise. /// </summary> /// <returns>A <see langword="bool"/> indicating whether or not the vector is normalized.</returns> - public bool IsNormalized() + public readonly bool IsNormalized() { return Mathf.Abs(LengthSquared() - 1.0f) < Mathf.Epsilon; } @@ -328,7 +328,7 @@ namespace Godot /// </summary> /// <seealso cref="LengthSquared"/> /// <returns>The length of this vector.</returns> - public real_t Length() + public readonly real_t Length() { real_t x2 = x * x; real_t y2 = y * y; @@ -343,7 +343,7 @@ namespace Godot /// you need to compare vectors or need the squared length for some formula. /// </summary> /// <returns>The squared length of this vector.</returns> - public real_t LengthSquared() + public readonly real_t LengthSquared() { real_t x2 = x * x; real_t y2 = y * y; @@ -359,7 +359,7 @@ namespace Godot /// <param name="to">The destination vector for interpolation.</param> /// <param name="weight">A value on the range of 0.0 to 1.0, representing the amount of interpolation.</param> /// <returns>The resulting vector of the interpolation.</returns> - public Vector3 Lerp(Vector3 to, real_t weight) + public readonly Vector3 Lerp(Vector3 to, real_t weight) { return new Vector3 ( @@ -376,7 +376,7 @@ namespace Godot /// <param name="to">The destination vector for interpolation.</param> /// <param name="weight">A vector with components on the range of 0.0 to 1.0, representing the amount of interpolation.</param> /// <returns>The resulting vector of the interpolation.</returns> - public Vector3 Lerp(Vector3 to, Vector3 weight) + public readonly Vector3 Lerp(Vector3 to, Vector3 weight) { return new Vector3 ( @@ -391,7 +391,7 @@ namespace Godot /// </summary> /// <param name="length">The length to limit to.</param> /// <returns>The vector with its length limited.</returns> - public Vector3 LimitLength(real_t length = 1.0f) + public readonly Vector3 LimitLength(real_t length = 1.0f) { Vector3 v = this; real_t l = Length(); @@ -410,7 +410,7 @@ namespace Godot /// If all components are equal, this method returns <see cref="Axis.X"/>. /// </summary> /// <returns>The index of the highest axis.</returns> - public Axis MaxAxisIndex() + public readonly Axis MaxAxisIndex() { return x < y ? (y < z ? Axis.Z : Axis.Y) : (x < z ? Axis.Z : Axis.X); } @@ -420,7 +420,7 @@ namespace Godot /// If all components are equal, this method returns <see cref="Axis.Z"/>. /// </summary> /// <returns>The index of the lowest axis.</returns> - public Axis MinAxisIndex() + public readonly Axis MinAxisIndex() { return x < y ? (x < z ? Axis.X : Axis.Z) : (y < z ? Axis.Y : Axis.Z); } @@ -431,7 +431,7 @@ namespace Godot /// <param name="to">The vector to move towards.</param> /// <param name="delta">The amount to move towards by.</param> /// <returns>The resulting vector.</returns> - public Vector3 MoveToward(Vector3 to, real_t delta) + public readonly Vector3 MoveToward(Vector3 to, real_t delta) { Vector3 v = this; Vector3 vd = to - v; @@ -446,7 +446,7 @@ namespace Godot /// Returns the vector scaled to unit length. Equivalent to <c>v / v.Length()</c>. /// </summary> /// <returns>A normalized version of the vector.</returns> - public Vector3 Normalized() + public readonly Vector3 Normalized() { Vector3 v = this; v.Normalize(); @@ -458,7 +458,7 @@ namespace Godot /// </summary> /// <param name="with">The other vector.</param> /// <returns>A <see cref="Basis"/> representing the outer product matrix.</returns> - public Basis Outer(Vector3 with) + public readonly Basis Outer(Vector3 with) { return new Basis( x * with.x, x * with.y, x * with.z, @@ -475,7 +475,7 @@ namespace Godot /// <returns> /// A vector with each component <see cref="Mathf.PosMod(real_t, real_t)"/> by <paramref name="mod"/>. /// </returns> - public Vector3 PosMod(real_t mod) + public readonly Vector3 PosMod(real_t mod) { Vector3 v; v.x = Mathf.PosMod(x, mod); @@ -492,7 +492,7 @@ namespace Godot /// <returns> /// A vector with each component <see cref="Mathf.PosMod(real_t, real_t)"/> by <paramref name="modv"/>'s components. /// </returns> - public Vector3 PosMod(Vector3 modv) + public readonly Vector3 PosMod(Vector3 modv) { Vector3 v; v.x = Mathf.PosMod(x, modv.x); @@ -506,7 +506,7 @@ namespace Godot /// </summary> /// <param name="onNormal">The vector to project onto.</param> /// <returns>The projected vector.</returns> - public Vector3 Project(Vector3 onNormal) + public readonly Vector3 Project(Vector3 onNormal) { return onNormal * (Dot(onNormal) / onNormal.LengthSquared()); } @@ -516,7 +516,7 @@ namespace Godot /// </summary> /// <param name="normal">The normal vector defining the plane to reflect from. Must be normalized.</param> /// <returns>The reflected vector.</returns> - public Vector3 Reflect(Vector3 normal) + public readonly Vector3 Reflect(Vector3 normal) { #if DEBUG if (!normal.IsNormalized()) @@ -534,7 +534,7 @@ namespace Godot /// <param name="axis">The vector to rotate around. Must be normalized.</param> /// <param name="angle">The angle to rotate by, in radians.</param> /// <returns>The rotated vector.</returns> - public Vector3 Rotated(Vector3 axis, real_t angle) + public readonly Vector3 Rotated(Vector3 axis, real_t angle) { #if DEBUG if (!axis.IsNormalized()) @@ -550,7 +550,7 @@ namespace Godot /// with halfway cases rounded towards the nearest multiple of two. /// </summary> /// <returns>The rounded vector.</returns> - public Vector3 Round() + public readonly Vector3 Round() { return new Vector3(Mathf.Round(x), Mathf.Round(y), Mathf.Round(z)); } @@ -561,7 +561,7 @@ namespace Godot /// by calling <see cref="Mathf.Sign(real_t)"/> on each component. /// </summary> /// <returns>A vector with all components as either <c>1</c>, <c>-1</c>, or <c>0</c>.</returns> - public Vector3 Sign() + public readonly Vector3 Sign() { Vector3 v; v.x = Mathf.Sign(x); @@ -579,7 +579,7 @@ namespace Godot /// <param name="to">The other vector to compare this vector to.</param> /// <param name="axis">The reference axis to use for the angle sign.</param> /// <returns>The signed angle between the two vectors, in radians.</returns> - public real_t SignedAngleTo(Vector3 to, Vector3 axis) + public readonly real_t SignedAngleTo(Vector3 to, Vector3 axis) { Vector3 crossTo = Cross(to); real_t unsignedAngle = Mathf.Atan2(crossTo.Length(), Dot(to)); @@ -598,7 +598,7 @@ namespace Godot /// <param name="to">The destination vector for interpolation.</param> /// <param name="weight">A value on the range of 0.0 to 1.0, representing the amount of interpolation.</param> /// <returns>The resulting vector of the interpolation.</returns> - public Vector3 Slerp(Vector3 to, real_t weight) + public readonly Vector3 Slerp(Vector3 to, real_t weight) { real_t startLengthSquared = LengthSquared(); real_t endLengthSquared = to.LengthSquared(); @@ -618,7 +618,7 @@ namespace Godot /// </summary> /// <param name="normal">The normal vector defining the plane to slide on.</param> /// <returns>The slid vector.</returns> - public Vector3 Slide(Vector3 normal) + public readonly Vector3 Slide(Vector3 normal) { return this - (normal * Dot(normal)); } @@ -629,7 +629,7 @@ namespace Godot /// </summary> /// <param name="step">A vector value representing the step size to snap to.</param> /// <returns>The snapped vector.</returns> - public Vector3 Snapped(Vector3 step) + public readonly Vector3 Snapped(Vector3 step) { return new Vector3 ( @@ -1015,7 +1015,7 @@ namespace Godot /// </summary> /// <param name="obj">The object to compare with.</param> /// <returns>Whether or not the vector and the object are equal.</returns> - public override bool Equals(object obj) + public override readonly bool Equals(object obj) { return obj is Vector3 other && Equals(other); } @@ -1027,7 +1027,7 @@ namespace Godot /// </summary> /// <param name="other">The other vector.</param> /// <returns>Whether or not the vectors are exactly equal.</returns> - public bool Equals(Vector3 other) + public readonly bool Equals(Vector3 other) { return x == other.x && y == other.y && z == other.z; } @@ -1038,7 +1038,7 @@ namespace Godot /// </summary> /// <param name="other">The other vector to compare.</param> /// <returns>Whether or not the vectors are approximately equal.</returns> - public bool IsEqualApprox(Vector3 other) + public readonly bool IsEqualApprox(Vector3 other) { return Mathf.IsEqualApprox(x, other.x) && Mathf.IsEqualApprox(y, other.y) && Mathf.IsEqualApprox(z, other.z); } @@ -1047,7 +1047,7 @@ namespace Godot /// Serves as the hash function for <see cref="Vector3"/>. /// </summary> /// <returns>A hash code for this vector.</returns> - public override int GetHashCode() + public override readonly int GetHashCode() { return y.GetHashCode() ^ x.GetHashCode() ^ z.GetHashCode(); } @@ -1056,7 +1056,7 @@ namespace Godot /// Converts this <see cref="Vector3"/> to a string. /// </summary> /// <returns>A string representation of this vector.</returns> - public override string ToString() + public override readonly string ToString() { return $"({x}, {y}, {z})"; } @@ -1065,7 +1065,7 @@ namespace Godot /// Converts this <see cref="Vector3"/> to a string with the given <paramref name="format"/>. /// </summary> /// <returns>A string representation of this vector.</returns> - public string ToString(string format) + public readonly string ToString(string format) { return $"({x.ToString(format)}, {y.ToString(format)}, {z.ToString(format)})"; } diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector3i.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector3i.cs index e88a043cb3..e631a9f443 100644 --- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector3i.cs +++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector3i.cs @@ -58,7 +58,7 @@ namespace Godot /// </value> public int this[int index] { - get + readonly get { switch (index) { @@ -94,7 +94,7 @@ namespace Godot /// <summary> /// Helper method for deconstruction into a tuple. /// </summary> - public void Deconstruct(out int x, out int y, out int z) + public readonly void Deconstruct(out int x, out int y, out int z) { x = this.x; y = this.y; @@ -105,7 +105,7 @@ namespace Godot /// Returns a new vector with all components in absolute values (i.e. positive). /// </summary> /// <returns>A vector with <see cref="Mathf.Abs(int)"/> called on each component.</returns> - public Vector3i Abs() + public readonly Vector3i Abs() { return new Vector3i(Mathf.Abs(x), Mathf.Abs(y), Mathf.Abs(z)); } @@ -118,7 +118,7 @@ namespace Godot /// <param name="min">The vector with minimum allowed values.</param> /// <param name="max">The vector with maximum allowed values.</param> /// <returns>The vector with all components clamped.</returns> - public Vector3i Clamp(Vector3i min, Vector3i max) + public readonly Vector3i Clamp(Vector3i min, Vector3i max) { return new Vector3i ( @@ -135,7 +135,7 @@ namespace Godot /// </summary> /// <param name="to">The other vector to use.</param> /// <returns>The squared distance between the two vectors.</returns> - public int DistanceSquaredTo(Vector3i to) + public readonly int DistanceSquaredTo(Vector3i to) { return (to - this).LengthSquared(); } @@ -146,7 +146,7 @@ namespace Godot /// <seealso cref="DistanceSquaredTo(Vector3i)"/> /// <param name="to">The other vector to use.</param> /// <returns>The distance between the two vectors.</returns> - public real_t DistanceTo(Vector3i to) + public readonly real_t DistanceTo(Vector3i to) { return (to - this).Length(); } @@ -156,7 +156,7 @@ namespace Godot /// </summary> /// <param name="with">The other vector to use.</param> /// <returns>The dot product of the two vectors.</returns> - public int Dot(Vector3i with) + public readonly int Dot(Vector3i with) { return x * with.x + y * with.y + z * with.z; } @@ -166,7 +166,7 @@ namespace Godot /// </summary> /// <seealso cref="LengthSquared"/> /// <returns>The length of this vector.</returns> - public real_t Length() + public readonly real_t Length() { int x2 = x * x; int y2 = y * y; @@ -181,7 +181,7 @@ namespace Godot /// you need to compare vectors or need the squared length for some formula. /// </summary> /// <returns>The squared length of this vector.</returns> - public int LengthSquared() + public readonly int LengthSquared() { int x2 = x * x; int y2 = y * y; @@ -195,7 +195,7 @@ namespace Godot /// If all components are equal, this method returns <see cref="Axis.X"/>. /// </summary> /// <returns>The index of the highest axis.</returns> - public Axis MaxAxisIndex() + public readonly Axis MaxAxisIndex() { return x < y ? (y < z ? Axis.Z : Axis.Y) : (x < z ? Axis.Z : Axis.X); } @@ -205,7 +205,7 @@ namespace Godot /// If all components are equal, this method returns <see cref="Axis.Z"/>. /// </summary> /// <returns>The index of the lowest axis.</returns> - public Axis MinAxisIndex() + public readonly Axis MinAxisIndex() { return x < y ? (x < z ? Axis.X : Axis.Z) : (y < z ? Axis.Y : Axis.Z); } @@ -218,7 +218,7 @@ namespace Godot /// <returns> /// A vector with each component <see cref="Mathf.PosMod(int, int)"/> by <paramref name="mod"/>. /// </returns> - public Vector3i PosMod(int mod) + public readonly Vector3i PosMod(int mod) { Vector3i v = this; v.x = Mathf.PosMod(v.x, mod); @@ -235,7 +235,7 @@ namespace Godot /// <returns> /// A vector with each component <see cref="Mathf.PosMod(int, int)"/> by <paramref name="modv"/>'s components. /// </returns> - public Vector3i PosMod(Vector3i modv) + public readonly Vector3i PosMod(Vector3i modv) { Vector3i v = this; v.x = Mathf.PosMod(v.x, modv.x); @@ -250,7 +250,7 @@ namespace Godot /// by calling <see cref="Mathf.Sign(int)"/> on each component. /// </summary> /// <returns>A vector with all components as either <c>1</c>, <c>-1</c>, or <c>0</c>.</returns> - public Vector3i Sign() + public readonly Vector3i Sign() { Vector3i v = this; v.x = Mathf.Sign(v.x); @@ -674,7 +674,7 @@ namespace Godot /// </summary> /// <param name="obj">The object to compare with.</param> /// <returns>Whether or not the vector and the object are equal.</returns> - public override bool Equals(object obj) + public override readonly bool Equals(object obj) { return obj is Vector3i other && Equals(other); } @@ -684,7 +684,7 @@ namespace Godot /// </summary> /// <param name="other">The other vector.</param> /// <returns>Whether or not the vectors are equal.</returns> - public bool Equals(Vector3i other) + public readonly bool Equals(Vector3i other) { return x == other.x && y == other.y && z == other.z; } @@ -693,7 +693,7 @@ namespace Godot /// Serves as the hash function for <see cref="Vector3i"/>. /// </summary> /// <returns>A hash code for this vector.</returns> - public override int GetHashCode() + public override readonly int GetHashCode() { return y.GetHashCode() ^ x.GetHashCode() ^ z.GetHashCode(); } @@ -702,7 +702,7 @@ namespace Godot /// Converts this <see cref="Vector3i"/> to a string. /// </summary> /// <returns>A string representation of this vector.</returns> - public override string ToString() + public override readonly string ToString() { return $"({x}, {y}, {z})"; } @@ -711,7 +711,7 @@ namespace Godot /// Converts this <see cref="Vector3i"/> to a string with the given <paramref name="format"/>. /// </summary> /// <returns>A string representation of this vector.</returns> - public string ToString(string format) + public readonly string ToString(string format) { return $"({x.ToString(format)}, {y.ToString(format)}, {z.ToString(format)})"; } diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector4.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector4.cs index e2da41ff47..3191e8adc0 100644 --- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector4.cs +++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector4.cs @@ -68,7 +68,7 @@ namespace Godot /// </value> public real_t this[int index] { - get + readonly get { switch (index) { @@ -109,7 +109,7 @@ namespace Godot /// <summary> /// Helper method for deconstruction into a tuple. /// </summary> - public void Deconstruct(out real_t x, out real_t y, out real_t z, out real_t w) + public readonly void Deconstruct(out real_t x, out real_t y, out real_t z, out real_t w) { x = this.x; y = this.y; @@ -139,7 +139,7 @@ namespace Godot /// Returns a new vector with all components in absolute values (i.e. positive). /// </summary> /// <returns>A vector with <see cref="Mathf.Abs(real_t)"/> called on each component.</returns> - public Vector4 Abs() + public readonly Vector4 Abs() { return new Vector4(Mathf.Abs(x), Mathf.Abs(y), Mathf.Abs(z), Mathf.Abs(w)); } @@ -148,7 +148,7 @@ namespace Godot /// Returns a new vector with all components rounded up (towards positive infinity). /// </summary> /// <returns>A vector with <see cref="Mathf.Ceil"/> called on each component.</returns> - public Vector4 Ceil() + public readonly Vector4 Ceil() { return new Vector4(Mathf.Ceil(x), Mathf.Ceil(y), Mathf.Ceil(z), Mathf.Ceil(w)); } @@ -161,7 +161,7 @@ namespace Godot /// <param name="min">The vector with minimum allowed values.</param> /// <param name="max">The vector with maximum allowed values.</param> /// <returns>The vector with all components clamped.</returns> - public Vector4 Clamp(Vector4 min, Vector4 max) + public readonly Vector4 Clamp(Vector4 min, Vector4 max) { return new Vector4 ( @@ -181,7 +181,7 @@ namespace Godot /// <param name="postB">A vector after <paramref name="b"/>.</param> /// <param name="weight">A value on the range of 0.0 to 1.0, representing the amount of interpolation.</param> /// <returns>The interpolated vector.</returns> - public Vector4 CubicInterpolate(Vector4 b, Vector4 preA, Vector4 postB, real_t weight) + public readonly Vector4 CubicInterpolate(Vector4 b, Vector4 preA, Vector4 postB, real_t weight) { return new Vector4 ( @@ -206,7 +206,7 @@ namespace Godot /// <param name="preAT"></param> /// <param name="postBT"></param> /// <returns>The interpolated vector.</returns> - public Vector4 CubicInterpolateInTime(Vector4 b, Vector4 preA, Vector4 postB, real_t weight, real_t t, real_t preAT, real_t postBT) + public readonly Vector4 CubicInterpolateInTime(Vector4 b, Vector4 preA, Vector4 postB, real_t weight, real_t t, real_t preAT, real_t postBT) { return new Vector4 ( @@ -222,7 +222,7 @@ namespace Godot /// </summary> /// <param name="to">The other vector to point towards.</param> /// <returns>The direction from this vector to <paramref name="to"/>.</returns> - public Vector4 DirectionTo(Vector4 to) + public readonly Vector4 DirectionTo(Vector4 to) { Vector4 ret = new Vector4(to.x - x, to.y - y, to.z - z, to.w - w); ret.Normalize(); @@ -236,7 +236,7 @@ namespace Godot /// </summary> /// <param name="to">The other vector to use.</param> /// <returns>The squared distance between the two vectors.</returns> - public real_t DistanceSquaredTo(Vector4 to) + public readonly real_t DistanceSquaredTo(Vector4 to) { return (to - this).LengthSquared(); } @@ -246,7 +246,7 @@ namespace Godot /// </summary> /// <param name="to">The other vector to use.</param> /// <returns>The distance between the two vectors.</returns> - public real_t DistanceTo(Vector4 to) + public readonly real_t DistanceTo(Vector4 to) { return (to - this).Length(); } @@ -256,7 +256,7 @@ namespace Godot /// </summary> /// <param name="with">The other vector to use.</param> /// <returns>The dot product of the two vectors.</returns> - public real_t Dot(Vector4 with) + public readonly real_t Dot(Vector4 with) { return (x * with.x) + (y * with.y) + (z * with.z) + (w * with.w); } @@ -265,7 +265,7 @@ namespace Godot /// Returns a new vector with all components rounded down (towards negative infinity). /// </summary> /// <returns>A vector with <see cref="Mathf.Floor"/> called on each component.</returns> - public Vector4 Floor() + public readonly Vector4 Floor() { return new Vector4(Mathf.Floor(x), Mathf.Floor(y), Mathf.Floor(z), Mathf.Floor(w)); } @@ -274,7 +274,7 @@ namespace Godot /// Returns the inverse of this vector. This is the same as <c>new Vector4(1 / v.x, 1 / v.y, 1 / v.z, 1 / v.w)</c>. /// </summary> /// <returns>The inverse of this vector.</returns> - public Vector4 Inverse() + public readonly Vector4 Inverse() { return new Vector4(1 / x, 1 / y, 1 / z, 1 / w); } @@ -283,7 +283,7 @@ namespace Godot /// Returns <see langword="true"/> if the vector is normalized, and <see langword="false"/> otherwise. /// </summary> /// <returns>A <see langword="bool"/> indicating whether or not the vector is normalized.</returns> - public bool IsNormalized() + public readonly bool IsNormalized() { return Mathf.Abs(LengthSquared() - 1.0f) < Mathf.Epsilon; } @@ -293,7 +293,7 @@ namespace Godot /// </summary> /// <seealso cref="LengthSquared"/> /// <returns>The length of this vector.</returns> - public real_t Length() + public readonly real_t Length() { real_t x2 = x * x; real_t y2 = y * y; @@ -309,7 +309,7 @@ namespace Godot /// you need to compare vectors or need the squared length for some formula. /// </summary> /// <returns>The squared length of this vector.</returns> - public real_t LengthSquared() + public readonly real_t LengthSquared() { real_t x2 = x * x; real_t y2 = y * y; @@ -326,7 +326,7 @@ namespace Godot /// <param name="to">The destination vector for interpolation.</param> /// <param name="weight">A value on the range of 0.0 to 1.0, representing the amount of interpolation.</param> /// <returns>The resulting vector of the interpolation.</returns> - public Vector4 Lerp(Vector4 to, real_t weight) + public readonly Vector4 Lerp(Vector4 to, real_t weight) { return new Vector4 ( @@ -342,7 +342,7 @@ namespace Godot /// If all components are equal, this method returns <see cref="Axis.X"/>. /// </summary> /// <returns>The index of the highest axis.</returns> - public Axis MaxAxisIndex() + public readonly Axis MaxAxisIndex() { int max_index = 0; real_t max_value = x; @@ -362,7 +362,7 @@ namespace Godot /// If all components are equal, this method returns <see cref="Axis.W"/>. /// </summary> /// <returns>The index of the lowest axis.</returns> - public Axis MinAxisIndex() + public readonly Axis MinAxisIndex() { int min_index = 0; real_t min_value = x; @@ -381,7 +381,7 @@ namespace Godot /// Returns the vector scaled to unit length. Equivalent to <c>v / v.Length()</c>. /// </summary> /// <returns>A normalized version of the vector.</returns> - public Vector4 Normalized() + public readonly Vector4 Normalized() { Vector4 v = this; v.Normalize(); @@ -396,7 +396,7 @@ namespace Godot /// <returns> /// A vector with each component <see cref="Mathf.PosMod(real_t, real_t)"/> by <paramref name="mod"/>. /// </returns> - public Vector4 PosMod(real_t mod) + public readonly Vector4 PosMod(real_t mod) { return new Vector4( Mathf.PosMod(x, mod), @@ -414,7 +414,7 @@ namespace Godot /// <returns> /// A vector with each component <see cref="Mathf.PosMod(real_t, real_t)"/> by <paramref name="modv"/>'s components. /// </returns> - public Vector4 PosMod(Vector4 modv) + public readonly Vector4 PosMod(Vector4 modv) { return new Vector4( Mathf.PosMod(x, modv.x), @@ -429,7 +429,7 @@ namespace Godot /// with halfway cases rounded towards the nearest multiple of two. /// </summary> /// <returns>The rounded vector.</returns> - public Vector4 Round() + public readonly Vector4 Round() { return new Vector4(Mathf.Round(x), Mathf.Round(y), Mathf.Round(z), Mathf.Round(w)); } @@ -440,7 +440,7 @@ namespace Godot /// by calling <see cref="Mathf.Sign(real_t)"/> on each component. /// </summary> /// <returns>A vector with all components as either <c>1</c>, <c>-1</c>, or <c>0</c>.</returns> - public Vector4 Sign() + public readonly Vector4 Sign() { Vector4 v; v.x = Mathf.Sign(x); @@ -456,7 +456,7 @@ namespace Godot /// </summary> /// <param name="step">A vector value representing the step size to snap to.</param> /// <returns>The snapped vector.</returns> - public Vector4 Snapped(Vector4 step) + public readonly Vector4 Snapped(Vector4 step) { return new Vector4( Mathf.Snapped(x, step.x), @@ -828,7 +828,7 @@ namespace Godot /// </summary> /// <param name="obj">The object to compare with.</param> /// <returns>Whether or not the vector and the object are equal.</returns> - public override bool Equals(object obj) + public override readonly bool Equals(object obj) { return obj is Vector4 other && Equals(other); } @@ -840,7 +840,7 @@ namespace Godot /// </summary> /// <param name="other">The other vector.</param> /// <returns>Whether or not the vectors are exactly equal.</returns> - public bool Equals(Vector4 other) + public readonly bool Equals(Vector4 other) { return x == other.x && y == other.y && z == other.z && w == other.w; } @@ -851,7 +851,7 @@ namespace Godot /// </summary> /// <param name="other">The other vector to compare.</param> /// <returns>Whether or not the vectors are approximately equal.</returns> - public bool IsEqualApprox(Vector4 other) + public readonly bool IsEqualApprox(Vector4 other) { return Mathf.IsEqualApprox(x, other.x) && Mathf.IsEqualApprox(y, other.y) && Mathf.IsEqualApprox(z, other.z) && Mathf.IsEqualApprox(w, other.w); } @@ -860,7 +860,7 @@ namespace Godot /// Serves as the hash function for <see cref="Vector4"/>. /// </summary> /// <returns>A hash code for this vector.</returns> - public override int GetHashCode() + public override readonly int GetHashCode() { return y.GetHashCode() ^ x.GetHashCode() ^ z.GetHashCode() ^ w.GetHashCode(); } @@ -878,7 +878,7 @@ namespace Godot /// Converts this <see cref="Vector4"/> to a string with the given <paramref name="format"/>. /// </summary> /// <returns>A string representation of this vector.</returns> - public string ToString(string format) + public readonly string ToString(string format) { return $"({x.ToString(format)}, {y.ToString(format)}, {z.ToString(format)}, {w.ToString(format)})"; } diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector4i.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector4i.cs index 4b1bb3ba19..8146991fd7 100644 --- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector4i.cs +++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector4i.cs @@ -68,7 +68,7 @@ namespace Godot /// </value> public int this[int index] { - get + readonly get { switch (index) { @@ -109,7 +109,7 @@ namespace Godot /// <summary> /// Helper method for deconstruction into a tuple. /// </summary> - public void Deconstruct(out int x, out int y, out int z, out int w) + public readonly void Deconstruct(out int x, out int y, out int z, out int w) { x = this.x; y = this.y; @@ -121,7 +121,7 @@ namespace Godot /// Returns a new vector with all components in absolute values (i.e. positive). /// </summary> /// <returns>A vector with <see cref="Mathf.Abs(int)"/> called on each component.</returns> - public Vector4i Abs() + public readonly Vector4i Abs() { return new Vector4i(Mathf.Abs(x), Mathf.Abs(y), Mathf.Abs(z), Mathf.Abs(w)); } @@ -134,7 +134,7 @@ namespace Godot /// <param name="min">The vector with minimum allowed values.</param> /// <param name="max">The vector with maximum allowed values.</param> /// <returns>The vector with all components clamped.</returns> - public Vector4i Clamp(Vector4i min, Vector4i max) + public readonly Vector4i Clamp(Vector4i min, Vector4i max) { return new Vector4i ( @@ -150,7 +150,7 @@ namespace Godot /// </summary> /// <seealso cref="LengthSquared"/> /// <returns>The length of this vector.</returns> - public real_t Length() + public readonly real_t Length() { int x2 = x * x; int y2 = y * y; @@ -166,7 +166,7 @@ namespace Godot /// you need to compare vectors or need the squared length for some formula. /// </summary> /// <returns>The squared length of this vector.</returns> - public int LengthSquared() + public readonly int LengthSquared() { int x2 = x * x; int y2 = y * y; @@ -181,7 +181,7 @@ namespace Godot /// If all components are equal, this method returns <see cref="Axis.X"/>. /// </summary> /// <returns>The index of the highest axis.</returns> - public Axis MaxAxisIndex() + public readonly Axis MaxAxisIndex() { int max_index = 0; int max_value = x; @@ -201,7 +201,7 @@ namespace Godot /// If all components are equal, this method returns <see cref="Axis.W"/>. /// </summary> /// <returns>The index of the lowest axis.</returns> - public Axis MinAxisIndex() + public readonly Axis MinAxisIndex() { int min_index = 0; int min_value = x; @@ -222,7 +222,7 @@ namespace Godot /// by calling <see cref="Mathf.Sign(int)"/> on each component. /// </summary> /// <returns>A vector with all components as either <c>1</c>, <c>-1</c>, or <c>0</c>.</returns> - public Vector4i Sign() + public readonly Vector4i Sign() { return new Vector4i(Mathf.Sign(x), Mathf.Sign(y), Mathf.Sign(z), Mathf.Sign(w)); } @@ -627,7 +627,7 @@ namespace Godot /// </summary> /// <param name="obj">The object to compare with.</param> /// <returns>Whether or not the vector and the object are equal.</returns> - public override bool Equals(object obj) + public override readonly bool Equals(object obj) { return obj is Vector4i other && Equals(other); } @@ -637,7 +637,7 @@ namespace Godot /// </summary> /// <param name="other">The other vector.</param> /// <returns>Whether or not the vectors are equal.</returns> - public bool Equals(Vector4i other) + public readonly bool Equals(Vector4i other) { return x == other.x && y == other.y && z == other.z && w == other.w; } @@ -646,7 +646,7 @@ namespace Godot /// Serves as the hash function for <see cref="Vector4i"/>. /// </summary> /// <returns>A hash code for this vector.</returns> - public override int GetHashCode() + public override readonly int GetHashCode() { return y.GetHashCode() ^ x.GetHashCode() ^ z.GetHashCode() ^ w.GetHashCode(); } @@ -655,7 +655,7 @@ namespace Godot /// Converts this <see cref="Vector4i"/> to a string. /// </summary> /// <returns>A string representation of this vector.</returns> - public override string ToString() + public override readonly string ToString() { return $"({x}, {y}, {z}, {w})"; } @@ -664,7 +664,7 @@ namespace Godot /// Converts this <see cref="Vector4i"/> to a string with the given <paramref name="format"/>. /// </summary> /// <returns>A string representation of this vector.</returns> - public string ToString(string format) + public readonly string ToString(string format) { return $"({x.ToString(format)}, {y.ToString(format)}, {z.ToString(format)}), {w.ToString(format)})"; } |