/**************************************************************************/ /* variant_construct.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_construct.h" struct VariantConstructData { void (*construct)(Variant &r_base, const Variant **p_args, Callable::CallError &r_error) = nullptr; Variant::ValidatedConstructor validated_construct = nullptr; Variant::PTRConstructor ptr_construct = nullptr; Variant::Type (*get_argument_type)(int) = nullptr; int argument_count = 0; Vector arg_names; }; static LocalVector construct_data[Variant::VARIANT_MAX]; template static void add_constructor(const Vector &arg_names) { ERR_FAIL_COND_MSG(arg_names.size() != T::get_argument_count(), "Argument names size mismatch for " + Variant::get_type_name(T::get_base_type()) + "."); VariantConstructData cd; cd.construct = T::construct; cd.validated_construct = T::validated_construct; cd.ptr_construct = T::ptr_construct; cd.get_argument_type = T::get_argument_type; cd.argument_count = T::get_argument_count(); cd.arg_names = arg_names; construct_data[T::get_base_type()].push_back(cd); } void Variant::_register_variant_constructors() { add_constructor(sarray()); add_constructor(sarray("from")); add_constructor>(sarray()); add_constructor>(sarray("from")); add_constructor>(sarray("from")); add_constructor>(sarray("from")); add_constructor>(sarray()); add_constructor>(sarray("from")); add_constructor>(sarray("from")); add_constructor>(sarray("from")); add_constructor>(sarray("from")); add_constructor>(sarray()); add_constructor>(sarray("from")); add_constructor>(sarray("from")); add_constructor>(sarray("from")); add_constructor>(sarray("from")); add_constructor>(sarray()); add_constructor>(sarray("from")); add_constructor>(sarray("from")); add_constructor>(sarray("from")); add_constructor>(sarray()); add_constructor>(sarray("from")); add_constructor>(sarray("from")); add_constructor>(sarray("x", "y")); add_constructor>(sarray()); add_constructor>(sarray("from")); add_constructor>(sarray("from")); add_constructor>(sarray("x", "y")); add_constructor>(sarray()); add_constructor>(sarray("from")); add_constructor>(sarray("from")); add_constructor>(sarray("position", "size")); add_constructor>(sarray("x", "y", "width", "height")); add_constructor>(sarray()); add_constructor>(sarray("from")); add_constructor>(sarray("from")); add_constructor>(sarray("position", "size")); add_constructor>(sarray("x", "y", "width", "height")); add_constructor>(sarray()); add_constructor>(sarray("from")); add_constructor>(sarray("from")); add_constructor>(sarray("x", "y", "z")); add_constructor>(sarray()); add_constructor>(sarray("from")); add_constructor>(sarray("from")); add_constructor>(sarray("x", "y", "z")); add_constructor>(sarray()); add_constructor>(sarray("from")); add_constructor>(sarray("from")); add_constructor>(sarray("x", "y", "z", "w")); add_constructor>(sarray()); add_constructor>(sarray("from")); add_constructor>(sarray("from")); add_constructor>(sarray("x", "y", "z", "w")); add_constructor>(sarray()); add_constructor>(sarray("from")); add_constructor>(sarray("rotation", "position")); add_constructor>(sarray("rotation", "scale", "skew", "position")); add_constructor>(sarray("x_axis", "y_axis", "origin")); add_constructor>(sarray()); add_constructor>(sarray("from")); add_constructor>(sarray("normal")); add_constructor>(sarray("normal", "d")); add_constructor>(sarray("normal", "point")); add_constructor>(sarray("point1", "point2", "point3")); add_constructor>(sarray("a", "b", "c", "d")); add_constructor>(sarray()); add_constructor>(sarray("from")); add_constructor>(sarray("from")); add_constructor>(sarray("axis", "angle")); add_constructor>(sarray("arc_from", "arc_to")); add_constructor>(sarray("x", "y", "z", "w")); add_constructor>(sarray()); add_constructor>(sarray("from")); add_constructor>(sarray("position", "size")); add_constructor>(sarray()); add_constructor>(sarray("from")); add_constructor>(sarray("from")); add_constructor>(sarray("axis", "angle")); add_constructor>(sarray("x_axis", "y_axis", "z_axis")); add_constructor>(sarray()); add_constructor>(sarray("from")); add_constructor>(sarray("basis", "origin")); add_constructor>(sarray("x_axis", "y_axis", "z_axis", "origin")); add_constructor>(sarray("from")); add_constructor>(sarray()); add_constructor>(sarray("from")); add_constructor>(sarray("from")); add_constructor>(sarray("x_axis", "y_axis", "z_axis", "w_axis")); add_constructor>(sarray()); add_constructor>(sarray("from")); add_constructor>(sarray("from", "alpha")); add_constructor>(sarray("r", "g", "b")); add_constructor>(sarray("r", "g", "b", "a")); add_constructor>(sarray("code")); add_constructor>(sarray("code", "alpha")); add_constructor>(sarray()); add_constructor>(sarray("from")); add_constructor>(sarray("from")); add_constructor>(sarray()); add_constructor>(sarray("from")); add_constructor>(sarray("from")); add_constructor>(sarray()); add_constructor>(sarray("from")); add_constructor(sarray()); add_constructor(sarray("from")); add_constructor(sarray("from")); add_constructor>(sarray()); add_constructor>(sarray("from")); add_constructor(sarray("object", "method")); add_constructor>(sarray()); add_constructor>(sarray("from")); add_constructor(sarray("object", "signal")); add_constructor>(sarray()); add_constructor>(sarray("from")); add_constructor>(sarray()); add_constructor>(sarray("from")); add_constructor(sarray("base", "type", "class_name", "script")); add_constructor>(sarray("from")); add_constructor>(sarray("from")); add_constructor>(sarray("from")); add_constructor>(sarray("from")); add_constructor>(sarray("from")); add_constructor>(sarray("from")); add_constructor>(sarray("from")); add_constructor>(sarray("from")); add_constructor>(sarray("from")); add_constructor>(sarray()); add_constructor>(sarray("from")); add_constructor>(sarray("from")); add_constructor>(sarray()); add_constructor>(sarray("from")); add_constructor>(sarray("from")); add_constructor>(sarray()); add_constructor>(sarray("from")); add_constructor>(sarray("from")); add_constructor>(sarray()); add_constructor>(sarray("from")); add_constructor>(sarray("from")); add_constructor>(sarray()); add_constructor>(sarray("from")); add_constructor>(sarray("from")); add_constructor>(sarray()); add_constructor>(sarray("from")); add_constructor>(sarray("from")); add_constructor>(sarray()); add_constructor>(sarray("from")); add_constructor>(sarray("from")); add_constructor>(sarray()); add_constructor>(sarray("from")); add_constructor>(sarray("from")); add_constructor>(sarray()); add_constructor>(sarray("from")); add_constructor>(sarray("from")); } void Variant::_unregister_variant_constructors() { for (int i = 0; i < Variant::VARIANT_MAX; i++) { construct_data[i].clear(); } } void Variant::construct(Variant::Type p_type, Variant &base, const Variant **p_args, int p_argcount, Callable::CallError &r_error) { ERR_FAIL_INDEX(p_type, Variant::VARIANT_MAX); uint32_t s = construct_data[p_type].size(); for (uint32_t i = 0; i < s; i++) { int argc = construct_data[p_type][i].argument_count; if (argc != p_argcount) { continue; } bool args_match = true; for (int j = 0; j < argc; j++) { if (!Variant::can_convert_strict(p_args[j]->get_type(), construct_data[p_type][i].get_argument_type(j))) { args_match = false; break; } } if (!args_match) { continue; } construct_data[p_type][i].construct(base, p_args, r_error); return; } r_error.error = Callable::CallError::CALL_ERROR_INVALID_METHOD; } int Variant::get_constructor_count(Variant::Type p_type) { ERR_FAIL_INDEX_V(p_type, Variant::VARIANT_MAX, -1); return construct_data[p_type].size(); } Variant::ValidatedConstructor Variant::get_validated_constructor(Variant::Type p_type, int p_constructor) { ERR_FAIL_INDEX_V(p_type, Variant::VARIANT_MAX, nullptr); ERR_FAIL_INDEX_V(p_constructor, (int)construct_data[p_type].size(), nullptr); return construct_data[p_type][p_constructor].validated_construct; } Variant::PTRConstructor Variant::get_ptr_constructor(Variant::Type p_type, int p_constructor) { ERR_FAIL_INDEX_V(p_type, Variant::VARIANT_MAX, nullptr); ERR_FAIL_INDEX_V(p_constructor, (int)construct_data[p_type].size(), nullptr); return construct_data[p_type][p_constructor].ptr_construct; } int Variant::get_constructor_argument_count(Variant::Type p_type, int p_constructor) { ERR_FAIL_INDEX_V(p_type, Variant::VARIANT_MAX, -1); ERR_FAIL_INDEX_V(p_constructor, (int)construct_data[p_type].size(), -1); return construct_data[p_type][p_constructor].argument_count; } Variant::Type Variant::get_constructor_argument_type(Variant::Type p_type, int p_constructor, int p_argument) { ERR_FAIL_INDEX_V(p_type, Variant::VARIANT_MAX, Variant::VARIANT_MAX); ERR_FAIL_INDEX_V(p_constructor, (int)construct_data[p_type].size(), Variant::VARIANT_MAX); return construct_data[p_type][p_constructor].get_argument_type(p_argument); } String Variant::get_constructor_argument_name(Variant::Type p_type, int p_constructor, int p_argument) { ERR_FAIL_INDEX_V(p_type, Variant::VARIANT_MAX, String()); ERR_FAIL_INDEX_V(p_constructor, (int)construct_data[p_type].size(), String()); return construct_data[p_type][p_constructor].arg_names[p_argument]; } void VariantInternal::object_assign(Variant *v, const Object *o) { if (o) { if (o->is_ref_counted()) { RefCounted *ref_counted = const_cast(static_cast(o)); if (!ref_counted->init_ref()) { v->_get_obj().obj = nullptr; v->_get_obj().id = ObjectID(); return; } } v->_get_obj().obj = const_cast(o); v->_get_obj().id = o->get_instance_id(); } else { v->_get_obj().obj = nullptr; v->_get_obj().id = ObjectID(); } } void Variant::get_constructor_list(Type p_type, List *r_list) { ERR_FAIL_INDEX(p_type, Variant::VARIANT_MAX); MethodInfo mi; mi.return_val.type = p_type; mi.name = get_type_name(p_type); for (int i = 0; i < get_constructor_count(p_type); i++) { int ac = get_constructor_argument_count(p_type, i); mi.arguments.clear(); for (int j = 0; j < ac; j++) { PropertyInfo arg; arg.name = get_constructor_argument_name(p_type, i, j); arg.type = get_constructor_argument_type(p_type, i, j); mi.arguments.push_back(arg); } r_list->push_back(mi); } }