feat: godot-engine-source-4.3-stable

This commit is contained in:
Jan van der Weide 2025-01-17 16:36:38 +01:00
parent c59a7dcade
commit 7125d019b5
11149 changed files with 5070401 additions and 0 deletions

View file

@ -0,0 +1,7 @@
#!/usr/bin/env python
Import("env")
env_variant = env.Clone()
env_variant.add_source_files(env.core_sources, "*.cpp")

View file

@ -0,0 +1,840 @@
/**************************************************************************/
/* array.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 "array.h"
#include "container_type_validate.h"
#include "core/math/math_funcs.h"
#include "core/object/class_db.h"
#include "core/object/script_language.h"
#include "core/templates/hashfuncs.h"
#include "core/templates/search_array.h"
#include "core/templates/vector.h"
#include "core/variant/callable.h"
#include "core/variant/dictionary.h"
#include "core/variant/variant.h"
class ArrayPrivate {
public:
SafeRefCount refcount;
Vector<Variant> array;
Variant *read_only = nullptr; // If enabled, a pointer is used to a temporary value that is used to return read-only values.
ContainerTypeValidate typed;
};
void Array::_ref(const Array &p_from) const {
ArrayPrivate *_fp = p_from._p;
ERR_FAIL_NULL(_fp); // Should NOT happen.
if (_fp == _p) {
return; // whatever it is, nothing to do here move along
}
bool success = _fp->refcount.ref();
ERR_FAIL_COND(!success); // should really not happen either
_unref();
_p = _fp;
}
void Array::_unref() const {
if (!_p) {
return;
}
if (_p->refcount.unref()) {
if (_p->read_only) {
memdelete(_p->read_only);
}
memdelete(_p);
}
_p = nullptr;
}
Array::Iterator Array::begin() {
return Iterator(_p->array.ptrw(), _p->read_only);
}
Array::Iterator Array::end() {
return Iterator(_p->array.ptrw() + _p->array.size(), _p->read_only);
}
Array::ConstIterator Array::begin() const {
return ConstIterator(_p->array.ptr(), _p->read_only);
}
Array::ConstIterator Array::end() const {
return ConstIterator(_p->array.ptr() + _p->array.size(), _p->read_only);
}
Variant &Array::operator[](int p_idx) {
if (unlikely(_p->read_only)) {
*_p->read_only = _p->array[p_idx];
return *_p->read_only;
}
return _p->array.write[p_idx];
}
const Variant &Array::operator[](int p_idx) const {
if (unlikely(_p->read_only)) {
*_p->read_only = _p->array[p_idx];
return *_p->read_only;
}
return _p->array[p_idx];
}
int Array::size() const {
return _p->array.size();
}
bool Array::is_empty() const {
return _p->array.is_empty();
}
void Array::clear() {
ERR_FAIL_COND_MSG(_p->read_only, "Array is in read-only state.");
_p->array.clear();
}
bool Array::operator==(const Array &p_array) const {
return recursive_equal(p_array, 0);
}
bool Array::operator!=(const Array &p_array) const {
return !recursive_equal(p_array, 0);
}
bool Array::recursive_equal(const Array &p_array, int recursion_count) const {
// Cheap checks
if (_p == p_array._p) {
return true;
}
const Vector<Variant> &a1 = _p->array;
const Vector<Variant> &a2 = p_array._p->array;
const int size = a1.size();
if (size != a2.size()) {
return false;
}
// Heavy O(n) check
if (recursion_count > MAX_RECURSION) {
ERR_PRINT("Max recursion reached");
return true;
}
recursion_count++;
for (int i = 0; i < size; i++) {
if (!a1[i].hash_compare(a2[i], recursion_count, false)) {
return false;
}
}
return true;
}
bool Array::operator<(const Array &p_array) const {
int a_len = size();
int b_len = p_array.size();
int min_cmp = MIN(a_len, b_len);
for (int i = 0; i < min_cmp; i++) {
if (operator[](i) < p_array[i]) {
return true;
} else if (p_array[i] < operator[](i)) {
return false;
}
}
return a_len < b_len;
}
bool Array::operator<=(const Array &p_array) const {
return !operator>(p_array);
}
bool Array::operator>(const Array &p_array) const {
return p_array < *this;
}
bool Array::operator>=(const Array &p_array) const {
return !operator<(p_array);
}
uint32_t Array::hash() const {
return recursive_hash(0);
}
uint32_t Array::recursive_hash(int recursion_count) const {
if (recursion_count > MAX_RECURSION) {
ERR_PRINT("Max recursion reached");
return 0;
}
uint32_t h = hash_murmur3_one_32(Variant::ARRAY);
recursion_count++;
for (int i = 0; i < _p->array.size(); i++) {
h = hash_murmur3_one_32(_p->array[i].recursive_hash(recursion_count), h);
}
return hash_fmix32(h);
}
void Array::operator=(const Array &p_array) {
if (this == &p_array) {
return;
}
_ref(p_array);
}
void Array::assign(const Array &p_array) {
const ContainerTypeValidate &typed = _p->typed;
const ContainerTypeValidate &source_typed = p_array._p->typed;
if (typed == source_typed || typed.type == Variant::NIL || (source_typed.type == Variant::OBJECT && typed.can_reference(source_typed))) {
// from same to same or
// from anything to variants or
// from subclasses to base classes
_p->array = p_array._p->array;
return;
}
const Variant *source = p_array._p->array.ptr();
int size = p_array._p->array.size();
if ((source_typed.type == Variant::NIL && typed.type == Variant::OBJECT) || (source_typed.type == Variant::OBJECT && source_typed.can_reference(typed))) {
// from variants to objects or
// from base classes to subclasses
for (int i = 0; i < size; i++) {
const Variant &element = source[i];
if (element.get_type() != Variant::NIL && (element.get_type() != Variant::OBJECT || !typed.validate_object(element, "assign"))) {
ERR_FAIL_MSG(vformat(R"(Unable to convert array index %d from "%s" to "%s".)", i, Variant::get_type_name(element.get_type()), Variant::get_type_name(typed.type)));
}
}
_p->array = p_array._p->array;
return;
}
if (typed.type == Variant::OBJECT || source_typed.type == Variant::OBJECT) {
ERR_FAIL_MSG(vformat(R"(Cannot assign contents of "Array[%s]" to "Array[%s]".)", Variant::get_type_name(source_typed.type), Variant::get_type_name(typed.type)));
}
Vector<Variant> array;
array.resize(size);
Variant *data = array.ptrw();
if (source_typed.type == Variant::NIL && typed.type != Variant::OBJECT) {
// from variants to primitives
for (int i = 0; i < size; i++) {
const Variant *value = source + i;
if (value->get_type() == typed.type) {
data[i] = *value;
continue;
}
if (!Variant::can_convert_strict(value->get_type(), typed.type)) {
ERR_FAIL_MSG(vformat(R"(Unable to convert array index %d from "%s" to "%s".)", i, Variant::get_type_name(value->get_type()), Variant::get_type_name(typed.type)));
}
Callable::CallError ce;
Variant::construct(typed.type, data[i], &value, 1, ce);
ERR_FAIL_COND_MSG(ce.error, vformat(R"(Unable to convert array index %d from "%s" to "%s".)", i, Variant::get_type_name(value->get_type()), Variant::get_type_name(typed.type)));
}
} else if (Variant::can_convert_strict(source_typed.type, typed.type)) {
// from primitives to different convertible primitives
for (int i = 0; i < size; i++) {
const Variant *value = source + i;
Callable::CallError ce;
Variant::construct(typed.type, data[i], &value, 1, ce);
ERR_FAIL_COND_MSG(ce.error, vformat(R"(Unable to convert array index %d from "%s" to "%s".)", i, Variant::get_type_name(value->get_type()), Variant::get_type_name(typed.type)));
}
} else {
ERR_FAIL_MSG(vformat(R"(Cannot assign contents of "Array[%s]" to "Array[%s]".)", Variant::get_type_name(source_typed.type), Variant::get_type_name(typed.type)));
}
_p->array = array;
}
void Array::push_back(const Variant &p_value) {
ERR_FAIL_COND_MSG(_p->read_only, "Array is in read-only state.");
Variant value = p_value;
ERR_FAIL_COND(!_p->typed.validate(value, "push_back"));
_p->array.push_back(value);
}
void Array::append_array(const Array &p_array) {
ERR_FAIL_COND_MSG(_p->read_only, "Array is in read-only state.");
Vector<Variant> validated_array = p_array._p->array;
for (int i = 0; i < validated_array.size(); ++i) {
ERR_FAIL_COND(!_p->typed.validate(validated_array.write[i], "append_array"));
}
_p->array.append_array(validated_array);
}
Error Array::resize(int p_new_size) {
ERR_FAIL_COND_V_MSG(_p->read_only, ERR_LOCKED, "Array is in read-only state.");
Variant::Type &variant_type = _p->typed.type;
int old_size = _p->array.size();
Error err = _p->array.resize_zeroed(p_new_size);
if (!err && variant_type != Variant::NIL && variant_type != Variant::OBJECT) {
for (int i = old_size; i < p_new_size; i++) {
VariantInternal::initialize(&_p->array.write[i], variant_type);
}
}
return err;
}
Error Array::insert(int p_pos, const Variant &p_value) {
ERR_FAIL_COND_V_MSG(_p->read_only, ERR_LOCKED, "Array is in read-only state.");
Variant value = p_value;
ERR_FAIL_COND_V(!_p->typed.validate(value, "insert"), ERR_INVALID_PARAMETER);
return _p->array.insert(p_pos, value);
}
void Array::fill(const Variant &p_value) {
ERR_FAIL_COND_MSG(_p->read_only, "Array is in read-only state.");
Variant value = p_value;
ERR_FAIL_COND(!_p->typed.validate(value, "fill"));
_p->array.fill(value);
}
void Array::erase(const Variant &p_value) {
ERR_FAIL_COND_MSG(_p->read_only, "Array is in read-only state.");
Variant value = p_value;
ERR_FAIL_COND(!_p->typed.validate(value, "erase"));
_p->array.erase(value);
}
Variant Array::front() const {
ERR_FAIL_COND_V_MSG(_p->array.is_empty(), Variant(), "Can't take value from empty array.");
return operator[](0);
}
Variant Array::back() const {
ERR_FAIL_COND_V_MSG(_p->array.is_empty(), Variant(), "Can't take value from empty array.");
return operator[](_p->array.size() - 1);
}
Variant Array::pick_random() const {
ERR_FAIL_COND_V_MSG(_p->array.is_empty(), Variant(), "Can't take value from empty array.");
return operator[](Math::rand() % _p->array.size());
}
int Array::find(const Variant &p_value, int p_from) const {
if (_p->array.size() == 0) {
return -1;
}
Variant value = p_value;
ERR_FAIL_COND_V(!_p->typed.validate(value, "find"), -1);
int ret = -1;
if (p_from < 0 || size() == 0) {
return ret;
}
for (int i = p_from; i < size(); i++) {
if (StringLikeVariantComparator::compare(_p->array[i], value)) {
ret = i;
break;
}
}
return ret;
}
int Array::rfind(const Variant &p_value, int p_from) const {
if (_p->array.size() == 0) {
return -1;
}
Variant value = p_value;
ERR_FAIL_COND_V(!_p->typed.validate(value, "rfind"), -1);
if (p_from < 0) {
// Relative offset from the end
p_from = _p->array.size() + p_from;
}
if (p_from < 0 || p_from >= _p->array.size()) {
// Limit to array boundaries
p_from = _p->array.size() - 1;
}
for (int i = p_from; i >= 0; i--) {
if (StringLikeVariantComparator::compare(_p->array[i], value)) {
return i;
}
}
return -1;
}
int Array::count(const Variant &p_value) const {
Variant value = p_value;
ERR_FAIL_COND_V(!_p->typed.validate(value, "count"), 0);
if (_p->array.size() == 0) {
return 0;
}
int amount = 0;
for (int i = 0; i < _p->array.size(); i++) {
if (StringLikeVariantComparator::compare(_p->array[i], value)) {
amount++;
}
}
return amount;
}
bool Array::has(const Variant &p_value) const {
Variant value = p_value;
ERR_FAIL_COND_V(!_p->typed.validate(value, "use 'has'"), false);
return find(value) != -1;
}
void Array::remove_at(int p_pos) {
ERR_FAIL_COND_MSG(_p->read_only, "Array is in read-only state.");
_p->array.remove_at(p_pos);
}
void Array::set(int p_idx, const Variant &p_value) {
ERR_FAIL_COND_MSG(_p->read_only, "Array is in read-only state.");
Variant value = p_value;
ERR_FAIL_COND(!_p->typed.validate(value, "set"));
operator[](p_idx) = value;
}
const Variant &Array::get(int p_idx) const {
return operator[](p_idx);
}
Array Array::duplicate(bool p_deep) const {
return recursive_duplicate(p_deep, 0);
}
Array Array::recursive_duplicate(bool p_deep, int recursion_count) const {
Array new_arr;
new_arr._p->typed = _p->typed;
if (recursion_count > MAX_RECURSION) {
ERR_PRINT("Max recursion reached");
return new_arr;
}
if (p_deep) {
recursion_count++;
int element_count = size();
new_arr.resize(element_count);
for (int i = 0; i < element_count; i++) {
new_arr[i] = get(i).recursive_duplicate(true, recursion_count);
}
} else {
new_arr._p->array = _p->array;
}
return new_arr;
}
Array Array::slice(int p_begin, int p_end, int p_step, bool p_deep) const {
Array result;
result._p->typed = _p->typed;
ERR_FAIL_COND_V_MSG(p_step == 0, result, "Slice step cannot be zero.");
const int s = size();
if (s == 0 || (p_begin < -s && p_step < 0) || (p_begin >= s && p_step > 0)) {
return result;
}
int begin = CLAMP(p_begin, -s, s - 1);
if (begin < 0) {
begin += s;
}
int end = CLAMP(p_end, -s - 1, s);
if (end < 0) {
end += s;
}
ERR_FAIL_COND_V_MSG(p_step > 0 && begin > end, result, "Slice step is positive, but bounds are decreasing.");
ERR_FAIL_COND_V_MSG(p_step < 0 && begin < end, result, "Slice step is negative, but bounds are increasing.");
int result_size = (end - begin) / p_step + (((end - begin) % p_step != 0) ? 1 : 0);
result.resize(result_size);
for (int src_idx = begin, dest_idx = 0; dest_idx < result_size; ++dest_idx) {
result[dest_idx] = p_deep ? get(src_idx).duplicate(true) : get(src_idx);
src_idx += p_step;
}
return result;
}
Array Array::filter(const Callable &p_callable) const {
Array new_arr;
new_arr.resize(size());
new_arr._p->typed = _p->typed;
int accepted_count = 0;
const Variant *argptrs[1];
for (int i = 0; i < size(); i++) {
argptrs[0] = &get(i);
Variant result;
Callable::CallError ce;
p_callable.callp(argptrs, 1, result, ce);
if (ce.error != Callable::CallError::CALL_OK) {
ERR_FAIL_V_MSG(Array(), "Error calling method from 'filter': " + Variant::get_callable_error_text(p_callable, argptrs, 1, ce));
}
if (result.operator bool()) {
new_arr[accepted_count] = get(i);
accepted_count++;
}
}
new_arr.resize(accepted_count);
return new_arr;
}
Array Array::map(const Callable &p_callable) const {
Array new_arr;
new_arr.resize(size());
const Variant *argptrs[1];
for (int i = 0; i < size(); i++) {
argptrs[0] = &get(i);
Variant result;
Callable::CallError ce;
p_callable.callp(argptrs, 1, result, ce);
if (ce.error != Callable::CallError::CALL_OK) {
ERR_FAIL_V_MSG(Array(), "Error calling method from 'map': " + Variant::get_callable_error_text(p_callable, argptrs, 1, ce));
}
new_arr[i] = result;
}
return new_arr;
}
Variant Array::reduce(const Callable &p_callable, const Variant &p_accum) const {
int start = 0;
Variant ret = p_accum;
if (ret == Variant() && size() > 0) {
ret = front();
start = 1;
}
const Variant *argptrs[2];
for (int i = start; i < size(); i++) {
argptrs[0] = &ret;
argptrs[1] = &get(i);
Variant result;
Callable::CallError ce;
p_callable.callp(argptrs, 2, result, ce);
if (ce.error != Callable::CallError::CALL_OK) {
ERR_FAIL_V_MSG(Variant(), "Error calling method from 'reduce': " + Variant::get_callable_error_text(p_callable, argptrs, 2, ce));
}
ret = result;
}
return ret;
}
bool Array::any(const Callable &p_callable) const {
const Variant *argptrs[1];
for (int i = 0; i < size(); i++) {
argptrs[0] = &get(i);
Variant result;
Callable::CallError ce;
p_callable.callp(argptrs, 1, result, ce);
if (ce.error != Callable::CallError::CALL_OK) {
ERR_FAIL_V_MSG(false, "Error calling method from 'any': " + Variant::get_callable_error_text(p_callable, argptrs, 1, ce));
}
if (result.operator bool()) {
// Return as early as possible when one of the conditions is `true`.
// This improves performance compared to relying on `filter(...).size() >= 1`.
return true;
}
}
return false;
}
bool Array::all(const Callable &p_callable) const {
const Variant *argptrs[1];
for (int i = 0; i < size(); i++) {
argptrs[0] = &get(i);
Variant result;
Callable::CallError ce;
p_callable.callp(argptrs, 1, result, ce);
if (ce.error != Callable::CallError::CALL_OK) {
ERR_FAIL_V_MSG(false, "Error calling method from 'all': " + Variant::get_callable_error_text(p_callable, argptrs, 1, ce));
}
if (!(result.operator bool())) {
// Return as early as possible when one of the inverted conditions is `false`.
// This improves performance compared to relying on `filter(...).size() >= array_size().`.
return false;
}
}
return true;
}
struct _ArrayVariantSort {
_FORCE_INLINE_ bool operator()(const Variant &p_l, const Variant &p_r) const {
bool valid = false;
Variant res;
Variant::evaluate(Variant::OP_LESS, p_l, p_r, res, valid);
if (!valid) {
res = false;
}
return res;
}
};
void Array::sort() {
ERR_FAIL_COND_MSG(_p->read_only, "Array is in read-only state.");
_p->array.sort_custom<_ArrayVariantSort>();
}
void Array::sort_custom(const Callable &p_callable) {
ERR_FAIL_COND_MSG(_p->read_only, "Array is in read-only state.");
_p->array.sort_custom<CallableComparator, true>(p_callable);
}
void Array::shuffle() {
ERR_FAIL_COND_MSG(_p->read_only, "Array is in read-only state.");
const int n = _p->array.size();
if (n < 2) {
return;
}
Variant *data = _p->array.ptrw();
for (int i = n - 1; i >= 1; i--) {
const int j = Math::rand() % (i + 1);
const Variant tmp = data[j];
data[j] = data[i];
data[i] = tmp;
}
}
int Array::bsearch(const Variant &p_value, bool p_before) const {
Variant value = p_value;
ERR_FAIL_COND_V(!_p->typed.validate(value, "binary search"), -1);
SearchArray<Variant, _ArrayVariantSort> avs;
return avs.bisect(_p->array.ptrw(), _p->array.size(), value, p_before);
}
int Array::bsearch_custom(const Variant &p_value, const Callable &p_callable, bool p_before) const {
Variant value = p_value;
ERR_FAIL_COND_V(!_p->typed.validate(value, "custom binary search"), -1);
return _p->array.bsearch_custom<CallableComparator>(value, p_before, p_callable);
}
void Array::reverse() {
ERR_FAIL_COND_MSG(_p->read_only, "Array is in read-only state.");
_p->array.reverse();
}
void Array::push_front(const Variant &p_value) {
ERR_FAIL_COND_MSG(_p->read_only, "Array is in read-only state.");
Variant value = p_value;
ERR_FAIL_COND(!_p->typed.validate(value, "push_front"));
_p->array.insert(0, value);
}
Variant Array::pop_back() {
ERR_FAIL_COND_V_MSG(_p->read_only, Variant(), "Array is in read-only state.");
if (!_p->array.is_empty()) {
const int n = _p->array.size() - 1;
const Variant ret = _p->array.get(n);
_p->array.resize(n);
return ret;
}
return Variant();
}
Variant Array::pop_front() {
ERR_FAIL_COND_V_MSG(_p->read_only, Variant(), "Array is in read-only state.");
if (!_p->array.is_empty()) {
const Variant ret = _p->array.get(0);
_p->array.remove_at(0);
return ret;
}
return Variant();
}
Variant Array::pop_at(int p_pos) {
ERR_FAIL_COND_V_MSG(_p->read_only, Variant(), "Array is in read-only state.");
if (_p->array.is_empty()) {
// Return `null` without printing an error to mimic `pop_back()` and `pop_front()` behavior.
return Variant();
}
if (p_pos < 0) {
// Relative offset from the end
p_pos = _p->array.size() + p_pos;
}
ERR_FAIL_INDEX_V_MSG(
p_pos,
_p->array.size(),
Variant(),
vformat(
"The calculated index %s is out of bounds (the array has %s elements). Leaving the array untouched and returning `null`.",
p_pos,
_p->array.size()));
const Variant ret = _p->array.get(p_pos);
_p->array.remove_at(p_pos);
return ret;
}
Variant Array::min() const {
Variant minval;
for (int i = 0; i < size(); i++) {
if (i == 0) {
minval = get(i);
} else {
bool valid;
Variant ret;
Variant test = get(i);
Variant::evaluate(Variant::OP_LESS, test, minval, ret, valid);
if (!valid) {
return Variant(); //not a valid comparison
}
if (bool(ret)) {
//is less
minval = test;
}
}
}
return minval;
}
Variant Array::max() const {
Variant maxval;
for (int i = 0; i < size(); i++) {
if (i == 0) {
maxval = get(i);
} else {
bool valid;
Variant ret;
Variant test = get(i);
Variant::evaluate(Variant::OP_GREATER, test, maxval, ret, valid);
if (!valid) {
return Variant(); //not a valid comparison
}
if (bool(ret)) {
//is less
maxval = test;
}
}
}
return maxval;
}
const void *Array::id() const {
return _p;
}
Array::Array(const Array &p_from, uint32_t p_type, const StringName &p_class_name, const Variant &p_script) {
_p = memnew(ArrayPrivate);
_p->refcount.init();
set_typed(p_type, p_class_name, p_script);
assign(p_from);
}
void Array::set_typed(uint32_t p_type, const StringName &p_class_name, const Variant &p_script) {
ERR_FAIL_COND_MSG(_p->read_only, "Array is in read-only state.");
ERR_FAIL_COND_MSG(_p->array.size() > 0, "Type can only be set when array is empty.");
ERR_FAIL_COND_MSG(_p->refcount.get() > 1, "Type can only be set when array has no more than one user.");
ERR_FAIL_COND_MSG(_p->typed.type != Variant::NIL, "Type can only be set once.");
ERR_FAIL_COND_MSG(p_class_name != StringName() && p_type != Variant::OBJECT, "Class names can only be set for type OBJECT");
Ref<Script> script = p_script;
ERR_FAIL_COND_MSG(script.is_valid() && p_class_name == StringName(), "Script class can only be set together with base class name");
_p->typed.type = Variant::Type(p_type);
_p->typed.class_name = p_class_name;
_p->typed.script = script;
_p->typed.where = "TypedArray";
}
bool Array::is_typed() const {
return _p->typed.type != Variant::NIL;
}
bool Array::is_same_typed(const Array &p_other) const {
return _p->typed == p_other._p->typed;
}
uint32_t Array::get_typed_builtin() const {
return _p->typed.type;
}
StringName Array::get_typed_class_name() const {
return _p->typed.class_name;
}
Variant Array::get_typed_script() const {
return _p->typed.script;
}
void Array::make_read_only() {
if (_p->read_only == nullptr) {
_p->read_only = memnew(Variant);
}
}
bool Array::is_read_only() const {
return _p->read_only != nullptr;
}
Array::Array(const Array &p_from) {
_p = nullptr;
_ref(p_from);
}
Array::Array() {
_p = memnew(ArrayPrivate);
_p->refcount.init();
}
Array::~Array() {
_unref();
}

202
engine/core/variant/array.h Normal file
View file

@ -0,0 +1,202 @@
/**************************************************************************/
/* array.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 ARRAY_H
#define ARRAY_H
#include "core/typedefs.h"
#include <climits>
class Variant;
class ArrayPrivate;
class Object;
class StringName;
class Callable;
class Array {
mutable ArrayPrivate *_p;
void _unref() const;
public:
struct ConstIterator {
_FORCE_INLINE_ const Variant &operator*() const;
_FORCE_INLINE_ const Variant *operator->() const;
_FORCE_INLINE_ ConstIterator &operator++();
_FORCE_INLINE_ ConstIterator &operator--();
_FORCE_INLINE_ bool operator==(const ConstIterator &p_other) const { return element_ptr == p_other.element_ptr; }
_FORCE_INLINE_ bool operator!=(const ConstIterator &p_other) const { return element_ptr != p_other.element_ptr; }
_FORCE_INLINE_ ConstIterator(const Variant *p_element_ptr, Variant *p_read_only = nullptr) :
element_ptr(p_element_ptr), read_only(p_read_only) {}
_FORCE_INLINE_ ConstIterator() {}
_FORCE_INLINE_ ConstIterator(const ConstIterator &p_other) :
element_ptr(p_other.element_ptr), read_only(p_other.read_only) {}
_FORCE_INLINE_ ConstIterator &operator=(const ConstIterator &p_other) {
element_ptr = p_other.element_ptr;
read_only = p_other.read_only;
return *this;
}
private:
const Variant *element_ptr = nullptr;
Variant *read_only = nullptr;
};
struct Iterator {
_FORCE_INLINE_ Variant &operator*() const;
_FORCE_INLINE_ Variant *operator->() const;
_FORCE_INLINE_ Iterator &operator++();
_FORCE_INLINE_ Iterator &operator--();
_FORCE_INLINE_ bool operator==(const Iterator &p_other) const { return element_ptr == p_other.element_ptr; }
_FORCE_INLINE_ bool operator!=(const Iterator &p_other) const { return element_ptr != p_other.element_ptr; }
_FORCE_INLINE_ Iterator(Variant *p_element_ptr, Variant *p_read_only = nullptr) :
element_ptr(p_element_ptr), read_only(p_read_only) {}
_FORCE_INLINE_ Iterator() {}
_FORCE_INLINE_ Iterator(const Iterator &p_other) :
element_ptr(p_other.element_ptr), read_only(p_other.read_only) {}
_FORCE_INLINE_ Iterator &operator=(const Iterator &p_other) {
element_ptr = p_other.element_ptr;
read_only = p_other.read_only;
return *this;
}
operator ConstIterator() const {
return ConstIterator(element_ptr, read_only);
}
private:
Variant *element_ptr = nullptr;
Variant *read_only = nullptr;
};
Iterator begin();
Iterator end();
ConstIterator begin() const;
ConstIterator end() const;
void _ref(const Array &p_from) const;
Variant &operator[](int p_idx);
const Variant &operator[](int p_idx) const;
void set(int p_idx, const Variant &p_value);
const Variant &get(int p_idx) const;
int size() const;
bool is_empty() const;
void clear();
bool operator==(const Array &p_array) const;
bool operator!=(const Array &p_array) const;
bool recursive_equal(const Array &p_array, int recursion_count) const;
uint32_t hash() const;
uint32_t recursive_hash(int recursion_count) const;
void operator=(const Array &p_array);
void assign(const Array &p_array);
void push_back(const Variant &p_value);
_FORCE_INLINE_ void append(const Variant &p_value) { push_back(p_value); } //for python compatibility
void append_array(const Array &p_array);
Error resize(int p_new_size);
Error insert(int p_pos, const Variant &p_value);
void remove_at(int p_pos);
void fill(const Variant &p_value);
Variant front() const;
Variant back() const;
Variant pick_random() const;
void sort();
void sort_custom(const Callable &p_callable);
void shuffle();
int bsearch(const Variant &p_value, bool p_before = true) const;
int bsearch_custom(const Variant &p_value, const Callable &p_callable, bool p_before = true) const;
void reverse();
int find(const Variant &p_value, int p_from = 0) const;
int rfind(const Variant &p_value, int p_from = -1) const;
int count(const Variant &p_value) const;
bool has(const Variant &p_value) const;
void erase(const Variant &p_value);
void push_front(const Variant &p_value);
Variant pop_back();
Variant pop_front();
Variant pop_at(int p_pos);
Array duplicate(bool p_deep = false) const;
Array recursive_duplicate(bool p_deep, int recursion_count) const;
Array slice(int p_begin, int p_end = INT_MAX, int p_step = 1, bool p_deep = false) const;
Array filter(const Callable &p_callable) const;
Array map(const Callable &p_callable) const;
Variant reduce(const Callable &p_callable, const Variant &p_accum) const;
bool any(const Callable &p_callable) const;
bool all(const Callable &p_callable) const;
bool operator<(const Array &p_array) const;
bool operator<=(const Array &p_array) const;
bool operator>(const Array &p_array) const;
bool operator>=(const Array &p_array) const;
Variant min() const;
Variant max() const;
const void *id() const;
void set_typed(uint32_t p_type, const StringName &p_class_name, const Variant &p_script);
bool is_typed() const;
bool is_same_typed(const Array &p_other) const;
uint32_t get_typed_builtin() const;
StringName get_typed_class_name() const;
Variant get_typed_script() const;
void make_read_only();
bool is_read_only() const;
Array(const Array &p_base, uint32_t p_type, const StringName &p_class_name, const Variant &p_script);
Array(const Array &p_from);
Array();
~Array();
};
#endif // ARRAY_H

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,584 @@
/**************************************************************************/
/* 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 "callable.h"
#include "core/object/object.h"
#include "core/object/ref_counted.h"
#include "core/object/script_language.h"
#include "core/variant/callable_bind.h"
#include "core/variant/variant_callable.h"
void Callable::call_deferredp(const Variant **p_arguments, int p_argcount) const {
MessageQueue::get_singleton()->push_callablep(*this, p_arguments, p_argcount, true);
}
void Callable::callp(const Variant **p_arguments, int p_argcount, Variant &r_return_value, CallError &r_call_error) const {
if (is_null()) {
r_call_error.error = CallError::CALL_ERROR_INSTANCE_IS_NULL;
r_call_error.argument = 0;
r_call_error.expected = 0;
r_return_value = Variant();
} else if (is_custom()) {
if (!is_valid()) {
r_call_error.error = CallError::CALL_ERROR_INSTANCE_IS_NULL;
r_call_error.argument = 0;
r_call_error.expected = 0;
r_return_value = Variant();
return;
}
custom->call(p_arguments, p_argcount, r_return_value, r_call_error);
} else {
Object *obj = ObjectDB::get_instance(ObjectID(object));
#ifdef DEBUG_ENABLED
if (!obj) {
r_call_error.error = CallError::CALL_ERROR_INSTANCE_IS_NULL;
r_call_error.argument = 0;
r_call_error.expected = 0;
r_return_value = Variant();
return;
}
#endif
r_return_value = obj->callp(method, p_arguments, p_argcount, r_call_error);
}
}
Variant Callable::callv(const Array &p_arguments) const {
int argcount = p_arguments.size();
const Variant **argptrs = nullptr;
if (argcount) {
argptrs = (const Variant **)alloca(sizeof(Variant *) * argcount);
for (int i = 0; i < argcount; i++) {
argptrs[i] = &p_arguments[i];
}
}
CallError ce;
Variant ret;
callp(argptrs, argcount, ret, ce);
return ret;
}
Error Callable::rpcp(int p_id, const Variant **p_arguments, int p_argcount, CallError &r_call_error) const {
if (is_null()) {
r_call_error.error = CallError::CALL_ERROR_INSTANCE_IS_NULL;
r_call_error.argument = 0;
r_call_error.expected = 0;
return ERR_UNCONFIGURED;
} else if (!is_custom()) {
Object *obj = ObjectDB::get_instance(ObjectID(object));
#ifdef DEBUG_ENABLED
if (!obj || !obj->is_class("Node")) {
r_call_error.error = CallError::CALL_ERROR_INSTANCE_IS_NULL;
r_call_error.argument = 0;
r_call_error.expected = 0;
return ERR_UNCONFIGURED;
}
#endif
int argcount = p_argcount + 2;
const Variant **argptrs = (const Variant **)alloca(sizeof(Variant *) * argcount);
const Variant args[2] = { p_id, method };
argptrs[0] = &args[0];
argptrs[1] = &args[1];
for (int i = 0; i < p_argcount; ++i) {
argptrs[i + 2] = p_arguments[i];
}
CallError tmp;
Error err = (Error)obj->callp(SNAME("rpc_id"), argptrs, argcount, tmp).operator int64_t();
r_call_error.error = Callable::CallError::CALL_OK;
return err;
} else {
return custom->rpc(p_id, p_arguments, p_argcount, r_call_error);
}
}
Callable Callable::bindp(const Variant **p_arguments, int p_argcount) const {
Vector<Variant> args;
args.resize(p_argcount);
for (int i = 0; i < p_argcount; i++) {
args.write[i] = *p_arguments[i];
}
return Callable(memnew(CallableCustomBind(*this, args)));
}
Callable Callable::bindv(const Array &p_arguments) {
if (p_arguments.is_empty()) {
return *this; // No point in creating a new callable if nothing is bound.
}
Vector<Variant> args;
args.resize(p_arguments.size());
for (int i = 0; i < p_arguments.size(); i++) {
args.write[i] = p_arguments[i];
}
return Callable(memnew(CallableCustomBind(*this, args)));
}
Callable Callable::unbind(int p_argcount) const {
ERR_FAIL_COND_V_MSG(p_argcount <= 0, Callable(*this), "Amount of unbind() arguments must be 1 or greater.");
return Callable(memnew(CallableCustomUnbind(*this, p_argcount)));
}
bool Callable::is_valid() const {
if (is_custom()) {
return get_custom()->is_valid();
} else {
return get_object() && get_object()->has_method(get_method());
}
}
Object *Callable::get_object() const {
if (is_null()) {
return nullptr;
} else if (is_custom()) {
return ObjectDB::get_instance(custom->get_object());
} else {
return ObjectDB::get_instance(ObjectID(object));
}
}
ObjectID Callable::get_object_id() const {
if (is_null()) {
return ObjectID();
} else if (is_custom()) {
return custom->get_object();
} else {
return ObjectID(object);
}
}
StringName Callable::get_method() const {
if (is_custom()) {
return get_custom()->get_method();
}
return method;
}
int Callable::get_argument_count(bool *r_is_valid) const {
if (is_custom()) {
bool valid = false;
return custom->get_argument_count(r_is_valid ? *r_is_valid : valid);
} else if (!is_null()) {
return get_object()->get_method_argument_count(method, r_is_valid);
} else {
if (r_is_valid) {
*r_is_valid = false;
}
return 0;
}
}
int Callable::get_bound_arguments_count() const {
if (!is_null() && is_custom()) {
return custom->get_bound_arguments_count();
} else {
return 0;
}
}
void Callable::get_bound_arguments_ref(Vector<Variant> &r_arguments, int &r_argcount) const {
if (!is_null() && is_custom()) {
custom->get_bound_arguments(r_arguments, r_argcount);
} else {
r_arguments.clear();
r_argcount = 0;
}
}
Array Callable::get_bound_arguments() const {
Vector<Variant> arr;
int ac;
get_bound_arguments_ref(arr, ac);
Array ret;
ret.resize(arr.size());
for (int i = 0; i < arr.size(); i++) {
ret[i] = arr[i];
}
return ret;
}
CallableCustom *Callable::get_custom() const {
ERR_FAIL_COND_V_MSG(!is_custom(), nullptr,
vformat("Can't get custom on non-CallableCustom \"%s\".", operator String()));
return custom;
}
const Callable *Callable::get_base_comparator() const {
const Callable *comparator = nullptr;
if (is_custom()) {
comparator = custom->get_base_comparator();
}
if (comparator) {
return comparator;
} else {
return this;
}
}
uint32_t Callable::hash() const {
if (is_custom()) {
return custom->hash();
} else {
uint32_t hash = method.hash();
hash = hash_murmur3_one_64(object, hash);
return hash_fmix32(hash);
}
}
bool Callable::operator==(const Callable &p_callable) const {
bool custom_a = is_custom();
bool custom_b = p_callable.is_custom();
if (custom_a == custom_b) {
if (custom_a) {
if (custom == p_callable.custom) {
return true; //same pointer, don't even compare
}
CallableCustom::CompareEqualFunc eq_a = custom->get_compare_equal_func();
CallableCustom::CompareEqualFunc eq_b = p_callable.custom->get_compare_equal_func();
if (eq_a == eq_b) {
return eq_a(custom, p_callable.custom);
} else {
return false;
}
} else {
return object == p_callable.object && method == p_callable.method;
}
} else {
return false;
}
}
bool Callable::operator!=(const Callable &p_callable) const {
return !(*this == p_callable);
}
bool Callable::operator<(const Callable &p_callable) const {
bool custom_a = is_custom();
bool custom_b = p_callable.is_custom();
if (custom_a == custom_b) {
if (custom_a) {
if (custom == p_callable.custom) {
return false; //same pointer, don't even compare
}
CallableCustom::CompareLessFunc less_a = custom->get_compare_less_func();
CallableCustom::CompareLessFunc less_b = p_callable.custom->get_compare_less_func();
if (less_a == less_b) {
return less_a(custom, p_callable.custom);
} else {
return less_a < less_b; //it's something..
}
} else {
if (object == p_callable.object) {
return method < p_callable.method;
} else {
return object < p_callable.object;
}
}
} else {
return int(custom_a ? 1 : 0) < int(custom_b ? 1 : 0);
}
}
void Callable::operator=(const Callable &p_callable) {
if (is_custom()) {
if (p_callable.is_custom()) {
if (custom == p_callable.custom) {
return;
}
}
if (custom->ref_count.unref()) {
memdelete(custom);
custom = nullptr;
}
}
if (p_callable.is_custom()) {
method = StringName();
if (!p_callable.custom->ref_count.ref()) {
object = 0;
} else {
object = 0;
custom = p_callable.custom;
}
} else {
method = p_callable.method;
object = p_callable.object;
}
}
Callable::operator String() const {
if (is_custom()) {
return custom->get_as_text();
} else {
if (is_null()) {
return "null::null";
}
Object *base = get_object();
if (base) {
String class_name = base->get_class();
Ref<Script> script = base->get_script();
if (script.is_valid() && script->get_path().is_resource_file()) {
class_name += "(" + script->get_path().get_file() + ")";
}
return class_name + "::" + String(method);
} else {
return "null::" + String(method);
}
}
}
Callable Callable::create(const Variant &p_variant, const StringName &p_method) {
ERR_FAIL_COND_V_MSG(p_method == StringName(), Callable(), "Method argument to Callable::create method must be a non-empty string.");
switch (p_variant.get_type()) {
case Variant::NIL:
return Callable(ObjectID(), p_method);
case Variant::OBJECT:
return Callable(p_variant.operator ObjectID(), p_method);
default:
return Callable(memnew(VariantCallable(p_variant, p_method)));
}
}
Callable::Callable(const Object *p_object, const StringName &p_method) {
if (unlikely(p_method == StringName())) {
object = 0;
ERR_FAIL_MSG("Method argument to Callable constructor must be a non-empty string.");
}
if (unlikely(p_object == nullptr)) {
object = 0;
ERR_FAIL_MSG("Object argument to Callable constructor must be non-null.");
}
object = p_object->get_instance_id();
method = p_method;
}
Callable::Callable(ObjectID p_object, const StringName &p_method) {
if (unlikely(p_method == StringName())) {
object = 0;
ERR_FAIL_MSG("Method argument to Callable constructor must be a non-empty string.");
}
object = p_object;
method = p_method;
}
Callable::Callable(CallableCustom *p_custom) {
if (unlikely(p_custom->referenced)) {
object = 0;
ERR_FAIL_MSG("Callable custom is already referenced.");
}
p_custom->referenced = true;
object = 0; //ensure object is all zero, since pointer may be 32 bits
custom = p_custom;
}
Callable::Callable(const Callable &p_callable) {
if (p_callable.is_custom()) {
if (!p_callable.custom->ref_count.ref()) {
object = 0;
} else {
object = 0;
custom = p_callable.custom;
}
} else {
method = p_callable.method;
object = p_callable.object;
}
}
Callable::~Callable() {
if (is_custom()) {
if (custom->ref_count.unref()) {
memdelete(custom);
custom = nullptr;
}
}
}
bool CallableCustom::is_valid() const {
// Sensible default implementation so most custom callables don't need their own.
return ObjectDB::get_instance(get_object());
}
StringName CallableCustom::get_method() const {
ERR_FAIL_V_MSG(StringName(), vformat("Can't get method on CallableCustom \"%s\".", get_as_text()));
}
Error CallableCustom::rpc(int p_peer_id, const Variant **p_arguments, int p_argcount, Callable::CallError &r_call_error) const {
r_call_error.error = Callable::CallError::CALL_ERROR_INVALID_METHOD;
r_call_error.argument = 0;
r_call_error.expected = 0;
return ERR_UNCONFIGURED;
}
const Callable *CallableCustom::get_base_comparator() const {
return nullptr;
}
int CallableCustom::get_argument_count(bool &r_is_valid) const {
r_is_valid = false;
return 0;
}
int CallableCustom::get_bound_arguments_count() const {
return 0;
}
void CallableCustom::get_bound_arguments(Vector<Variant> &r_arguments, int &r_argcount) const {
r_arguments = Vector<Variant>();
r_argcount = 0;
}
CallableCustom::CallableCustom() {
ref_count.init();
}
//////////////////////////////////
Object *Signal::get_object() const {
return ObjectDB::get_instance(object);
}
ObjectID Signal::get_object_id() const {
return object;
}
StringName Signal::get_name() const {
return name;
}
bool Signal::operator==(const Signal &p_signal) const {
return object == p_signal.object && name == p_signal.name;
}
bool Signal::operator!=(const Signal &p_signal) const {
return object != p_signal.object || name != p_signal.name;
}
bool Signal::operator<(const Signal &p_signal) const {
if (object == p_signal.object) {
return name < p_signal.name;
} else {
return object < p_signal.object;
}
}
Signal::operator String() const {
Object *base = get_object();
if (base) {
String class_name = base->get_class();
Ref<Script> script = base->get_script();
if (script.is_valid() && script->get_path().is_resource_file()) {
class_name += "(" + script->get_path().get_file() + ")";
}
return class_name + "::[signal]" + String(name);
} else {
return "null::[signal]" + String(name);
}
}
Error Signal::emit(const Variant **p_arguments, int p_argcount) const {
Object *obj = ObjectDB::get_instance(object);
if (!obj) {
return ERR_INVALID_DATA;
}
return obj->emit_signalp(name, p_arguments, p_argcount);
}
Error Signal::connect(const Callable &p_callable, uint32_t p_flags) {
Object *obj = get_object();
ERR_FAIL_NULL_V(obj, ERR_UNCONFIGURED);
return obj->connect(name, p_callable, p_flags);
}
void Signal::disconnect(const Callable &p_callable) {
Object *obj = get_object();
ERR_FAIL_NULL(obj);
obj->disconnect(name, p_callable);
}
bool Signal::is_connected(const Callable &p_callable) const {
Object *obj = get_object();
ERR_FAIL_NULL_V(obj, false);
return obj->is_connected(name, p_callable);
}
Array Signal::get_connections() const {
Object *obj = get_object();
if (!obj) {
return Array();
}
List<Object::Connection> connections;
obj->get_signal_connection_list(name, &connections);
Array arr;
for (const Object::Connection &E : connections) {
arr.push_back(E);
}
return arr;
}
Signal::Signal(const Object *p_object, const StringName &p_name) {
ERR_FAIL_NULL_MSG(p_object, "Object argument to Signal constructor must be non-null.");
object = p_object->get_instance_id();
name = p_name;
}
Signal::Signal(ObjectID p_object, const StringName &p_name) {
object = p_object;
name = p_name;
}
bool CallableComparator::operator()(const Variant &p_l, const Variant &p_r) const {
const Variant *args[2] = { &p_l, &p_r };
Callable::CallError err;
Variant res;
func.callp(args, 2, res, err);
ERR_FAIL_COND_V_MSG(err.error != Callable::CallError::CALL_OK, false,
"Error calling compare method: " + Variant::get_callable_error_text(func, args, 2, err));
return res;
}

View file

@ -0,0 +1,208 @@
/**************************************************************************/
/* 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 CALLABLE_H
#define CALLABLE_H
#include "core/object/object_id.h"
#include "core/string/string_name.h"
#include "core/templates/list.h"
class Object;
class Variant;
class CallableCustom;
// This is an abstraction of things that can be called.
// It is used for signals and other cases where efficient calling of functions
// is required. It is designed for the standard case (object and method)
// but can be optimized or customized.
// Enforce 16 bytes with `alignas` to avoid arch-specific alignment issues on x86 vs armv7.
class Callable {
alignas(8) StringName method;
union {
uint64_t object = 0;
CallableCustom *custom;
};
public:
struct CallError {
enum Error {
CALL_OK,
CALL_ERROR_INVALID_METHOD,
CALL_ERROR_INVALID_ARGUMENT, // expected is variant type
CALL_ERROR_TOO_MANY_ARGUMENTS, // expected is number of arguments
CALL_ERROR_TOO_FEW_ARGUMENTS, // expected is number of arguments
CALL_ERROR_INSTANCE_IS_NULL,
CALL_ERROR_METHOD_NOT_CONST,
};
Error error = Error::CALL_OK;
int argument = 0;
int expected = 0;
};
template <typename... VarArgs>
Variant call(VarArgs... p_args) const;
void callp(const Variant **p_arguments, int p_argcount, Variant &r_return_value, CallError &r_call_error) const;
void call_deferredp(const Variant **p_arguments, int p_argcount) const;
Variant callv(const Array &p_arguments) const;
template <typename... VarArgs>
void call_deferred(VarArgs... p_args) const {
Variant args[sizeof...(p_args) + 1] = { p_args..., 0 }; // +1 makes sure zero sized arrays are also supported.
const Variant *argptrs[sizeof...(p_args) + 1];
for (uint32_t i = 0; i < sizeof...(p_args); i++) {
argptrs[i] = &args[i];
}
return call_deferredp(sizeof...(p_args) == 0 ? nullptr : (const Variant **)argptrs, sizeof...(p_args));
}
Error rpcp(int p_id, const Variant **p_arguments, int p_argcount, CallError &r_call_error) const;
_FORCE_INLINE_ bool is_null() const {
return method == StringName() && object == 0;
}
_FORCE_INLINE_ bool is_custom() const {
return method == StringName() && custom != nullptr;
}
_FORCE_INLINE_ bool is_standard() const {
return method != StringName();
}
bool is_valid() const;
template <typename... VarArgs>
Callable bind(VarArgs... p_args) const;
Callable bindv(const Array &p_arguments);
Callable bindp(const Variant **p_arguments, int p_argcount) const;
Callable unbind(int p_argcount) const;
Object *get_object() const;
ObjectID get_object_id() const;
StringName get_method() const;
CallableCustom *get_custom() const;
int get_argument_count(bool *r_is_valid = nullptr) const;
int get_bound_arguments_count() const;
void get_bound_arguments_ref(Vector<Variant> &r_arguments, int &r_argcount) const; // Internal engine use, the exposed one is below.
Array get_bound_arguments() const;
uint32_t hash() const;
const Callable *get_base_comparator() const; //used for bind/unbind to do less precise comparisons (ignoring binds) in signal connect/disconnect
bool operator==(const Callable &p_callable) const;
bool operator!=(const Callable &p_callable) const;
bool operator<(const Callable &p_callable) const;
void operator=(const Callable &p_callable);
operator String() const;
static Callable create(const Variant &p_variant, const StringName &p_method);
Callable(const Object *p_object, const StringName &p_method);
Callable(ObjectID p_object, const StringName &p_method);
Callable(CallableCustom *p_custom);
Callable(const Callable &p_callable);
Callable() {}
~Callable();
};
class CallableCustom {
friend class Callable;
SafeRefCount ref_count;
bool referenced = false;
public:
typedef bool (*CompareEqualFunc)(const CallableCustom *p_a, const CallableCustom *p_b);
typedef bool (*CompareLessFunc)(const CallableCustom *p_a, const CallableCustom *p_b);
//for every type that inherits, these must always be the same for this type
virtual uint32_t hash() const = 0;
virtual String get_as_text() const = 0;
virtual CompareEqualFunc get_compare_equal_func() const = 0;
virtual CompareLessFunc get_compare_less_func() const = 0;
virtual bool is_valid() const;
virtual StringName get_method() const;
virtual ObjectID get_object() const = 0;
virtual void call(const Variant **p_arguments, int p_argcount, Variant &r_return_value, Callable::CallError &r_call_error) const = 0;
virtual Error rpc(int p_peer_id, const Variant **p_arguments, int p_argcount, Callable::CallError &r_call_error) const;
virtual const Callable *get_base_comparator() const;
virtual int get_argument_count(bool &r_is_valid) const;
virtual int get_bound_arguments_count() const;
virtual void get_bound_arguments(Vector<Variant> &r_arguments, int &r_argcount) const;
CallableCustom();
virtual ~CallableCustom() {}
};
// This is just a proxy object to object signals, its only
// allocated on demand by/for scripting languages so it can
// be put inside a Variant, but it is not
// used by the engine itself.
// Enforce 16 bytes with `alignas` to avoid arch-specific alignment issues on x86 vs armv7.
class Signal {
alignas(8) StringName name;
ObjectID object;
public:
_FORCE_INLINE_ bool is_null() const {
return object.is_null() && name == StringName();
}
Object *get_object() const;
ObjectID get_object_id() const;
StringName get_name() const;
bool operator==(const Signal &p_signal) const;
bool operator!=(const Signal &p_signal) const;
bool operator<(const Signal &p_signal) const;
operator String() const;
Error emit(const Variant **p_arguments, int p_argcount) const;
Error connect(const Callable &p_callable, uint32_t p_flags = 0);
void disconnect(const Callable &p_callable);
bool is_connected(const Callable &p_callable) const;
Array get_connections() const;
Signal(const Object *p_object, const StringName &p_name);
Signal(ObjectID p_object, const StringName &p_name);
Signal() {}
};
struct CallableComparator {
const Callable &func;
bool operator()(const Variant &p_l, const Variant &p_r) const;
};
#endif // CALLABLE_H

View file

@ -0,0 +1,287 @@
/**************************************************************************/
/* callable_bind.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 "callable_bind.h"
//////////////////////////////////
uint32_t CallableCustomBind::hash() const {
return callable.hash();
}
String CallableCustomBind::get_as_text() const {
return callable.operator String();
}
bool CallableCustomBind::_equal_func(const CallableCustom *p_a, const CallableCustom *p_b) {
const CallableCustomBind *a = static_cast<const CallableCustomBind *>(p_a);
const CallableCustomBind *b = static_cast<const CallableCustomBind *>(p_b);
if (!(a->callable != b->callable)) {
return false;
}
if (a->binds.size() != b->binds.size()) {
return false;
}
return true;
}
bool CallableCustomBind::_less_func(const CallableCustom *p_a, const CallableCustom *p_b) {
const CallableCustomBind *a = static_cast<const CallableCustomBind *>(p_a);
const CallableCustomBind *b = static_cast<const CallableCustomBind *>(p_b);
if (a->callable < b->callable) {
return true;
} else if (b->callable < a->callable) {
return false;
}
return a->binds.size() < b->binds.size();
}
CallableCustom::CompareEqualFunc CallableCustomBind::get_compare_equal_func() const {
return _equal_func;
}
CallableCustom::CompareLessFunc CallableCustomBind::get_compare_less_func() const {
return _less_func;
}
bool CallableCustomBind::is_valid() const {
return callable.is_valid();
}
StringName CallableCustomBind::get_method() const {
return callable.get_method();
}
ObjectID CallableCustomBind::get_object() const {
return callable.get_object_id();
}
const Callable *CallableCustomBind::get_base_comparator() const {
return callable.get_base_comparator();
}
int CallableCustomBind::get_argument_count(bool &r_is_valid) const {
int ret = callable.get_argument_count(&r_is_valid);
if (r_is_valid) {
return ret - binds.size();
}
return 0;
}
int CallableCustomBind::get_bound_arguments_count() const {
return callable.get_bound_arguments_count() + binds.size();
}
void CallableCustomBind::get_bound_arguments(Vector<Variant> &r_arguments, int &r_argcount) const {
Vector<Variant> sub_args;
int sub_count;
callable.get_bound_arguments_ref(sub_args, sub_count);
if (sub_count == 0) {
r_arguments = binds;
r_argcount = binds.size();
return;
}
int new_count = sub_count + binds.size();
r_argcount = new_count;
if (new_count <= 0) {
// Removed more arguments than it adds.
r_arguments = Vector<Variant>();
return;
}
r_arguments.resize(new_count);
if (sub_count > 0) {
for (int i = 0; i < sub_count; i++) {
r_arguments.write[i] = sub_args[i];
}
for (int i = 0; i < binds.size(); i++) {
r_arguments.write[i + sub_count] = binds[i];
}
r_argcount = new_count;
} else {
for (int i = 0; i < binds.size() + sub_count; i++) {
r_arguments.write[i] = binds[i - sub_count];
}
}
}
void CallableCustomBind::call(const Variant **p_arguments, int p_argcount, Variant &r_return_value, Callable::CallError &r_call_error) const {
const Variant **args = (const Variant **)alloca(sizeof(Variant *) * (binds.size() + p_argcount));
for (int i = 0; i < p_argcount; i++) {
args[i] = (const Variant *)p_arguments[i];
}
for (int i = 0; i < binds.size(); i++) {
args[i + p_argcount] = (const Variant *)&binds[i];
}
callable.callp(args, p_argcount + binds.size(), r_return_value, r_call_error);
}
Error CallableCustomBind::rpc(int p_peer_id, const Variant **p_arguments, int p_argcount, Callable::CallError &r_call_error) const {
const Variant **args = (const Variant **)alloca(sizeof(Variant *) * (binds.size() + p_argcount));
for (int i = 0; i < p_argcount; i++) {
args[i] = (const Variant *)p_arguments[i];
}
for (int i = 0; i < binds.size(); i++) {
args[i + p_argcount] = (const Variant *)&binds[i];
}
return callable.rpcp(p_peer_id, args, p_argcount + binds.size(), r_call_error);
}
CallableCustomBind::CallableCustomBind(const Callable &p_callable, const Vector<Variant> &p_binds) {
callable = p_callable;
binds = p_binds;
}
CallableCustomBind::~CallableCustomBind() {
}
//////////////////////////////////
uint32_t CallableCustomUnbind::hash() const {
return callable.hash();
}
String CallableCustomUnbind::get_as_text() const {
return callable.operator String();
}
bool CallableCustomUnbind::_equal_func(const CallableCustom *p_a, const CallableCustom *p_b) {
const CallableCustomUnbind *a = static_cast<const CallableCustomUnbind *>(p_a);
const CallableCustomUnbind *b = static_cast<const CallableCustomUnbind *>(p_b);
if (!(a->callable != b->callable)) {
return false;
}
if (a->argcount != b->argcount) {
return false;
}
return true;
}
bool CallableCustomUnbind::_less_func(const CallableCustom *p_a, const CallableCustom *p_b) {
const CallableCustomUnbind *a = static_cast<const CallableCustomUnbind *>(p_a);
const CallableCustomUnbind *b = static_cast<const CallableCustomUnbind *>(p_b);
if (a->callable < b->callable) {
return true;
} else if (b->callable < a->callable) {
return false;
}
return a->argcount < b->argcount;
}
CallableCustom::CompareEqualFunc CallableCustomUnbind::get_compare_equal_func() const {
return _equal_func;
}
CallableCustom::CompareLessFunc CallableCustomUnbind::get_compare_less_func() const {
return _less_func;
}
bool CallableCustomUnbind::is_valid() const {
return callable.is_valid();
}
StringName CallableCustomUnbind::get_method() const {
return callable.get_method();
}
ObjectID CallableCustomUnbind::get_object() const {
return callable.get_object_id();
}
const Callable *CallableCustomUnbind::get_base_comparator() const {
return callable.get_base_comparator();
}
int CallableCustomUnbind::get_argument_count(bool &r_is_valid) const {
int ret = callable.get_argument_count(&r_is_valid);
if (r_is_valid) {
return ret + argcount;
}
return 0;
}
int CallableCustomUnbind::get_bound_arguments_count() const {
return callable.get_bound_arguments_count() - argcount;
}
void CallableCustomUnbind::get_bound_arguments(Vector<Variant> &r_arguments, int &r_argcount) const {
Vector<Variant> sub_args;
int sub_count;
callable.get_bound_arguments_ref(sub_args, sub_count);
r_argcount = sub_args.size() - argcount;
if (argcount >= sub_args.size()) {
r_arguments = Vector<Variant>();
} else {
sub_args.resize(sub_args.size() - argcount);
r_arguments = sub_args;
}
}
void CallableCustomUnbind::call(const Variant **p_arguments, int p_argcount, Variant &r_return_value, Callable::CallError &r_call_error) const {
if (p_argcount < argcount) {
r_call_error.error = Callable::CallError::CALL_ERROR_TOO_FEW_ARGUMENTS;
r_call_error.expected = argcount;
return;
}
callable.callp(p_arguments, p_argcount - argcount, r_return_value, r_call_error);
}
Error CallableCustomUnbind::rpc(int p_peer_id, const Variant **p_arguments, int p_argcount, Callable::CallError &r_call_error) const {
if (p_argcount < argcount) {
r_call_error.error = Callable::CallError::CALL_ERROR_TOO_FEW_ARGUMENTS;
r_call_error.expected = argcount;
return ERR_UNCONFIGURED;
}
return callable.rpcp(p_peer_id, p_arguments, p_argcount - argcount, r_call_error);
}
CallableCustomUnbind::CallableCustomUnbind(const Callable &p_callable, int p_argcount) {
callable = p_callable;
argcount = p_argcount;
}
CallableCustomUnbind::~CallableCustomUnbind() {
}

View file

@ -0,0 +1,96 @@
/**************************************************************************/
/* callable_bind.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 CALLABLE_BIND_H
#define CALLABLE_BIND_H
#include "core/variant/callable.h"
#include "core/variant/variant.h"
class CallableCustomBind : public CallableCustom {
Callable callable;
Vector<Variant> binds;
static bool _equal_func(const CallableCustom *p_a, const CallableCustom *p_b);
static bool _less_func(const CallableCustom *p_a, const CallableCustom *p_b);
public:
//for every type that inherits, these must always be the same for this type
virtual uint32_t hash() const override;
virtual String get_as_text() const override;
virtual CompareEqualFunc get_compare_equal_func() const override;
virtual CompareLessFunc get_compare_less_func() const override;
virtual bool is_valid() const override;
virtual StringName get_method() const override;
virtual ObjectID get_object() const override;
virtual void call(const Variant **p_arguments, int p_argcount, Variant &r_return_value, Callable::CallError &r_call_error) const override;
virtual Error rpc(int p_peer_id, const Variant **p_arguments, int p_argcount, Callable::CallError &r_call_error) const override;
virtual const Callable *get_base_comparator() const override;
virtual int get_argument_count(bool &r_is_valid) const override;
virtual int get_bound_arguments_count() const override;
virtual void get_bound_arguments(Vector<Variant> &r_arguments, int &r_argcount) const override;
Callable get_callable() { return callable; }
Vector<Variant> get_binds() { return binds; }
CallableCustomBind(const Callable &p_callable, const Vector<Variant> &p_binds);
virtual ~CallableCustomBind();
};
class CallableCustomUnbind : public CallableCustom {
Callable callable;
int argcount;
static bool _equal_func(const CallableCustom *p_a, const CallableCustom *p_b);
static bool _less_func(const CallableCustom *p_a, const CallableCustom *p_b);
public:
//for every type that inherits, these must always be the same for this type
virtual uint32_t hash() const override;
virtual String get_as_text() const override;
virtual CompareEqualFunc get_compare_equal_func() const override;
virtual CompareLessFunc get_compare_less_func() const override;
virtual bool is_valid() const override;
virtual StringName get_method() const override;
virtual ObjectID get_object() const override;
virtual void call(const Variant **p_arguments, int p_argcount, Variant &r_return_value, Callable::CallError &r_call_error) const override;
virtual Error rpc(int p_peer_id, const Variant **p_arguments, int p_argcount, Callable::CallError &r_call_error) const override;
virtual const Callable *get_base_comparator() const override;
virtual int get_argument_count(bool &r_is_valid) const override;
virtual int get_bound_arguments_count() const override;
virtual void get_bound_arguments(Vector<Variant> &r_arguments, int &r_argcount) const override;
Callable get_callable() { return callable; }
int get_unbinds() { return argcount; }
CallableCustomUnbind(const Callable &p_callable, int p_argcount);
virtual ~CallableCustomUnbind();
};
#endif // CALLABLE_BIND_H

View file

@ -0,0 +1,146 @@
/**************************************************************************/
/* container_type_validate.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 CONTAINER_TYPE_VALIDATE_H
#define CONTAINER_TYPE_VALIDATE_H
#include "core/object/script_language.h"
#include "core/variant/variant.h"
struct ContainerTypeValidate {
Variant::Type type = Variant::NIL;
StringName class_name;
Ref<Script> script;
const char *where = "container";
_FORCE_INLINE_ bool can_reference(const ContainerTypeValidate &p_type) const {
if (type != p_type.type) {
return false;
} else if (type != Variant::OBJECT) {
return true;
}
if (class_name == StringName()) {
return true;
} else if (p_type.class_name == StringName()) {
return false;
} else if (class_name != p_type.class_name && !ClassDB::is_parent_class(p_type.class_name, class_name)) {
return false;
}
if (script.is_null()) {
return true;
} else if (p_type.script.is_null()) {
return false;
} else if (script != p_type.script && !p_type.script->inherits_script(script)) {
return false;
}
return true;
}
_FORCE_INLINE_ bool operator==(const ContainerTypeValidate &p_type) const {
return type == p_type.type && class_name == p_type.class_name && script == p_type.script;
}
_FORCE_INLINE_ bool operator!=(const ContainerTypeValidate &p_type) const {
return type != p_type.type || class_name != p_type.class_name || script != p_type.script;
}
// Coerces String and StringName into each other and int into float when needed.
_FORCE_INLINE_ bool validate(Variant &inout_variant, const char *p_operation = "use") const {
if (type == Variant::NIL) {
return true;
}
if (type != inout_variant.get_type()) {
if (inout_variant.get_type() == Variant::NIL && type == Variant::OBJECT) {
return true;
}
if (type == Variant::STRING && inout_variant.get_type() == Variant::STRING_NAME) {
inout_variant = String(inout_variant);
return true;
} else if (type == Variant::STRING_NAME && inout_variant.get_type() == Variant::STRING) {
inout_variant = StringName(inout_variant);
return true;
} else if (type == Variant::FLOAT && inout_variant.get_type() == Variant::INT) {
inout_variant = (float)inout_variant;
return true;
}
ERR_FAIL_V_MSG(false, "Attempted to " + String(p_operation) + " a variable of type '" + Variant::get_type_name(inout_variant.get_type()) + "' into a " + where + " of type '" + Variant::get_type_name(type) + "'.");
}
if (type != Variant::OBJECT) {
return true;
}
return validate_object(inout_variant, p_operation);
}
_FORCE_INLINE_ bool validate_object(const Variant &p_variant, const char *p_operation = "use") const {
ERR_FAIL_COND_V(p_variant.get_type() != Variant::OBJECT, false);
#ifdef DEBUG_ENABLED
ObjectID object_id = p_variant;
if (object_id == ObjectID()) {
return true; // This is fine, it's null.
}
Object *object = ObjectDB::get_instance(object_id);
ERR_FAIL_NULL_V_MSG(object, false, "Attempted to " + String(p_operation) + " an invalid (previously freed?) object instance into a '" + String(where) + ".");
#else
Object *object = p_variant;
if (object == nullptr) {
return true; //fine
}
#endif
if (class_name == StringName()) {
return true; // All good, no class type requested.
}
StringName obj_class = object->get_class_name();
if (obj_class != class_name) {
ERR_FAIL_COND_V_MSG(!ClassDB::is_parent_class(object->get_class_name(), class_name), false, "Attempted to " + String(p_operation) + " an object of type '" + object->get_class() + "' into a " + where + ", which does not inherit from '" + String(class_name) + "'.");
}
if (script.is_null()) {
return true; // All good, no script requested.
}
Ref<Script> other_script = object->get_script();
// Check base script..
ERR_FAIL_COND_V_MSG(other_script.is_null(), false, "Attempted to " + String(p_operation) + " an object into a " + String(where) + ", that does not inherit from '" + String(script->get_class_name()) + "'.");
ERR_FAIL_COND_V_MSG(!other_script->inherits_script(script), false, "Attempted to " + String(p_operation) + " an object into a " + String(where) + ", that does not inherit from '" + String(script->get_class_name()) + "'.");
return true;
}
};
#endif // CONTAINER_TYPE_VALIDATE_H

View file

@ -0,0 +1,413 @@
/**************************************************************************/
/* dictionary.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 "dictionary.h"
#include "core/templates/hash_map.h"
#include "core/templates/safe_refcount.h"
#include "core/variant/variant.h"
// required in this order by VariantInternal, do not remove this comment.
#include "core/object/class_db.h"
#include "core/object/object.h"
#include "core/variant/type_info.h"
#include "core/variant/variant_internal.h"
struct DictionaryPrivate {
SafeRefCount refcount;
Variant *read_only = nullptr; // If enabled, a pointer is used to a temporary value that is used to return read-only values.
HashMap<Variant, Variant, VariantHasher, StringLikeVariantComparator> variant_map;
};
void Dictionary::get_key_list(List<Variant> *p_keys) const {
if (_p->variant_map.is_empty()) {
return;
}
for (const KeyValue<Variant, Variant> &E : _p->variant_map) {
p_keys->push_back(E.key);
}
}
Variant Dictionary::get_key_at_index(int p_index) const {
int index = 0;
for (const KeyValue<Variant, Variant> &E : _p->variant_map) {
if (index == p_index) {
return E.key;
}
index++;
}
return Variant();
}
Variant Dictionary::get_value_at_index(int p_index) const {
int index = 0;
for (const KeyValue<Variant, Variant> &E : _p->variant_map) {
if (index == p_index) {
return E.value;
}
index++;
}
return Variant();
}
Variant &Dictionary::operator[](const Variant &p_key) {
if (unlikely(_p->read_only)) {
if (p_key.get_type() == Variant::STRING_NAME) {
const StringName *sn = VariantInternal::get_string_name(&p_key);
const String &key = sn->operator String();
if (likely(_p->variant_map.has(key))) {
*_p->read_only = _p->variant_map[key];
} else {
*_p->read_only = Variant();
}
} else if (likely(_p->variant_map.has(p_key))) {
*_p->read_only = _p->variant_map[p_key];
} else {
*_p->read_only = Variant();
}
return *_p->read_only;
} else {
if (p_key.get_type() == Variant::STRING_NAME) {
const StringName *sn = VariantInternal::get_string_name(&p_key);
return _p->variant_map[sn->operator String()];
} else {
return _p->variant_map[p_key];
}
}
}
const Variant &Dictionary::operator[](const Variant &p_key) const {
// Will not insert key, so no conversion is necessary.
return _p->variant_map[p_key];
}
const Variant *Dictionary::getptr(const Variant &p_key) const {
HashMap<Variant, Variant, VariantHasher, StringLikeVariantComparator>::ConstIterator E(_p->variant_map.find(p_key));
if (!E) {
return nullptr;
}
return &E->value;
}
Variant *Dictionary::getptr(const Variant &p_key) {
HashMap<Variant, Variant, VariantHasher, StringLikeVariantComparator>::Iterator E(_p->variant_map.find(p_key));
if (!E) {
return nullptr;
}
if (unlikely(_p->read_only != nullptr)) {
*_p->read_only = E->value;
return _p->read_only;
} else {
return &E->value;
}
}
Variant Dictionary::get_valid(const Variant &p_key) const {
HashMap<Variant, Variant, VariantHasher, StringLikeVariantComparator>::ConstIterator E(_p->variant_map.find(p_key));
if (!E) {
return Variant();
}
return E->value;
}
Variant Dictionary::get(const Variant &p_key, const Variant &p_default) const {
const Variant *result = getptr(p_key);
if (!result) {
return p_default;
}
return *result;
}
Variant Dictionary::get_or_add(const Variant &p_key, const Variant &p_default) {
const Variant *result = getptr(p_key);
if (!result) {
operator[](p_key) = p_default;
return p_default;
}
return *result;
}
int Dictionary::size() const {
return _p->variant_map.size();
}
bool Dictionary::is_empty() const {
return !_p->variant_map.size();
}
bool Dictionary::has(const Variant &p_key) const {
return _p->variant_map.has(p_key);
}
bool Dictionary::has_all(const Array &p_keys) const {
for (int i = 0; i < p_keys.size(); i++) {
if (!has(p_keys[i])) {
return false;
}
}
return true;
}
Variant Dictionary::find_key(const Variant &p_value) const {
for (const KeyValue<Variant, Variant> &E : _p->variant_map) {
if (E.value == p_value) {
return E.key;
}
}
return Variant();
}
bool Dictionary::erase(const Variant &p_key) {
ERR_FAIL_COND_V_MSG(_p->read_only, false, "Dictionary is in read-only state.");
return _p->variant_map.erase(p_key);
}
bool Dictionary::operator==(const Dictionary &p_dictionary) const {
return recursive_equal(p_dictionary, 0);
}
bool Dictionary::operator!=(const Dictionary &p_dictionary) const {
return !recursive_equal(p_dictionary, 0);
}
bool Dictionary::recursive_equal(const Dictionary &p_dictionary, int recursion_count) const {
// Cheap checks
if (_p == p_dictionary._p) {
return true;
}
if (_p->variant_map.size() != p_dictionary._p->variant_map.size()) {
return false;
}
// Heavy O(n) check
if (recursion_count > MAX_RECURSION) {
ERR_PRINT("Max recursion reached");
return true;
}
recursion_count++;
for (const KeyValue<Variant, Variant> &this_E : _p->variant_map) {
HashMap<Variant, Variant, VariantHasher, StringLikeVariantComparator>::ConstIterator other_E(p_dictionary._p->variant_map.find(this_E.key));
if (!other_E || !this_E.value.hash_compare(other_E->value, recursion_count, false)) {
return false;
}
}
return true;
}
void Dictionary::_ref(const Dictionary &p_from) const {
//make a copy first (thread safe)
if (!p_from._p->refcount.ref()) {
return; // couldn't copy
}
//if this is the same, unreference the other one
if (p_from._p == _p) {
_p->refcount.unref();
return;
}
if (_p) {
_unref();
}
_p = p_from._p;
}
void Dictionary::clear() {
ERR_FAIL_COND_MSG(_p->read_only, "Dictionary is in read-only state.");
_p->variant_map.clear();
}
void Dictionary::merge(const Dictionary &p_dictionary, bool p_overwrite) {
ERR_FAIL_COND_MSG(_p->read_only, "Dictionary is in read-only state.");
for (const KeyValue<Variant, Variant> &E : p_dictionary._p->variant_map) {
if (p_overwrite || !has(E.key)) {
operator[](E.key) = E.value;
}
}
}
Dictionary Dictionary::merged(const Dictionary &p_dictionary, bool p_overwrite) const {
Dictionary ret = duplicate();
ret.merge(p_dictionary, p_overwrite);
return ret;
}
void Dictionary::_unref() const {
ERR_FAIL_NULL(_p);
if (_p->refcount.unref()) {
if (_p->read_only) {
memdelete(_p->read_only);
}
memdelete(_p);
}
_p = nullptr;
}
uint32_t Dictionary::hash() const {
return recursive_hash(0);
}
uint32_t Dictionary::recursive_hash(int recursion_count) const {
if (recursion_count > MAX_RECURSION) {
ERR_PRINT("Max recursion reached");
return 0;
}
uint32_t h = hash_murmur3_one_32(Variant::DICTIONARY);
recursion_count++;
for (const KeyValue<Variant, Variant> &E : _p->variant_map) {
h = hash_murmur3_one_32(E.key.recursive_hash(recursion_count), h);
h = hash_murmur3_one_32(E.value.recursive_hash(recursion_count), h);
}
return hash_fmix32(h);
}
Array Dictionary::keys() const {
Array varr;
if (_p->variant_map.is_empty()) {
return varr;
}
varr.resize(size());
int i = 0;
for (const KeyValue<Variant, Variant> &E : _p->variant_map) {
varr[i] = E.key;
i++;
}
return varr;
}
Array Dictionary::values() const {
Array varr;
if (_p->variant_map.is_empty()) {
return varr;
}
varr.resize(size());
int i = 0;
for (const KeyValue<Variant, Variant> &E : _p->variant_map) {
varr[i] = E.value;
i++;
}
return varr;
}
const Variant *Dictionary::next(const Variant *p_key) const {
if (p_key == nullptr) {
// caller wants to get the first element
if (_p->variant_map.begin()) {
return &_p->variant_map.begin()->key;
}
return nullptr;
}
HashMap<Variant, Variant, VariantHasher, StringLikeVariantComparator>::Iterator E = _p->variant_map.find(*p_key);
if (!E) {
return nullptr;
}
++E;
if (E) {
return &E->key;
}
return nullptr;
}
Dictionary Dictionary::duplicate(bool p_deep) const {
return recursive_duplicate(p_deep, 0);
}
void Dictionary::make_read_only() {
if (_p->read_only == nullptr) {
_p->read_only = memnew(Variant);
}
}
bool Dictionary::is_read_only() const {
return _p->read_only != nullptr;
}
Dictionary Dictionary::recursive_duplicate(bool p_deep, int recursion_count) const {
Dictionary n;
if (recursion_count > MAX_RECURSION) {
ERR_PRINT("Max recursion reached");
return n;
}
if (p_deep) {
recursion_count++;
for (const KeyValue<Variant, Variant> &E : _p->variant_map) {
n[E.key.recursive_duplicate(true, recursion_count)] = E.value.recursive_duplicate(true, recursion_count);
}
} else {
for (const KeyValue<Variant, Variant> &E : _p->variant_map) {
n[E.key] = E.value;
}
}
return n;
}
void Dictionary::operator=(const Dictionary &p_dictionary) {
if (this == &p_dictionary) {
return;
}
_ref(p_dictionary);
}
const void *Dictionary::id() const {
return _p;
}
Dictionary::Dictionary(const Dictionary &p_from) {
_p = nullptr;
_ref(p_from);
}
Dictionary::Dictionary() {
_p = memnew(DictionaryPrivate);
_p->refcount.init();
}
Dictionary::~Dictionary() {
_unref();
}

View file

@ -0,0 +1,101 @@
/**************************************************************************/
/* dictionary.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 DICTIONARY_H
#define DICTIONARY_H
#include "core/string/ustring.h"
#include "core/templates/list.h"
#include "core/variant/array.h"
class Variant;
struct DictionaryPrivate;
class Dictionary {
mutable DictionaryPrivate *_p;
void _ref(const Dictionary &p_from) const;
void _unref() const;
public:
void get_key_list(List<Variant> *p_keys) const;
Variant get_key_at_index(int p_index) const;
Variant get_value_at_index(int p_index) const;
Variant &operator[](const Variant &p_key);
const Variant &operator[](const Variant &p_key) const;
const Variant *getptr(const Variant &p_key) const;
Variant *getptr(const Variant &p_key);
Variant get_valid(const Variant &p_key) const;
Variant get(const Variant &p_key, const Variant &p_default) const;
Variant get_or_add(const Variant &p_key, const Variant &p_default);
int size() const;
bool is_empty() const;
void clear();
void merge(const Dictionary &p_dictionary, bool p_overwrite = false);
Dictionary merged(const Dictionary &p_dictionary, bool p_overwrite = false) const;
bool has(const Variant &p_key) const;
bool has_all(const Array &p_keys) const;
Variant find_key(const Variant &p_value) const;
bool erase(const Variant &p_key);
bool operator==(const Dictionary &p_dictionary) const;
bool operator!=(const Dictionary &p_dictionary) const;
bool recursive_equal(const Dictionary &p_dictionary, int recursion_count) const;
uint32_t hash() const;
uint32_t recursive_hash(int recursion_count) const;
void operator=(const Dictionary &p_dictionary);
const Variant *next(const Variant *p_key = nullptr) const;
Array keys() const;
Array values() const;
Dictionary duplicate(bool p_deep = false) const;
Dictionary recursive_duplicate(bool p_deep, int recursion_count) const;
void make_read_only();
bool is_read_only() const;
const void *id() const;
Dictionary(const Dictionary &p_from);
Dictionary();
~Dictionary();
};
#endif // DICTIONARY_H

View file

@ -0,0 +1,462 @@
/**************************************************************************/
/* method_ptrcall.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 METHOD_PTRCALL_H
#define METHOD_PTRCALL_H
#include "core/object/object_id.h"
#include "core/typedefs.h"
#include "core/variant/variant.h"
template <typename T>
struct PtrToArg {};
#define MAKE_PTRARG(m_type) \
template <> \
struct PtrToArg<m_type> { \
_FORCE_INLINE_ static const m_type &convert(const void *p_ptr) { \
return *reinterpret_cast<const m_type *>(p_ptr); \
} \
typedef m_type EncodeT; \
_FORCE_INLINE_ static void encode(m_type p_val, void *p_ptr) { \
*((m_type *)p_ptr) = p_val; \
} \
}; \
template <> \
struct PtrToArg<const m_type &> { \
_FORCE_INLINE_ static const m_type &convert(const void *p_ptr) { \
return *reinterpret_cast<const m_type *>(p_ptr); \
} \
typedef m_type EncodeT; \
_FORCE_INLINE_ static void encode(m_type p_val, void *p_ptr) { \
*((m_type *)p_ptr) = p_val; \
} \
}
#define MAKE_PTRARGCONV(m_type, m_conv) \
template <> \
struct PtrToArg<m_type> { \
_FORCE_INLINE_ static m_type convert(const void *p_ptr) { \
return static_cast<m_type>(*reinterpret_cast<const m_conv *>(p_ptr)); \
} \
typedef m_conv EncodeT; \
_FORCE_INLINE_ static void encode(m_type p_val, void *p_ptr) { \
*((m_conv *)p_ptr) = static_cast<m_conv>(p_val); \
} \
}; \
template <> \
struct PtrToArg<const m_type &> { \
_FORCE_INLINE_ static m_type convert(const void *p_ptr) { \
return static_cast<m_type>(*reinterpret_cast<const m_conv *>(p_ptr)); \
} \
typedef m_conv EncodeT; \
_FORCE_INLINE_ static void encode(m_type p_val, void *p_ptr) { \
*((m_conv *)p_ptr) = static_cast<m_conv>(p_val); \
} \
}
#define MAKE_PTRARG_BY_REFERENCE(m_type) \
template <> \
struct PtrToArg<m_type> { \
_FORCE_INLINE_ static const m_type &convert(const void *p_ptr) { \
return *reinterpret_cast<const m_type *>(p_ptr); \
} \
typedef m_type EncodeT; \
_FORCE_INLINE_ static void encode(const m_type &p_val, void *p_ptr) { \
*((m_type *)p_ptr) = p_val; \
} \
}; \
template <> \
struct PtrToArg<const m_type &> { \
_FORCE_INLINE_ static const m_type &convert(const void *p_ptr) { \
return *reinterpret_cast<const m_type *>(p_ptr); \
} \
typedef m_type EncodeT; \
_FORCE_INLINE_ static void encode(const m_type &p_val, void *p_ptr) { \
*((m_type *)p_ptr) = p_val; \
} \
}
MAKE_PTRARGCONV(bool, uint8_t);
// Integer types.
MAKE_PTRARGCONV(uint8_t, int64_t);
MAKE_PTRARGCONV(int8_t, int64_t);
MAKE_PTRARGCONV(uint16_t, int64_t);
MAKE_PTRARGCONV(int16_t, int64_t);
MAKE_PTRARGCONV(uint32_t, int64_t);
MAKE_PTRARGCONV(int32_t, int64_t);
MAKE_PTRARG(int64_t);
MAKE_PTRARG(uint64_t);
// Float types
MAKE_PTRARGCONV(float, double);
MAKE_PTRARG(double);
MAKE_PTRARG(String);
MAKE_PTRARG(Vector2);
MAKE_PTRARG(Vector2i);
MAKE_PTRARG(Rect2);
MAKE_PTRARG(Rect2i);
MAKE_PTRARG_BY_REFERENCE(Vector3);
MAKE_PTRARG_BY_REFERENCE(Vector3i);
MAKE_PTRARG_BY_REFERENCE(Vector4);
MAKE_PTRARG_BY_REFERENCE(Vector4i);
MAKE_PTRARG(Transform2D);
MAKE_PTRARG(Projection);
MAKE_PTRARG_BY_REFERENCE(Plane);
MAKE_PTRARG(Quaternion);
MAKE_PTRARG_BY_REFERENCE(AABB);
MAKE_PTRARG_BY_REFERENCE(Basis);
MAKE_PTRARG_BY_REFERENCE(Transform3D);
MAKE_PTRARG_BY_REFERENCE(Color);
MAKE_PTRARG(StringName);
MAKE_PTRARG(NodePath);
MAKE_PTRARG(RID);
// Object doesn't need this.
MAKE_PTRARG(Callable);
MAKE_PTRARG(Signal);
MAKE_PTRARG(Dictionary);
MAKE_PTRARG(Array);
MAKE_PTRARG(PackedByteArray);
MAKE_PTRARG(PackedInt32Array);
MAKE_PTRARG(PackedInt64Array);
MAKE_PTRARG(PackedFloat32Array);
MAKE_PTRARG(PackedFloat64Array);
MAKE_PTRARG(PackedStringArray);
MAKE_PTRARG(PackedVector2Array);
MAKE_PTRARG(PackedVector3Array);
MAKE_PTRARG(PackedColorArray);
MAKE_PTRARG(PackedVector4Array);
MAKE_PTRARG_BY_REFERENCE(Variant);
// This is for Object.
template <typename T>
struct PtrToArg<T *> {
_FORCE_INLINE_ static T *convert(const void *p_ptr) {
return likely(p_ptr) ? const_cast<T *>(*reinterpret_cast<T *const *>(p_ptr)) : nullptr;
}
typedef Object *EncodeT;
_FORCE_INLINE_ static void encode(T *p_var, void *p_ptr) {
*((T **)p_ptr) = p_var;
}
};
template <typename T>
struct PtrToArg<const T *> {
_FORCE_INLINE_ static const T *convert(const void *p_ptr) {
return likely(p_ptr) ? *reinterpret_cast<T *const *>(p_ptr) : nullptr;
}
typedef const Object *EncodeT;
_FORCE_INLINE_ static void encode(T *p_var, void *p_ptr) {
*((T **)p_ptr) = p_var;
}
};
// This is for ObjectID.
template <>
struct PtrToArg<ObjectID> {
_FORCE_INLINE_ static const ObjectID convert(const void *p_ptr) {
return ObjectID(*reinterpret_cast<const uint64_t *>(p_ptr));
}
typedef uint64_t EncodeT;
_FORCE_INLINE_ static void encode(const ObjectID &p_val, void *p_ptr) {
*((uint64_t *)p_ptr) = p_val;
}
};
// This is for the special cases used by Variant.
// No EncodeT because direct pointer conversion not possible.
#define MAKE_VECARG(m_type) \
template <> \
struct PtrToArg<Vector<m_type>> { \
_FORCE_INLINE_ static Vector<m_type> convert(const void *p_ptr) { \
const Vector<m_type> *dvs = reinterpret_cast<const Vector<m_type> *>(p_ptr); \
Vector<m_type> ret; \
int len = dvs->size(); \
ret.resize(len); \
{ \
const m_type *r = dvs->ptr(); \
for (int i = 0; i < len; i++) { \
ret.write[i] = r[i]; \
} \
} \
return ret; \
} \
_FORCE_INLINE_ static void encode(const Vector<m_type> &p_vec, void *p_ptr) { \
Vector<m_type> *dv = reinterpret_cast<Vector<m_type> *>(p_ptr); \
int len = p_vec.size(); \
dv->resize(len); \
{ \
m_type *w = dv->ptrw(); \
for (int i = 0; i < len; i++) { \
w[i] = p_vec[i]; \
} \
} \
} \
}; \
template <> \
struct PtrToArg<const Vector<m_type> &> { \
_FORCE_INLINE_ static Vector<m_type> convert(const void *p_ptr) { \
const Vector<m_type> *dvs = reinterpret_cast<const Vector<m_type> *>(p_ptr); \
Vector<m_type> ret; \
int len = dvs->size(); \
ret.resize(len); \
{ \
const m_type *r = dvs->ptr(); \
for (int i = 0; i < len; i++) { \
ret.write[i] = r[i]; \
} \
} \
return ret; \
} \
}
// No EncodeT because direct pointer conversion not possible.
#define MAKE_VECARG_ALT(m_type, m_type_alt) \
template <> \
struct PtrToArg<Vector<m_type_alt>> { \
_FORCE_INLINE_ static Vector<m_type_alt> convert(const void *p_ptr) { \
const Vector<m_type> *dvs = reinterpret_cast<const Vector<m_type> *>(p_ptr); \
Vector<m_type_alt> ret; \
int len = dvs->size(); \
ret.resize(len); \
{ \
const m_type *r = dvs->ptr(); \
for (int i = 0; i < len; i++) { \
ret.write[i] = r[i]; \
} \
} \
return ret; \
} \
_FORCE_INLINE_ static void encode(const Vector<m_type_alt> &p_vec, void *p_ptr) { \
Vector<m_type> *dv = reinterpret_cast<Vector<m_type> *>(p_ptr); \
int len = p_vec.size(); \
dv->resize(len); \
{ \
m_type *w = dv->ptrw(); \
for (int i = 0; i < len; i++) { \
w[i] = p_vec[i]; \
} \
} \
} \
}; \
template <> \
struct PtrToArg<const Vector<m_type_alt> &> { \
_FORCE_INLINE_ static Vector<m_type_alt> convert(const void *p_ptr) { \
const Vector<m_type> *dvs = reinterpret_cast<const Vector<m_type> *>(p_ptr); \
Vector<m_type_alt> ret; \
int len = dvs->size(); \
ret.resize(len); \
{ \
const m_type *r = dvs->ptr(); \
for (int i = 0; i < len; i++) { \
ret.write[i] = r[i]; \
} \
} \
return ret; \
} \
}
MAKE_VECARG_ALT(String, StringName);
// For stuff that gets converted to Array vectors.
// No EncodeT because direct pointer conversion not possible.
#define MAKE_VECARR(m_type) \
template <> \
struct PtrToArg<Vector<m_type>> { \
_FORCE_INLINE_ static Vector<m_type> convert(const void *p_ptr) { \
const Array *arr = reinterpret_cast<const Array *>(p_ptr); \
Vector<m_type> ret; \
int len = arr->size(); \
ret.resize(len); \
for (int i = 0; i < len; i++) { \
ret.write[i] = (*arr)[i]; \
} \
return ret; \
} \
_FORCE_INLINE_ static void encode(const Vector<m_type> &p_vec, void *p_ptr) { \
Array *arr = reinterpret_cast<Array *>(p_ptr); \
int len = p_vec.size(); \
arr->resize(len); \
for (int i = 0; i < len; i++) { \
(*arr)[i] = p_vec[i]; \
} \
} \
}; \
template <> \
struct PtrToArg<const Vector<m_type> &> { \
_FORCE_INLINE_ static Vector<m_type> convert(const void *p_ptr) { \
const Array *arr = reinterpret_cast<const Array *>(p_ptr); \
Vector<m_type> ret; \
int len = arr->size(); \
ret.resize(len); \
for (int i = 0; i < len; i++) { \
ret.write[i] = (*arr)[i]; \
} \
return ret; \
} \
}
MAKE_VECARR(Variant);
MAKE_VECARR(RID);
MAKE_VECARR(Plane);
// No EncodeT because direct pointer conversion not possible.
#define MAKE_DVECARR(m_type) \
template <> \
struct PtrToArg<Vector<m_type>> { \
_FORCE_INLINE_ static Vector<m_type> convert(const void *p_ptr) { \
const Array *arr = reinterpret_cast<const Array *>(p_ptr); \
Vector<m_type> ret; \
int len = arr->size(); \
ret.resize(len); \
{ \
m_type *w = ret.ptrw(); \
for (int i = 0; i < len; i++) { \
w[i] = (*arr)[i]; \
} \
} \
return ret; \
} \
_FORCE_INLINE_ static void encode(const Vector<m_type> &p_vec, void *p_ptr) { \
Array *arr = reinterpret_cast<Array *>(p_ptr); \
int len = p_vec.size(); \
arr->resize(len); \
{ \
const m_type *r = p_vec.ptr(); \
for (int i = 0; i < len; i++) { \
(*arr)[i] = r[i]; \
} \
} \
} \
}; \
template <> \
struct PtrToArg<const Vector<m_type> &> { \
_FORCE_INLINE_ static Vector<m_type> convert(const void *p_ptr) { \
const Array *arr = reinterpret_cast<const Array *>(p_ptr); \
Vector<m_type> ret; \
int len = arr->size(); \
ret.resize(len); \
{ \
m_type *w = ret.ptrw(); \
for (int i = 0; i < len; i++) { \
w[i] = (*arr)[i]; \
} \
} \
return ret; \
} \
}
// Special case for IPAddress.
// No EncodeT because direct pointer conversion not possible.
#define MAKE_STRINGCONV_BY_REFERENCE(m_type) \
template <> \
struct PtrToArg<m_type> { \
_FORCE_INLINE_ static m_type convert(const void *p_ptr) { \
m_type s = *reinterpret_cast<const String *>(p_ptr); \
return s; \
} \
_FORCE_INLINE_ static void encode(const m_type &p_vec, void *p_ptr) { \
String *arr = reinterpret_cast<String *>(p_ptr); \
*arr = p_vec; \
} \
}; \
\
template <> \
struct PtrToArg<const m_type &> { \
_FORCE_INLINE_ static m_type convert(const void *p_ptr) { \
m_type s = *reinterpret_cast<const String *>(p_ptr); \
return s; \
} \
}
MAKE_STRINGCONV_BY_REFERENCE(IPAddress);
// No EncodeT because direct pointer conversion not possible.
template <>
struct PtrToArg<Vector<Face3>> {
_FORCE_INLINE_ static Vector<Face3> convert(const void *p_ptr) {
const Vector<Vector3> *dvs = reinterpret_cast<const Vector<Vector3> *>(p_ptr);
Vector<Face3> ret;
int len = dvs->size() / 3;
ret.resize(len);
{
const Vector3 *r = dvs->ptr();
Face3 *w = ret.ptrw();
for (int i = 0; i < len; i++) {
w[i].vertex[0] = r[i * 3 + 0];
w[i].vertex[1] = r[i * 3 + 1];
w[i].vertex[2] = r[i * 3 + 2];
}
}
return ret;
}
_FORCE_INLINE_ static void encode(const Vector<Face3> &p_vec, void *p_ptr) {
Vector<Vector3> *arr = reinterpret_cast<Vector<Vector3> *>(p_ptr);
int len = p_vec.size();
arr->resize(len * 3);
{
const Face3 *r = p_vec.ptr();
Vector3 *w = arr->ptrw();
for (int i = 0; i < len; i++) {
w[i * 3 + 0] = r[i].vertex[0];
w[i * 3 + 1] = r[i].vertex[1];
w[i * 3 + 2] = r[i].vertex[2];
}
}
}
};
// No EncodeT because direct pointer conversion not possible.
template <>
struct PtrToArg<const Vector<Face3> &> {
_FORCE_INLINE_ static Vector<Face3> convert(const void *p_ptr) {
const Vector<Vector3> *dvs = reinterpret_cast<const Vector<Vector3> *>(p_ptr);
Vector<Face3> ret;
int len = dvs->size() / 3;
ret.resize(len);
{
const Vector3 *r = dvs->ptr();
Face3 *w = ret.ptrw();
for (int i = 0; i < len; i++) {
w[i].vertex[0] = r[i * 3 + 0];
w[i].vertex[1] = r[i * 3 + 1];
w[i].vertex[2] = r[i * 3 + 2];
}
}
return ret;
}
};
#endif // METHOD_PTRCALL_H

View file

@ -0,0 +1,156 @@
/**************************************************************************/
/* native_ptr.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 NATIVE_PTR_H
#define NATIVE_PTR_H
#include "core/math/audio_frame.h"
#include "core/variant/method_ptrcall.h"
#include "core/variant/type_info.h"
template <typename T>
struct GDExtensionConstPtr {
const T *data = nullptr;
GDExtensionConstPtr(const T *p_assign) { data = p_assign; }
static const char *get_name() { return "const void"; }
operator const T *() const { return data; }
operator Variant() const { return uint64_t(data); }
};
template <typename T>
struct GDExtensionPtr {
T *data = nullptr;
GDExtensionPtr(T *p_assign) { data = p_assign; }
static const char *get_name() { return "void"; }
operator T *() const { return data; }
operator Variant() const { return uint64_t(data); }
};
#define GDVIRTUAL_NATIVE_PTR(m_type) \
template <> \
struct GDExtensionConstPtr<const m_type> { \
const m_type *data = nullptr; \
GDExtensionConstPtr() {} \
GDExtensionConstPtr(const m_type *p_assign) { data = p_assign; } \
static const char *get_name() { return "const " #m_type; } \
operator const m_type *() const { return data; } \
operator Variant() const { return uint64_t(data); } \
}; \
template <> \
struct VariantCaster<GDExtensionConstPtr<const m_type>> { \
static _FORCE_INLINE_ GDExtensionConstPtr<const m_type> cast(const Variant &p_variant) { \
return GDExtensionConstPtr<const m_type>((const m_type *)p_variant.operator uint64_t()); \
} \
}; \
template <> \
struct VariantInternalAccessor<GDExtensionConstPtr<const m_type>> { \
static _FORCE_INLINE_ const GDExtensionConstPtr<const m_type> &get(const Variant *v) { return *reinterpret_cast<const GDExtensionConstPtr<const m_type> *>(VariantInternal::get_int(v)); } \
static _FORCE_INLINE_ void set(Variant *v, const GDExtensionConstPtr<const m_type> &p_value) { *VariantInternal::get_int(v) = uint64_t(p_value.data); } \
}; \
template <> \
struct GDExtensionPtr<m_type> { \
m_type *data = nullptr; \
GDExtensionPtr() {} \
GDExtensionPtr(m_type *p_assign) { data = p_assign; } \
static const char *get_name() { return #m_type; } \
operator m_type *() const { return data; } \
operator Variant() const { return uint64_t(data); } \
}; \
template <> \
struct VariantCaster<GDExtensionPtr<m_type>> { \
static _FORCE_INLINE_ GDExtensionPtr<m_type> cast(const Variant &p_variant) { \
return GDExtensionPtr<m_type>((m_type *)p_variant.operator uint64_t()); \
} \
}; \
template <> \
struct VariantInternalAccessor<GDExtensionPtr<m_type>> { \
static _FORCE_INLINE_ const GDExtensionPtr<m_type> &get(const Variant *v) { return *reinterpret_cast<const GDExtensionPtr<m_type> *>(VariantInternal::get_int(v)); } \
static _FORCE_INLINE_ void set(Variant *v, const GDExtensionPtr<m_type> &p_value) { *VariantInternal::get_int(v) = uint64_t(p_value.data); } \
};
template <typename T>
struct GetTypeInfo<GDExtensionConstPtr<T>> {
static const Variant::Type VARIANT_TYPE = Variant::NIL;
static const GodotTypeInfo::Metadata METADATA = GodotTypeInfo::METADATA_NONE;
static inline PropertyInfo get_class_info() {
return PropertyInfo(Variant::INT, String(), PROPERTY_HINT_INT_IS_POINTER, GDExtensionConstPtr<T>::get_name());
}
};
template <typename T>
struct GetTypeInfo<GDExtensionPtr<T>> {
static const Variant::Type VARIANT_TYPE = Variant::NIL;
static const GodotTypeInfo::Metadata METADATA = GodotTypeInfo::METADATA_NONE;
static inline PropertyInfo get_class_info() {
return PropertyInfo(Variant::INT, String(), PROPERTY_HINT_INT_IS_POINTER, GDExtensionPtr<T>::get_name());
}
};
template <typename T>
struct PtrToArg<GDExtensionConstPtr<T>> {
_FORCE_INLINE_ static GDExtensionConstPtr<T> convert(const void *p_ptr) {
return GDExtensionConstPtr<T>(reinterpret_cast<const T *>(p_ptr));
}
typedef const T *EncodeT;
_FORCE_INLINE_ static void encode(GDExtensionConstPtr<T> p_val, void *p_ptr) {
*((const T **)p_ptr) = p_val.data;
}
};
template <typename T>
struct PtrToArg<GDExtensionPtr<T>> {
_FORCE_INLINE_ static GDExtensionPtr<T> convert(const void *p_ptr) {
return GDExtensionPtr<T>(reinterpret_cast<const T *>(p_ptr));
}
typedef T *EncodeT;
_FORCE_INLINE_ static void encode(GDExtensionPtr<T> p_val, void *p_ptr) {
*((T **)p_ptr) = p_val.data;
}
};
GDVIRTUAL_NATIVE_PTR(void)
GDVIRTUAL_NATIVE_PTR(AudioFrame)
GDVIRTUAL_NATIVE_PTR(bool)
GDVIRTUAL_NATIVE_PTR(char)
GDVIRTUAL_NATIVE_PTR(char16_t)
GDVIRTUAL_NATIVE_PTR(char32_t)
GDVIRTUAL_NATIVE_PTR(wchar_t)
GDVIRTUAL_NATIVE_PTR(uint8_t)
GDVIRTUAL_NATIVE_PTR(uint8_t *)
GDVIRTUAL_NATIVE_PTR(int8_t)
GDVIRTUAL_NATIVE_PTR(uint16_t)
GDVIRTUAL_NATIVE_PTR(int16_t)
GDVIRTUAL_NATIVE_PTR(uint32_t)
GDVIRTUAL_NATIVE_PTR(int32_t)
GDVIRTUAL_NATIVE_PTR(int64_t)
GDVIRTUAL_NATIVE_PTR(uint64_t)
GDVIRTUAL_NATIVE_PTR(float)
GDVIRTUAL_NATIVE_PTR(double)
#endif // NATIVE_PTR_H

View file

@ -0,0 +1,339 @@
/**************************************************************************/
/* type_info.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 TYPE_INFO_H
#define TYPE_INFO_H
#include "core/typedefs.h"
#include <type_traits>
namespace GodotTypeInfo {
enum Metadata {
METADATA_NONE,
METADATA_INT_IS_INT8,
METADATA_INT_IS_INT16,
METADATA_INT_IS_INT32,
METADATA_INT_IS_INT64,
METADATA_INT_IS_UINT8,
METADATA_INT_IS_UINT16,
METADATA_INT_IS_UINT32,
METADATA_INT_IS_UINT64,
METADATA_REAL_IS_FLOAT,
METADATA_REAL_IS_DOUBLE
};
}
// If the compiler fails because it's trying to instantiate the primary 'GetTypeInfo' template
// instead of one of the specializations, it's most likely because the type 'T' is not supported.
// If 'T' is a class that inherits 'Object', make sure it can see the actual class declaration
// instead of a forward declaration. You can always forward declare 'T' in a header file, and then
// include the actual declaration of 'T' in the source file where 'GetTypeInfo<T>' is instantiated.
template <typename T, typename = void>
struct GetTypeInfo;
#define MAKE_TYPE_INFO(m_type, m_var_type) \
template <> \
struct GetTypeInfo<m_type> { \
static const Variant::Type VARIANT_TYPE = m_var_type; \
static const GodotTypeInfo::Metadata METADATA = GodotTypeInfo::METADATA_NONE; \
static inline PropertyInfo get_class_info() { \
return PropertyInfo(VARIANT_TYPE, String()); \
} \
}; \
template <> \
struct GetTypeInfo<const m_type &> { \
static const Variant::Type VARIANT_TYPE = m_var_type; \
static const GodotTypeInfo::Metadata METADATA = GodotTypeInfo::METADATA_NONE; \
static inline PropertyInfo get_class_info() { \
return PropertyInfo(VARIANT_TYPE, String()); \
} \
};
#define MAKE_TYPE_INFO_WITH_META(m_type, m_var_type, m_metadata) \
template <> \
struct GetTypeInfo<m_type> { \
static const Variant::Type VARIANT_TYPE = m_var_type; \
static const GodotTypeInfo::Metadata METADATA = m_metadata; \
static inline PropertyInfo get_class_info() { \
return PropertyInfo(VARIANT_TYPE, String()); \
} \
}; \
template <> \
struct GetTypeInfo<const m_type &> { \
static const Variant::Type VARIANT_TYPE = m_var_type; \
static const GodotTypeInfo::Metadata METADATA = m_metadata; \
static inline PropertyInfo get_class_info() { \
return PropertyInfo(VARIANT_TYPE, String()); \
} \
};
MAKE_TYPE_INFO(bool, Variant::BOOL)
MAKE_TYPE_INFO_WITH_META(uint8_t, Variant::INT, GodotTypeInfo::METADATA_INT_IS_UINT8)
MAKE_TYPE_INFO_WITH_META(int8_t, Variant::INT, GodotTypeInfo::METADATA_INT_IS_INT8)
MAKE_TYPE_INFO_WITH_META(uint16_t, Variant::INT, GodotTypeInfo::METADATA_INT_IS_UINT16)
MAKE_TYPE_INFO_WITH_META(int16_t, Variant::INT, GodotTypeInfo::METADATA_INT_IS_INT16)
MAKE_TYPE_INFO_WITH_META(uint32_t, Variant::INT, GodotTypeInfo::METADATA_INT_IS_UINT32)
MAKE_TYPE_INFO_WITH_META(int32_t, Variant::INT, GodotTypeInfo::METADATA_INT_IS_INT32)
MAKE_TYPE_INFO_WITH_META(uint64_t, Variant::INT, GodotTypeInfo::METADATA_INT_IS_UINT64)
MAKE_TYPE_INFO_WITH_META(int64_t, Variant::INT, GodotTypeInfo::METADATA_INT_IS_INT64)
MAKE_TYPE_INFO(char16_t, Variant::INT)
MAKE_TYPE_INFO(char32_t, Variant::INT)
MAKE_TYPE_INFO_WITH_META(float, Variant::FLOAT, GodotTypeInfo::METADATA_REAL_IS_FLOAT)
MAKE_TYPE_INFO_WITH_META(double, Variant::FLOAT, GodotTypeInfo::METADATA_REAL_IS_DOUBLE)
MAKE_TYPE_INFO(String, Variant::STRING)
MAKE_TYPE_INFO(Vector2, Variant::VECTOR2)
MAKE_TYPE_INFO(Rect2, Variant::RECT2)
MAKE_TYPE_INFO(Vector3, Variant::VECTOR3)
MAKE_TYPE_INFO(Vector2i, Variant::VECTOR2I)
MAKE_TYPE_INFO(Rect2i, Variant::RECT2I)
MAKE_TYPE_INFO(Vector3i, Variant::VECTOR3I)
MAKE_TYPE_INFO(Vector4, Variant::VECTOR4)
MAKE_TYPE_INFO(Vector4i, Variant::VECTOR4I)
MAKE_TYPE_INFO(Transform2D, Variant::TRANSFORM2D)
MAKE_TYPE_INFO(Plane, Variant::PLANE)
MAKE_TYPE_INFO(Quaternion, Variant::QUATERNION)
MAKE_TYPE_INFO(AABB, Variant::AABB)
MAKE_TYPE_INFO(Basis, Variant::BASIS)
MAKE_TYPE_INFO(Transform3D, Variant::TRANSFORM3D)
MAKE_TYPE_INFO(Projection, Variant::PROJECTION)
MAKE_TYPE_INFO(Color, Variant::COLOR)
MAKE_TYPE_INFO(StringName, Variant::STRING_NAME)
MAKE_TYPE_INFO(NodePath, Variant::NODE_PATH)
MAKE_TYPE_INFO(RID, Variant::RID)
MAKE_TYPE_INFO(Callable, Variant::CALLABLE)
MAKE_TYPE_INFO(Signal, Variant::SIGNAL)
MAKE_TYPE_INFO(Dictionary, Variant::DICTIONARY)
MAKE_TYPE_INFO(Array, Variant::ARRAY)
MAKE_TYPE_INFO(PackedByteArray, Variant::PACKED_BYTE_ARRAY)
MAKE_TYPE_INFO(PackedInt32Array, Variant::PACKED_INT32_ARRAY)
MAKE_TYPE_INFO(PackedInt64Array, Variant::PACKED_INT64_ARRAY)
MAKE_TYPE_INFO(PackedFloat32Array, Variant::PACKED_FLOAT32_ARRAY)
MAKE_TYPE_INFO(PackedFloat64Array, Variant::PACKED_FLOAT64_ARRAY)
MAKE_TYPE_INFO(PackedStringArray, Variant::PACKED_STRING_ARRAY)
MAKE_TYPE_INFO(PackedVector2Array, Variant::PACKED_VECTOR2_ARRAY)
MAKE_TYPE_INFO(PackedVector3Array, Variant::PACKED_VECTOR3_ARRAY)
MAKE_TYPE_INFO(PackedColorArray, Variant::PACKED_COLOR_ARRAY)
MAKE_TYPE_INFO(PackedVector4Array, Variant::PACKED_VECTOR4_ARRAY)
MAKE_TYPE_INFO(IPAddress, Variant::STRING)
//objectID
template <>
struct GetTypeInfo<ObjectID> {
static const Variant::Type VARIANT_TYPE = Variant::INT;
static const GodotTypeInfo::Metadata METADATA = GodotTypeInfo::METADATA_INT_IS_UINT64;
static inline PropertyInfo get_class_info() {
return PropertyInfo(Variant::INT, String(), PROPERTY_HINT_INT_IS_OBJECTID);
}
};
//for variant
template <>
struct GetTypeInfo<Variant> {
static const Variant::Type VARIANT_TYPE = Variant::NIL;
static const GodotTypeInfo::Metadata METADATA = GodotTypeInfo::METADATA_NONE;
static inline PropertyInfo get_class_info() {
return PropertyInfo(Variant::NIL, String(), PROPERTY_HINT_NONE, String(), PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_NIL_IS_VARIANT);
}
};
template <>
struct GetTypeInfo<const Variant &> {
static const Variant::Type VARIANT_TYPE = Variant::NIL;
static const GodotTypeInfo::Metadata METADATA = GodotTypeInfo::METADATA_NONE;
static inline PropertyInfo get_class_info() {
return PropertyInfo(Variant::NIL, String(), PROPERTY_HINT_NONE, String(), PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_NIL_IS_VARIANT);
}
};
#define MAKE_TEMPLATE_TYPE_INFO(m_template, m_type, m_var_type) \
template <> \
struct GetTypeInfo<m_template<m_type>> { \
static const Variant::Type VARIANT_TYPE = m_var_type; \
static const GodotTypeInfo::Metadata METADATA = GodotTypeInfo::METADATA_NONE; \
static inline PropertyInfo get_class_info() { \
return PropertyInfo(VARIANT_TYPE, String()); \
} \
}; \
template <> \
struct GetTypeInfo<const m_template<m_type> &> { \
static const Variant::Type VARIANT_TYPE = m_var_type; \
static const GodotTypeInfo::Metadata METADATA = GodotTypeInfo::METADATA_NONE; \
static inline PropertyInfo get_class_info() { \
return PropertyInfo(VARIANT_TYPE, String()); \
} \
};
MAKE_TEMPLATE_TYPE_INFO(Vector, Variant, Variant::ARRAY)
MAKE_TEMPLATE_TYPE_INFO(Vector, RID, Variant::ARRAY)
MAKE_TEMPLATE_TYPE_INFO(Vector, Plane, Variant::ARRAY)
MAKE_TEMPLATE_TYPE_INFO(Vector, Face3, Variant::PACKED_VECTOR3_ARRAY)
MAKE_TEMPLATE_TYPE_INFO(Vector, StringName, Variant::PACKED_STRING_ARRAY)
template <typename T>
struct GetTypeInfo<T *, std::enable_if_t<std::is_base_of_v<Object, T>>> {
static const Variant::Type VARIANT_TYPE = Variant::OBJECT;
static const GodotTypeInfo::Metadata METADATA = GodotTypeInfo::METADATA_NONE;
static inline PropertyInfo get_class_info() {
return PropertyInfo(StringName(T::get_class_static()));
}
};
namespace godot {
namespace details {
inline String enum_qualified_name_to_class_info_name(const String &p_qualified_name) {
Vector<String> parts = p_qualified_name.split("::", false);
if (parts.size() <= 2) {
return String(".").join(parts);
}
// Contains namespace. We only want the class and enum names.
return parts[parts.size() - 2] + "." + parts[parts.size() - 1];
}
} // namespace details
} // namespace godot
#define TEMPL_MAKE_ENUM_TYPE_INFO(m_enum, m_impl) \
template <> \
struct GetTypeInfo<m_impl> { \
static const Variant::Type VARIANT_TYPE = Variant::INT; \
static const GodotTypeInfo::Metadata METADATA = GodotTypeInfo::METADATA_NONE; \
static inline PropertyInfo get_class_info() { \
return PropertyInfo(Variant::INT, String(), PROPERTY_HINT_NONE, String(), PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_CLASS_IS_ENUM, \
godot::details::enum_qualified_name_to_class_info_name(String(#m_enum))); \
} \
};
#define MAKE_ENUM_TYPE_INFO(m_enum) \
TEMPL_MAKE_ENUM_TYPE_INFO(m_enum, m_enum) \
TEMPL_MAKE_ENUM_TYPE_INFO(m_enum, m_enum const) \
TEMPL_MAKE_ENUM_TYPE_INFO(m_enum, m_enum &) \
TEMPL_MAKE_ENUM_TYPE_INFO(m_enum, const m_enum &)
template <typename T>
inline StringName __constant_get_enum_name(T param, const String &p_constant) {
if constexpr (GetTypeInfo<T>::VARIANT_TYPE == Variant::NIL) {
ERR_PRINT("Missing VARIANT_ENUM_CAST for constant's enum: " + p_constant);
}
return GetTypeInfo<T>::get_class_info().class_name;
}
template <typename T>
class BitField {
int64_t value = 0;
public:
_FORCE_INLINE_ BitField<T> &set_flag(T p_flag) {
value |= (int64_t)p_flag;
return *this;
}
_FORCE_INLINE_ bool has_flag(T p_flag) const { return value & (int64_t)p_flag; }
_FORCE_INLINE_ bool is_empty() const { return value == 0; }
_FORCE_INLINE_ void clear_flag(T p_flag) { value &= ~(int64_t)p_flag; }
_FORCE_INLINE_ void clear() { value = 0; }
_FORCE_INLINE_ constexpr BitField() = default;
_FORCE_INLINE_ constexpr BitField(int64_t p_value) { value = p_value; }
_FORCE_INLINE_ constexpr BitField(T p_value) { value = (int64_t)p_value; }
_FORCE_INLINE_ operator int64_t() const { return value; }
_FORCE_INLINE_ operator Variant() const { return value; }
_FORCE_INLINE_ BitField<T> operator^(const BitField<T> &p_b) const { return BitField<T>(value ^ p_b.value); }
};
#define TEMPL_MAKE_BITFIELD_TYPE_INFO(m_enum, m_impl) \
template <> \
struct GetTypeInfo<m_impl> { \
static const Variant::Type VARIANT_TYPE = Variant::INT; \
static const GodotTypeInfo::Metadata METADATA = GodotTypeInfo::METADATA_NONE; \
static inline PropertyInfo get_class_info() { \
return PropertyInfo(Variant::INT, String(), PROPERTY_HINT_NONE, String(), PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_CLASS_IS_BITFIELD, \
godot::details::enum_qualified_name_to_class_info_name(String(#m_enum))); \
} \
}; \
template <> \
struct GetTypeInfo<BitField<m_impl>> { \
static const Variant::Type VARIANT_TYPE = Variant::INT; \
static const GodotTypeInfo::Metadata METADATA = GodotTypeInfo::METADATA_NONE; \
static inline PropertyInfo get_class_info() { \
return PropertyInfo(Variant::INT, String(), PROPERTY_HINT_NONE, String(), PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_CLASS_IS_BITFIELD, \
godot::details::enum_qualified_name_to_class_info_name(String(#m_enum))); \
} \
};
#define MAKE_BITFIELD_TYPE_INFO(m_enum) \
TEMPL_MAKE_BITFIELD_TYPE_INFO(m_enum, m_enum) \
TEMPL_MAKE_BITFIELD_TYPE_INFO(m_enum, m_enum const) \
TEMPL_MAKE_BITFIELD_TYPE_INFO(m_enum, m_enum &) \
TEMPL_MAKE_BITFIELD_TYPE_INFO(m_enum, const m_enum &)
template <typename T>
inline StringName __constant_get_bitfield_name(T param, const String &p_constant) {
if (GetTypeInfo<T>::VARIANT_TYPE == Variant::NIL) {
ERR_PRINT("Missing VARIANT_ENUM_CAST for constant's bitfield: " + p_constant);
}
return GetTypeInfo<BitField<T>>::get_class_info().class_name;
}
#define CLASS_INFO(m_type) (GetTypeInfo<m_type *>::get_class_info())
template <typename T>
struct ZeroInitializer {
static void initialize(T &value) {} //no initialization by default
};
template <>
struct ZeroInitializer<bool> {
static void initialize(bool &value) { value = false; }
};
template <typename T>
struct ZeroInitializer<T *> {
static void initialize(T *&value) { value = nullptr; }
};
#define ZERO_INITIALIZER_NUMBER(m_type) \
template <> \
struct ZeroInitializer<m_type> { \
static void initialize(m_type &value) { value = 0; } \
};
ZERO_INITIALIZER_NUMBER(uint8_t)
ZERO_INITIALIZER_NUMBER(int8_t)
ZERO_INITIALIZER_NUMBER(uint16_t)
ZERO_INITIALIZER_NUMBER(int16_t)
ZERO_INITIALIZER_NUMBER(uint32_t)
ZERO_INITIALIZER_NUMBER(int32_t)
ZERO_INITIALIZER_NUMBER(uint64_t)
ZERO_INITIALIZER_NUMBER(int64_t)
ZERO_INITIALIZER_NUMBER(char16_t)
ZERO_INITIALIZER_NUMBER(char32_t)
ZERO_INITIALIZER_NUMBER(float)
ZERO_INITIALIZER_NUMBER(double)
#endif // TYPE_INFO_H

View file

@ -0,0 +1,255 @@
/**************************************************************************/
/* typed_array.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 TYPED_ARRAY_H
#define TYPED_ARRAY_H
#include "core/object/object.h"
#include "core/variant/array.h"
#include "core/variant/binder_common.h"
#include "core/variant/method_ptrcall.h"
#include "core/variant/type_info.h"
#include "core/variant/variant.h"
template <typename T>
class TypedArray : public Array {
public:
_FORCE_INLINE_ void operator=(const Array &p_array) {
ERR_FAIL_COND_MSG(!is_same_typed(p_array), "Cannot assign an array with a different element type.");
_ref(p_array);
}
_FORCE_INLINE_ TypedArray(const Variant &p_variant) :
TypedArray(Array(p_variant)) {
}
_FORCE_INLINE_ TypedArray(const Array &p_array) {
set_typed(Variant::OBJECT, T::get_class_static(), Variant());
if (is_same_typed(p_array)) {
_ref(p_array);
} else {
assign(p_array);
}
}
_FORCE_INLINE_ TypedArray() {
set_typed(Variant::OBJECT, T::get_class_static(), Variant());
}
};
template <typename T>
struct VariantInternalAccessor<TypedArray<T>> {
static _FORCE_INLINE_ TypedArray<T> get(const Variant *v) { return *VariantInternal::get_array(v); }
static _FORCE_INLINE_ void set(Variant *v, const TypedArray<T> &p_array) { *VariantInternal::get_array(v) = p_array; }
};
template <typename T>
struct VariantInternalAccessor<const TypedArray<T> &> {
static _FORCE_INLINE_ TypedArray<T> get(const Variant *v) { return *VariantInternal::get_array(v); }
static _FORCE_INLINE_ void set(Variant *v, const TypedArray<T> &p_array) { *VariantInternal::get_array(v) = p_array; }
};
//specialization for the rest of variant types
#define MAKE_TYPED_ARRAY(m_type, m_variant_type) \
template <> \
class TypedArray<m_type> : public Array { \
public: \
_FORCE_INLINE_ void operator=(const Array &p_array) { \
ERR_FAIL_COND_MSG(!is_same_typed(p_array), "Cannot assign an array with a different element type."); \
_ref(p_array); \
} \
_FORCE_INLINE_ TypedArray(const Variant &p_variant) : \
TypedArray(Array(p_variant)) { \
} \
_FORCE_INLINE_ TypedArray(const Array &p_array) { \
set_typed(m_variant_type, StringName(), Variant()); \
if (is_same_typed(p_array)) { \
_ref(p_array); \
} else { \
assign(p_array); \
} \
} \
_FORCE_INLINE_ TypedArray() { \
set_typed(m_variant_type, StringName(), Variant()); \
} \
};
// All Variant::OBJECT types are intentionally omitted from this list because they are handled by
// the unspecialized TypedArray definition.
MAKE_TYPED_ARRAY(bool, Variant::BOOL)
MAKE_TYPED_ARRAY(uint8_t, Variant::INT)
MAKE_TYPED_ARRAY(int8_t, Variant::INT)
MAKE_TYPED_ARRAY(uint16_t, Variant::INT)
MAKE_TYPED_ARRAY(int16_t, Variant::INT)
MAKE_TYPED_ARRAY(uint32_t, Variant::INT)
MAKE_TYPED_ARRAY(int32_t, Variant::INT)
MAKE_TYPED_ARRAY(uint64_t, Variant::INT)
MAKE_TYPED_ARRAY(int64_t, Variant::INT)
MAKE_TYPED_ARRAY(float, Variant::FLOAT)
MAKE_TYPED_ARRAY(double, Variant::FLOAT)
MAKE_TYPED_ARRAY(String, Variant::STRING)
MAKE_TYPED_ARRAY(Vector2, Variant::VECTOR2)
MAKE_TYPED_ARRAY(Vector2i, Variant::VECTOR2I)
MAKE_TYPED_ARRAY(Rect2, Variant::RECT2)
MAKE_TYPED_ARRAY(Rect2i, Variant::RECT2I)
MAKE_TYPED_ARRAY(Vector3, Variant::VECTOR3)
MAKE_TYPED_ARRAY(Vector3i, Variant::VECTOR3I)
MAKE_TYPED_ARRAY(Transform2D, Variant::TRANSFORM2D)
MAKE_TYPED_ARRAY(Vector4, Variant::VECTOR4)
MAKE_TYPED_ARRAY(Vector4i, Variant::VECTOR4I)
MAKE_TYPED_ARRAY(Plane, Variant::PLANE)
MAKE_TYPED_ARRAY(Quaternion, Variant::QUATERNION)
MAKE_TYPED_ARRAY(AABB, Variant::AABB)
MAKE_TYPED_ARRAY(Basis, Variant::BASIS)
MAKE_TYPED_ARRAY(Transform3D, Variant::TRANSFORM3D)
MAKE_TYPED_ARRAY(Projection, Variant::PROJECTION)
MAKE_TYPED_ARRAY(Color, Variant::COLOR)
MAKE_TYPED_ARRAY(StringName, Variant::STRING_NAME)
MAKE_TYPED_ARRAY(NodePath, Variant::NODE_PATH)
MAKE_TYPED_ARRAY(RID, Variant::RID)
MAKE_TYPED_ARRAY(Callable, Variant::CALLABLE)
MAKE_TYPED_ARRAY(Signal, Variant::SIGNAL)
MAKE_TYPED_ARRAY(Dictionary, Variant::DICTIONARY)
MAKE_TYPED_ARRAY(Array, Variant::ARRAY)
MAKE_TYPED_ARRAY(PackedByteArray, Variant::PACKED_BYTE_ARRAY)
MAKE_TYPED_ARRAY(PackedInt32Array, Variant::PACKED_INT32_ARRAY)
MAKE_TYPED_ARRAY(PackedInt64Array, Variant::PACKED_INT64_ARRAY)
MAKE_TYPED_ARRAY(PackedFloat32Array, Variant::PACKED_FLOAT32_ARRAY)
MAKE_TYPED_ARRAY(PackedFloat64Array, Variant::PACKED_FLOAT64_ARRAY)
MAKE_TYPED_ARRAY(PackedStringArray, Variant::PACKED_STRING_ARRAY)
MAKE_TYPED_ARRAY(PackedVector2Array, Variant::PACKED_VECTOR2_ARRAY)
MAKE_TYPED_ARRAY(PackedVector3Array, Variant::PACKED_VECTOR3_ARRAY)
MAKE_TYPED_ARRAY(PackedColorArray, Variant::PACKED_COLOR_ARRAY)
MAKE_TYPED_ARRAY(PackedVector4Array, Variant::PACKED_VECTOR4_ARRAY)
MAKE_TYPED_ARRAY(IPAddress, Variant::STRING)
template <typename T>
struct PtrToArg<TypedArray<T>> {
_FORCE_INLINE_ static TypedArray<T> convert(const void *p_ptr) {
return TypedArray<T>(*reinterpret_cast<const Array *>(p_ptr));
}
typedef Array EncodeT;
_FORCE_INLINE_ static void encode(TypedArray<T> p_val, void *p_ptr) {
*(Array *)p_ptr = p_val;
}
};
template <typename T>
struct PtrToArg<const TypedArray<T> &> {
typedef Array EncodeT;
_FORCE_INLINE_ static TypedArray<T> convert(const void *p_ptr) {
return TypedArray<T>(*reinterpret_cast<const Array *>(p_ptr));
}
};
template <typename T>
struct GetTypeInfo<TypedArray<T>> {
static const Variant::Type VARIANT_TYPE = Variant::ARRAY;
static const GodotTypeInfo::Metadata METADATA = GodotTypeInfo::METADATA_NONE;
static inline PropertyInfo get_class_info() {
return PropertyInfo(Variant::ARRAY, String(), PROPERTY_HINT_ARRAY_TYPE, T::get_class_static());
}
};
template <typename T>
struct GetTypeInfo<const TypedArray<T> &> {
static const Variant::Type VARIANT_TYPE = Variant::ARRAY;
static const GodotTypeInfo::Metadata METADATA = GodotTypeInfo::METADATA_NONE;
static inline PropertyInfo get_class_info() {
return PropertyInfo(Variant::ARRAY, String(), PROPERTY_HINT_ARRAY_TYPE, T::get_class_static());
}
};
#define MAKE_TYPED_ARRAY_INFO(m_type, m_variant_type) \
template <> \
struct GetTypeInfo<TypedArray<m_type>> { \
static const Variant::Type VARIANT_TYPE = Variant::ARRAY; \
static const GodotTypeInfo::Metadata METADATA = GodotTypeInfo::METADATA_NONE; \
static inline PropertyInfo get_class_info() { \
return PropertyInfo(Variant::ARRAY, String(), PROPERTY_HINT_ARRAY_TYPE, Variant::get_type_name(m_variant_type)); \
} \
}; \
template <> \
struct GetTypeInfo<const TypedArray<m_type> &> { \
static const Variant::Type VARIANT_TYPE = Variant::ARRAY; \
static const GodotTypeInfo::Metadata METADATA = GodotTypeInfo::METADATA_NONE; \
static inline PropertyInfo get_class_info() { \
return PropertyInfo(Variant::ARRAY, String(), PROPERTY_HINT_ARRAY_TYPE, Variant::get_type_name(m_variant_type)); \
} \
};
MAKE_TYPED_ARRAY_INFO(bool, Variant::BOOL)
MAKE_TYPED_ARRAY_INFO(uint8_t, Variant::INT)
MAKE_TYPED_ARRAY_INFO(int8_t, Variant::INT)
MAKE_TYPED_ARRAY_INFO(uint16_t, Variant::INT)
MAKE_TYPED_ARRAY_INFO(int16_t, Variant::INT)
MAKE_TYPED_ARRAY_INFO(uint32_t, Variant::INT)
MAKE_TYPED_ARRAY_INFO(int32_t, Variant::INT)
MAKE_TYPED_ARRAY_INFO(uint64_t, Variant::INT)
MAKE_TYPED_ARRAY_INFO(int64_t, Variant::INT)
MAKE_TYPED_ARRAY_INFO(float, Variant::FLOAT)
MAKE_TYPED_ARRAY_INFO(double, Variant::FLOAT)
MAKE_TYPED_ARRAY_INFO(String, Variant::STRING)
MAKE_TYPED_ARRAY_INFO(Vector2, Variant::VECTOR2)
MAKE_TYPED_ARRAY_INFO(Vector2i, Variant::VECTOR2I)
MAKE_TYPED_ARRAY_INFO(Rect2, Variant::RECT2)
MAKE_TYPED_ARRAY_INFO(Rect2i, Variant::RECT2I)
MAKE_TYPED_ARRAY_INFO(Vector3, Variant::VECTOR3)
MAKE_TYPED_ARRAY_INFO(Vector3i, Variant::VECTOR3I)
MAKE_TYPED_ARRAY_INFO(Transform2D, Variant::TRANSFORM2D)
MAKE_TYPED_ARRAY_INFO(Vector4, Variant::VECTOR4)
MAKE_TYPED_ARRAY_INFO(Vector4i, Variant::VECTOR4I)
MAKE_TYPED_ARRAY_INFO(Plane, Variant::PLANE)
MAKE_TYPED_ARRAY_INFO(Quaternion, Variant::QUATERNION)
MAKE_TYPED_ARRAY_INFO(AABB, Variant::AABB)
MAKE_TYPED_ARRAY_INFO(Basis, Variant::BASIS)
MAKE_TYPED_ARRAY_INFO(Transform3D, Variant::TRANSFORM3D)
MAKE_TYPED_ARRAY_INFO(Projection, Variant::PROJECTION)
MAKE_TYPED_ARRAY_INFO(Color, Variant::COLOR)
MAKE_TYPED_ARRAY_INFO(StringName, Variant::STRING_NAME)
MAKE_TYPED_ARRAY_INFO(NodePath, Variant::NODE_PATH)
MAKE_TYPED_ARRAY_INFO(RID, Variant::RID)
MAKE_TYPED_ARRAY_INFO(Callable, Variant::CALLABLE)
MAKE_TYPED_ARRAY_INFO(Signal, Variant::SIGNAL)
MAKE_TYPED_ARRAY_INFO(Dictionary, Variant::DICTIONARY)
MAKE_TYPED_ARRAY_INFO(Array, Variant::ARRAY)
MAKE_TYPED_ARRAY_INFO(PackedByteArray, Variant::PACKED_BYTE_ARRAY)
MAKE_TYPED_ARRAY_INFO(PackedInt32Array, Variant::PACKED_INT32_ARRAY)
MAKE_TYPED_ARRAY_INFO(PackedInt64Array, Variant::PACKED_INT64_ARRAY)
MAKE_TYPED_ARRAY_INFO(PackedFloat32Array, Variant::PACKED_FLOAT32_ARRAY)
MAKE_TYPED_ARRAY_INFO(PackedFloat64Array, Variant::PACKED_FLOAT64_ARRAY)
MAKE_TYPED_ARRAY_INFO(PackedStringArray, Variant::PACKED_STRING_ARRAY)
MAKE_TYPED_ARRAY_INFO(PackedVector2Array, Variant::PACKED_VECTOR2_ARRAY)
MAKE_TYPED_ARRAY_INFO(PackedVector3Array, Variant::PACKED_VECTOR3_ARRAY)
MAKE_TYPED_ARRAY_INFO(PackedColorArray, Variant::PACKED_COLOR_ARRAY)
MAKE_TYPED_ARRAY_INFO(PackedVector4Array, Variant::PACKED_VECTOR4_ARRAY)
MAKE_TYPED_ARRAY_INFO(IPAddress, Variant::STRING)
#undef MAKE_TYPED_ARRAY
#undef MAKE_TYPED_ARRAY_INFO
#endif // TYPED_ARRAY_H

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,941 @@
/**************************************************************************/
/* variant.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_H
#define VARIANT_H
#include "core/core_string_names.h"
#include "core/input/input_enums.h"
#include "core/io/ip_address.h"
#include "core/math/aabb.h"
#include "core/math/basis.h"
#include "core/math/color.h"
#include "core/math/face3.h"
#include "core/math/plane.h"
#include "core/math/projection.h"
#include "core/math/quaternion.h"
#include "core/math/rect2.h"
#include "core/math/rect2i.h"
#include "core/math/transform_2d.h"
#include "core/math/transform_3d.h"
#include "core/math/vector2.h"
#include "core/math/vector2i.h"
#include "core/math/vector3.h"
#include "core/math/vector3i.h"
#include "core/math/vector4.h"
#include "core/math/vector4i.h"
#include "core/object/object_id.h"
#include "core/os/keyboard.h"
#include "core/string/node_path.h"
#include "core/string/ustring.h"
#include "core/templates/paged_allocator.h"
#include "core/templates/rid.h"
#include "core/variant/array.h"
#include "core/variant/callable.h"
#include "core/variant/dictionary.h"
class Object;
struct PropertyInfo;
struct MethodInfo;
typedef Vector<uint8_t> PackedByteArray;
typedef Vector<int32_t> PackedInt32Array;
typedef Vector<int64_t> PackedInt64Array;
typedef Vector<float> PackedFloat32Array;
typedef Vector<double> PackedFloat64Array;
typedef Vector<real_t> PackedRealArray;
typedef Vector<String> PackedStringArray;
typedef Vector<Vector2> PackedVector2Array;
typedef Vector<Vector3> PackedVector3Array;
typedef Vector<Color> PackedColorArray;
typedef Vector<Vector4> PackedVector4Array;
class Variant {
public:
// If this changes the table in variant_op must be updated
enum Type {
NIL,
// atomic types
BOOL,
INT,
FLOAT,
STRING,
// math types
VECTOR2,
VECTOR2I,
RECT2,
RECT2I,
VECTOR3,
VECTOR3I,
TRANSFORM2D,
VECTOR4,
VECTOR4I,
PLANE,
QUATERNION,
AABB,
BASIS,
TRANSFORM3D,
PROJECTION,
// misc types
COLOR,
STRING_NAME,
NODE_PATH,
RID,
OBJECT,
CALLABLE,
SIGNAL,
DICTIONARY,
ARRAY,
// typed arrays
PACKED_BYTE_ARRAY,
PACKED_INT32_ARRAY,
PACKED_INT64_ARRAY,
PACKED_FLOAT32_ARRAY,
PACKED_FLOAT64_ARRAY,
PACKED_STRING_ARRAY,
PACKED_VECTOR2_ARRAY,
PACKED_VECTOR3_ARRAY,
PACKED_COLOR_ARRAY,
PACKED_VECTOR4_ARRAY,
VARIANT_MAX
};
enum {
// Maximum recursion depth allowed when serializing variants.
MAX_RECURSION_DEPTH = 1024,
};
private:
struct Pools {
union BucketSmall {
BucketSmall() {}
~BucketSmall() {}
Transform2D _transform2d;
::AABB _aabb;
};
union BucketMedium {
BucketMedium() {}
~BucketMedium() {}
Basis _basis;
Transform3D _transform3d;
};
union BucketLarge {
BucketLarge() {}
~BucketLarge() {}
Projection _projection;
};
static PagedAllocator<BucketSmall, true> _bucket_small;
static PagedAllocator<BucketMedium, true> _bucket_medium;
static PagedAllocator<BucketLarge, true> _bucket_large;
};
friend struct _VariantCall;
friend class VariantInternal;
// Variant takes 24 bytes when real_t is float, and 40 bytes if double.
// It only allocates extra memory for AABB/Transform2D (24, 48 if double),
// Basis/Transform3D (48, 96 if double), Projection (64, 128 if double),
// and PackedArray/Array/Dictionary (platform-dependent).
Type type = NIL;
struct ObjData {
ObjectID id;
Object *obj = nullptr;
};
/* array helpers */
struct PackedArrayRefBase {
SafeRefCount refcount;
_FORCE_INLINE_ PackedArrayRefBase *reference() {
if (refcount.ref()) {
return this;
} else {
return nullptr;
}
}
static _FORCE_INLINE_ PackedArrayRefBase *reference_from(PackedArrayRefBase *p_base, PackedArrayRefBase *p_from) {
if (p_base == p_from) {
return p_base; //same thing, do nothing
}
if (p_from->reference()) {
if (p_base->refcount.unref()) {
memdelete(p_base);
}
return p_from;
} else {
return p_base; //keep, could not reference new
}
}
static _FORCE_INLINE_ void destroy(PackedArrayRefBase *p_array) {
if (p_array->refcount.unref()) {
memdelete(p_array);
}
}
_FORCE_INLINE_ virtual ~PackedArrayRefBase() {} //needs virtual destructor, but make inline
};
template <typename T>
struct PackedArrayRef : public PackedArrayRefBase {
Vector<T> array;
static _FORCE_INLINE_ PackedArrayRef<T> *create() {
return memnew(PackedArrayRef<T>);
}
static _FORCE_INLINE_ PackedArrayRef<T> *create(const Vector<T> &p_from) {
return memnew(PackedArrayRef<T>(p_from));
}
static _FORCE_INLINE_ const Vector<T> &get_array(PackedArrayRefBase *p_base) {
return static_cast<PackedArrayRef<T> *>(p_base)->array;
}
static _FORCE_INLINE_ Vector<T> *get_array_ptr(const PackedArrayRefBase *p_base) {
return &const_cast<PackedArrayRef<T> *>(static_cast<const PackedArrayRef<T> *>(p_base))->array;
}
_FORCE_INLINE_ PackedArrayRef(const Vector<T> &p_from) {
array = p_from;
refcount.init();
}
_FORCE_INLINE_ PackedArrayRef() {
refcount.init();
}
};
/* end of array helpers */
_ALWAYS_INLINE_ ObjData &_get_obj();
_ALWAYS_INLINE_ const ObjData &_get_obj() const;
union {
bool _bool;
int64_t _int;
double _float;
Transform2D *_transform2d;
::AABB *_aabb;
Basis *_basis;
Transform3D *_transform3d;
Projection *_projection;
PackedArrayRefBase *packed_array;
void *_ptr; //generic pointer
uint8_t _mem[sizeof(ObjData) > (sizeof(real_t) * 4) ? sizeof(ObjData) : (sizeof(real_t) * 4)]{ 0 };
} _data alignas(8);
void reference(const Variant &p_variant);
static bool initialize_ref(Object *p_object);
void _clear_internal();
_FORCE_INLINE_ void clear() {
static const bool needs_deinit[Variant::VARIANT_MAX] = {
false, //NIL,
false, //BOOL,
false, //INT,
false, //FLOAT,
true, //STRING,
false, //VECTOR2,
false, //VECTOR2I,
false, //RECT2,
false, //RECT2I,
false, //VECTOR3,
false, //VECTOR3I,
true, //TRANSFORM2D,
false, //VECTOR4,
false, //VECTOR4I,
false, //PLANE,
false, //QUATERNION,
true, //AABB,
true, //BASIS,
true, //TRANSFORM,
true, //PROJECTION,
// misc types
false, //COLOR,
true, //STRING_NAME,
true, //NODE_PATH,
false, //RID,
true, //OBJECT,
true, //CALLABLE,
true, //SIGNAL,
true, //DICTIONARY,
true, //ARRAY,
// typed arrays
true, //PACKED_BYTE_ARRAY,
true, //PACKED_INT32_ARRAY,
true, //PACKED_INT64_ARRAY,
true, //PACKED_FLOAT32_ARRAY,
true, //PACKED_FLOAT64_ARRAY,
true, //PACKED_STRING_ARRAY,
true, //PACKED_VECTOR2_ARRAY,
true, //PACKED_VECTOR3_ARRAY,
true, //PACKED_COLOR_ARRAY,
true, //PACKED_VECTOR4_ARRAY,
};
if (unlikely(needs_deinit[type])) { // Make it fast for types that don't need deinit.
_clear_internal();
}
type = NIL;
}
static void _register_variant_operators();
static void _unregister_variant_operators();
static void _register_variant_methods();
static void _unregister_variant_methods();
static void _register_variant_setters_getters();
static void _unregister_variant_setters_getters();
static void _register_variant_constructors();
static void _unregister_variant_destructors();
static void _register_variant_destructors();
static void _unregister_variant_constructors();
static void _register_variant_utility_functions();
static void _unregister_variant_utility_functions();
void _variant_call_error(const String &p_method, Callable::CallError &error);
// Avoid accidental conversion. If you reached this point, it's because you most likely forgot to dereference
// a Variant pointer (so add * like this: *variant_pointer).
Variant(const Variant *) {}
Variant(const Variant **) {}
public:
_FORCE_INLINE_ Type get_type() const {
return type;
}
static String get_type_name(Variant::Type p_type);
static bool can_convert(Type p_type_from, Type p_type_to);
static bool can_convert_strict(Type p_type_from, Type p_type_to);
static bool is_type_shared(Variant::Type p_type);
bool is_ref_counted() const;
_FORCE_INLINE_ bool is_num() const {
return type == INT || type == FLOAT;
}
_FORCE_INLINE_ bool is_string() const {
return type == STRING || type == STRING_NAME;
}
_FORCE_INLINE_ bool is_array() const {
return type >= ARRAY;
}
bool is_shared() const;
bool is_zero() const;
bool is_one() const;
bool is_null() const;
bool is_read_only() const;
// Make sure Variant is not implicitly cast when accessing it with bracket notation (GH-49469).
Variant &operator[](const Variant &p_key) = delete;
const Variant &operator[](const Variant &p_key) const = delete;
operator bool() const;
operator int64_t() const;
operator int32_t() const;
operator int16_t() const;
operator int8_t() const;
operator uint64_t() const;
operator uint32_t() const;
operator uint16_t() const;
operator uint8_t() const;
operator ObjectID() const;
operator char32_t() const;
operator float() const;
operator double() const;
operator String() const;
operator StringName() const;
operator Vector2() const;
operator Vector2i() const;
operator Rect2() const;
operator Rect2i() const;
operator Vector3() const;
operator Vector3i() const;
operator Vector4() const;
operator Vector4i() const;
operator Plane() const;
operator ::AABB() const;
operator Quaternion() const;
operator Basis() const;
operator Transform2D() const;
operator Transform3D() const;
operator Projection() const;
operator Color() const;
operator NodePath() const;
operator ::RID() const;
operator Object *() const;
operator Callable() const;
operator Signal() const;
operator Dictionary() const;
operator Array() const;
operator PackedByteArray() const;
operator PackedInt32Array() const;
operator PackedInt64Array() const;
operator PackedFloat32Array() const;
operator PackedFloat64Array() const;
operator PackedStringArray() const;
operator PackedVector3Array() const;
operator PackedVector2Array() const;
operator PackedColorArray() const;
operator PackedVector4Array() const;
operator Vector<::RID>() const;
operator Vector<Plane>() const;
operator Vector<Face3>() const;
operator Vector<Variant>() const;
operator Vector<StringName>() const;
// some core type enums to convert to
operator Side() const;
operator Orientation() const;
operator IPAddress() const;
Object *get_validated_object() const;
Object *get_validated_object_with_check(bool &r_previously_freed) const;
Variant(bool p_bool);
Variant(int64_t p_int64);
Variant(int32_t p_int32);
Variant(int16_t p_int16);
Variant(int8_t p_int8);
Variant(uint64_t p_uint64);
Variant(uint32_t p_uint32);
Variant(uint16_t p_uint16);
Variant(uint8_t p_uint8);
Variant(float p_float);
Variant(double p_double);
Variant(const ObjectID &p_id);
Variant(const String &p_string);
Variant(const StringName &p_string);
Variant(const char *const p_cstring);
Variant(const char32_t *p_wstring);
Variant(const Vector2 &p_vector2);
Variant(const Vector2i &p_vector2i);
Variant(const Rect2 &p_rect2);
Variant(const Rect2i &p_rect2i);
Variant(const Vector3 &p_vector3);
Variant(const Vector3i &p_vector3i);
Variant(const Vector4 &p_vector4);
Variant(const Vector4i &p_vector4i);
Variant(const Plane &p_plane);
Variant(const ::AABB &p_aabb);
Variant(const Quaternion &p_quat);
Variant(const Basis &p_matrix);
Variant(const Transform2D &p_transform);
Variant(const Transform3D &p_transform);
Variant(const Projection &p_projection);
Variant(const Color &p_color);
Variant(const NodePath &p_node_path);
Variant(const ::RID &p_rid);
Variant(const Object *p_object);
Variant(const Callable &p_callable);
Variant(const Signal &p_signal);
Variant(const Dictionary &p_dictionary);
Variant(const Array &p_array);
Variant(const PackedByteArray &p_byte_array);
Variant(const PackedInt32Array &p_int32_array);
Variant(const PackedInt64Array &p_int64_array);
Variant(const PackedFloat32Array &p_float32_array);
Variant(const PackedFloat64Array &p_float64_array);
Variant(const PackedStringArray &p_string_array);
Variant(const PackedVector2Array &p_vector2_array);
Variant(const PackedVector3Array &p_vector3_array);
Variant(const PackedColorArray &p_color_array);
Variant(const PackedVector4Array &p_vector4_array);
Variant(const Vector<::RID> &p_array); // helper
Variant(const Vector<Plane> &p_array); // helper
Variant(const Vector<Face3> &p_face_array);
Variant(const Vector<Variant> &p_array);
Variant(const Vector<StringName> &p_array);
Variant(const IPAddress &p_address);
#define VARIANT_ENUM_CLASS_CONSTRUCTOR(m_enum) \
Variant(m_enum p_value) : \
type(INT) { \
_data._int = (int64_t)p_value; \
}
// Only enum classes that need to be bound need this to be defined.
VARIANT_ENUM_CLASS_CONSTRUCTOR(EulerOrder)
VARIANT_ENUM_CLASS_CONSTRUCTOR(JoyAxis)
VARIANT_ENUM_CLASS_CONSTRUCTOR(JoyButton)
VARIANT_ENUM_CLASS_CONSTRUCTOR(Key)
VARIANT_ENUM_CLASS_CONSTRUCTOR(KeyLocation)
VARIANT_ENUM_CLASS_CONSTRUCTOR(MIDIMessage)
VARIANT_ENUM_CLASS_CONSTRUCTOR(MouseButton)
#undef VARIANT_ENUM_CLASS_CONSTRUCTOR
// If this changes the table in variant_op must be updated
enum Operator {
//comparison
OP_EQUAL,
OP_NOT_EQUAL,
OP_LESS,
OP_LESS_EQUAL,
OP_GREATER,
OP_GREATER_EQUAL,
//mathematic
OP_ADD,
OP_SUBTRACT,
OP_MULTIPLY,
OP_DIVIDE,
OP_NEGATE,
OP_POSITIVE,
OP_MODULE,
OP_POWER,
//bitwise
OP_SHIFT_LEFT,
OP_SHIFT_RIGHT,
OP_BIT_AND,
OP_BIT_OR,
OP_BIT_XOR,
OP_BIT_NEGATE,
//logic
OP_AND,
OP_OR,
OP_XOR,
OP_NOT,
//containment
OP_IN,
OP_MAX
};
static String get_operator_name(Operator p_op);
static void evaluate(const Operator &p_op, const Variant &p_a, const Variant &p_b, Variant &r_ret, bool &r_valid);
static _FORCE_INLINE_ Variant evaluate(const Operator &p_op, const Variant &p_a, const Variant &p_b) {
bool valid = true;
Variant res;
evaluate(p_op, p_a, p_b, res, valid);
return res;
}
static Variant::Type get_operator_return_type(Operator p_operator, Type p_type_a, Type p_type_b);
typedef void (*ValidatedOperatorEvaluator)(const Variant *left, const Variant *right, Variant *r_ret);
static ValidatedOperatorEvaluator get_validated_operator_evaluator(Operator p_operator, Type p_type_a, Type p_type_b);
typedef void (*PTROperatorEvaluator)(const void *left, const void *right, void *r_ret);
static PTROperatorEvaluator get_ptr_operator_evaluator(Operator p_operator, Type p_type_a, Type p_type_b);
void zero();
Variant duplicate(bool p_deep = false) const;
Variant recursive_duplicate(bool p_deep, int recursion_count) const;
/* Built-In Methods */
typedef void (*ValidatedBuiltInMethod)(Variant *base, const Variant **p_args, int p_argcount, Variant *r_ret);
typedef void (*PTRBuiltInMethod)(void *p_base, const void **p_args, void *r_ret, int p_argcount);
static bool has_builtin_method(Variant::Type p_type, const StringName &p_method);
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);
static Vector<Variant> get_builtin_method_default_arguments(Variant::Type p_type, const StringName &p_method);
static bool has_builtin_method_return_value(Variant::Type p_type, const StringName &p_method);
static Variant::Type get_builtin_method_return_type(Variant::Type p_type, const StringName &p_method);
static bool is_builtin_method_const(Variant::Type p_type, const StringName &p_method);
static bool is_builtin_method_static(Variant::Type p_type, const StringName &p_method);
static bool is_builtin_method_vararg(Variant::Type p_type, const StringName &p_method);
static void get_builtin_method_list(Variant::Type p_type, List<StringName> *p_list);
static int get_builtin_method_count(Variant::Type p_type);
static uint32_t get_builtin_method_hash(Variant::Type p_type, const StringName &p_method);
void callp(const StringName &p_method, const Variant **p_args, int p_argcount, Variant &r_ret, Callable::CallError &r_error);
template <typename... VarArgs>
Variant call(const StringName &p_method, VarArgs... p_args) {
Variant args[sizeof...(p_args) + 1] = { p_args..., Variant() }; // +1 makes sure zero sized arrays are also supported.
const Variant *argptrs[sizeof...(p_args) + 1];
for (uint32_t i = 0; i < sizeof...(p_args); i++) {
argptrs[i] = &args[i];
}
Callable::CallError cerr;
Variant ret;
callp(p_method, sizeof...(p_args) == 0 ? nullptr : (const Variant **)argptrs, sizeof...(p_args), ret, cerr);
if (cerr.error != Callable::CallError::CALL_OK) {
_variant_call_error(p_method, cerr);
}
return ret;
}
void call_const(const StringName &p_method, const Variant **p_args, int p_argcount, Variant &r_ret, Callable::CallError &r_error);
static void call_static(Variant::Type p_type, const StringName &p_method, const Variant **p_args, int p_argcount, Variant &r_ret, Callable::CallError &r_error);
static String get_call_error_text(const StringName &p_method, const Variant **p_argptrs, int p_argcount, const Callable::CallError &ce);
static String get_call_error_text(Object *p_base, const StringName &p_method, const Variant **p_argptrs, int p_argcount, const Callable::CallError &ce);
static String get_callable_error_text(const Callable &p_callable, const Variant **p_argptrs, int p_argcount, const Callable::CallError &ce);
//dynamic (includes Object)
void get_method_list(List<MethodInfo> *p_list) const;
bool has_method(const StringName &p_method) const;
/* Constructors */
typedef void (*ValidatedConstructor)(Variant *r_base, const Variant **p_args);
typedef void (*PTRConstructor)(void *base, const void **p_args);
static int get_constructor_count(Variant::Type p_type);
static ValidatedConstructor get_validated_constructor(Variant::Type p_type, int p_constructor);
static PTRConstructor get_ptr_constructor(Variant::Type p_type, int p_constructor);
static int get_constructor_argument_count(Variant::Type p_type, int p_constructor);
static Variant::Type get_constructor_argument_type(Variant::Type p_type, int p_constructor, int p_argument);
static String get_constructor_argument_name(Variant::Type p_type, int p_constructor, int p_argument);
static void construct(Variant::Type, Variant &base, const Variant **p_args, int p_argcount, Callable::CallError &r_error);
static void get_constructor_list(Type p_type, List<MethodInfo> *r_list); //convenience
/* Destructors */
// Only ptrcall is available.
typedef void (*PTRDestructor)(void *base);
static PTRDestructor get_ptr_destructor(Variant::Type p_type);
static bool has_destructor(Variant::Type p_type);
/* Properties */
void set_named(const StringName &p_member, const Variant &p_value, bool &r_valid);
Variant get_named(const StringName &p_member, bool &r_valid) const;
typedef void (*ValidatedSetter)(Variant *base, const Variant *value);
typedef void (*ValidatedGetter)(const Variant *base, Variant *value);
static bool has_member(Variant::Type p_type, const StringName &p_member);
static Variant::Type get_member_type(Variant::Type p_type, const StringName &p_member);
static void get_member_list(Type p_type, List<StringName> *r_members);
static int get_member_count(Type p_type);
static ValidatedSetter get_member_validated_setter(Variant::Type p_type, const StringName &p_member);
static ValidatedGetter get_member_validated_getter(Variant::Type p_type, const StringName &p_member);
typedef void (*PTRSetter)(void *base, const void *value);
typedef void (*PTRGetter)(const void *base, void *value);
static PTRSetter get_member_ptr_setter(Variant::Type p_type, const StringName &p_member);
static PTRGetter get_member_ptr_getter(Variant::Type p_type, const StringName &p_member);
/* Indexing */
static bool has_indexing(Variant::Type p_type);
static Variant::Type get_indexed_element_type(Variant::Type p_type);
static uint32_t get_indexed_element_usage(Variant::Type p_type);
typedef void (*ValidatedIndexedSetter)(Variant *base, int64_t index, const Variant *value, bool *oob);
typedef void (*ValidatedIndexedGetter)(const Variant *base, int64_t index, Variant *value, bool *oob);
static ValidatedIndexedSetter get_member_validated_indexed_setter(Variant::Type p_type);
static ValidatedIndexedGetter get_member_validated_indexed_getter(Variant::Type p_type);
typedef void (*PTRIndexedSetter)(void *base, int64_t index, const void *value);
typedef void (*PTRIndexedGetter)(const void *base, int64_t index, void *value);
static PTRIndexedSetter get_member_ptr_indexed_setter(Variant::Type p_type);
static PTRIndexedGetter get_member_ptr_indexed_getter(Variant::Type p_type);
void set_indexed(int64_t p_index, const Variant &p_value, bool &r_valid, bool &r_oob);
Variant get_indexed(int64_t p_index, bool &r_valid, bool &r_oob) const;
uint64_t get_indexed_size() const;
/* Keying */
static bool is_keyed(Variant::Type p_type);
typedef void (*ValidatedKeyedSetter)(Variant *base, const Variant *key, const Variant *value, bool *valid);
typedef void (*ValidatedKeyedGetter)(const Variant *base, const Variant *key, Variant *value, bool *valid);
typedef bool (*ValidatedKeyedChecker)(const Variant *base, const Variant *key, bool *valid);
static ValidatedKeyedSetter get_member_validated_keyed_setter(Variant::Type p_type);
static ValidatedKeyedGetter get_member_validated_keyed_getter(Variant::Type p_type);
static ValidatedKeyedChecker get_member_validated_keyed_checker(Variant::Type p_type);
typedef void (*PTRKeyedSetter)(void *base, const void *key, const void *value);
typedef void (*PTRKeyedGetter)(const void *base, const void *key, void *value);
typedef uint32_t (*PTRKeyedChecker)(const void *base, const void *key);
static PTRKeyedSetter get_member_ptr_keyed_setter(Variant::Type p_type);
static PTRKeyedGetter get_member_ptr_keyed_getter(Variant::Type p_type);
static PTRKeyedChecker get_member_ptr_keyed_checker(Variant::Type p_type);
void set_keyed(const Variant &p_key, const Variant &p_value, bool &r_valid);
Variant get_keyed(const Variant &p_key, bool &r_valid) const;
bool has_key(const Variant &p_key, bool &r_valid) const;
/* Generic */
enum VariantSetError {
SET_OK,
SET_KEYED_ERR,
SET_NAMED_ERR,
SET_INDEXED_ERR
};
enum VariantGetError {
GET_OK,
GET_KEYED_ERR,
GET_NAMED_ERR,
GET_INDEXED_ERR
};
void set(const Variant &p_index, const Variant &p_value, bool *r_valid = nullptr, VariantSetError *err_code = nullptr);
Variant get(const Variant &p_index, bool *r_valid = nullptr, VariantGetError *err_code = nullptr) const;
bool in(const Variant &p_index, bool *r_valid = nullptr) const;
bool iter_init(Variant &r_iter, bool &r_valid) const;
bool iter_next(Variant &r_iter, bool &r_valid) const;
Variant iter_get(const Variant &r_iter, bool &r_valid) const;
void get_property_list(List<PropertyInfo> *p_list) const;
static void call_utility_function(const StringName &p_name, Variant *r_ret, const Variant **p_args, int p_argcount, Callable::CallError &r_error);
static bool has_utility_function(const StringName &p_name);
typedef void (*ValidatedUtilityFunction)(Variant *r_ret, const Variant **p_args, int p_argcount);
typedef void (*PTRUtilityFunction)(void *r_ret, const void **p_args, int p_argcount);
static ValidatedUtilityFunction get_validated_utility_function(const StringName &p_name);
static PTRUtilityFunction get_ptr_utility_function(const StringName &p_name);
enum UtilityFunctionType {
UTILITY_FUNC_TYPE_MATH,
UTILITY_FUNC_TYPE_RANDOM,
UTILITY_FUNC_TYPE_GENERAL,
};
static UtilityFunctionType get_utility_function_type(const StringName &p_name);
static MethodInfo get_utility_function_info(const StringName &p_name);
static int get_utility_function_argument_count(const StringName &p_name);
static Variant::Type get_utility_function_argument_type(const StringName &p_name, int p_arg);
static String get_utility_function_argument_name(const StringName &p_name, int p_arg);
static bool has_utility_function_return_value(const StringName &p_name);
static Variant::Type get_utility_function_return_type(const StringName &p_name);
static bool is_utility_function_vararg(const StringName &p_name);
static uint32_t get_utility_function_hash(const StringName &p_name);
static void get_utility_function_list(List<StringName> *r_functions);
static int get_utility_function_count();
//argsVariant call()
bool operator==(const Variant &p_variant) const;
bool operator!=(const Variant &p_variant) const;
bool operator<(const Variant &p_variant) const;
uint32_t hash() const;
uint32_t recursive_hash(int recursion_count) const;
// By default, performs a semantic comparison. Otherwise, numeric/binary comparison (if appropriate).
bool hash_compare(const Variant &p_variant, int recursion_count = 0, bool semantic_comparison = true) const;
bool identity_compare(const Variant &p_variant) const;
bool booleanize() const;
String stringify(int recursion_count = 0) const;
String to_json_string() const;
void static_assign(const Variant &p_variant);
static void get_constants_for_type(Variant::Type p_type, List<StringName> *p_constants);
static int get_constants_count_for_type(Variant::Type p_type);
static bool has_constant(Variant::Type p_type, const StringName &p_value);
static Variant get_constant_value(Variant::Type p_type, const StringName &p_value, bool *r_valid = nullptr);
static void get_enums_for_type(Variant::Type p_type, List<StringName> *p_enums);
static void get_enumerations_for_enum(Variant::Type p_type, const StringName &p_enum_name, List<StringName> *p_enumerations);
static int get_enum_value(Variant::Type p_type, const StringName &p_enum_name, const StringName &p_enumeration, bool *r_valid = nullptr);
typedef String (*ObjectDeConstruct)(const Variant &p_object, void *ud);
typedef void (*ObjectConstruct)(const String &p_text, void *ud, Variant &r_value);
String get_construct_string() const;
static void construct_from_string(const String &p_string, Variant &r_value, ObjectConstruct p_obj_construct = nullptr, void *p_construct_ud = nullptr);
void operator=(const Variant &p_variant); // only this is enough for all the other types
static void register_types();
static void unregister_types();
Variant(const Variant &p_variant);
_FORCE_INLINE_ Variant() :
type(NIL) {}
_FORCE_INLINE_ ~Variant() {
clear();
}
};
//typedef Dictionary Dictionary; no
//typedef Array Array;
template <typename... VarArgs>
Vector<Variant> varray(VarArgs... p_args) {
Vector<Variant> v;
Variant args[sizeof...(p_args) + 1] = { p_args..., Variant() }; // +1 makes sure zero sized arrays are also supported.
uint32_t argc = sizeof...(p_args);
if (argc > 0) {
v.resize(argc);
Variant *vw = v.ptrw();
for (uint32_t i = 0; i < argc; i++) {
vw[i] = args[i];
}
}
return v;
}
struct VariantHasher {
static _FORCE_INLINE_ uint32_t hash(const Variant &p_variant) { return p_variant.hash(); }
};
struct VariantComparator {
static _FORCE_INLINE_ bool compare(const Variant &p_lhs, const Variant &p_rhs) { return p_lhs.hash_compare(p_rhs); }
};
struct StringLikeVariantComparator {
static bool compare(const Variant &p_lhs, const Variant &p_rhs);
};
Variant::ObjData &Variant::_get_obj() {
return *reinterpret_cast<ObjData *>(&_data._mem[0]);
}
const Variant::ObjData &Variant::_get_obj() const {
return *reinterpret_cast<const ObjData *>(&_data._mem[0]);
}
template <typename... VarArgs>
String vformat(const String &p_text, const VarArgs... p_args) {
Variant args[sizeof...(p_args) + 1] = { p_args..., Variant() }; // +1 makes sure zero sized arrays are also supported.
Array args_array;
args_array.resize(sizeof...(p_args));
for (uint32_t i = 0; i < sizeof...(p_args); i++) {
args_array[i] = args[i];
}
bool error = false;
String fmt = p_text.sprintf(args_array, &error);
ERR_FAIL_COND_V_MSG(error, String(), String("Formatting error in string \"") + p_text + "\": " + fmt + ".");
return fmt;
}
template <typename... VarArgs>
Variant Callable::call(VarArgs... p_args) const {
Variant args[sizeof...(p_args) + 1] = { p_args..., 0 }; // +1 makes sure zero sized arrays are also supported.
const Variant *argptrs[sizeof...(p_args) + 1];
for (uint32_t i = 0; i < sizeof...(p_args); i++) {
argptrs[i] = &args[i];
}
Variant ret;
CallError ce;
callp(sizeof...(p_args) == 0 ? nullptr : (const Variant **)argptrs, sizeof...(p_args), ret, ce);
return ret;
}
template <typename... VarArgs>
Callable Callable::bind(VarArgs... p_args) const {
Variant args[sizeof...(p_args) + 1] = { p_args..., Variant() }; // +1 makes sure zero sized arrays are also supported.
const Variant *argptrs[sizeof...(p_args) + 1];
for (uint32_t i = 0; i < sizeof...(p_args); i++) {
argptrs[i] = &args[i];
}
return bindp(sizeof...(p_args) == 0 ? nullptr : (const Variant **)argptrs, sizeof...(p_args));
}
Variant &Array::Iterator::operator*() const {
if (unlikely(read_only)) {
*read_only = *element_ptr;
return *read_only;
}
return *element_ptr;
}
Variant *Array::Iterator::operator->() const {
if (unlikely(read_only)) {
*read_only = *element_ptr;
return read_only;
}
return element_ptr;
}
Array::Iterator &Array::Iterator::operator++() {
element_ptr++;
return *this;
}
Array::Iterator &Array::Iterator::operator--() {
element_ptr--;
return *this;
}
const Variant &Array::ConstIterator::operator*() const {
if (unlikely(read_only)) {
*read_only = *element_ptr;
return *read_only;
}
return *element_ptr;
}
const Variant *Array::ConstIterator::operator->() const {
if (unlikely(read_only)) {
*read_only = *element_ptr;
return read_only;
}
return element_ptr;
}
Array::ConstIterator &Array::ConstIterator::operator++() {
element_ptr++;
return *this;
}
Array::ConstIterator &Array::ConstIterator::operator--() {
element_ptr--;
return *this;
}
#endif // VARIANT_H

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,90 @@
/**************************************************************************/
/* 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();
}
int VariantCallable::get_argument_count(bool &r_is_valid) const {
if (!Variant::has_builtin_method(variant.get_type(), method)) {
r_is_valid = false;
return 0;
}
r_is_valid = true;
return Variant::get_builtin_method_argument_count(variant.get_type(), method);
}
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);
}

View file

@ -0,0 +1,59 @@
/**************************************************************************/
/* 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;
int get_argument_count(bool &r_is_valid) 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

View file

@ -0,0 +1,373 @@
/**************************************************************************/
/* 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<String> arg_names;
};
static LocalVector<VariantConstructData> construct_data[Variant::VARIANT_MAX];
template <typename T>
static void add_constructor(const Vector<String> &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<VariantConstructNoArgsNil>(sarray());
add_constructor<VariantConstructorNil>(sarray("from"));
add_constructor<VariantConstructNoArgs<bool>>(sarray());
add_constructor<VariantConstructor<bool, bool>>(sarray("from"));
add_constructor<VariantConstructor<bool, int64_t>>(sarray("from"));
add_constructor<VariantConstructor<bool, double>>(sarray("from"));
add_constructor<VariantConstructNoArgs<int64_t>>(sarray());
add_constructor<VariantConstructor<int64_t, int64_t>>(sarray("from"));
add_constructor<VariantConstructor<int64_t, double>>(sarray("from"));
add_constructor<VariantConstructor<int64_t, bool>>(sarray("from"));
add_constructor<VariantConstructorFromString<int64_t>>(sarray("from"));
add_constructor<VariantConstructNoArgs<double>>(sarray());
add_constructor<VariantConstructor<double, double>>(sarray("from"));
add_constructor<VariantConstructor<double, int64_t>>(sarray("from"));
add_constructor<VariantConstructor<double, bool>>(sarray("from"));
add_constructor<VariantConstructorFromString<double>>(sarray("from"));
add_constructor<VariantConstructNoArgs<String>>(sarray());
add_constructor<VariantConstructor<String, String>>(sarray("from"));
add_constructor<VariantConstructor<String, StringName>>(sarray("from"));
add_constructor<VariantConstructor<String, NodePath>>(sarray("from"));
add_constructor<VariantConstructNoArgs<Vector2>>(sarray());
add_constructor<VariantConstructor<Vector2, Vector2>>(sarray("from"));
add_constructor<VariantConstructor<Vector2, Vector2i>>(sarray("from"));
add_constructor<VariantConstructor<Vector2, double, double>>(sarray("x", "y"));
add_constructor<VariantConstructNoArgs<Vector2i>>(sarray());
add_constructor<VariantConstructor<Vector2i, Vector2i>>(sarray("from"));
add_constructor<VariantConstructor<Vector2i, Vector2>>(sarray("from"));
add_constructor<VariantConstructor<Vector2i, int64_t, int64_t>>(sarray("x", "y"));
add_constructor<VariantConstructNoArgs<Rect2>>(sarray());
add_constructor<VariantConstructor<Rect2, Rect2>>(sarray("from"));
add_constructor<VariantConstructor<Rect2, Rect2i>>(sarray("from"));
add_constructor<VariantConstructor<Rect2, Vector2, Vector2>>(sarray("position", "size"));
add_constructor<VariantConstructor<Rect2, double, double, double, double>>(sarray("x", "y", "width", "height"));
add_constructor<VariantConstructNoArgs<Rect2i>>(sarray());
add_constructor<VariantConstructor<Rect2i, Rect2i>>(sarray("from"));
add_constructor<VariantConstructor<Rect2i, Rect2>>(sarray("from"));
add_constructor<VariantConstructor<Rect2i, Vector2i, Vector2i>>(sarray("position", "size"));
add_constructor<VariantConstructor<Rect2i, int64_t, int64_t, int64_t, int64_t>>(sarray("x", "y", "width", "height"));
add_constructor<VariantConstructNoArgs<Vector3>>(sarray());
add_constructor<VariantConstructor<Vector3, Vector3>>(sarray("from"));
add_constructor<VariantConstructor<Vector3, Vector3i>>(sarray("from"));
add_constructor<VariantConstructor<Vector3, double, double, double>>(sarray("x", "y", "z"));
add_constructor<VariantConstructNoArgs<Vector3i>>(sarray());
add_constructor<VariantConstructor<Vector3i, Vector3i>>(sarray("from"));
add_constructor<VariantConstructor<Vector3i, Vector3>>(sarray("from"));
add_constructor<VariantConstructor<Vector3i, int64_t, int64_t, int64_t>>(sarray("x", "y", "z"));
add_constructor<VariantConstructNoArgs<Vector4>>(sarray());
add_constructor<VariantConstructor<Vector4, Vector4>>(sarray("from"));
add_constructor<VariantConstructor<Vector4, Vector4i>>(sarray("from"));
add_constructor<VariantConstructor<Vector4, double, double, double, double>>(sarray("x", "y", "z", "w"));
add_constructor<VariantConstructNoArgs<Vector4i>>(sarray());
add_constructor<VariantConstructor<Vector4i, Vector4i>>(sarray("from"));
add_constructor<VariantConstructor<Vector4i, Vector4>>(sarray("from"));
add_constructor<VariantConstructor<Vector4i, int64_t, int64_t, int64_t, int64_t>>(sarray("x", "y", "z", "w"));
add_constructor<VariantConstructNoArgs<Transform2D>>(sarray());
add_constructor<VariantConstructor<Transform2D, Transform2D>>(sarray("from"));
add_constructor<VariantConstructor<Transform2D, float, Vector2>>(sarray("rotation", "position"));
add_constructor<VariantConstructor<Transform2D, float, Size2, float, Vector2>>(sarray("rotation", "scale", "skew", "position"));
add_constructor<VariantConstructor<Transform2D, Vector2, Vector2, Vector2>>(sarray("x_axis", "y_axis", "origin"));
add_constructor<VariantConstructNoArgs<Plane>>(sarray());
add_constructor<VariantConstructor<Plane, Plane>>(sarray("from"));
add_constructor<VariantConstructor<Plane, Vector3>>(sarray("normal"));
add_constructor<VariantConstructor<Plane, Vector3, double>>(sarray("normal", "d"));
add_constructor<VariantConstructor<Plane, Vector3, Vector3>>(sarray("normal", "point"));
add_constructor<VariantConstructor<Plane, Vector3, Vector3, Vector3>>(sarray("point1", "point2", "point3"));
add_constructor<VariantConstructor<Plane, double, double, double, double>>(sarray("a", "b", "c", "d"));
add_constructor<VariantConstructNoArgs<Quaternion>>(sarray());
add_constructor<VariantConstructor<Quaternion, Quaternion>>(sarray("from"));
add_constructor<VariantConstructor<Quaternion, Basis>>(sarray("from"));
add_constructor<VariantConstructor<Quaternion, Vector3, double>>(sarray("axis", "angle"));
add_constructor<VariantConstructor<Quaternion, Vector3, Vector3>>(sarray("arc_from", "arc_to"));
add_constructor<VariantConstructor<Quaternion, double, double, double, double>>(sarray("x", "y", "z", "w"));
add_constructor<VariantConstructNoArgs<::AABB>>(sarray());
add_constructor<VariantConstructor<::AABB, ::AABB>>(sarray("from"));
add_constructor<VariantConstructor<::AABB, Vector3, Vector3>>(sarray("position", "size"));
add_constructor<VariantConstructNoArgs<Basis>>(sarray());
add_constructor<VariantConstructor<Basis, Basis>>(sarray("from"));
add_constructor<VariantConstructor<Basis, Quaternion>>(sarray("from"));
add_constructor<VariantConstructor<Basis, Vector3, double>>(sarray("axis", "angle"));
add_constructor<VariantConstructor<Basis, Vector3, Vector3, Vector3>>(sarray("x_axis", "y_axis", "z_axis"));
add_constructor<VariantConstructNoArgs<Transform3D>>(sarray());
add_constructor<VariantConstructor<Transform3D, Transform3D>>(sarray("from"));
add_constructor<VariantConstructor<Transform3D, Basis, Vector3>>(sarray("basis", "origin"));
add_constructor<VariantConstructor<Transform3D, Vector3, Vector3, Vector3, Vector3>>(sarray("x_axis", "y_axis", "z_axis", "origin"));
add_constructor<VariantConstructor<Transform3D, Projection>>(sarray("from"));
add_constructor<VariantConstructNoArgs<Projection>>(sarray());
add_constructor<VariantConstructor<Projection, Projection>>(sarray("from"));
add_constructor<VariantConstructor<Projection, Transform3D>>(sarray("from"));
add_constructor<VariantConstructor<Projection, Vector4, Vector4, Vector4, Vector4>>(sarray("x_axis", "y_axis", "z_axis", "w_axis"));
add_constructor<VariantConstructNoArgs<Color>>(sarray());
add_constructor<VariantConstructor<Color, Color>>(sarray("from"));
add_constructor<VariantConstructor<Color, Color, double>>(sarray("from", "alpha"));
add_constructor<VariantConstructor<Color, double, double, double>>(sarray("r", "g", "b"));
add_constructor<VariantConstructor<Color, double, double, double, double>>(sarray("r", "g", "b", "a"));
add_constructor<VariantConstructor<Color, String>>(sarray("code"));
add_constructor<VariantConstructor<Color, String, double>>(sarray("code", "alpha"));
add_constructor<VariantConstructNoArgs<StringName>>(sarray());
add_constructor<VariantConstructor<StringName, StringName>>(sarray("from"));
add_constructor<VariantConstructor<StringName, String>>(sarray("from"));
add_constructor<VariantConstructNoArgs<NodePath>>(sarray());
add_constructor<VariantConstructor<NodePath, NodePath>>(sarray("from"));
add_constructor<VariantConstructor<NodePath, String>>(sarray("from"));
add_constructor<VariantConstructNoArgs<::RID>>(sarray());
add_constructor<VariantConstructor<::RID, ::RID>>(sarray("from"));
add_constructor<VariantConstructNoArgsObject>(sarray());
add_constructor<VariantConstructorObject>(sarray("from"));
add_constructor<VariantConstructorNilObject>(sarray("from"));
add_constructor<VariantConstructNoArgs<Callable>>(sarray());
add_constructor<VariantConstructor<Callable, Callable>>(sarray("from"));
add_constructor<VariantConstructorCallableArgs>(sarray("object", "method"));
add_constructor<VariantConstructNoArgs<Signal>>(sarray());
add_constructor<VariantConstructor<Signal, Signal>>(sarray("from"));
add_constructor<VariantConstructorSignalArgs>(sarray("object", "signal"));
add_constructor<VariantConstructNoArgs<Dictionary>>(sarray());
add_constructor<VariantConstructor<Dictionary, Dictionary>>(sarray("from"));
add_constructor<VariantConstructNoArgs<Array>>(sarray());
add_constructor<VariantConstructor<Array, Array>>(sarray("from"));
add_constructor<VariantConstructorTypedArray>(sarray("base", "type", "class_name", "script"));
add_constructor<VariantConstructorToArray<PackedByteArray>>(sarray("from"));
add_constructor<VariantConstructorToArray<PackedInt32Array>>(sarray("from"));
add_constructor<VariantConstructorToArray<PackedInt64Array>>(sarray("from"));
add_constructor<VariantConstructorToArray<PackedFloat32Array>>(sarray("from"));
add_constructor<VariantConstructorToArray<PackedFloat64Array>>(sarray("from"));
add_constructor<VariantConstructorToArray<PackedStringArray>>(sarray("from"));
add_constructor<VariantConstructorToArray<PackedVector2Array>>(sarray("from"));
add_constructor<VariantConstructorToArray<PackedVector3Array>>(sarray("from"));
add_constructor<VariantConstructorToArray<PackedColorArray>>(sarray("from"));
add_constructor<VariantConstructorToArray<PackedVector4Array>>(sarray("from"));
add_constructor<VariantConstructNoArgs<PackedByteArray>>(sarray());
add_constructor<VariantConstructor<PackedByteArray, PackedByteArray>>(sarray("from"));
add_constructor<VariantConstructorFromArray<PackedByteArray>>(sarray("from"));
add_constructor<VariantConstructNoArgs<PackedInt32Array>>(sarray());
add_constructor<VariantConstructor<PackedInt32Array, PackedInt32Array>>(sarray("from"));
add_constructor<VariantConstructorFromArray<PackedInt32Array>>(sarray("from"));
add_constructor<VariantConstructNoArgs<PackedInt64Array>>(sarray());
add_constructor<VariantConstructor<PackedInt64Array, PackedInt64Array>>(sarray("from"));
add_constructor<VariantConstructorFromArray<PackedInt64Array>>(sarray("from"));
add_constructor<VariantConstructNoArgs<PackedFloat32Array>>(sarray());
add_constructor<VariantConstructor<PackedFloat32Array, PackedFloat32Array>>(sarray("from"));
add_constructor<VariantConstructorFromArray<PackedFloat32Array>>(sarray("from"));
add_constructor<VariantConstructNoArgs<PackedFloat64Array>>(sarray());
add_constructor<VariantConstructor<PackedFloat64Array, PackedFloat64Array>>(sarray("from"));
add_constructor<VariantConstructorFromArray<PackedFloat64Array>>(sarray("from"));
add_constructor<VariantConstructNoArgs<PackedStringArray>>(sarray());
add_constructor<VariantConstructor<PackedStringArray, PackedStringArray>>(sarray("from"));
add_constructor<VariantConstructorFromArray<PackedStringArray>>(sarray("from"));
add_constructor<VariantConstructNoArgs<PackedVector2Array>>(sarray());
add_constructor<VariantConstructor<PackedVector2Array, PackedVector2Array>>(sarray("from"));
add_constructor<VariantConstructorFromArray<PackedVector2Array>>(sarray("from"));
add_constructor<VariantConstructNoArgs<PackedVector3Array>>(sarray());
add_constructor<VariantConstructor<PackedVector3Array, PackedVector3Array>>(sarray("from"));
add_constructor<VariantConstructorFromArray<PackedVector3Array>>(sarray("from"));
add_constructor<VariantConstructNoArgs<PackedColorArray>>(sarray());
add_constructor<VariantConstructor<PackedColorArray, PackedColorArray>>(sarray("from"));
add_constructor<VariantConstructorFromArray<PackedColorArray>>(sarray("from"));
add_constructor<VariantConstructNoArgs<PackedVector4Array>>(sarray());
add_constructor<VariantConstructor<PackedVector4Array, PackedVector4Array>>(sarray("from"));
add_constructor<VariantConstructorFromArray<PackedVector4Array>>(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::refcounted_object_assign(Variant *v, const RefCounted *rc) {
if (!rc || !const_cast<RefCounted *>(rc)->init_ref()) {
v->_get_obj().obj = nullptr;
v->_get_obj().id = ObjectID();
return;
}
v->_get_obj().obj = const_cast<RefCounted *>(rc);
v->_get_obj().id = rc->get_instance_id();
}
void VariantInternal::object_assign(Variant *v, const Object *o) {
if (o) {
if (o->is_ref_counted()) {
RefCounted *ref_counted = const_cast<RefCounted *>(static_cast<const RefCounted *>(o));
if (!ref_counted->init_ref()) {
v->_get_obj().obj = nullptr;
v->_get_obj().id = ObjectID();
return;
}
}
v->_get_obj().obj = const_cast<Object *>(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<MethodInfo> *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);
}
}

View file

@ -0,0 +1,713 @@
/**************************************************************************/
/* variant_construct.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_CONSTRUCT_H
#define VARIANT_CONSTRUCT_H
#include "variant.h"
#include "core/crypto/crypto_core.h"
#include "core/debugger/engine_debugger.h"
#include "core/io/compression.h"
#include "core/object/class_db.h"
#include "core/os/os.h"
#include "core/templates/local_vector.h"
#include "core/templates/oa_hash_map.h"
template <typename T>
struct PtrConstruct {};
#define MAKE_PTRCONSTRUCT(m_type) \
template <> \
struct PtrConstruct<m_type> { \
_FORCE_INLINE_ static void construct(const m_type &p_value, void *p_ptr) { \
memnew_placement(p_ptr, m_type(p_value)); \
} \
};
MAKE_PTRCONSTRUCT(bool);
MAKE_PTRCONSTRUCT(int64_t);
MAKE_PTRCONSTRUCT(double);
MAKE_PTRCONSTRUCT(String);
MAKE_PTRCONSTRUCT(Vector2);
MAKE_PTRCONSTRUCT(Vector2i);
MAKE_PTRCONSTRUCT(Rect2);
MAKE_PTRCONSTRUCT(Rect2i);
MAKE_PTRCONSTRUCT(Vector3);
MAKE_PTRCONSTRUCT(Vector3i);
MAKE_PTRCONSTRUCT(Vector4);
MAKE_PTRCONSTRUCT(Vector4i);
MAKE_PTRCONSTRUCT(Transform2D);
MAKE_PTRCONSTRUCT(Plane);
MAKE_PTRCONSTRUCT(Quaternion);
MAKE_PTRCONSTRUCT(AABB);
MAKE_PTRCONSTRUCT(Basis);
MAKE_PTRCONSTRUCT(Transform3D);
MAKE_PTRCONSTRUCT(Projection);
MAKE_PTRCONSTRUCT(Color);
MAKE_PTRCONSTRUCT(StringName);
MAKE_PTRCONSTRUCT(NodePath);
MAKE_PTRCONSTRUCT(RID);
template <>
struct PtrConstruct<Object *> {
_FORCE_INLINE_ static void construct(Object *p_value, void *p_ptr) {
*((Object **)p_ptr) = p_value;
}
};
MAKE_PTRCONSTRUCT(Callable);
MAKE_PTRCONSTRUCT(Signal);
MAKE_PTRCONSTRUCT(Dictionary);
MAKE_PTRCONSTRUCT(Array);
MAKE_PTRCONSTRUCT(PackedByteArray);
MAKE_PTRCONSTRUCT(PackedInt32Array);
MAKE_PTRCONSTRUCT(PackedInt64Array);
MAKE_PTRCONSTRUCT(PackedFloat32Array);
MAKE_PTRCONSTRUCT(PackedFloat64Array);
MAKE_PTRCONSTRUCT(PackedStringArray);
MAKE_PTRCONSTRUCT(PackedVector2Array);
MAKE_PTRCONSTRUCT(PackedVector3Array);
MAKE_PTRCONSTRUCT(PackedColorArray);
MAKE_PTRCONSTRUCT(PackedVector4Array);
MAKE_PTRCONSTRUCT(Variant);
template <typename T, typename... P>
class VariantConstructor {
template <size_t... Is>
static _FORCE_INLINE_ void construct_helper(T &base, const Variant **p_args, Callable::CallError &r_error, IndexSequence<Is...>) {
r_error.error = Callable::CallError::CALL_OK;
#ifdef DEBUG_METHODS_ENABLED
base = T(VariantCasterAndValidate<P>::cast(p_args, Is, r_error)...);
#else
base = T(VariantCaster<P>::cast(*p_args[Is])...);
#endif
}
template <size_t... Is>
static _FORCE_INLINE_ void validated_construct_helper(T &base, const Variant **p_args, IndexSequence<Is...>) {
base = T((*VariantGetInternalPtr<P>::get_ptr(p_args[Is]))...);
}
template <size_t... Is>
static _FORCE_INLINE_ void ptr_construct_helper(void *base, const void **p_args, IndexSequence<Is...>) {
PtrConstruct<T>::construct(T(PtrToArg<P>::convert(p_args[Is])...), base);
}
public:
static void construct(Variant &r_ret, const Variant **p_args, Callable::CallError &r_error) {
r_error.error = Callable::CallError::CALL_OK;
VariantTypeChanger<T>::change(&r_ret);
construct_helper(*VariantGetInternalPtr<T>::get_ptr(&r_ret), p_args, r_error, BuildIndexSequence<sizeof...(P)>{});
}
static inline void validated_construct(Variant *r_ret, const Variant **p_args) {
VariantTypeChanger<T>::change(r_ret);
validated_construct_helper(*VariantGetInternalPtr<T>::get_ptr(r_ret), p_args, BuildIndexSequence<sizeof...(P)>{});
}
static void ptr_construct(void *base, const void **p_args) {
ptr_construct_helper(base, p_args, BuildIndexSequence<sizeof...(P)>{});
}
static int get_argument_count() {
return sizeof...(P);
}
static Variant::Type get_argument_type(int p_arg) {
return call_get_argument_type<P...>(p_arg);
}
static Variant::Type get_base_type() {
return GetTypeInfo<T>::VARIANT_TYPE;
}
};
class VariantConstructorObject {
public:
static void construct(Variant &r_ret, const Variant **p_args, Callable::CallError &r_error) {
if (p_args[0]->get_type() == Variant::NIL) {
VariantInternal::clear(&r_ret);
VariantTypeChanger<Object *>::change(&r_ret);
VariantInternal::object_assign_null(&r_ret);
r_error.error = Callable::CallError::CALL_OK;
} else if (p_args[0]->get_type() == Variant::OBJECT) {
VariantInternal::clear(&r_ret);
VariantTypeChanger<Object *>::change(&r_ret);
VariantInternal::object_assign(&r_ret, p_args[0]);
r_error.error = Callable::CallError::CALL_OK;
} else {
r_error.error = Callable::CallError::CALL_ERROR_INVALID_ARGUMENT;
r_error.argument = 0;
r_error.expected = Variant::OBJECT;
}
}
static inline void validated_construct(Variant *r_ret, const Variant **p_args) {
VariantInternal::clear(r_ret);
VariantTypeChanger<Object *>::change(r_ret);
VariantInternal::object_assign(r_ret, p_args[0]);
}
static void ptr_construct(void *base, const void **p_args) {
PtrConstruct<Object *>::construct(PtrToArg<Object *>::convert(p_args[0]), base);
}
static int get_argument_count() {
return 1;
}
static Variant::Type get_argument_type(int p_arg) {
return Variant::OBJECT;
}
static Variant::Type get_base_type() {
return Variant::OBJECT;
}
};
class VariantConstructorNilObject {
public:
static void construct(Variant &r_ret, const Variant **p_args, Callable::CallError &r_error) {
if (p_args[0]->get_type() != Variant::NIL) {
r_error.error = Callable::CallError::CALL_ERROR_INVALID_ARGUMENT;
r_error.argument = 0;
r_error.expected = Variant::NIL;
}
VariantInternal::clear(&r_ret);
VariantTypeChanger<Object *>::change(&r_ret);
VariantInternal::object_assign_null(&r_ret);
}
static inline void validated_construct(Variant *r_ret, const Variant **p_args) {
VariantInternal::clear(r_ret);
VariantTypeChanger<Object *>::change(r_ret);
VariantInternal::object_assign_null(r_ret);
}
static void ptr_construct(void *base, const void **p_args) {
PtrConstruct<Object *>::construct(nullptr, base);
}
static int get_argument_count() {
return 1;
}
static Variant::Type get_argument_type(int p_arg) {
return Variant::NIL;
}
static Variant::Type get_base_type() {
return Variant::OBJECT;
}
};
template <typename T>
class VariantConstructorFromString {
public:
static void construct(Variant &r_ret, const Variant **p_args, Callable::CallError &r_error) {
if (p_args[0]->get_type() != Variant::STRING) {
r_error.error = Callable::CallError::CALL_ERROR_INVALID_ARGUMENT;
r_error.argument = 0;
r_error.expected = Variant::STRING;
return;
}
VariantTypeChanger<T>::change(&r_ret);
const String &src_str = *VariantGetInternalPtr<String>::get_ptr(p_args[0]);
if (r_ret.get_type() == Variant::Type::INT) {
r_ret = src_str.to_int();
} else if (r_ret.get_type() == Variant::Type::FLOAT) {
r_ret = src_str.to_float();
}
}
static inline void validated_construct(Variant *r_ret, const Variant **p_args) {
VariantTypeChanger<T>::change(r_ret);
const String &src_str = *VariantGetInternalPtr<String>::get_ptr(p_args[0]);
T ret = Variant();
if (r_ret->get_type() == Variant::Type::INT) {
ret = src_str.to_int();
} else if (r_ret->get_type() == Variant::Type::FLOAT) {
ret = src_str.to_float();
}
*r_ret = ret;
}
static void ptr_construct(void *base, const void **p_args) {
String src_str = PtrToArg<String>::convert(p_args[0]);
T dst_var = Variant();
Variant type_test = Variant(dst_var);
if (type_test.get_type() == Variant::Type::INT) {
dst_var = src_str.to_int();
} else if (type_test.get_type() == Variant::Type::FLOAT) {
dst_var = src_str.to_float();
}
PtrConstruct<T>::construct(dst_var, base);
}
static int get_argument_count() {
return 1;
}
static Variant::Type get_argument_type(int p_arg) {
return Variant::STRING;
}
static Variant::Type get_base_type() {
return GetTypeInfo<T>::VARIANT_TYPE;
}
};
class VariantConstructorCallableArgs {
public:
static void construct(Variant &r_ret, const Variant **p_args, Callable::CallError &r_error) {
ObjectID object_id;
StringName method;
if (p_args[0]->get_type() == Variant::NIL) {
// leave as is
} else if (p_args[0]->get_type() == Variant::OBJECT) {
object_id = VariantInternal::get_object_id(p_args[0]);
} else {
r_error.error = Callable::CallError::CALL_ERROR_INVALID_ARGUMENT;
r_error.argument = 0;
r_error.expected = Variant::OBJECT;
return;
}
if (p_args[1]->get_type() == Variant::STRING_NAME) {
method = *VariantGetInternalPtr<StringName>::get_ptr(p_args[1]);
} else if (p_args[1]->get_type() == Variant::STRING) {
method = *VariantGetInternalPtr<String>::get_ptr(p_args[1]);
} else {
r_error.error = Callable::CallError::CALL_ERROR_INVALID_ARGUMENT;
r_error.argument = 1;
r_error.expected = Variant::STRING_NAME;
return;
}
VariantTypeChanger<Callable>::change(&r_ret);
*VariantGetInternalPtr<Callable>::get_ptr(&r_ret) = Callable(object_id, method);
}
static inline void validated_construct(Variant *r_ret, const Variant **p_args) {
VariantTypeChanger<Callable>::change(r_ret);
*VariantGetInternalPtr<Callable>::get_ptr(r_ret) = Callable(VariantInternal::get_object_id(p_args[0]), *VariantGetInternalPtr<StringName>::get_ptr(p_args[1]));
}
static void ptr_construct(void *base, const void **p_args) {
PtrConstruct<Callable>::construct(Callable(PtrToArg<Object *>::convert(p_args[0]), PtrToArg<StringName>::convert(p_args[1])), base);
}
static int get_argument_count() {
return 2;
}
static Variant::Type get_argument_type(int p_arg) {
if (p_arg == 0) {
return Variant::OBJECT;
} else {
return Variant::STRING_NAME;
}
}
static Variant::Type get_base_type() {
return Variant::CALLABLE;
}
};
class VariantConstructorSignalArgs {
public:
static void construct(Variant &r_ret, const Variant **p_args, Callable::CallError &r_error) {
ObjectID object_id;
StringName method;
if (p_args[0]->get_type() == Variant::NIL) {
// leave as is
} else if (p_args[0]->get_type() == Variant::OBJECT) {
object_id = VariantInternal::get_object_id(p_args[0]);
} else {
r_error.error = Callable::CallError::CALL_ERROR_INVALID_ARGUMENT;
r_error.argument = 0;
r_error.expected = Variant::OBJECT;
return;
}
if (p_args[1]->get_type() == Variant::STRING_NAME) {
method = *VariantGetInternalPtr<StringName>::get_ptr(p_args[1]);
} else if (p_args[1]->get_type() == Variant::STRING) {
method = *VariantGetInternalPtr<String>::get_ptr(p_args[1]);
} else {
r_error.error = Callable::CallError::CALL_ERROR_INVALID_ARGUMENT;
r_error.argument = 1;
r_error.expected = Variant::STRING_NAME;
return;
}
VariantTypeChanger<Signal>::change(&r_ret);
*VariantGetInternalPtr<Signal>::get_ptr(&r_ret) = Signal(object_id, method);
}
static inline void validated_construct(Variant *r_ret, const Variant **p_args) {
VariantTypeChanger<Signal>::change(r_ret);
*VariantGetInternalPtr<Signal>::get_ptr(r_ret) = Signal(VariantInternal::get_object_id(p_args[0]), *VariantGetInternalPtr<StringName>::get_ptr(p_args[1]));
}
static void ptr_construct(void *base, const void **p_args) {
PtrConstruct<Signal>::construct(Signal(PtrToArg<Object *>::convert(p_args[0]), PtrToArg<StringName>::convert(p_args[1])), base);
}
static int get_argument_count() {
return 2;
}
static Variant::Type get_argument_type(int p_arg) {
if (p_arg == 0) {
return Variant::OBJECT;
} else {
return Variant::STRING_NAME;
}
}
static Variant::Type get_base_type() {
return Variant::SIGNAL;
}
};
class VariantConstructorTypedArray {
public:
static void construct(Variant &r_ret, const Variant **p_args, Callable::CallError &r_error) {
if (p_args[0]->get_type() != Variant::ARRAY) {
r_error.error = Callable::CallError::CALL_ERROR_INVALID_ARGUMENT;
r_error.argument = 0;
r_error.expected = Variant::ARRAY;
return;
}
if (p_args[1]->get_type() != Variant::INT) {
r_error.error = Callable::CallError::CALL_ERROR_INVALID_ARGUMENT;
r_error.argument = 1;
r_error.expected = Variant::INT;
return;
}
if (p_args[2]->get_type() != Variant::STRING_NAME) {
r_error.error = Callable::CallError::CALL_ERROR_INVALID_ARGUMENT;
r_error.argument = 2;
r_error.expected = Variant::STRING_NAME;
return;
}
const Array &base_arr = *VariantGetInternalPtr<Array>::get_ptr(p_args[0]);
const uint32_t type = p_args[1]->operator uint32_t();
const StringName &class_name = *VariantGetInternalPtr<StringName>::get_ptr(p_args[2]);
r_ret = Array(base_arr, type, class_name, *p_args[3]);
}
static inline void validated_construct(Variant *r_ret, const Variant **p_args) {
const Array &base_arr = *VariantGetInternalPtr<Array>::get_ptr(p_args[0]);
const uint32_t type = p_args[1]->operator uint32_t();
const StringName &class_name = *VariantGetInternalPtr<StringName>::get_ptr(p_args[2]);
*r_ret = Array(base_arr, type, class_name, *p_args[3]);
}
static void ptr_construct(void *base, const void **p_args) {
const Array &base_arr = PtrToArg<Array>::convert(p_args[0]);
const uint32_t type = PtrToArg<uint32_t>::convert(p_args[1]);
const StringName &class_name = PtrToArg<StringName>::convert(p_args[2]);
const Variant &script = PtrToArg<Variant>::convert(p_args[3]);
Array dst_arr = Array(base_arr, type, class_name, script);
PtrConstruct<Array>::construct(dst_arr, base);
}
static int get_argument_count() {
return 4;
}
static Variant::Type get_argument_type(int p_arg) {
switch (p_arg) {
case 0: {
return Variant::ARRAY;
} break;
case 1: {
return Variant::INT;
} break;
case 2: {
return Variant::STRING_NAME;
} break;
case 3: {
return Variant::NIL;
} break;
default: {
return Variant::NIL;
} break;
}
}
static Variant::Type get_base_type() {
return Variant::ARRAY;
}
};
template <typename T>
class VariantConstructorToArray {
public:
static void construct(Variant &r_ret, const Variant **p_args, Callable::CallError &r_error) {
if (p_args[0]->get_type() != GetTypeInfo<T>::VARIANT_TYPE) {
r_error.error = Callable::CallError::CALL_ERROR_INVALID_ARGUMENT;
r_error.argument = 0;
r_error.expected = GetTypeInfo<T>::VARIANT_TYPE;
return;
}
r_ret = Array();
Array &dst_arr = *VariantGetInternalPtr<Array>::get_ptr(&r_ret);
const T &src_arr = *VariantGetInternalPtr<T>::get_ptr(p_args[0]);
int size = src_arr.size();
dst_arr.resize(size);
for (int i = 0; i < size; i++) {
dst_arr[i] = src_arr[i];
}
}
static inline void validated_construct(Variant *r_ret, const Variant **p_args) {
*r_ret = Array();
Array &dst_arr = *VariantGetInternalPtr<Array>::get_ptr(r_ret);
const T &src_arr = *VariantGetInternalPtr<T>::get_ptr(p_args[0]);
int size = src_arr.size();
dst_arr.resize(size);
for (int i = 0; i < size; i++) {
dst_arr[i] = src_arr[i];
}
}
static void ptr_construct(void *base, const void **p_args) {
Array dst_arr;
T src_arr = PtrToArg<T>::convert(p_args[0]);
int size = src_arr.size();
dst_arr.resize(size);
for (int i = 0; i < size; i++) {
dst_arr[i] = src_arr[i];
}
PtrConstruct<Array>::construct(dst_arr, base);
}
static int get_argument_count() {
return 1;
}
static Variant::Type get_argument_type(int p_arg) {
return GetTypeInfo<T>::VARIANT_TYPE;
}
static Variant::Type get_base_type() {
return Variant::ARRAY;
}
};
template <typename T>
class VariantConstructorFromArray {
public:
static void construct(Variant &r_ret, const Variant **p_args, Callable::CallError &r_error) {
if (p_args[0]->get_type() != Variant::ARRAY) {
r_error.error = Callable::CallError::CALL_ERROR_INVALID_ARGUMENT;
r_error.argument = 0;
r_error.expected = Variant::ARRAY;
return;
}
VariantTypeChanger<T>::change(&r_ret);
const Array &src_arr = *VariantGetInternalPtr<Array>::get_ptr(p_args[0]);
T &dst_arr = *VariantGetInternalPtr<T>::get_ptr(&r_ret);
int size = src_arr.size();
dst_arr.resize(size);
for (int i = 0; i < size; i++) {
dst_arr.write[i] = src_arr[i];
}
}
static inline void validated_construct(Variant *r_ret, const Variant **p_args) {
VariantTypeChanger<T>::change(r_ret);
const Array &src_arr = *VariantGetInternalPtr<Array>::get_ptr(p_args[0]);
T &dst_arr = *VariantGetInternalPtr<T>::get_ptr(r_ret);
int size = src_arr.size();
dst_arr.resize(size);
for (int i = 0; i < size; i++) {
dst_arr.write[i] = src_arr[i];
}
}
static void ptr_construct(void *base, const void **p_args) {
Array src_arr = PtrToArg<Array>::convert(p_args[0]);
T dst_arr;
int size = src_arr.size();
dst_arr.resize(size);
for (int i = 0; i < size; i++) {
dst_arr.write[i] = src_arr[i];
}
PtrConstruct<T>::construct(dst_arr, base);
}
static int get_argument_count() {
return 1;
}
static Variant::Type get_argument_type(int p_arg) {
return Variant::ARRAY;
}
static Variant::Type get_base_type() {
return GetTypeInfo<T>::VARIANT_TYPE;
}
};
class VariantConstructorNil {
public:
static void construct(Variant &r_ret, const Variant **p_args, Callable::CallError &r_error) {
if (p_args[0]->get_type() != Variant::NIL) {
r_error.error = Callable::CallError::CALL_ERROR_INVALID_ARGUMENT;
r_error.argument = 0;
r_error.expected = Variant::NIL;
return;
}
r_error.error = Callable::CallError::CALL_OK;
VariantInternal::clear(&r_ret);
}
static inline void validated_construct(Variant *r_ret, const Variant **p_args) {
VariantInternal::clear(r_ret);
}
static void ptr_construct(void *base, const void **p_args) {
PtrConstruct<Variant>::construct(Variant(), base);
}
static int get_argument_count() {
return 1;
}
static Variant::Type get_argument_type(int p_arg) {
return Variant::NIL;
}
static Variant::Type get_base_type() {
return Variant::NIL;
}
};
template <typename T>
class VariantConstructNoArgs {
public:
static void construct(Variant &r_ret, const Variant **p_args, Callable::CallError &r_error) {
VariantTypeChanger<T>::change_and_reset(&r_ret);
r_error.error = Callable::CallError::CALL_OK;
}
static inline void validated_construct(Variant *r_ret, const Variant **p_args) {
VariantTypeChanger<T>::change_and_reset(r_ret);
}
static void ptr_construct(void *base, const void **p_args) {
PtrConstruct<T>::construct(T(), base);
}
static int get_argument_count() {
return 0;
}
static Variant::Type get_argument_type(int p_arg) {
return Variant::NIL;
}
static Variant::Type get_base_type() {
return GetTypeInfo<T>::VARIANT_TYPE;
}
};
class VariantConstructNoArgsNil {
public:
static void construct(Variant &r_ret, const Variant **p_args, Callable::CallError &r_error) {
VariantInternal::clear(&r_ret);
r_error.error = Callable::CallError::CALL_OK;
}
static inline void validated_construct(Variant *r_ret, const Variant **p_args) {
VariantInternal::clear(r_ret);
}
static void ptr_construct(void *base, const void **p_args) {
ERR_FAIL_MSG("Cannot ptrcall nil constructor");
}
static int get_argument_count() {
return 0;
}
static Variant::Type get_argument_type(int p_arg) {
return Variant::NIL;
}
static Variant::Type get_base_type() {
return Variant::NIL;
}
};
class VariantConstructNoArgsObject {
public:
static void construct(Variant &r_ret, const Variant **p_args, Callable::CallError &r_error) {
r_ret = (Object *)nullptr; // Must construct a TYPE_OBJECT containing nullptr.
r_error.error = Callable::CallError::CALL_OK;
}
static inline void validated_construct(Variant *r_ret, const Variant **p_args) {
*r_ret = (Object *)nullptr; // Must construct a TYPE_OBJECT containing nullptr.
}
static void ptr_construct(void *base, const void **p_args) {
PtrConstruct<Object *>::construct(nullptr, base);
}
static int get_argument_count() {
return 0;
}
static Variant::Type get_argument_type(int p_arg) {
return Variant::NIL;
}
static Variant::Type get_base_type() {
return Variant::OBJECT;
}
};
#endif // VARIANT_CONSTRUCT_H

View file

@ -0,0 +1,74 @@
/**************************************************************************/
/* variant_destruct.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_destruct.h"
#include "core/templates/local_vector.h"
static Variant::PTRDestructor destruct_pointers[Variant::VARIANT_MAX] = { nullptr };
template <typename T>
static void add_destructor() {
destruct_pointers[T::get_base_type()] = T::ptr_destruct;
}
void Variant::_register_variant_destructors() {
add_destructor<VariantDestruct<String>>();
add_destructor<VariantDestruct<StringName>>();
add_destructor<VariantDestruct<NodePath>>();
add_destructor<VariantDestruct<Callable>>();
add_destructor<VariantDestruct<Signal>>();
add_destructor<VariantDestruct<Dictionary>>();
add_destructor<VariantDestruct<Array>>();
add_destructor<VariantDestruct<PackedByteArray>>();
add_destructor<VariantDestruct<PackedInt32Array>>();
add_destructor<VariantDestruct<PackedInt64Array>>();
add_destructor<VariantDestruct<PackedFloat32Array>>();
add_destructor<VariantDestruct<PackedFloat64Array>>();
add_destructor<VariantDestruct<PackedStringArray>>();
add_destructor<VariantDestruct<PackedVector2Array>>();
add_destructor<VariantDestruct<PackedVector3Array>>();
add_destructor<VariantDestruct<PackedColorArray>>();
add_destructor<VariantDestruct<PackedVector4Array>>();
}
void Variant::_unregister_variant_destructors() {
// Nothing to be done.
}
Variant::PTRDestructor Variant::get_ptr_destructor(Variant::Type p_type) {
ERR_FAIL_INDEX_V(p_type, Variant::VARIANT_MAX, nullptr);
return destruct_pointers[p_type];
}
bool Variant::has_destructor(Variant::Type p_type) {
ERR_FAIL_INDEX_V(p_type, Variant::VARIANT_MAX, false);
return destruct_pointers[p_type] != nullptr;
}

View file

@ -0,0 +1,72 @@
/**************************************************************************/
/* variant_destruct.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_DESTRUCT_H
#define VARIANT_DESTRUCT_H
#include "core/variant/variant.h"
#include "core/object/class_db.h"
template <typename T>
struct VariantDestruct {};
#define MAKE_PTRDESTRUCT(m_type) \
template <> \
struct VariantDestruct<m_type> { \
_FORCE_INLINE_ static void ptr_destruct(void *p_ptr) { \
reinterpret_cast<m_type *>(p_ptr)->~m_type(); \
} \
_FORCE_INLINE_ static Variant::Type get_base_type() { \
return GetTypeInfo<m_type>::VARIANT_TYPE; \
} \
}
MAKE_PTRDESTRUCT(String);
MAKE_PTRDESTRUCT(StringName);
MAKE_PTRDESTRUCT(NodePath);
MAKE_PTRDESTRUCT(Callable);
MAKE_PTRDESTRUCT(Signal);
MAKE_PTRDESTRUCT(Dictionary);
MAKE_PTRDESTRUCT(Array);
MAKE_PTRDESTRUCT(PackedByteArray);
MAKE_PTRDESTRUCT(PackedInt32Array);
MAKE_PTRDESTRUCT(PackedInt64Array);
MAKE_PTRDESTRUCT(PackedFloat32Array);
MAKE_PTRDESTRUCT(PackedFloat64Array);
MAKE_PTRDESTRUCT(PackedStringArray);
MAKE_PTRDESTRUCT(PackedVector2Array);
MAKE_PTRDESTRUCT(PackedVector3Array);
MAKE_PTRDESTRUCT(PackedColorArray);
MAKE_PTRDESTRUCT(PackedVector4Array);
#undef MAKE_PTRDESTRUCT
#endif // VARIANT_DESTRUCT_H

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,168 @@
/**************************************************************************/
/* variant_parser.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_PARSER_H
#define VARIANT_PARSER_H
#include "core/io/file_access.h"
#include "core/io/resource.h"
#include "core/variant/variant.h"
class VariantParser {
public:
struct Stream {
private:
enum { READAHEAD_SIZE = 2048 };
char32_t readahead_buffer[READAHEAD_SIZE];
uint32_t readahead_pointer = 0;
uint32_t readahead_filled = 0;
bool eof = false;
protected:
bool readahead_enabled = true;
virtual uint32_t _read_buffer(char32_t *p_buffer, uint32_t p_num_chars) = 0;
virtual bool _is_eof() const = 0;
public:
char32_t saved = 0;
char32_t get_char();
virtual bool is_utf8() const = 0;
bool is_eof() const;
Stream() {}
virtual ~Stream() {}
};
struct StreamFile : public Stream {
protected:
virtual uint32_t _read_buffer(char32_t *p_buffer, uint32_t p_num_chars) override;
virtual bool _is_eof() const override;
public:
Ref<FileAccess> f;
virtual bool is_utf8() const override;
StreamFile(bool p_readahead_enabled = true) { readahead_enabled = p_readahead_enabled; }
};
struct StreamString : public Stream {
String s;
private:
int pos = 0;
protected:
virtual uint32_t _read_buffer(char32_t *p_buffer, uint32_t p_num_chars) override;
virtual bool _is_eof() const override;
public:
virtual bool is_utf8() const override;
StreamString(bool p_readahead_enabled = true) { readahead_enabled = p_readahead_enabled; }
};
typedef Error (*ParseResourceFunc)(void *p_self, Stream *p_stream, Ref<Resource> &r_res, int &line, String &r_err_str);
struct ResourceParser {
void *userdata = nullptr;
ParseResourceFunc func = nullptr;
ParseResourceFunc ext_func = nullptr;
ParseResourceFunc sub_func = nullptr;
};
enum TokenType {
TK_CURLY_BRACKET_OPEN,
TK_CURLY_BRACKET_CLOSE,
TK_BRACKET_OPEN,
TK_BRACKET_CLOSE,
TK_PARENTHESIS_OPEN,
TK_PARENTHESIS_CLOSE,
TK_IDENTIFIER,
TK_STRING,
TK_STRING_NAME,
TK_NUMBER,
TK_COLOR,
TK_COLON,
TK_COMMA,
TK_PERIOD,
TK_EQUAL,
TK_EOF,
TK_ERROR,
TK_MAX
};
enum Expecting {
EXPECT_OBJECT,
EXPECT_OBJECT_KEY,
EXPECT_COLON,
EXPECT_OBJECT_VALUE,
};
struct Token {
TokenType type;
Variant value;
};
struct Tag {
String name;
HashMap<String, Variant> fields;
};
private:
static const char *tk_name[TK_MAX];
template <typename T>
static Error _parse_construct(Stream *p_stream, Vector<T> &r_construct, int &line, String &r_err_str);
static Error _parse_byte_array(Stream *p_stream, Vector<uint8_t> &r_construct, int &line, String &r_err_str);
static Error _parse_enginecfg(Stream *p_stream, Vector<String> &strings, int &line, String &r_err_str);
static Error _parse_dictionary(Dictionary &object, Stream *p_stream, int &line, String &r_err_str, ResourceParser *p_res_parser = nullptr);
static Error _parse_array(Array &array, Stream *p_stream, int &line, String &r_err_str, ResourceParser *p_res_parser = nullptr);
static Error _parse_tag(Token &token, Stream *p_stream, int &line, String &r_err_str, Tag &r_tag, ResourceParser *p_res_parser = nullptr, bool p_simple_tag = false);
public:
static Error parse_tag(Stream *p_stream, int &line, String &r_err_str, Tag &r_tag, ResourceParser *p_res_parser = nullptr, bool p_simple_tag = false);
static Error parse_tag_assign_eof(Stream *p_stream, int &line, String &r_err_str, Tag &r_tag, String &r_assign, Variant &r_value, ResourceParser *p_res_parser = nullptr, bool p_simple_tag = false);
static Error parse_value(Token &token, Variant &value, Stream *p_stream, int &line, String &r_err_str, ResourceParser *p_res_parser = nullptr);
static Error get_token(Stream *p_stream, Token &r_token, int &line, String &r_err_str);
static Error parse(Stream *p_stream, Variant &r_ret, String &r_err_str, int &r_err_line, ResourceParser *p_res_parser = nullptr);
};
class VariantWriter {
public:
typedef Error (*StoreStringFunc)(void *ud, const String &p_string);
typedef String (*EncodeResourceFunc)(void *ud, const Ref<Resource> &p_resource);
static Error write(const Variant &p_variant, StoreStringFunc p_store_string_func, void *p_store_string_ud, EncodeResourceFunc p_encode_res_func, void *p_encode_res_ud, int p_recursion_count = 0, bool p_compat = true);
static Error write_to_string(const Variant &p_variant, String &r_string, EncodeResourceFunc p_encode_res_func = nullptr, void *p_encode_res_ud = nullptr, bool p_compat = true);
};
#endif // VARIANT_PARSER_H

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,350 @@
/**************************************************************************/
/* variant_setget.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_SETGET_H
#define VARIANT_SETGET_H
#include "variant.h"
#include "core/debugger/engine_debugger.h"
#include "core/object/class_db.h"
#include "core/templates/local_vector.h"
#include "core/variant/variant_internal.h"
/**** NAMED SETTERS AND GETTERS ****/
#define SETGET_STRUCT(m_base_type, m_member_type, m_member) \
struct VariantSetGet_##m_base_type##_##m_member { \
static void get(const Variant *base, Variant *member) { \
VariantTypeAdjust<m_member_type>::adjust(member); \
*VariantGetInternalPtr<m_member_type>::get_ptr(member) = VariantGetInternalPtr<m_base_type>::get_ptr(base)->m_member; \
} \
static inline void validated_get(const Variant *base, Variant *member) { \
*VariantGetInternalPtr<m_member_type>::get_ptr(member) = VariantGetInternalPtr<m_base_type>::get_ptr(base)->m_member; \
} \
static void ptr_get(const void *base, void *member) { \
PtrToArg<m_member_type>::encode(PtrToArg<m_base_type>::convert(base).m_member, member); \
} \
static void set(Variant *base, const Variant *value, bool &valid) { \
if (value->get_type() == GetTypeInfo<m_member_type>::VARIANT_TYPE) { \
VariantGetInternalPtr<m_base_type>::get_ptr(base)->m_member = *VariantGetInternalPtr<m_member_type>::get_ptr(value); \
valid = true; \
} else { \
valid = false; \
} \
} \
static inline void validated_set(Variant *base, const Variant *value) { \
VariantGetInternalPtr<m_base_type>::get_ptr(base)->m_member = *VariantGetInternalPtr<m_member_type>::get_ptr(value); \
} \
static void ptr_set(void *base, const void *member) { \
m_base_type b = PtrToArg<m_base_type>::convert(base); \
b.m_member = PtrToArg<m_member_type>::convert(member); \
PtrToArg<m_base_type>::encode(b, base); \
} \
static Variant::Type get_type() { return GetTypeInfo<m_member_type>::VARIANT_TYPE; } \
};
#define SETGET_NUMBER_STRUCT(m_base_type, m_member_type, m_member) \
struct VariantSetGet_##m_base_type##_##m_member { \
static void get(const Variant *base, Variant *member) { \
VariantTypeAdjust<m_member_type>::adjust(member); \
*VariantGetInternalPtr<m_member_type>::get_ptr(member) = VariantGetInternalPtr<m_base_type>::get_ptr(base)->m_member; \
} \
static inline void validated_get(const Variant *base, Variant *member) { \
*VariantGetInternalPtr<m_member_type>::get_ptr(member) = VariantGetInternalPtr<m_base_type>::get_ptr(base)->m_member; \
} \
static void ptr_get(const void *base, void *member) { \
PtrToArg<m_member_type>::encode(PtrToArg<m_base_type>::convert(base).m_member, member); \
} \
static void set(Variant *base, const Variant *value, bool &valid) { \
if (value->get_type() == Variant::FLOAT) { \
VariantGetInternalPtr<m_base_type>::get_ptr(base)->m_member = *VariantGetInternalPtr<double>::get_ptr(value); \
valid = true; \
} else if (value->get_type() == Variant::INT) { \
VariantGetInternalPtr<m_base_type>::get_ptr(base)->m_member = *VariantGetInternalPtr<int64_t>::get_ptr(value); \
valid = true; \
} else { \
valid = false; \
} \
} \
static inline void validated_set(Variant *base, const Variant *value) { \
VariantGetInternalPtr<m_base_type>::get_ptr(base)->m_member = *VariantGetInternalPtr<m_member_type>::get_ptr(value); \
} \
static void ptr_set(void *base, const void *member) { \
m_base_type b = PtrToArg<m_base_type>::convert(base); \
b.m_member = PtrToArg<m_member_type>::convert(member); \
PtrToArg<m_base_type>::encode(b, base); \
} \
static Variant::Type get_type() { return GetTypeInfo<m_member_type>::VARIANT_TYPE; } \
};
#define SETGET_STRUCT_CUSTOM(m_base_type, m_member_type, m_member, m_custom) \
struct VariantSetGet_##m_base_type##_##m_member { \
static void get(const Variant *base, Variant *member) { \
VariantTypeAdjust<m_member_type>::adjust(member); \
*VariantGetInternalPtr<m_member_type>::get_ptr(member) = VariantGetInternalPtr<m_base_type>::get_ptr(base)->m_custom; \
} \
static inline void validated_get(const Variant *base, Variant *member) { \
*VariantGetInternalPtr<m_member_type>::get_ptr(member) = VariantGetInternalPtr<m_base_type>::get_ptr(base)->m_custom; \
} \
static void ptr_get(const void *base, void *member) { \
PtrToArg<m_member_type>::encode(PtrToArg<m_base_type>::convert(base).m_custom, member); \
} \
static void set(Variant *base, const Variant *value, bool &valid) { \
if (value->get_type() == GetTypeInfo<m_member_type>::VARIANT_TYPE) { \
VariantGetInternalPtr<m_base_type>::get_ptr(base)->m_custom = *VariantGetInternalPtr<m_member_type>::get_ptr(value); \
valid = true; \
} else { \
valid = false; \
} \
} \
static inline void validated_set(Variant *base, const Variant *value) { \
VariantGetInternalPtr<m_base_type>::get_ptr(base)->m_custom = *VariantGetInternalPtr<m_member_type>::get_ptr(value); \
} \
static void ptr_set(void *base, const void *member) { \
m_base_type b = PtrToArg<m_base_type>::convert(base); \
b.m_custom = PtrToArg<m_member_type>::convert(member); \
PtrToArg<m_base_type>::encode(b, base); \
} \
static Variant::Type get_type() { return GetTypeInfo<m_member_type>::VARIANT_TYPE; } \
};
#define SETGET_NUMBER_STRUCT_CUSTOM(m_base_type, m_member_type, m_member, m_custom) \
struct VariantSetGet_##m_base_type##_##m_member { \
static void get(const Variant *base, Variant *member) { \
VariantTypeAdjust<m_member_type>::adjust(member); \
*VariantGetInternalPtr<m_member_type>::get_ptr(member) = VariantGetInternalPtr<m_base_type>::get_ptr(base)->m_custom; \
} \
static inline void validated_get(const Variant *base, Variant *member) { \
*VariantGetInternalPtr<m_member_type>::get_ptr(member) = VariantGetInternalPtr<m_base_type>::get_ptr(base)->m_custom; \
} \
static void ptr_get(const void *base, void *member) { \
PtrToArg<m_member_type>::encode(PtrToArg<m_base_type>::convert(base).m_custom, member); \
} \
static void set(Variant *base, const Variant *value, bool &valid) { \
if (value->get_type() == Variant::FLOAT) { \
VariantGetInternalPtr<m_base_type>::get_ptr(base)->m_custom = *VariantGetInternalPtr<double>::get_ptr(value); \
valid = true; \
} else if (value->get_type() == Variant::INT) { \
VariantGetInternalPtr<m_base_type>::get_ptr(base)->m_custom = *VariantGetInternalPtr<int64_t>::get_ptr(value); \
valid = true; \
} else { \
valid = false; \
} \
} \
static inline void validated_set(Variant *base, const Variant *value) { \
VariantGetInternalPtr<m_base_type>::get_ptr(base)->m_custom = *VariantGetInternalPtr<m_member_type>::get_ptr(value); \
} \
static void ptr_set(void *base, const void *member) { \
m_base_type b = PtrToArg<m_base_type>::convert(base); \
b.m_custom = PtrToArg<m_member_type>::convert(member); \
PtrToArg<m_base_type>::encode(b, base); \
} \
static Variant::Type get_type() { return GetTypeInfo<m_member_type>::VARIANT_TYPE; } \
};
#define SETGET_STRUCT_FUNC(m_base_type, m_member_type, m_member, m_setter, m_getter) \
struct VariantSetGet_##m_base_type##_##m_member { \
static void get(const Variant *base, Variant *member) { \
VariantTypeAdjust<m_member_type>::adjust(member); \
*VariantGetInternalPtr<m_member_type>::get_ptr(member) = VariantGetInternalPtr<m_base_type>::get_ptr(base)->m_getter(); \
} \
static inline void validated_get(const Variant *base, Variant *member) { \
*VariantGetInternalPtr<m_member_type>::get_ptr(member) = VariantGetInternalPtr<m_base_type>::get_ptr(base)->m_getter(); \
} \
static void ptr_get(const void *base, void *member) { \
PtrToArg<m_member_type>::encode(PtrToArg<m_base_type>::convert(base).m_getter(), member); \
} \
static void set(Variant *base, const Variant *value, bool &valid) { \
if (value->get_type() == GetTypeInfo<m_member_type>::VARIANT_TYPE) { \
VariantGetInternalPtr<m_base_type>::get_ptr(base)->m_setter(*VariantGetInternalPtr<m_member_type>::get_ptr(value)); \
valid = true; \
} else { \
valid = false; \
} \
} \
static inline void validated_set(Variant *base, const Variant *value) { \
VariantGetInternalPtr<m_base_type>::get_ptr(base)->m_setter(*VariantGetInternalPtr<m_member_type>::get_ptr(value)); \
} \
static void ptr_set(void *base, const void *member) { \
m_base_type b = PtrToArg<m_base_type>::convert(base); \
b.m_setter(PtrToArg<m_member_type>::convert(member)); \
PtrToArg<m_base_type>::encode(b, base); \
} \
static Variant::Type get_type() { return GetTypeInfo<m_member_type>::VARIANT_TYPE; } \
};
#define SETGET_NUMBER_STRUCT_FUNC(m_base_type, m_member_type, m_member, m_setter, m_getter) \
struct VariantSetGet_##m_base_type##_##m_member { \
static void get(const Variant *base, Variant *member) { \
VariantTypeAdjust<m_member_type>::adjust(member); \
*VariantGetInternalPtr<m_member_type>::get_ptr(member) = VariantGetInternalPtr<m_base_type>::get_ptr(base)->m_getter(); \
} \
static inline void validated_get(const Variant *base, Variant *member) { \
*VariantGetInternalPtr<m_member_type>::get_ptr(member) = VariantGetInternalPtr<m_base_type>::get_ptr(base)->m_getter(); \
} \
static void ptr_get(const void *base, void *member) { \
PtrToArg<m_member_type>::encode(PtrToArg<m_base_type>::convert(base).m_getter(), member); \
} \
static void set(Variant *base, const Variant *value, bool &valid) { \
if (value->get_type() == Variant::FLOAT) { \
VariantGetInternalPtr<m_base_type>::get_ptr(base)->m_setter(*VariantGetInternalPtr<double>::get_ptr(value)); \
valid = true; \
} else if (value->get_type() == Variant::INT) { \
VariantGetInternalPtr<m_base_type>::get_ptr(base)->m_setter(*VariantGetInternalPtr<int64_t>::get_ptr(value)); \
valid = true; \
} else { \
valid = false; \
} \
} \
static inline void validated_set(Variant *base, const Variant *value) { \
VariantGetInternalPtr<m_base_type>::get_ptr(base)->m_setter(*VariantGetInternalPtr<m_member_type>::get_ptr(value)); \
} \
static void ptr_set(void *base, const void *member) { \
m_base_type b = PtrToArg<m_base_type>::convert(base); \
b.m_setter(PtrToArg<m_member_type>::convert(member)); \
PtrToArg<m_base_type>::encode(b, base); \
} \
static Variant::Type get_type() { return GetTypeInfo<m_member_type>::VARIANT_TYPE; } \
};
#define SETGET_STRUCT_FUNC_INDEX(m_base_type, m_member_type, m_member, m_setter, m_getter, m_index) \
struct VariantSetGet_##m_base_type##_##m_member { \
static void get(const Variant *base, Variant *member) { \
VariantTypeAdjust<m_member_type>::adjust(member); \
*VariantGetInternalPtr<m_member_type>::get_ptr(member) = VariantGetInternalPtr<m_base_type>::get_ptr(base)->m_getter(m_index); \
} \
static inline void validated_get(const Variant *base, Variant *member) { \
*VariantGetInternalPtr<m_member_type>::get_ptr(member) = VariantGetInternalPtr<m_base_type>::get_ptr(base)->m_getter(m_index); \
} \
static void ptr_get(const void *base, void *member) { \
PtrToArg<m_member_type>::encode(PtrToArg<m_base_type>::convert(base).m_getter(m_index), member); \
} \
static void set(Variant *base, const Variant *value, bool &valid) { \
if (value->get_type() == GetTypeInfo<m_member_type>::VARIANT_TYPE) { \
VariantGetInternalPtr<m_base_type>::get_ptr(base)->m_setter(m_index, *VariantGetInternalPtr<m_member_type>::get_ptr(value)); \
valid = true; \
} else { \
valid = false; \
} \
} \
static inline void validated_set(Variant *base, const Variant *value) { \
VariantGetInternalPtr<m_base_type>::get_ptr(base)->m_setter(m_index, *VariantGetInternalPtr<m_member_type>::get_ptr(value)); \
} \
static void ptr_set(void *base, const void *member) { \
m_base_type b = PtrToArg<m_base_type>::convert(base); \
b.m_setter(m_index, PtrToArg<m_member_type>::convert(member)); \
PtrToArg<m_base_type>::encode(b, base); \
} \
static Variant::Type get_type() { return GetTypeInfo<m_member_type>::VARIANT_TYPE; } \
};
SETGET_NUMBER_STRUCT(Vector2, double, x)
SETGET_NUMBER_STRUCT(Vector2, double, y)
SETGET_NUMBER_STRUCT(Vector2i, int64_t, x)
SETGET_NUMBER_STRUCT(Vector2i, int64_t, y)
SETGET_NUMBER_STRUCT(Vector3, double, x)
SETGET_NUMBER_STRUCT(Vector3, double, y)
SETGET_NUMBER_STRUCT(Vector3, double, z)
SETGET_NUMBER_STRUCT(Vector3i, int64_t, x)
SETGET_NUMBER_STRUCT(Vector3i, int64_t, y)
SETGET_NUMBER_STRUCT(Vector3i, int64_t, z)
SETGET_NUMBER_STRUCT(Vector4, double, x)
SETGET_NUMBER_STRUCT(Vector4, double, y)
SETGET_NUMBER_STRUCT(Vector4, double, z)
SETGET_NUMBER_STRUCT(Vector4, double, w)
SETGET_NUMBER_STRUCT(Vector4i, int64_t, x)
SETGET_NUMBER_STRUCT(Vector4i, int64_t, y)
SETGET_NUMBER_STRUCT(Vector4i, int64_t, z)
SETGET_NUMBER_STRUCT(Vector4i, int64_t, w)
SETGET_STRUCT(Rect2, Vector2, position)
SETGET_STRUCT(Rect2, Vector2, size)
SETGET_STRUCT_FUNC(Rect2, Vector2, end, set_end, get_end)
SETGET_STRUCT(Rect2i, Vector2i, position)
SETGET_STRUCT(Rect2i, Vector2i, size)
SETGET_STRUCT_FUNC(Rect2i, Vector2i, end, set_end, get_end)
SETGET_STRUCT(AABB, Vector3, position)
SETGET_STRUCT(AABB, Vector3, size)
SETGET_STRUCT_FUNC(AABB, Vector3, end, set_end, get_end)
SETGET_STRUCT_CUSTOM(Transform2D, Vector2, x, columns[0])
SETGET_STRUCT_CUSTOM(Transform2D, Vector2, y, columns[1])
SETGET_STRUCT_CUSTOM(Transform2D, Vector2, origin, columns[2])
SETGET_NUMBER_STRUCT_CUSTOM(Plane, double, x, normal.x)
SETGET_NUMBER_STRUCT_CUSTOM(Plane, double, y, normal.y)
SETGET_NUMBER_STRUCT_CUSTOM(Plane, double, z, normal.z)
SETGET_STRUCT(Plane, Vector3, normal)
SETGET_NUMBER_STRUCT(Plane, double, d)
SETGET_NUMBER_STRUCT(Quaternion, double, x)
SETGET_NUMBER_STRUCT(Quaternion, double, y)
SETGET_NUMBER_STRUCT(Quaternion, double, z)
SETGET_NUMBER_STRUCT(Quaternion, double, w)
SETGET_STRUCT_FUNC_INDEX(Basis, Vector3, x, set_column, get_column, 0)
SETGET_STRUCT_FUNC_INDEX(Basis, Vector3, y, set_column, get_column, 1)
SETGET_STRUCT_FUNC_INDEX(Basis, Vector3, z, set_column, get_column, 2)
SETGET_STRUCT(Transform3D, Basis, basis)
SETGET_STRUCT(Transform3D, Vector3, origin)
SETGET_STRUCT_CUSTOM(Projection, Vector4, x, columns[0])
SETGET_STRUCT_CUSTOM(Projection, Vector4, y, columns[1])
SETGET_STRUCT_CUSTOM(Projection, Vector4, z, columns[2])
SETGET_STRUCT_CUSTOM(Projection, Vector4, w, columns[3])
SETGET_NUMBER_STRUCT(Color, double, r)
SETGET_NUMBER_STRUCT(Color, double, g)
SETGET_NUMBER_STRUCT(Color, double, b)
SETGET_NUMBER_STRUCT(Color, double, a)
SETGET_NUMBER_STRUCT_FUNC(Color, int64_t, r8, set_r8, get_r8)
SETGET_NUMBER_STRUCT_FUNC(Color, int64_t, g8, set_g8, get_g8)
SETGET_NUMBER_STRUCT_FUNC(Color, int64_t, b8, set_b8, get_b8)
SETGET_NUMBER_STRUCT_FUNC(Color, int64_t, a8, set_a8, get_a8)
SETGET_NUMBER_STRUCT_FUNC(Color, double, h, set_h, get_h)
SETGET_NUMBER_STRUCT_FUNC(Color, double, s, set_s, get_s)
SETGET_NUMBER_STRUCT_FUNC(Color, double, v, set_v, get_v)
SETGET_NUMBER_STRUCT_FUNC(Color, double, ok_hsl_h, set_ok_hsl_h, get_ok_hsl_h)
SETGET_NUMBER_STRUCT_FUNC(Color, double, ok_hsl_s, set_ok_hsl_s, get_ok_hsl_s)
SETGET_NUMBER_STRUCT_FUNC(Color, double, ok_hsl_l, set_ok_hsl_l, get_ok_hsl_l)
#endif // VARIANT_SETGET_H

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,159 @@
/**************************************************************************/
/* variant_utility.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_UTILITY_H
#define VARIANT_UTILITY_H
#include "variant.h"
struct VariantUtilityFunctions {
// Math
static double sin(double arg);
static double cos(double arg);
static double tan(double arg);
static double sinh(double arg);
static double cosh(double arg);
static double tanh(double arg);
static double asin(double arg);
static double acos(double arg);
static double atan(double arg);
static double atan2(double y, double x);
static double asinh(double arg);
static double acosh(double arg);
static double atanh(double arg);
static double sqrt(double x);
static double fmod(double b, double r);
static double fposmod(double b, double r);
static int64_t posmod(int64_t b, int64_t r);
static Variant floor(const Variant &x, Callable::CallError &r_error);
static double floorf(double x);
static int64_t floori(double x);
static Variant ceil(const Variant &x, Callable::CallError &r_error);
static double ceilf(double x);
static int64_t ceili(double x);
static Variant round(const Variant &x, Callable::CallError &r_error);
static double roundf(double x);
static int64_t roundi(double x);
static Variant abs(const Variant &x, Callable::CallError &r_error);
static double absf(double x);
static int64_t absi(int64_t x);
static Variant sign(const Variant &x, Callable::CallError &r_error);
static double signf(double x);
static int64_t signi(int64_t x);
static double pow(double x, double y);
static double log(double x);
static double exp(double x);
static bool is_nan(double x);
static bool is_inf(double x);
static bool is_equal_approx(double x, double y);
static bool is_zero_approx(double x);
static bool is_finite(double x);
static double ease(float x, float curve);
static int step_decimals(float step);
static Variant snapped(const Variant &x, const Variant &step, Callable::CallError &r_error);
static double snappedf(double x, double step);
static int64_t snappedi(double x, int64_t step);
static Variant lerp(const Variant &from, const Variant &to, double weight, Callable::CallError &r_error);
static double lerpf(double from, double to, double weight);
static double cubic_interpolate(double from, double to, double pre, double post, double weight);
static double cubic_interpolate_angle(double from, double to, double pre, double post, double weight);
static double cubic_interpolate_in_time(double from, double to, double pre, double post, double weight,
double to_t, double pre_t, double post_t);
static double cubic_interpolate_angle_in_time(double from, double to, double pre, double post, double weight,
double to_t, double pre_t, double post_t);
static double bezier_interpolate(double p_start, double p_control_1, double p_control_2, double p_end, double p_t);
static double bezier_derivative(double p_start, double p_control_1, double p_control_2, double p_end, double p_t);
static double angle_difference(double from, double to);
static double lerp_angle(double from, double to, double weight);
static double inverse_lerp(double from, double to, double weight);
static double remap(double value, double istart, double istop, double ostart, double ostop);
static double smoothstep(double from, double to, double val);
static double move_toward(double from, double to, double delta);
static double rotate_toward(double from, double to, double delta);
static double deg_to_rad(double angle_deg);
static double rad_to_deg(double angle_rad);
static double linear_to_db(double linear);
static double db_to_linear(double db);
static Variant wrap(const Variant &p_x, const Variant &p_min, const Variant &p_max, Callable::CallError &r_error);
static int64_t wrapi(int64_t value, int64_t min, int64_t max);
static double wrapf(double value, double min, double max);
static double pingpong(double value, double length);
static Variant max(const Variant **p_args, int p_argcount, Callable::CallError &r_error);
static double maxf(double x, double y);
static int64_t maxi(int64_t x, int64_t y);
static Variant min(const Variant **p_args, int p_argcount, Callable::CallError &r_error);
static double minf(double x, double y);
static int64_t mini(int64_t x, int64_t y);
static Variant clamp(const Variant &x, const Variant &min, const Variant &max, Callable::CallError &r_error);
static double clampf(double x, double min, double max);
static int64_t clampi(int64_t x, int64_t min, int64_t max);
static int64_t nearest_po2(int64_t x);
// Random
static void randomize();
static int64_t randi();
static double randf();
static double randfn(double mean, double deviation);
static int64_t randi_range(int64_t from, int64_t to);
static double randf_range(double from, double to);
static void seed(int64_t s);
static PackedInt64Array rand_from_seed(int64_t seed);
// Utility
static Variant weakref(const Variant &obj, Callable::CallError &r_error);
static int64_t _typeof(const Variant &obj);
static Variant type_convert(const Variant &p_variant, const Variant::Type p_type);
static String str(const Variant **p_args, int p_arg_count, Callable::CallError &r_error);
static String error_string(Error error);
static String type_string(Variant::Type p_type);
static void print(const Variant **p_args, int p_arg_count, Callable::CallError &r_error);
static void print_rich(const Variant **p_args, int p_arg_count, Callable::CallError &r_error);
#undef print_verbose
static void print_verbose(const Variant **p_args, int p_arg_count, Callable::CallError &r_error);
static void printerr(const Variant **p_args, int p_arg_count, Callable::CallError &r_error);
static void printt(const Variant **p_args, int p_arg_count, Callable::CallError &r_error);
static void prints(const Variant **p_args, int p_arg_count, Callable::CallError &r_error);
static void printraw(const Variant **p_args, int p_arg_count, Callable::CallError &r_error);
static void push_error(const Variant **p_args, int p_arg_count, Callable::CallError &r_error);
static void push_warning(const Variant **p_args, int p_arg_count, Callable::CallError &r_error);
static String var_to_str(const Variant &p_var);
static Variant str_to_var(const String &p_var);
static PackedByteArray var_to_bytes(const Variant &p_var);
static PackedByteArray var_to_bytes_with_objects(const Variant &p_var);
static Variant bytes_to_var(const PackedByteArray &p_arr);
static Variant bytes_to_var_with_objects(const PackedByteArray &p_arr);
static int64_t hash(const Variant &p_arr);
static Object *instance_from_id(int64_t p_id);
static bool is_instance_id_valid(int64_t p_id);
static bool is_instance_valid(const Variant &p_instance);
static uint64_t rid_allocate_id();
static RID rid_from_int64(uint64_t p_base);
static bool is_same(const Variant &p_a, const Variant &p_b);
};
#endif // VARIANT_UTILITY_H