diff options
Diffstat (limited to 'core/variant')
-rw-r--r-- | core/variant/variant.h | 1 | ||||
-rw-r--r-- | core/variant/variant_call.cpp | 85 | ||||
-rw-r--r-- | core/variant/variant_callable.cpp | 81 | ||||
-rw-r--r-- | core/variant/variant_callable.h | 58 | ||||
-rw-r--r-- | core/variant/variant_setget.cpp | 53 |
5 files changed, 217 insertions, 61 deletions
diff --git a/core/variant/variant.h b/core/variant/variant.h index 480f21df98..e93733040a 100644 --- a/core/variant/variant.h +++ b/core/variant/variant.h @@ -572,6 +572,7 @@ public: static ValidatedBuiltInMethod get_validated_builtin_method(Variant::Type p_type, const StringName &p_method); static PTRBuiltInMethod get_ptr_builtin_method(Variant::Type p_type, const StringName &p_method); + static MethodInfo get_builtin_method_info(Variant::Type p_type, const StringName &p_method); static int get_builtin_method_argument_count(Variant::Type p_type, const StringName &p_method); static Variant::Type get_builtin_method_argument_type(Variant::Type p_type, const StringName &p_method, int p_argument); static String get_builtin_method_argument_name(Variant::Type p_type, const StringName &p_method, int p_argument); diff --git a/core/variant/variant_call.cpp b/core/variant/variant_call.cpp index 7121b4da96..dd793dbcd4 100644 --- a/core/variant/variant_call.cpp +++ b/core/variant/variant_call.cpp @@ -1114,6 +1114,46 @@ struct VariantBuiltInMethodInfo { Variant::Type return_type; int argument_count = 0; Variant::Type (*get_argument_type)(int p_arg) = nullptr; + + MethodInfo get_method_info(const StringName &p_name) const { + MethodInfo mi; + mi.name = p_name; + + if (has_return_type) { + mi.return_val.type = return_type; + if (mi.return_val.type == Variant::NIL) { + mi.return_val.usage |= PROPERTY_USAGE_NIL_IS_VARIANT; + } + } + + if (is_const) { + mi.flags |= METHOD_FLAG_CONST; + } + if (is_vararg) { + mi.flags |= METHOD_FLAG_VARARG; + } + if (is_static) { + mi.flags |= METHOD_FLAG_STATIC; + } + + for (int i = 0; i < argument_count; i++) { + PropertyInfo pi; +#ifdef DEBUG_METHODS_ENABLED + pi.name = argument_names[i]; +#else + pi.name = "arg" + itos(i + 1); +#endif + pi.type = (*get_argument_type)(i); + if (pi.type == Variant::NIL) { + pi.usage |= PROPERTY_USAGE_NIL_IS_VARIANT; + } + mi.arguments.push_back(pi); + } + + mi.default_arguments = default_arguments; + + return mi; + } }; typedef OAHashMap<StringName, VariantBuiltInMethodInfo> BuiltinMethodMap; @@ -1268,6 +1308,13 @@ Variant::PTRBuiltInMethod Variant::get_ptr_builtin_method(Variant::Type p_type, return method->ptrcall; } +MethodInfo Variant::get_builtin_method_info(Variant::Type p_type, const StringName &p_method) { + ERR_FAIL_INDEX_V(p_type, Variant::VARIANT_MAX, MethodInfo()); + const VariantBuiltInMethodInfo *method = builtin_method_info[p_type].lookup_ptr(p_method); + ERR_FAIL_NULL_V(method, MethodInfo()); + return method->get_method_info(p_method); +} + int Variant::get_builtin_method_argument_count(Variant::Type p_type, const StringName &p_method) { ERR_FAIL_INDEX_V(p_type, Variant::VARIANT_MAX, 0); const VariantBuiltInMethodInfo *method = builtin_method_info[p_type].lookup_ptr(p_method); @@ -1378,43 +1425,7 @@ void Variant::get_method_list(List<MethodInfo> *p_list) const { for (const StringName &E : builtin_method_names[type]) { const VariantBuiltInMethodInfo *method = builtin_method_info[type].lookup_ptr(E); ERR_CONTINUE(!method); - - MethodInfo mi; - mi.name = E; - - //return type - if (method->has_return_type) { - mi.return_val.type = method->return_type; - if (mi.return_val.type == Variant::NIL) { - mi.return_val.usage |= PROPERTY_USAGE_NIL_IS_VARIANT; - } - } - - if (method->is_const) { - mi.flags |= METHOD_FLAG_CONST; - } - if (method->is_vararg) { - mi.flags |= METHOD_FLAG_VARARG; - } - if (method->is_static) { - mi.flags |= METHOD_FLAG_STATIC; - } - for (int i = 0; i < method->argument_count; i++) { - PropertyInfo pi; -#ifdef DEBUG_METHODS_ENABLED - pi.name = method->argument_names[i]; -#else - pi.name = "arg" + itos(i + 1); -#endif - pi.type = method->get_argument_type(i); - if (pi.type == Variant::NIL) { - pi.usage |= PROPERTY_USAGE_NIL_IS_VARIANT; - } - mi.arguments.push_back(pi); - } - - mi.default_arguments = method->default_arguments; - p_list->push_back(mi); + p_list->push_back(method->get_method_info(E)); } } } diff --git a/core/variant/variant_callable.cpp b/core/variant/variant_callable.cpp new file mode 100644 index 0000000000..dc31b6d1ac --- /dev/null +++ b/core/variant/variant_callable.cpp @@ -0,0 +1,81 @@ +/**************************************************************************/ +/* variant_callable.cpp */ +/**************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/**************************************************************************/ +/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */ +/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/**************************************************************************/ + +#include "variant_callable.h" + +#include "core/templates/hashfuncs.h" + +bool VariantCallable::compare_equal(const CallableCustom *p_a, const CallableCustom *p_b) { + return p_a->hash() == p_b->hash(); +} + +bool VariantCallable::compare_less(const CallableCustom *p_a, const CallableCustom *p_b) { + return p_a->hash() < p_b->hash(); +} + +uint32_t VariantCallable::hash() const { + return h; +} + +String VariantCallable::get_as_text() const { + return vformat("%s::%s (Callable)", Variant::get_type_name(variant.get_type()), method); +} + +CallableCustom::CompareEqualFunc VariantCallable::get_compare_equal_func() const { + return compare_equal; +} + +CallableCustom::CompareLessFunc VariantCallable::get_compare_less_func() const { + return compare_less; +} + +bool VariantCallable::is_valid() const { + return Variant::has_builtin_method(variant.get_type(), method); +} + +StringName VariantCallable::get_method() const { + return method; +} + +ObjectID VariantCallable::get_object() const { + return ObjectID(); +} + +void VariantCallable::call(const Variant **p_arguments, int p_argcount, Variant &r_return_value, Callable::CallError &r_call_error) const { + Variant v = variant; + v.callp(method, p_arguments, p_argcount, r_return_value, r_call_error); +} + +VariantCallable::VariantCallable(const Variant &p_variant, const StringName &p_method) { + variant = p_variant; + method = p_method; + h = variant.hash(); + h = hash_murmur3_one_64(Variant::get_builtin_method_hash(variant.get_type(), method), h); +} diff --git a/core/variant/variant_callable.h b/core/variant/variant_callable.h new file mode 100644 index 0000000000..3f2b058aaf --- /dev/null +++ b/core/variant/variant_callable.h @@ -0,0 +1,58 @@ +/**************************************************************************/ +/* variant_callable.h */ +/**************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/**************************************************************************/ +/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */ +/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/**************************************************************************/ + +#ifndef VARIANT_CALLABLE_H +#define VARIANT_CALLABLE_H + +#include "core/variant/callable.h" +#include "core/variant/variant.h" + +class VariantCallable : public CallableCustom { + Variant variant; + StringName method; + uint32_t h = 0; + + static bool compare_equal(const CallableCustom *p_a, const CallableCustom *p_b); + static bool compare_less(const CallableCustom *p_a, const CallableCustom *p_b); + +public: + uint32_t hash() const override; + String get_as_text() const override; + CompareEqualFunc get_compare_equal_func() const override; + CompareLessFunc get_compare_less_func() const override; + bool is_valid() const override; + StringName get_method() const override; + ObjectID get_object() const override; + void call(const Variant **p_arguments, int p_argcount, Variant &r_return_value, Callable::CallError &r_call_error) const override; + + VariantCallable(const Variant &p_variant, const StringName &p_method); +}; + +#endif // VARIANT_CALLABLE_H diff --git a/core/variant/variant_setget.cpp b/core/variant/variant_setget.cpp index 05f7abf32c..b0e0a885f4 100644 --- a/core/variant/variant_setget.cpp +++ b/core/variant/variant_setget.cpp @@ -30,6 +30,8 @@ #include "variant_setget.h" +#include "variant_callable.h" + struct VariantSetterGetterInfo { void (*setter)(Variant *base, const Variant *value, bool &valid); void (*getter)(const Variant *base, Variant *value); @@ -264,42 +266,45 @@ void Variant::set_named(const StringName &p_member, const Variant &p_value, bool } Variant Variant::get_named(const StringName &p_member, bool &r_valid) const { - Variant ret; uint32_t s = variant_setters_getters[type].size(); if (s) { for (uint32_t i = 0; i < s; i++) { if (variant_setters_getters_names[type][i] == p_member) { + Variant ret; variant_setters_getters[type][i].getter(this, &ret); r_valid = true; return ret; } } + } - r_valid = false; - - } else if (type == Variant::OBJECT) { - Object *obj = get_validated_object(); - if (!obj) { - r_valid = false; - return "Instance base is null."; - } else { - return obj->get(p_member, &r_valid); - } - } else if (type == Variant::DICTIONARY) { - const Variant *v = VariantGetInternalPtr<Dictionary>::get_ptr(this)->getptr(p_member); - if (v) { - r_valid = true; - - return *v; - } else { - r_valid = false; - } - - } else { - r_valid = false; + switch (type) { + case Variant::OBJECT: { + Object *obj = get_validated_object(); + if (!obj) { + r_valid = false; + return "Instance base is null."; + } else { + return obj->get(p_member, &r_valid); + } + } break; + case Variant::DICTIONARY: { + const Variant *v = VariantGetInternalPtr<Dictionary>::get_ptr(this)->getptr(p_member); + if (v) { + r_valid = true; + return *v; + } + } break; + default: { + if (Variant::has_builtin_method(type, p_member)) { + r_valid = true; + return Callable(memnew(VariantCallable(*this, p_member))); + } + } break; } - return ret; + r_valid = false; + return Variant(); } /**** INDEXED SETTERS AND GETTERS ****/ |