reordered the libs
This commit is contained in:
58
lib/godot-cpp/src/classes/low_level.cpp
Normal file
58
lib/godot-cpp/src/classes/low_level.cpp
Normal file
@@ -0,0 +1,58 @@
|
||||
/**************************************************************************/
|
||||
/* low_level.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 <godot_cpp/classes/file_access.hpp>
|
||||
#include <godot_cpp/classes/worker_thread_pool.hpp>
|
||||
#include <godot_cpp/classes/xml_parser.hpp>
|
||||
|
||||
#include <godot_cpp/godot.hpp>
|
||||
|
||||
namespace godot {
|
||||
Error XMLParser::_open_buffer(const uint8_t *p_buffer, size_t p_size) {
|
||||
return (Error)internal::gde_interface->xml_parser_open_buffer(_owner, p_buffer, p_size);
|
||||
}
|
||||
|
||||
uint64_t FileAccess::get_buffer(uint8_t *p_dst, uint64_t p_length) const {
|
||||
return internal::gde_interface->file_access_get_buffer(_owner, p_dst, p_length);
|
||||
}
|
||||
|
||||
void FileAccess::store_buffer(const uint8_t *p_src, uint64_t p_length) {
|
||||
internal::gde_interface->file_access_store_buffer(_owner, p_src, p_length);
|
||||
}
|
||||
|
||||
WorkerThreadPool::TaskID WorkerThreadPool::add_native_task(void (*p_func)(void *), void *p_userdata, bool p_high_priority, const String &p_description) {
|
||||
return (TaskID)internal::gde_interface->worker_thread_pool_add_native_task(_owner, p_func, p_userdata, p_high_priority, (GDExtensionConstStringPtr)&p_description);
|
||||
}
|
||||
|
||||
WorkerThreadPool::GroupID WorkerThreadPool::add_native_group_task(void (*p_func)(void *, uint32_t), void *p_userdata, int p_elements, int p_tasks, bool p_high_priority, const String &p_description) {
|
||||
return (GroupID)internal::gde_interface->worker_thread_pool_add_native_group_task(_owner, p_func, p_userdata, p_elements, p_tasks, p_high_priority, (GDExtensionConstStringPtr)&p_description);
|
||||
}
|
||||
|
||||
} // namespace godot
|
63
lib/godot-cpp/src/classes/wrapped.cpp
Normal file
63
lib/godot-cpp/src/classes/wrapped.cpp
Normal file
@@ -0,0 +1,63 @@
|
||||
/**************************************************************************/
|
||||
/* wrapped.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 <godot_cpp/classes/wrapped.hpp>
|
||||
|
||||
#include <godot_cpp/variant/builtin_types.hpp>
|
||||
|
||||
#include <godot_cpp/classes/object.hpp>
|
||||
|
||||
namespace godot {
|
||||
|
||||
const StringName *Wrapped::_get_extension_class_name() const {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void Wrapped::_postinitialize() {
|
||||
const StringName *extension_class = _get_extension_class_name();
|
||||
if (extension_class) {
|
||||
godot::internal::gde_interface->object_set_instance(_owner, reinterpret_cast<GDExtensionConstStringNamePtr>(extension_class), this);
|
||||
}
|
||||
godot::internal::gde_interface->object_set_instance_binding(_owner, godot::internal::token, this, _get_bindings_callbacks());
|
||||
}
|
||||
|
||||
Wrapped::Wrapped(const StringName p_godot_class) {
|
||||
_owner = godot::internal::gde_interface->classdb_construct_object(reinterpret_cast<GDExtensionConstStringNamePtr>(p_godot_class._native_ptr()));
|
||||
}
|
||||
|
||||
Wrapped::Wrapped(GodotObject *p_godot_object) {
|
||||
_owner = p_godot_object;
|
||||
}
|
||||
|
||||
void postinitialize_handler(Wrapped *p_wrapped) {
|
||||
p_wrapped->_postinitialize();
|
||||
}
|
||||
|
||||
} // namespace godot
|
358
lib/godot-cpp/src/core/class_db.cpp
Normal file
358
lib/godot-cpp/src/core/class_db.cpp
Normal file
@@ -0,0 +1,358 @@
|
||||
/**************************************************************************/
|
||||
/* class_db.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 <godot_cpp/core/class_db.hpp>
|
||||
|
||||
#include <godot_cpp/core/error_macros.hpp>
|
||||
#include <godot_cpp/godot.hpp>
|
||||
|
||||
#include <godot_cpp/core/memory.hpp>
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
namespace godot {
|
||||
|
||||
std::unordered_map<StringName, ClassDB::ClassInfo> ClassDB::classes;
|
||||
GDExtensionInitializationLevel ClassDB::current_level = GDEXTENSION_INITIALIZATION_CORE;
|
||||
|
||||
MethodDefinition D_METHOD(StringName p_name) {
|
||||
return MethodDefinition(p_name);
|
||||
}
|
||||
|
||||
MethodDefinition D_METHOD(StringName p_name, StringName p_arg1) {
|
||||
MethodDefinition method(p_name);
|
||||
method.args.push_front(p_arg1);
|
||||
return method;
|
||||
}
|
||||
|
||||
void ClassDB::add_property_group(const StringName &p_class, const String &p_name, const String &p_prefix) {
|
||||
ERR_FAIL_COND_MSG(classes.find(p_class) == classes.end(), String("Trying to add property '{0}{1}' to non-existing class '{2}'.").format(Array::make(p_prefix, p_name, p_class)));
|
||||
|
||||
internal::gde_interface->classdb_register_extension_class_property_group(internal::library, p_class._native_ptr(), p_name._native_ptr(), p_prefix._native_ptr());
|
||||
}
|
||||
|
||||
void ClassDB::add_property_subgroup(const StringName &p_class, const String &p_name, const String &p_prefix) {
|
||||
ERR_FAIL_COND_MSG(classes.find(p_class) == classes.end(), String("Trying to add property '{0}{1}' to non-existing class '{2}'.").format(Array::make(p_prefix, p_name, p_class)));
|
||||
|
||||
internal::gde_interface->classdb_register_extension_class_property_subgroup(internal::library, p_class._native_ptr(), p_name._native_ptr(), p_prefix._native_ptr());
|
||||
}
|
||||
|
||||
void ClassDB::add_property(const StringName &p_class, const PropertyInfo &p_pinfo, const StringName &p_setter, const StringName &p_getter, int p_index) {
|
||||
ERR_FAIL_COND_MSG(classes.find(p_class) == classes.end(), String("Trying to add property '{0}' to non-existing class '{1}'.").format(Array::make(p_pinfo.name, p_class)));
|
||||
|
||||
ClassInfo &info = classes[p_class];
|
||||
|
||||
ERR_FAIL_COND_MSG(info.property_names.find(p_pinfo.name) != info.property_names.end(), String("Property '{0}' already exists in class '{1}'.").format(Array::make(p_pinfo.name, p_class)));
|
||||
|
||||
MethodBind *setter = nullptr;
|
||||
if (p_setter != String("")) {
|
||||
setter = get_method(p_class, p_setter);
|
||||
|
||||
ERR_FAIL_COND_MSG(!setter, String("Setter method '{0}::{1}()' not found for property '{2}::{3}'.").format(Array::make(p_class, p_setter, p_class, p_pinfo.name)));
|
||||
|
||||
size_t exp_args = 1 + (p_index >= 0 ? 1 : 0);
|
||||
ERR_FAIL_COND_MSG((int)exp_args != setter->get_argument_count(), String("Setter method '{0}::{1}()' must take a single argument.").format(Array::make(p_class, p_setter)));
|
||||
}
|
||||
|
||||
ERR_FAIL_COND_MSG(p_getter == String(""), String("Getter method must be specified for '{0}::{1}'.").format(Array::make(p_class, p_pinfo.name)));
|
||||
|
||||
MethodBind *getter = get_method(p_class, p_getter);
|
||||
ERR_FAIL_COND_MSG(!getter, String("Getter method '{0}::{1}()' not found for property '{2}::{3}'.").format(Array::make(p_class, p_getter, p_class, p_pinfo.name)));
|
||||
{
|
||||
size_t exp_args = 0 + (p_index >= 0 ? 1 : 0);
|
||||
ERR_FAIL_COND_MSG((int)exp_args != getter->get_argument_count(), String("Getter method '{0}::{1}()' must not take any argument.").format(Array::make(p_class, p_getter)));
|
||||
}
|
||||
|
||||
// register property with plugin
|
||||
info.property_names.insert(p_pinfo.name);
|
||||
|
||||
// register with Godot
|
||||
GDExtensionPropertyInfo prop_info = {
|
||||
static_cast<GDExtensionVariantType>(p_pinfo.type), // GDExtensionVariantType type;
|
||||
p_pinfo.name._native_ptr(), // GDExtensionStringNamePtr name;
|
||||
p_pinfo.class_name._native_ptr(), // GDExtensionStringNamePtr class_name;
|
||||
p_pinfo.hint, // NONE //uint32_t hint;
|
||||
p_pinfo.hint_string._native_ptr(), // GDExtensionStringPtr hint_string;
|
||||
p_pinfo.usage, // DEFAULT //uint32_t usage;
|
||||
};
|
||||
|
||||
PropertySetGet setget;
|
||||
setget.setter = p_setter;
|
||||
setget.getter = p_getter;
|
||||
setget._setptr = setter;
|
||||
setget._getptr = getter;
|
||||
setget.index = p_index;
|
||||
setget.type = p_pinfo.type;
|
||||
|
||||
internal::gde_interface->classdb_register_extension_class_property(internal::library, info.name._native_ptr(), &prop_info, setget.setter._native_ptr(), setget.getter._native_ptr());
|
||||
}
|
||||
|
||||
MethodBind *ClassDB::get_method(const StringName &p_class, const StringName &p_method) {
|
||||
ERR_FAIL_COND_V_MSG(classes.find(p_class) == classes.end(), nullptr, String("Class '{0}' not found.").format(Array::make(p_class)));
|
||||
|
||||
ClassInfo *type = &classes[p_class];
|
||||
while (type) {
|
||||
std::unordered_map<StringName, MethodBind *>::iterator method = type->method_map.find(p_method);
|
||||
if (method != type->method_map.end()) {
|
||||
return method->second;
|
||||
}
|
||||
type = type->parent_ptr;
|
||||
continue;
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
MethodBind *ClassDB::bind_methodfi(uint32_t p_flags, MethodBind *p_bind, const MethodDefinition &method_name, const void **p_defs, int p_defcount) {
|
||||
StringName instance_type = p_bind->get_instance_class();
|
||||
|
||||
std::unordered_map<StringName, ClassInfo>::iterator type_it = classes.find(instance_type);
|
||||
if (type_it == classes.end()) {
|
||||
memdelete(p_bind);
|
||||
ERR_FAIL_V_MSG(nullptr, String("Class '{0}' doesn't exist.").format(Array::make(instance_type)));
|
||||
}
|
||||
|
||||
ClassInfo &type = type_it->second;
|
||||
|
||||
if (type.method_map.find(method_name.name) != type.method_map.end()) {
|
||||
memdelete(p_bind);
|
||||
ERR_FAIL_V_MSG(nullptr, String("Binding duplicate method: {0}::{1}().").format(Array::make(instance_type, method_name.name)));
|
||||
}
|
||||
|
||||
if (type.virtual_methods.find(method_name.name) != type.virtual_methods.end()) {
|
||||
memdelete(p_bind);
|
||||
ERR_FAIL_V_MSG(nullptr, String("Method '{0}::{1}()' already bound as virtual.").format(Array::make(instance_type, method_name.name)));
|
||||
}
|
||||
|
||||
p_bind->set_name(method_name.name);
|
||||
|
||||
if ((int)method_name.args.size() > p_bind->get_argument_count()) {
|
||||
memdelete(p_bind);
|
||||
ERR_FAIL_V_MSG(nullptr, String("Method '{0}::{1}()' definition has more arguments than the actual method.").format(Array::make(instance_type, method_name.name)));
|
||||
}
|
||||
|
||||
p_bind->set_hint_flags(p_flags);
|
||||
|
||||
std::vector<StringName> args;
|
||||
args.resize(method_name.args.size());
|
||||
size_t arg_index = 0;
|
||||
for (StringName arg : method_name.args) {
|
||||
args[arg_index++] = arg;
|
||||
}
|
||||
|
||||
p_bind->set_argument_names(args);
|
||||
|
||||
std::vector<Variant> defvals;
|
||||
|
||||
defvals.resize(p_defcount);
|
||||
for (int i = 0; i < p_defcount; i++) {
|
||||
defvals[i] = *static_cast<const Variant *>(p_defs[i]);
|
||||
}
|
||||
|
||||
p_bind->set_default_arguments(defvals);
|
||||
p_bind->set_hint_flags(p_flags);
|
||||
|
||||
// register our method bind within our plugin
|
||||
type.method_map[method_name.name] = p_bind;
|
||||
|
||||
// and register with godot
|
||||
bind_method_godot(type.name, p_bind);
|
||||
|
||||
return p_bind;
|
||||
}
|
||||
|
||||
void ClassDB::bind_method_godot(const StringName &p_class_name, MethodBind *p_method) {
|
||||
std::vector<GDExtensionVariantPtr> def_args;
|
||||
const std::vector<Variant> &def_args_val = p_method->get_default_arguments();
|
||||
def_args.resize(def_args_val.size());
|
||||
for (size_t i = 0; i < def_args_val.size(); i++) {
|
||||
def_args[i] = (GDExtensionVariantPtr)&def_args_val[i];
|
||||
}
|
||||
|
||||
std::vector<PropertyInfo> return_value_and_arguments_info = p_method->get_arguments_info_list();
|
||||
std::vector<GDExtensionClassMethodArgumentMetadata> return_value_and_arguments_metadata = p_method->get_arguments_metadata_list();
|
||||
|
||||
std::vector<GDExtensionPropertyInfo> return_value_and_arguments_gdextension_info;
|
||||
return_value_and_arguments_gdextension_info.reserve(return_value_and_arguments_info.size());
|
||||
for (std::vector<PropertyInfo>::iterator it = return_value_and_arguments_info.begin(); it != return_value_and_arguments_info.end(); it++) {
|
||||
return_value_and_arguments_gdextension_info.push_back(
|
||||
GDExtensionPropertyInfo{
|
||||
static_cast<GDExtensionVariantType>(it->type), // GDExtensionVariantType type;
|
||||
it->name._native_ptr(), // GDExtensionStringNamePtr name;
|
||||
it->class_name._native_ptr(), // GDExtensionStringNamePtr class_name;
|
||||
it->hint, // uint32_t hint;
|
||||
it->hint_string._native_ptr(), // GDExtensionStringPtr hint_string;
|
||||
it->usage, // uint32_t usage;
|
||||
});
|
||||
}
|
||||
|
||||
GDExtensionPropertyInfo *return_value_info = return_value_and_arguments_gdextension_info.data();
|
||||
GDExtensionClassMethodArgumentMetadata *return_value_metadata = return_value_and_arguments_metadata.data();
|
||||
GDExtensionPropertyInfo *arguments_info = return_value_and_arguments_gdextension_info.data() + 1;
|
||||
GDExtensionClassMethodArgumentMetadata *arguments_metadata = return_value_and_arguments_metadata.data() + 1;
|
||||
|
||||
StringName name = p_method->get_name();
|
||||
GDExtensionClassMethodInfo method_info = {
|
||||
name._native_ptr(), // GDExtensionStringNamePtr;
|
||||
p_method, // void *method_userdata;
|
||||
MethodBind::bind_call, // GDExtensionClassMethodCall call_func;
|
||||
MethodBind::bind_ptrcall, // GDExtensionClassMethodPtrCall ptrcall_func;
|
||||
p_method->get_hint_flags(), // uint32_t method_flags; /* GDExtensionClassMethodFlags */
|
||||
(GDExtensionBool)p_method->has_return(), // GDExtensionBool has_return_value;
|
||||
return_value_info, // GDExtensionPropertyInfo *
|
||||
*return_value_metadata, // GDExtensionClassMethodArgumentMetadata *
|
||||
(uint32_t)p_method->get_argument_count(), // uint32_t argument_count;
|
||||
arguments_info, // GDExtensionPropertyInfo *
|
||||
arguments_metadata, // GDExtensionClassMethodArgumentMetadata *
|
||||
(uint32_t)p_method->get_default_argument_count(), // uint32_t default_argument_count;
|
||||
def_args.data(), // GDExtensionVariantPtr *default_arguments;
|
||||
};
|
||||
internal::gde_interface->classdb_register_extension_class_method(internal::library, p_class_name._native_ptr(), &method_info);
|
||||
}
|
||||
|
||||
void ClassDB::add_signal(const StringName &p_class, const MethodInfo &p_signal) {
|
||||
std::unordered_map<StringName, ClassInfo>::iterator type_it = classes.find(p_class);
|
||||
|
||||
ERR_FAIL_COND_MSG(type_it == classes.end(), String("Class '{0}' doesn't exist.").format(Array::make(p_class)));
|
||||
|
||||
ClassInfo &cl = type_it->second;
|
||||
|
||||
// Check if this signal is already register
|
||||
ClassInfo *check = &cl;
|
||||
while (check) {
|
||||
ERR_FAIL_COND_MSG(check->signal_names.find(p_signal.name) != check->signal_names.end(), String("Class '{0}' already has signal '{1}'.").format(Array::make(p_class, p_signal.name)));
|
||||
check = check->parent_ptr;
|
||||
}
|
||||
|
||||
// register our signal in our plugin
|
||||
cl.signal_names.insert(p_signal.name);
|
||||
|
||||
// register our signal in godot
|
||||
std::vector<GDExtensionPropertyInfo> parameters;
|
||||
parameters.reserve(p_signal.arguments.size());
|
||||
|
||||
for (const PropertyInfo &par : p_signal.arguments) {
|
||||
parameters.push_back(GDExtensionPropertyInfo{
|
||||
static_cast<GDExtensionVariantType>(par.type), // GDExtensionVariantType type;
|
||||
par.name._native_ptr(), // GDExtensionStringNamePtr name;
|
||||
par.class_name._native_ptr(), // GDExtensionStringNamePtr class_name;
|
||||
par.hint, // NONE //uint32_t hint;
|
||||
par.hint_string._native_ptr(), // GDExtensionStringPtr hint_string;
|
||||
par.usage, // DEFAULT //uint32_t usage;
|
||||
});
|
||||
}
|
||||
|
||||
internal::gde_interface->classdb_register_extension_class_signal(internal::library, cl.name._native_ptr(), p_signal.name._native_ptr(), parameters.data(), parameters.size());
|
||||
}
|
||||
|
||||
void ClassDB::bind_integer_constant(const StringName &p_class_name, const StringName &p_enum_name, const StringName &p_constant_name, GDExtensionInt p_constant_value, bool p_is_bitfield) {
|
||||
std::unordered_map<StringName, ClassInfo>::iterator type_it = classes.find(p_class_name);
|
||||
|
||||
ERR_FAIL_COND_MSG(type_it == classes.end(), String("Class '{0}' doesn't exist.").format(Array::make(p_class_name)));
|
||||
|
||||
ClassInfo &type = type_it->second;
|
||||
|
||||
// check if it already exists
|
||||
ERR_FAIL_COND_MSG(type.constant_names.find(p_constant_name) != type.constant_names.end(), String("Constant '{0}::{1}' already registered.").format(Array::make(p_class_name, p_constant_name)));
|
||||
|
||||
// register it with our plugin (purely to check for duplicates)
|
||||
type.constant_names.insert(p_constant_name);
|
||||
|
||||
// Register it with Godot
|
||||
internal::gde_interface->classdb_register_extension_class_integer_constant(internal::library, p_class_name._native_ptr(), p_enum_name._native_ptr(), p_constant_name._native_ptr(), p_constant_value, p_is_bitfield);
|
||||
}
|
||||
GDExtensionClassCallVirtual ClassDB::get_virtual_func(void *p_userdata, GDExtensionConstStringNamePtr p_name) {
|
||||
// This is called by Godot the first time it calls a virtual function, and it caches the result, per object instance.
|
||||
// Because of this, it can happen from different threads at once.
|
||||
// It should be ok not using any mutex as long as we only READ data.
|
||||
const StringName *class_name = reinterpret_cast<const StringName *>(p_userdata);
|
||||
const StringName *name = reinterpret_cast<const StringName *>(p_name);
|
||||
|
||||
std::unordered_map<StringName, ClassInfo>::iterator type_it = classes.find(*class_name);
|
||||
ERR_FAIL_COND_V_MSG(type_it == classes.end(), nullptr, String("Class '{0}' doesn't exist.").format(Array::make(*class_name)));
|
||||
|
||||
const ClassInfo *type = &type_it->second;
|
||||
|
||||
// Find method in current class, or any of its parent classes (Godot classes not included)
|
||||
while (type != nullptr) {
|
||||
std::unordered_map<StringName, GDExtensionClassCallVirtual>::const_iterator method_it = type->virtual_methods.find(*name);
|
||||
|
||||
if (method_it != type->virtual_methods.end()) {
|
||||
return method_it->second;
|
||||
}
|
||||
|
||||
type = type->parent_ptr;
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void ClassDB::bind_virtual_method(const StringName &p_class, const StringName &p_method, GDExtensionClassCallVirtual p_call) {
|
||||
std::unordered_map<StringName, ClassInfo>::iterator type_it = classes.find(p_class);
|
||||
ERR_FAIL_COND_MSG(type_it == classes.end(), String("Class '{0}' doesn't exist.").format(Array::make(p_class)));
|
||||
|
||||
ClassInfo &type = type_it->second;
|
||||
|
||||
ERR_FAIL_COND_MSG(type.method_map.find(p_method) != type.method_map.end(), String("Method '{0}::{1}()' already registered as non-virtual.").format(Array::make(p_class, p_method)));
|
||||
ERR_FAIL_COND_MSG(type.virtual_methods.find(p_method) != type.virtual_methods.end(), String("Virtual '{0}::{1}()' method already registered.").format(Array::make(p_class, p_method)));
|
||||
|
||||
type.virtual_methods[p_method] = p_call;
|
||||
}
|
||||
|
||||
void ClassDB::initialize_class(const ClassInfo &p_cl) {
|
||||
}
|
||||
|
||||
void ClassDB::initialize(GDExtensionInitializationLevel p_level) {
|
||||
for (const std::pair<StringName, ClassInfo> pair : classes) {
|
||||
const ClassInfo &cl = pair.second;
|
||||
if (cl.level != p_level) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Nothing to do here for now...
|
||||
}
|
||||
}
|
||||
|
||||
void ClassDB::deinitialize(GDExtensionInitializationLevel p_level) {
|
||||
for (const std::pair<StringName, ClassInfo> pair : classes) {
|
||||
const ClassInfo &cl = pair.second;
|
||||
if (cl.level != p_level) {
|
||||
continue;
|
||||
}
|
||||
|
||||
internal::gde_interface->classdb_unregister_extension_class(internal::library, cl.name._native_ptr());
|
||||
|
||||
for (auto method : cl.method_map) {
|
||||
memdelete(method.second);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace godot
|
86
lib/godot-cpp/src/core/error_macros.cpp
Normal file
86
lib/godot-cpp/src/core/error_macros.cpp
Normal file
@@ -0,0 +1,86 @@
|
||||
/**************************************************************************/
|
||||
/* error_macros.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 <godot_cpp/core/error_macros.hpp>
|
||||
|
||||
#include <godot_cpp/godot.hpp>
|
||||
#include <godot_cpp/variant/string.hpp>
|
||||
|
||||
#include <cstdio>
|
||||
|
||||
namespace godot {
|
||||
|
||||
void _err_print_error(const char *p_function, const char *p_file, int p_line, const char *p_error, bool p_editor_notify, bool p_is_warning) {
|
||||
if (p_is_warning) {
|
||||
internal::gde_interface->print_warning(p_error, p_function, p_file, p_line, p_editor_notify);
|
||||
} else {
|
||||
internal::gde_interface->print_error(p_error, p_function, p_file, p_line, p_editor_notify);
|
||||
}
|
||||
}
|
||||
|
||||
void _err_print_error(const char *p_function, const char *p_file, int p_line, const String &p_error, bool p_editor_notify, bool p_is_warning) {
|
||||
_err_print_error(p_function, p_file, p_line, p_error.utf8().get_data(), p_editor_notify, p_is_warning);
|
||||
}
|
||||
|
||||
void _err_print_error(const char *p_function, const char *p_file, int p_line, const char *p_error, const char *p_message, bool p_editor_notify, bool p_is_warning) {
|
||||
if (p_is_warning) {
|
||||
internal::gde_interface->print_warning_with_message(p_error, p_message, p_function, p_file, p_line, p_editor_notify);
|
||||
} else {
|
||||
internal::gde_interface->print_error_with_message(p_error, p_message, p_function, p_file, p_line, p_editor_notify);
|
||||
}
|
||||
}
|
||||
|
||||
void _err_print_error(const char *p_function, const char *p_file, int p_line, const String &p_error, const char *p_message, bool p_editor_notify, bool p_is_warning) {
|
||||
_err_print_error(p_function, p_file, p_line, p_error.utf8().get_data(), p_message, p_editor_notify, p_is_warning);
|
||||
}
|
||||
|
||||
void _err_print_error(const char *p_function, const char *p_file, int p_line, const char *p_error, const String &p_message, bool p_editor_notify, bool p_is_warning) {
|
||||
_err_print_error(p_function, p_file, p_line, p_error, p_message.utf8().get_data(), p_editor_notify, p_is_warning);
|
||||
}
|
||||
|
||||
void _err_print_error(const char *p_function, const char *p_file, int p_line, const String &p_error, const String &p_message, bool p_editor_notify, bool p_is_warning) {
|
||||
_err_print_error(p_function, p_file, p_line, p_error.utf8().get_data(), p_message.utf8().get_data(), p_editor_notify, p_is_warning);
|
||||
}
|
||||
|
||||
void _err_print_index_error(const char *p_function, const char *p_file, int p_line, int64_t p_index, int64_t p_size, const char *p_index_str, const char *p_size_str, const char *p_message, bool p_editor_notify, bool p_fatal) {
|
||||
String fstr(p_fatal ? "FATAL: " : "");
|
||||
String err(fstr + "Index " + p_index_str + " = " + itos(p_index) + " is out of bounds (" + p_size_str + " = " + itos(p_size) + ").");
|
||||
_err_print_error(p_function, p_file, p_line, err.utf8().get_data(), p_message, p_editor_notify, false);
|
||||
}
|
||||
|
||||
void _err_print_index_error(const char *p_function, const char *p_file, int p_line, int64_t p_index, int64_t p_size, const char *p_index_str, const char *p_size_str, const String &p_message, bool p_editor_notify, bool p_fatal) {
|
||||
_err_print_index_error(p_function, p_file, p_line, p_index, p_size, p_index_str, p_size_str, p_message.utf8().get_data(), p_editor_notify, p_fatal);
|
||||
}
|
||||
|
||||
void _err_flush_stdout() {
|
||||
fflush(stdout);
|
||||
}
|
||||
|
||||
} // namespace godot
|
132
lib/godot-cpp/src/core/memory.cpp
Normal file
132
lib/godot-cpp/src/core/memory.cpp
Normal file
@@ -0,0 +1,132 @@
|
||||
/**************************************************************************/
|
||||
/* memory.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 <godot_cpp/core/memory.hpp>
|
||||
|
||||
#include <godot_cpp/godot.hpp>
|
||||
|
||||
namespace godot {
|
||||
|
||||
void *Memory::alloc_static(size_t p_bytes, bool p_pad_align) {
|
||||
#ifdef DEBUG_ENABLED
|
||||
bool prepad = false; // Alredy pre paded in the engine.
|
||||
#else
|
||||
bool prepad = p_pad_align;
|
||||
#endif
|
||||
|
||||
void *mem = internal::gde_interface->mem_alloc(p_bytes + (prepad ? PAD_ALIGN : 0));
|
||||
ERR_FAIL_COND_V(!mem, nullptr);
|
||||
|
||||
if (prepad) {
|
||||
uint8_t *s8 = (uint8_t *)mem;
|
||||
return s8 + PAD_ALIGN;
|
||||
} else {
|
||||
return mem;
|
||||
}
|
||||
}
|
||||
|
||||
void *Memory::realloc_static(void *p_memory, size_t p_bytes, bool p_pad_align) {
|
||||
if (p_memory == nullptr) {
|
||||
return alloc_static(p_bytes, p_pad_align);
|
||||
} else if (p_bytes == 0) {
|
||||
free_static(p_memory, p_pad_align);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
uint8_t *mem = (uint8_t *)p_memory;
|
||||
|
||||
#ifdef DEBUG_ENABLED
|
||||
bool prepad = false; // Alredy pre paded in the engine.
|
||||
#else
|
||||
bool prepad = p_pad_align;
|
||||
#endif
|
||||
|
||||
if (prepad) {
|
||||
mem -= PAD_ALIGN;
|
||||
mem = (uint8_t *)internal::gde_interface->mem_realloc(mem, p_bytes + PAD_ALIGN);
|
||||
ERR_FAIL_COND_V(!mem, nullptr);
|
||||
return mem + PAD_ALIGN;
|
||||
} else {
|
||||
return (uint8_t *)internal::gde_interface->mem_realloc(mem, p_bytes);
|
||||
}
|
||||
}
|
||||
|
||||
void Memory::free_static(void *p_ptr, bool p_pad_align) {
|
||||
uint8_t *mem = (uint8_t *)p_ptr;
|
||||
|
||||
#ifdef DEBUG_ENABLED
|
||||
bool prepad = false; // Alredy pre paded in the engine.
|
||||
#else
|
||||
bool prepad = p_pad_align;
|
||||
#endif
|
||||
|
||||
if (prepad) {
|
||||
mem -= PAD_ALIGN;
|
||||
}
|
||||
internal::gde_interface->mem_free(mem);
|
||||
}
|
||||
|
||||
_GlobalNil::_GlobalNil() {
|
||||
left = this;
|
||||
right = this;
|
||||
parent = this;
|
||||
}
|
||||
|
||||
_GlobalNil _GlobalNilClass::_nil;
|
||||
|
||||
} // namespace godot
|
||||
|
||||
void *operator new(size_t p_size, const char *p_description) {
|
||||
return godot::Memory::alloc_static(p_size);
|
||||
}
|
||||
|
||||
void *operator new(size_t p_size, void *(*p_allocfunc)(size_t p_size)) {
|
||||
return p_allocfunc(p_size);
|
||||
}
|
||||
|
||||
using namespace godot;
|
||||
|
||||
#ifdef _MSC_VER
|
||||
void operator delete(void *p_mem, const char *p_description) {
|
||||
ERR_PRINT("Call to placement delete should not happen.");
|
||||
CRASH_NOW();
|
||||
}
|
||||
|
||||
void operator delete(void *p_mem, void *(*p_allocfunc)(size_t p_size)) {
|
||||
ERR_PRINT("Call to placement delete should not happen.");
|
||||
CRASH_NOW();
|
||||
}
|
||||
|
||||
void operator delete(void *p_mem, void *p_pointer, size_t check, const char *p_description) {
|
||||
ERR_PRINT("Call to placement delete should not happen.");
|
||||
CRASH_NOW();
|
||||
}
|
||||
|
||||
#endif
|
113
lib/godot-cpp/src/core/method_bind.cpp
Normal file
113
lib/godot-cpp/src/core/method_bind.cpp
Normal file
@@ -0,0 +1,113 @@
|
||||
/**************************************************************************/
|
||||
/* method_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 <godot_cpp/core/method_bind.hpp>
|
||||
|
||||
namespace godot {
|
||||
|
||||
StringName MethodBind::get_name() const {
|
||||
return name;
|
||||
}
|
||||
|
||||
void MethodBind::set_name(const StringName &p_name) {
|
||||
name = p_name;
|
||||
}
|
||||
|
||||
void MethodBind::set_argument_count(int p_count) {
|
||||
argument_count = p_count;
|
||||
}
|
||||
|
||||
void MethodBind::set_const(bool p_const) {
|
||||
_is_const = p_const;
|
||||
}
|
||||
|
||||
void MethodBind::set_return(bool p_return) {
|
||||
_has_return = p_return;
|
||||
}
|
||||
|
||||
void MethodBind::set_static(bool p_static) {
|
||||
_static = p_static;
|
||||
}
|
||||
|
||||
void MethodBind::set_vararg(bool p_vararg) {
|
||||
_vararg = p_vararg;
|
||||
}
|
||||
|
||||
void MethodBind::set_argument_names(const std::vector<StringName> &p_names) {
|
||||
argument_names = p_names;
|
||||
}
|
||||
|
||||
std::vector<StringName> MethodBind::get_argument_names() const {
|
||||
return argument_names;
|
||||
}
|
||||
|
||||
void MethodBind::generate_argument_types(int p_count) {
|
||||
set_argument_count(p_count);
|
||||
|
||||
if (argument_types != nullptr) {
|
||||
memdelete_arr(argument_types);
|
||||
}
|
||||
|
||||
argument_types = memnew_arr(GDExtensionVariantType, p_count + 1);
|
||||
|
||||
// -1 means return type.
|
||||
for (int i = -1; i < p_count; i++) {
|
||||
argument_types[i + 1] = gen_argument_type(i);
|
||||
}
|
||||
}
|
||||
|
||||
PropertyInfo MethodBind::get_argument_info(int p_argument) const {
|
||||
PropertyInfo info = gen_argument_type_info(p_argument);
|
||||
if (p_argument >= 0) {
|
||||
info.name = p_argument < (int)argument_names.size() ? argument_names[p_argument] : "";
|
||||
}
|
||||
return info;
|
||||
}
|
||||
|
||||
void MethodBind::bind_call(void *p_method_userdata, GDExtensionClassInstancePtr p_instance, const GDExtensionConstVariantPtr *p_args, GDExtensionInt p_argument_count, GDExtensionVariantPtr r_return, GDExtensionCallError *r_error) {
|
||||
const MethodBind *bind = reinterpret_cast<const MethodBind *>(p_method_userdata);
|
||||
Variant ret = bind->call(p_instance, p_args, p_argument_count, *r_error);
|
||||
// This assumes the return value is an empty Variant, so it doesn't need to call the destructor first.
|
||||
// Since only GDExtensionMethodBind calls this from the Godot side, it should always be the case.
|
||||
internal::gde_interface->variant_new_copy(r_return, ret._native_ptr());
|
||||
}
|
||||
|
||||
void MethodBind::bind_ptrcall(void *p_method_userdata, GDExtensionClassInstancePtr p_instance, const GDExtensionConstTypePtr *p_args, GDExtensionTypePtr r_return) {
|
||||
const MethodBind *bind = reinterpret_cast<const MethodBind *>(p_method_userdata);
|
||||
bind->ptrcall(p_instance, p_args, r_return);
|
||||
}
|
||||
|
||||
MethodBind::~MethodBind() {
|
||||
if (argument_types) {
|
||||
memdelete_arr(argument_types);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace godot
|
54
lib/godot-cpp/src/core/object.cpp
Normal file
54
lib/godot-cpp/src/core/object.cpp
Normal file
@@ -0,0 +1,54 @@
|
||||
/**************************************************************************/
|
||||
/* object.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 <godot_cpp/core/object.hpp>
|
||||
|
||||
namespace godot {
|
||||
|
||||
MethodInfo::MethodInfo() :
|
||||
flags(GDEXTENSION_METHOD_FLAG_NORMAL) {}
|
||||
|
||||
MethodInfo::MethodInfo(StringName p_name) :
|
||||
name(p_name), flags(GDEXTENSION_METHOD_FLAG_NORMAL) {}
|
||||
|
||||
MethodInfo::MethodInfo(Variant::Type ret) :
|
||||
flags(GDEXTENSION_METHOD_FLAG_NORMAL) {
|
||||
return_val.type = ret;
|
||||
}
|
||||
|
||||
MethodInfo::MethodInfo(Variant::Type ret, StringName p_name) :
|
||||
name(p_name), flags(GDEXTENSION_METHOD_FLAG_NORMAL) {
|
||||
return_val.type = ret;
|
||||
}
|
||||
|
||||
MethodInfo::MethodInfo(const PropertyInfo &p_ret, StringName p_name) :
|
||||
name(p_name), return_val(p_ret), flags(GDEXTENSION_METHOD_FLAG_NORMAL) {}
|
||||
|
||||
} // namespace godot
|
117
lib/godot-cpp/src/godot.cpp
Normal file
117
lib/godot-cpp/src/godot.cpp
Normal file
@@ -0,0 +1,117 @@
|
||||
/**************************************************************************/
|
||||
/* godot.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 <godot_cpp/godot.hpp>
|
||||
|
||||
#include <godot_cpp/classes/wrapped.hpp>
|
||||
#include <godot_cpp/core/class_db.hpp>
|
||||
#include <godot_cpp/core/memory.hpp>
|
||||
#include <godot_cpp/variant/variant.hpp>
|
||||
|
||||
#include <godot_cpp/core/error_macros.hpp>
|
||||
|
||||
namespace godot {
|
||||
|
||||
namespace internal {
|
||||
|
||||
const GDExtensionInterface *gde_interface = nullptr;
|
||||
GDExtensionClassLibraryPtr library = nullptr;
|
||||
void *token = nullptr;
|
||||
|
||||
} // namespace internal
|
||||
|
||||
GDExtensionBinding::Callback GDExtensionBinding::init_callback = nullptr;
|
||||
GDExtensionBinding::Callback GDExtensionBinding::terminate_callback = nullptr;
|
||||
GDExtensionInitializationLevel GDExtensionBinding::minimum_initialization_level = GDEXTENSION_INITIALIZATION_CORE;
|
||||
|
||||
GDExtensionBool GDExtensionBinding::init(const GDExtensionInterface *p_interface, GDExtensionClassLibraryPtr p_library, GDExtensionInitialization *r_initialization) {
|
||||
internal::gde_interface = p_interface;
|
||||
internal::library = p_library;
|
||||
internal::token = p_library;
|
||||
|
||||
r_initialization->initialize = initialize_level;
|
||||
r_initialization->deinitialize = deinitialize_level;
|
||||
r_initialization->minimum_initialization_level = minimum_initialization_level;
|
||||
|
||||
ERR_FAIL_COND_V_MSG(init_callback == nullptr, false, "Initialization callback must be defined.");
|
||||
|
||||
Variant::init_bindings();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void GDExtensionBinding::initialize_level(void *userdata, GDExtensionInitializationLevel p_level) {
|
||||
ClassDB::current_level = p_level;
|
||||
|
||||
if (init_callback) {
|
||||
init_callback(static_cast<ModuleInitializationLevel>(p_level));
|
||||
}
|
||||
|
||||
ClassDB::initialize(p_level);
|
||||
}
|
||||
|
||||
void GDExtensionBinding::deinitialize_level(void *userdata, GDExtensionInitializationLevel p_level) {
|
||||
ClassDB::current_level = p_level;
|
||||
|
||||
if (terminate_callback) {
|
||||
terminate_callback(static_cast<ModuleInitializationLevel>(p_level));
|
||||
}
|
||||
|
||||
ClassDB::deinitialize(p_level);
|
||||
}
|
||||
|
||||
void GDExtensionBinding::InitObject::register_initializer(Callback p_init) const {
|
||||
GDExtensionBinding::init_callback = p_init;
|
||||
}
|
||||
|
||||
void GDExtensionBinding::InitObject::register_terminator(Callback p_terminate) const {
|
||||
GDExtensionBinding::terminate_callback = p_terminate;
|
||||
}
|
||||
|
||||
void GDExtensionBinding::InitObject::set_minimum_library_initialization_level(ModuleInitializationLevel p_level) const {
|
||||
GDExtensionBinding::minimum_initialization_level = static_cast<GDExtensionInitializationLevel>(p_level);
|
||||
}
|
||||
|
||||
GDExtensionBool GDExtensionBinding::InitObject::init() const {
|
||||
return GDExtensionBinding::init(gde_interface, library, initialization);
|
||||
}
|
||||
|
||||
} // namespace godot
|
||||
|
||||
extern "C" {
|
||||
|
||||
void GDE_EXPORT initialize_level(void *userdata, GDExtensionInitializationLevel p_level) {
|
||||
godot::GDExtensionBinding::initialize_level(userdata, p_level);
|
||||
}
|
||||
|
||||
void GDE_EXPORT deinitialize_level(void *userdata, GDExtensionInitializationLevel p_level) {
|
||||
godot::GDExtensionBinding::deinitialize_level(userdata, p_level);
|
||||
}
|
||||
}
|
421
lib/godot-cpp/src/variant/aabb.cpp
Normal file
421
lib/godot-cpp/src/variant/aabb.cpp
Normal file
@@ -0,0 +1,421 @@
|
||||
/**************************************************************************/
|
||||
/* aabb.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 <godot_cpp/variant/aabb.hpp>
|
||||
|
||||
#include <godot_cpp/variant/string.hpp>
|
||||
#include <godot_cpp/variant/variant.hpp>
|
||||
|
||||
namespace godot {
|
||||
|
||||
real_t AABB::get_volume() const {
|
||||
return size.x * size.y * size.z;
|
||||
}
|
||||
|
||||
bool AABB::operator==(const AABB &p_rval) const {
|
||||
return ((position == p_rval.position) && (size == p_rval.size));
|
||||
}
|
||||
|
||||
bool AABB::operator!=(const AABB &p_rval) const {
|
||||
return ((position != p_rval.position) || (size != p_rval.size));
|
||||
}
|
||||
|
||||
void AABB::merge_with(const AABB &p_aabb) {
|
||||
#ifdef MATH_CHECKS
|
||||
if (unlikely(size.x < 0 || size.y < 0 || size.z < 0 || p_aabb.size.x < 0 || p_aabb.size.y < 0 || p_aabb.size.z < 0)) {
|
||||
ERR_PRINT("AABB size is negative, this is not supported. Use AABB.abs() to get an AABB with a positive size.");
|
||||
}
|
||||
#endif
|
||||
Vector3 beg_1, beg_2;
|
||||
Vector3 end_1, end_2;
|
||||
Vector3 min, max;
|
||||
|
||||
beg_1 = position;
|
||||
beg_2 = p_aabb.position;
|
||||
end_1 = size + beg_1;
|
||||
end_2 = p_aabb.size + beg_2;
|
||||
|
||||
min.x = (beg_1.x < beg_2.x) ? beg_1.x : beg_2.x;
|
||||
min.y = (beg_1.y < beg_2.y) ? beg_1.y : beg_2.y;
|
||||
min.z = (beg_1.z < beg_2.z) ? beg_1.z : beg_2.z;
|
||||
|
||||
max.x = (end_1.x > end_2.x) ? end_1.x : end_2.x;
|
||||
max.y = (end_1.y > end_2.y) ? end_1.y : end_2.y;
|
||||
max.z = (end_1.z > end_2.z) ? end_1.z : end_2.z;
|
||||
|
||||
position = min;
|
||||
size = max - min;
|
||||
}
|
||||
|
||||
bool AABB::is_equal_approx(const AABB &p_aabb) const {
|
||||
return position.is_equal_approx(p_aabb.position) && size.is_equal_approx(p_aabb.size);
|
||||
}
|
||||
|
||||
AABB AABB::intersection(const AABB &p_aabb) const {
|
||||
#ifdef MATH_CHECKS
|
||||
if (unlikely(size.x < 0 || size.y < 0 || size.z < 0 || p_aabb.size.x < 0 || p_aabb.size.y < 0 || p_aabb.size.z < 0)) {
|
||||
ERR_PRINT("AABB size is negative, this is not supported. Use AABB.abs() to get an AABB with a positive size.");
|
||||
}
|
||||
#endif
|
||||
Vector3 src_min = position;
|
||||
Vector3 src_max = position + size;
|
||||
Vector3 dst_min = p_aabb.position;
|
||||
Vector3 dst_max = p_aabb.position + p_aabb.size;
|
||||
|
||||
Vector3 min, max;
|
||||
|
||||
if (src_min.x > dst_max.x || src_max.x < dst_min.x) {
|
||||
return AABB();
|
||||
} else {
|
||||
min.x = (src_min.x > dst_min.x) ? src_min.x : dst_min.x;
|
||||
max.x = (src_max.x < dst_max.x) ? src_max.x : dst_max.x;
|
||||
}
|
||||
|
||||
if (src_min.y > dst_max.y || src_max.y < dst_min.y) {
|
||||
return AABB();
|
||||
} else {
|
||||
min.y = (src_min.y > dst_min.y) ? src_min.y : dst_min.y;
|
||||
max.y = (src_max.y < dst_max.y) ? src_max.y : dst_max.y;
|
||||
}
|
||||
|
||||
if (src_min.z > dst_max.z || src_max.z < dst_min.z) {
|
||||
return AABB();
|
||||
} else {
|
||||
min.z = (src_min.z > dst_min.z) ? src_min.z : dst_min.z;
|
||||
max.z = (src_max.z < dst_max.z) ? src_max.z : dst_max.z;
|
||||
}
|
||||
|
||||
return AABB(min, max - min);
|
||||
}
|
||||
|
||||
bool AABB::intersects_ray(const Vector3 &p_from, const Vector3 &p_dir, Vector3 *r_clip, Vector3 *r_normal) const {
|
||||
#ifdef MATH_CHECKS
|
||||
if (unlikely(size.x < 0 || size.y < 0 || size.z < 0)) {
|
||||
ERR_PRINT("AABB size is negative, this is not supported. Use AABB.abs() to get an AABB with a positive size.");
|
||||
}
|
||||
#endif
|
||||
Vector3 c1, c2;
|
||||
Vector3 end = position + size;
|
||||
real_t near = -1e20;
|
||||
real_t far = 1e20;
|
||||
int axis = 0;
|
||||
|
||||
for (int i = 0; i < 3; i++) {
|
||||
if (p_dir[i] == 0) {
|
||||
if ((p_from[i] < position[i]) || (p_from[i] > end[i])) {
|
||||
return false;
|
||||
}
|
||||
} else { // ray not parallel to planes in this direction
|
||||
c1[i] = (position[i] - p_from[i]) / p_dir[i];
|
||||
c2[i] = (end[i] - p_from[i]) / p_dir[i];
|
||||
|
||||
if (c1[i] > c2[i]) {
|
||||
SWAP(c1, c2);
|
||||
}
|
||||
if (c1[i] > near) {
|
||||
near = c1[i];
|
||||
axis = i;
|
||||
}
|
||||
if (c2[i] < far) {
|
||||
far = c2[i];
|
||||
}
|
||||
if ((near > far) || (far < 0)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (r_clip) {
|
||||
*r_clip = c1;
|
||||
}
|
||||
if (r_normal) {
|
||||
*r_normal = Vector3();
|
||||
(*r_normal)[axis] = p_dir[axis] ? -1 : 1;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool AABB::intersects_segment(const Vector3 &p_from, const Vector3 &p_to, Vector3 *r_clip, Vector3 *r_normal) const {
|
||||
#ifdef MATH_CHECKS
|
||||
if (unlikely(size.x < 0 || size.y < 0 || size.z < 0)) {
|
||||
ERR_PRINT("AABB size is negative, this is not supported. Use AABB.abs() to get an AABB with a positive size.");
|
||||
}
|
||||
#endif
|
||||
real_t min = 0, max = 1;
|
||||
int axis = 0;
|
||||
real_t sign = 0;
|
||||
|
||||
for (int i = 0; i < 3; i++) {
|
||||
real_t seg_from = p_from[i];
|
||||
real_t seg_to = p_to[i];
|
||||
real_t box_begin = position[i];
|
||||
real_t box_end = box_begin + size[i];
|
||||
real_t cmin, cmax;
|
||||
real_t csign;
|
||||
|
||||
if (seg_from < seg_to) {
|
||||
if (seg_from > box_end || seg_to < box_begin) {
|
||||
return false;
|
||||
}
|
||||
real_t length = seg_to - seg_from;
|
||||
cmin = (seg_from < box_begin) ? ((box_begin - seg_from) / length) : 0;
|
||||
cmax = (seg_to > box_end) ? ((box_end - seg_from) / length) : 1;
|
||||
csign = -1.0;
|
||||
|
||||
} else {
|
||||
if (seg_to > box_end || seg_from < box_begin) {
|
||||
return false;
|
||||
}
|
||||
real_t length = seg_to - seg_from;
|
||||
cmin = (seg_from > box_end) ? (box_end - seg_from) / length : 0;
|
||||
cmax = (seg_to < box_begin) ? (box_begin - seg_from) / length : 1;
|
||||
csign = 1.0;
|
||||
}
|
||||
|
||||
if (cmin > min) {
|
||||
min = cmin;
|
||||
axis = i;
|
||||
sign = csign;
|
||||
}
|
||||
if (cmax < max) {
|
||||
max = cmax;
|
||||
}
|
||||
if (max < min) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
Vector3 rel = p_to - p_from;
|
||||
|
||||
if (r_normal) {
|
||||
Vector3 normal;
|
||||
normal[axis] = sign;
|
||||
*r_normal = normal;
|
||||
}
|
||||
|
||||
if (r_clip) {
|
||||
*r_clip = p_from + rel * min;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool AABB::intersects_plane(const Plane &p_plane) const {
|
||||
Vector3 points[8] = {
|
||||
Vector3(position.x, position.y, position.z),
|
||||
Vector3(position.x, position.y, position.z + size.z),
|
||||
Vector3(position.x, position.y + size.y, position.z),
|
||||
Vector3(position.x, position.y + size.y, position.z + size.z),
|
||||
Vector3(position.x + size.x, position.y, position.z),
|
||||
Vector3(position.x + size.x, position.y, position.z + size.z),
|
||||
Vector3(position.x + size.x, position.y + size.y, position.z),
|
||||
Vector3(position.x + size.x, position.y + size.y, position.z + size.z),
|
||||
};
|
||||
|
||||
bool over = false;
|
||||
bool under = false;
|
||||
|
||||
for (int i = 0; i < 8; i++) {
|
||||
if (p_plane.distance_to(points[i]) > 0) {
|
||||
over = true;
|
||||
} else {
|
||||
under = true;
|
||||
}
|
||||
}
|
||||
|
||||
return under && over;
|
||||
}
|
||||
|
||||
Vector3 AABB::get_longest_axis() const {
|
||||
Vector3 axis(1, 0, 0);
|
||||
real_t max_size = size.x;
|
||||
|
||||
if (size.y > max_size) {
|
||||
axis = Vector3(0, 1, 0);
|
||||
max_size = size.y;
|
||||
}
|
||||
|
||||
if (size.z > max_size) {
|
||||
axis = Vector3(0, 0, 1);
|
||||
}
|
||||
|
||||
return axis;
|
||||
}
|
||||
|
||||
int AABB::get_longest_axis_index() const {
|
||||
int axis = 0;
|
||||
real_t max_size = size.x;
|
||||
|
||||
if (size.y > max_size) {
|
||||
axis = 1;
|
||||
max_size = size.y;
|
||||
}
|
||||
|
||||
if (size.z > max_size) {
|
||||
axis = 2;
|
||||
}
|
||||
|
||||
return axis;
|
||||
}
|
||||
|
||||
Vector3 AABB::get_shortest_axis() const {
|
||||
Vector3 axis(1, 0, 0);
|
||||
real_t min_size = size.x;
|
||||
|
||||
if (size.y < min_size) {
|
||||
axis = Vector3(0, 1, 0);
|
||||
min_size = size.y;
|
||||
}
|
||||
|
||||
if (size.z < min_size) {
|
||||
axis = Vector3(0, 0, 1);
|
||||
}
|
||||
|
||||
return axis;
|
||||
}
|
||||
|
||||
int AABB::get_shortest_axis_index() const {
|
||||
int axis = 0;
|
||||
real_t min_size = size.x;
|
||||
|
||||
if (size.y < min_size) {
|
||||
axis = 1;
|
||||
min_size = size.y;
|
||||
}
|
||||
|
||||
if (size.z < min_size) {
|
||||
axis = 2;
|
||||
}
|
||||
|
||||
return axis;
|
||||
}
|
||||
|
||||
AABB AABB::merge(const AABB &p_with) const {
|
||||
AABB aabb = *this;
|
||||
aabb.merge_with(p_with);
|
||||
return aabb;
|
||||
}
|
||||
|
||||
AABB AABB::expand(const Vector3 &p_vector) const {
|
||||
AABB aabb = *this;
|
||||
aabb.expand_to(p_vector);
|
||||
return aabb;
|
||||
}
|
||||
|
||||
AABB AABB::grow(real_t p_by) const {
|
||||
AABB aabb = *this;
|
||||
aabb.grow_by(p_by);
|
||||
return aabb;
|
||||
}
|
||||
|
||||
void AABB::get_edge(int p_edge, Vector3 &r_from, Vector3 &r_to) const {
|
||||
ERR_FAIL_INDEX(p_edge, 12);
|
||||
switch (p_edge) {
|
||||
case 0: {
|
||||
r_from = Vector3(position.x + size.x, position.y, position.z);
|
||||
r_to = Vector3(position.x, position.y, position.z);
|
||||
} break;
|
||||
case 1: {
|
||||
r_from = Vector3(position.x + size.x, position.y, position.z + size.z);
|
||||
r_to = Vector3(position.x + size.x, position.y, position.z);
|
||||
} break;
|
||||
case 2: {
|
||||
r_from = Vector3(position.x, position.y, position.z + size.z);
|
||||
r_to = Vector3(position.x + size.x, position.y, position.z + size.z);
|
||||
|
||||
} break;
|
||||
case 3: {
|
||||
r_from = Vector3(position.x, position.y, position.z);
|
||||
r_to = Vector3(position.x, position.y, position.z + size.z);
|
||||
|
||||
} break;
|
||||
case 4: {
|
||||
r_from = Vector3(position.x, position.y + size.y, position.z);
|
||||
r_to = Vector3(position.x + size.x, position.y + size.y, position.z);
|
||||
} break;
|
||||
case 5: {
|
||||
r_from = Vector3(position.x + size.x, position.y + size.y, position.z);
|
||||
r_to = Vector3(position.x + size.x, position.y + size.y, position.z + size.z);
|
||||
} break;
|
||||
case 6: {
|
||||
r_from = Vector3(position.x + size.x, position.y + size.y, position.z + size.z);
|
||||
r_to = Vector3(position.x, position.y + size.y, position.z + size.z);
|
||||
|
||||
} break;
|
||||
case 7: {
|
||||
r_from = Vector3(position.x, position.y + size.y, position.z + size.z);
|
||||
r_to = Vector3(position.x, position.y + size.y, position.z);
|
||||
|
||||
} break;
|
||||
case 8: {
|
||||
r_from = Vector3(position.x, position.y, position.z + size.z);
|
||||
r_to = Vector3(position.x, position.y + size.y, position.z + size.z);
|
||||
|
||||
} break;
|
||||
case 9: {
|
||||
r_from = Vector3(position.x, position.y, position.z);
|
||||
r_to = Vector3(position.x, position.y + size.y, position.z);
|
||||
|
||||
} break;
|
||||
case 10: {
|
||||
r_from = Vector3(position.x + size.x, position.y, position.z);
|
||||
r_to = Vector3(position.x + size.x, position.y + size.y, position.z);
|
||||
|
||||
} break;
|
||||
case 11: {
|
||||
r_from = Vector3(position.x + size.x, position.y, position.z + size.z);
|
||||
r_to = Vector3(position.x + size.x, position.y + size.y, position.z + size.z);
|
||||
|
||||
} break;
|
||||
}
|
||||
}
|
||||
|
||||
Variant AABB::intersects_segment_bind(const Vector3 &p_from, const Vector3 &p_to) const {
|
||||
Vector3 inters;
|
||||
if (intersects_segment(p_from, p_to, &inters)) {
|
||||
return inters;
|
||||
}
|
||||
return Variant();
|
||||
}
|
||||
|
||||
Variant AABB::intersects_ray_bind(const Vector3 &p_from, const Vector3 &p_dir) const {
|
||||
Vector3 inters;
|
||||
if (intersects_ray(p_from, p_dir, &inters)) {
|
||||
return inters;
|
||||
}
|
||||
return Variant();
|
||||
}
|
||||
|
||||
AABB::operator String() const {
|
||||
return "[P: " + position.operator String() + ", S: " + size + "]";
|
||||
}
|
||||
|
||||
} // namespace godot
|
1054
lib/godot-cpp/src/variant/basis.cpp
Normal file
1054
lib/godot-cpp/src/variant/basis.cpp
Normal file
File diff suppressed because it is too large
Load Diff
472
lib/godot-cpp/src/variant/char_string.cpp
Normal file
472
lib/godot-cpp/src/variant/char_string.cpp
Normal file
@@ -0,0 +1,472 @@
|
||||
/**************************************************************************/
|
||||
/* char_string.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 <godot_cpp/variant/char_string.hpp>
|
||||
|
||||
#include <godot_cpp/core/memory.hpp>
|
||||
#include <godot_cpp/variant/node_path.hpp>
|
||||
#include <godot_cpp/variant/string.hpp>
|
||||
#include <godot_cpp/variant/string_name.hpp>
|
||||
|
||||
#include <godot_cpp/godot.hpp>
|
||||
|
||||
#include <cmath>
|
||||
|
||||
namespace godot {
|
||||
|
||||
int CharString::length() const {
|
||||
return _length;
|
||||
}
|
||||
|
||||
const char *CharString::get_data() const {
|
||||
return _data;
|
||||
}
|
||||
|
||||
CharString::CharString(CharString &&p_str) {
|
||||
SWAP(_length, p_str._length);
|
||||
SWAP(_data, p_str._data);
|
||||
}
|
||||
|
||||
void CharString::operator=(CharString &&p_str) {
|
||||
SWAP(_length, p_str._length);
|
||||
SWAP(_data, p_str._data);
|
||||
}
|
||||
|
||||
CharString::CharString(const char *str, int length) :
|
||||
_data(str), _length(length) {}
|
||||
|
||||
CharString::~CharString() {
|
||||
if (_data != nullptr) {
|
||||
memdelete_arr(_data);
|
||||
}
|
||||
}
|
||||
|
||||
int Char16String::length() const {
|
||||
return _length;
|
||||
}
|
||||
|
||||
const char16_t *Char16String::get_data() const {
|
||||
return _data;
|
||||
}
|
||||
|
||||
Char16String::Char16String(Char16String &&p_str) {
|
||||
SWAP(_length, p_str._length);
|
||||
SWAP(_data, p_str._data);
|
||||
}
|
||||
|
||||
void Char16String::operator=(Char16String &&p_str) {
|
||||
SWAP(_length, p_str._length);
|
||||
SWAP(_data, p_str._data);
|
||||
}
|
||||
|
||||
Char16String::Char16String(const char16_t *str, int length) :
|
||||
_data(str), _length(length) {}
|
||||
|
||||
Char16String::~Char16String() {
|
||||
if (_data != nullptr) {
|
||||
memdelete_arr(_data);
|
||||
}
|
||||
}
|
||||
|
||||
int Char32String::length() const {
|
||||
return _length;
|
||||
}
|
||||
|
||||
const char32_t *Char32String::get_data() const {
|
||||
return _data;
|
||||
}
|
||||
|
||||
Char32String::Char32String(Char32String &&p_str) {
|
||||
SWAP(_length, p_str._length);
|
||||
SWAP(_data, p_str._data);
|
||||
}
|
||||
|
||||
void Char32String::operator=(Char32String &&p_str) {
|
||||
SWAP(_length, p_str._length);
|
||||
SWAP(_data, p_str._data);
|
||||
}
|
||||
|
||||
Char32String::Char32String(const char32_t *str, int length) :
|
||||
_data(str), _length(length) {}
|
||||
|
||||
Char32String::~Char32String() {
|
||||
if (_data != nullptr) {
|
||||
memdelete_arr(_data);
|
||||
}
|
||||
}
|
||||
|
||||
int CharWideString::length() const {
|
||||
return _length;
|
||||
}
|
||||
|
||||
const wchar_t *CharWideString::get_data() const {
|
||||
return _data;
|
||||
}
|
||||
|
||||
CharWideString::CharWideString(CharWideString &&p_str) {
|
||||
SWAP(_length, p_str._length);
|
||||
SWAP(_data, p_str._data);
|
||||
}
|
||||
|
||||
void CharWideString::operator=(CharWideString &&p_str) {
|
||||
SWAP(_length, p_str._length);
|
||||
SWAP(_data, p_str._data);
|
||||
}
|
||||
|
||||
CharWideString::CharWideString(const wchar_t *str, int length) :
|
||||
_data(str), _length(length) {}
|
||||
|
||||
CharWideString::~CharWideString() {
|
||||
if (_data != nullptr) {
|
||||
memdelete_arr(_data);
|
||||
}
|
||||
}
|
||||
|
||||
// Custom String functions that are not part of bound API.
|
||||
// It's easier to have them written in C++ directly than in a Python script that generates them.
|
||||
|
||||
String::String(const char *from) {
|
||||
internal::gde_interface->string_new_with_latin1_chars(_native_ptr(), from);
|
||||
}
|
||||
|
||||
String::String(const wchar_t *from) {
|
||||
internal::gde_interface->string_new_with_wide_chars(_native_ptr(), from);
|
||||
}
|
||||
|
||||
String::String(const char16_t *from) {
|
||||
internal::gde_interface->string_new_with_utf16_chars(_native_ptr(), from);
|
||||
}
|
||||
|
||||
String::String(const char32_t *from) {
|
||||
internal::gde_interface->string_new_with_utf32_chars(_native_ptr(), from);
|
||||
}
|
||||
|
||||
String String::utf8(const char *from, int len) {
|
||||
String ret;
|
||||
ret.parse_utf8(from, len);
|
||||
return ret;
|
||||
}
|
||||
|
||||
void String::parse_utf8(const char *from, int len) {
|
||||
internal::gde_interface->string_new_with_utf8_chars_and_len(_native_ptr(), from, len);
|
||||
}
|
||||
|
||||
String String::utf16(const char16_t *from, int len) {
|
||||
String ret;
|
||||
ret.parse_utf16(from, len);
|
||||
return ret;
|
||||
}
|
||||
|
||||
void String::parse_utf16(const char16_t *from, int len) {
|
||||
internal::gde_interface->string_new_with_utf16_chars_and_len(_native_ptr(), from, len);
|
||||
}
|
||||
|
||||
String String::num_real(double p_num, bool p_trailing) {
|
||||
if (p_num == (double)(int64_t)p_num) {
|
||||
if (p_trailing) {
|
||||
return num_int64((int64_t)p_num) + ".0";
|
||||
} else {
|
||||
return num_int64((int64_t)p_num);
|
||||
}
|
||||
}
|
||||
#ifdef REAL_T_IS_DOUBLE
|
||||
int decimals = 14;
|
||||
#else
|
||||
int decimals = 6;
|
||||
#endif
|
||||
// We want to align the digits to the above sane default, so we only
|
||||
// need to subtract log10 for numbers with a positive power of ten.
|
||||
if (p_num > 10) {
|
||||
decimals -= (int)floor(log10(p_num));
|
||||
}
|
||||
return num(p_num, decimals);
|
||||
}
|
||||
|
||||
String itos(int64_t p_val) {
|
||||
return String::num_int64(p_val);
|
||||
}
|
||||
|
||||
String uitos(uint64_t p_val) {
|
||||
return String::num_uint64(p_val);
|
||||
}
|
||||
|
||||
String rtos(double p_val) {
|
||||
return String::num(p_val);
|
||||
}
|
||||
|
||||
String rtoss(double p_val) {
|
||||
return String::num_scientific(p_val);
|
||||
}
|
||||
|
||||
CharString String::utf8() const {
|
||||
int length = internal::gde_interface->string_to_utf8_chars(_native_ptr(), nullptr, 0);
|
||||
int size = length + 1;
|
||||
char *cstr = memnew_arr(char, size);
|
||||
internal::gde_interface->string_to_utf8_chars(_native_ptr(), cstr, length);
|
||||
|
||||
cstr[length] = '\0';
|
||||
|
||||
return CharString(cstr, length);
|
||||
}
|
||||
|
||||
CharString String::ascii() const {
|
||||
int length = internal::gde_interface->string_to_latin1_chars(_native_ptr(), nullptr, 0);
|
||||
int size = length + 1;
|
||||
char *cstr = memnew_arr(char, size);
|
||||
internal::gde_interface->string_to_latin1_chars(_native_ptr(), cstr, length);
|
||||
|
||||
cstr[length] = '\0';
|
||||
|
||||
return CharString(cstr, length);
|
||||
}
|
||||
|
||||
Char16String String::utf16() const {
|
||||
int length = internal::gde_interface->string_to_utf16_chars(_native_ptr(), nullptr, 0);
|
||||
int size = length + 1;
|
||||
char16_t *cstr = memnew_arr(char16_t, size);
|
||||
internal::gde_interface->string_to_utf16_chars(_native_ptr(), cstr, length);
|
||||
|
||||
cstr[length] = '\0';
|
||||
|
||||
return Char16String(cstr, length);
|
||||
}
|
||||
|
||||
Char32String String::utf32() const {
|
||||
int length = internal::gde_interface->string_to_utf32_chars(_native_ptr(), nullptr, 0);
|
||||
int size = length + 1;
|
||||
char32_t *cstr = memnew_arr(char32_t, size);
|
||||
internal::gde_interface->string_to_utf32_chars(_native_ptr(), cstr, length);
|
||||
|
||||
cstr[length] = '\0';
|
||||
|
||||
return Char32String(cstr, length);
|
||||
}
|
||||
|
||||
CharWideString String::wide_string() const {
|
||||
int length = internal::gde_interface->string_to_wide_chars(_native_ptr(), nullptr, 0);
|
||||
int size = length + 1;
|
||||
wchar_t *cstr = memnew_arr(wchar_t, size);
|
||||
internal::gde_interface->string_to_wide_chars(_native_ptr(), cstr, length);
|
||||
|
||||
cstr[length] = '\0';
|
||||
|
||||
return CharWideString(cstr, length);
|
||||
}
|
||||
|
||||
String &String::operator=(const char *p_str) {
|
||||
*this = String(p_str);
|
||||
return *this;
|
||||
}
|
||||
|
||||
String &String::operator=(const wchar_t *p_str) {
|
||||
*this = String(p_str);
|
||||
return *this;
|
||||
}
|
||||
|
||||
String &String::operator=(const char16_t *p_str) {
|
||||
*this = String(p_str);
|
||||
return *this;
|
||||
}
|
||||
|
||||
String &String::operator=(const char32_t *p_str) {
|
||||
*this = String(p_str);
|
||||
return *this;
|
||||
}
|
||||
|
||||
bool String::operator==(const char *p_str) const {
|
||||
return *this == String(p_str);
|
||||
}
|
||||
|
||||
bool String::operator==(const wchar_t *p_str) const {
|
||||
return *this == String(p_str);
|
||||
}
|
||||
|
||||
bool String::operator==(const char16_t *p_str) const {
|
||||
return *this == String(p_str);
|
||||
}
|
||||
|
||||
bool String::operator==(const char32_t *p_str) const {
|
||||
return *this == String(p_str);
|
||||
}
|
||||
|
||||
bool String::operator!=(const char *p_str) const {
|
||||
return *this != String(p_str);
|
||||
}
|
||||
|
||||
bool String::operator!=(const wchar_t *p_str) const {
|
||||
return *this != String(p_str);
|
||||
}
|
||||
|
||||
bool String::operator!=(const char16_t *p_str) const {
|
||||
return *this != String(p_str);
|
||||
}
|
||||
|
||||
bool String::operator!=(const char32_t *p_str) const {
|
||||
return *this != String(p_str);
|
||||
}
|
||||
|
||||
String String::operator+(const char *p_str) {
|
||||
return *this + String(p_str);
|
||||
}
|
||||
|
||||
String String::operator+(const wchar_t *p_str) {
|
||||
return *this + String(p_str);
|
||||
}
|
||||
|
||||
String String::operator+(const char16_t *p_str) {
|
||||
return *this + String(p_str);
|
||||
}
|
||||
|
||||
String String::operator+(const char32_t *p_str) {
|
||||
return *this + String(p_str);
|
||||
}
|
||||
|
||||
String String::operator+(const char32_t p_char) {
|
||||
return *this + String::chr(p_char);
|
||||
}
|
||||
|
||||
String &String::operator+=(const String &p_str) {
|
||||
internal::gde_interface->string_operator_plus_eq_string((GDExtensionStringPtr)this, (GDExtensionConstStringPtr)&p_str);
|
||||
return *this;
|
||||
}
|
||||
|
||||
String &String::operator+=(char32_t p_char) {
|
||||
internal::gde_interface->string_operator_plus_eq_char((GDExtensionStringPtr)this, p_char);
|
||||
return *this;
|
||||
}
|
||||
|
||||
String &String::operator+=(const char *p_str) {
|
||||
internal::gde_interface->string_operator_plus_eq_cstr((GDExtensionStringPtr)this, p_str);
|
||||
return *this;
|
||||
}
|
||||
|
||||
String &String::operator+=(const wchar_t *p_str) {
|
||||
internal::gde_interface->string_operator_plus_eq_wcstr((GDExtensionStringPtr)this, p_str);
|
||||
return *this;
|
||||
}
|
||||
|
||||
String &String::operator+=(const char32_t *p_str) {
|
||||
internal::gde_interface->string_operator_plus_eq_c32str((GDExtensionStringPtr)this, p_str);
|
||||
return *this;
|
||||
}
|
||||
|
||||
const char32_t &String::operator[](int p_index) const {
|
||||
return *internal::gde_interface->string_operator_index_const((GDExtensionStringPtr)this, p_index);
|
||||
}
|
||||
|
||||
char32_t &String::operator[](int p_index) {
|
||||
return *internal::gde_interface->string_operator_index((GDExtensionStringPtr)this, p_index);
|
||||
}
|
||||
|
||||
const char32_t *String::ptr() const {
|
||||
return internal::gde_interface->string_operator_index_const((GDExtensionStringPtr)this, 0);
|
||||
}
|
||||
|
||||
char32_t *String::ptrw() {
|
||||
return internal::gde_interface->string_operator_index((GDExtensionStringPtr)this, 0);
|
||||
}
|
||||
|
||||
bool operator==(const char *p_chr, const String &p_str) {
|
||||
return p_str == String(p_chr);
|
||||
}
|
||||
|
||||
bool operator==(const wchar_t *p_chr, const String &p_str) {
|
||||
return p_str == String(p_chr);
|
||||
}
|
||||
|
||||
bool operator==(const char16_t *p_chr, const String &p_str) {
|
||||
return p_str == String(p_chr);
|
||||
}
|
||||
|
||||
bool operator==(const char32_t *p_chr, const String &p_str) {
|
||||
return p_str == String(p_chr);
|
||||
}
|
||||
|
||||
bool operator!=(const char *p_chr, const String &p_str) {
|
||||
return !(p_str == p_chr);
|
||||
}
|
||||
|
||||
bool operator!=(const wchar_t *p_chr, const String &p_str) {
|
||||
return !(p_str == p_chr);
|
||||
}
|
||||
|
||||
bool operator!=(const char16_t *p_chr, const String &p_str) {
|
||||
return !(p_str == p_chr);
|
||||
}
|
||||
|
||||
bool operator!=(const char32_t *p_chr, const String &p_str) {
|
||||
return !(p_str == p_chr);
|
||||
}
|
||||
|
||||
String operator+(const char *p_chr, const String &p_str) {
|
||||
return String(p_chr) + p_str;
|
||||
}
|
||||
|
||||
String operator+(const wchar_t *p_chr, const String &p_str) {
|
||||
return String(p_chr) + p_str;
|
||||
}
|
||||
|
||||
String operator+(const char16_t *p_chr, const String &p_str) {
|
||||
return String(p_chr) + p_str;
|
||||
}
|
||||
|
||||
String operator+(const char32_t *p_chr, const String &p_str) {
|
||||
return String(p_chr) + p_str;
|
||||
}
|
||||
|
||||
String operator+(char32_t p_char, const String &p_str) {
|
||||
return String::chr(p_char) + p_str;
|
||||
}
|
||||
|
||||
StringName::StringName(const char *from) :
|
||||
StringName(String(from)) {}
|
||||
|
||||
StringName::StringName(const wchar_t *from) :
|
||||
StringName(String(from)) {}
|
||||
|
||||
StringName::StringName(const char16_t *from) :
|
||||
StringName(String(from)) {}
|
||||
|
||||
StringName::StringName(const char32_t *from) :
|
||||
StringName(String(from)) {}
|
||||
|
||||
NodePath::NodePath(const char *from) :
|
||||
NodePath(String(from)) {}
|
||||
|
||||
NodePath::NodePath(const wchar_t *from) :
|
||||
NodePath(String(from)) {}
|
||||
|
||||
NodePath::NodePath(const char16_t *from) :
|
||||
NodePath(String(from)) {}
|
||||
|
||||
NodePath::NodePath(const char32_t *from) :
|
||||
NodePath(String(from)) {}
|
||||
|
||||
} // namespace godot
|
572
lib/godot-cpp/src/variant/color.cpp
Normal file
572
lib/godot-cpp/src/variant/color.cpp
Normal file
@@ -0,0 +1,572 @@
|
||||
/**************************************************************************/
|
||||
/* color.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 <godot_cpp/core/error_macros.hpp>
|
||||
#include <godot_cpp/variant/color.hpp>
|
||||
#include <godot_cpp/variant/color_names.inc.hpp>
|
||||
#include <godot_cpp/variant/string.hpp>
|
||||
|
||||
namespace godot {
|
||||
|
||||
uint32_t Color::to_argb32() const {
|
||||
uint32_t c = (uint8_t)Math::round(a * 255.0f);
|
||||
c <<= 8;
|
||||
c |= (uint8_t)Math::round(r * 255.0f);
|
||||
c <<= 8;
|
||||
c |= (uint8_t)Math::round(g * 255.0f);
|
||||
c <<= 8;
|
||||
c |= (uint8_t)Math::round(b * 255.0f);
|
||||
|
||||
return c;
|
||||
}
|
||||
|
||||
uint32_t Color::to_abgr32() const {
|
||||
uint32_t c = (uint8_t)Math::round(a * 255.0f);
|
||||
c <<= 8;
|
||||
c |= (uint8_t)Math::round(b * 255.0f);
|
||||
c <<= 8;
|
||||
c |= (uint8_t)Math::round(g * 255.0f);
|
||||
c <<= 8;
|
||||
c |= (uint8_t)Math::round(r * 255.0f);
|
||||
|
||||
return c;
|
||||
}
|
||||
|
||||
uint32_t Color::to_rgba32() const {
|
||||
uint32_t c = (uint8_t)Math::round(r * 255.0f);
|
||||
c <<= 8;
|
||||
c |= (uint8_t)Math::round(g * 255.0f);
|
||||
c <<= 8;
|
||||
c |= (uint8_t)Math::round(b * 255.0f);
|
||||
c <<= 8;
|
||||
c |= (uint8_t)Math::round(a * 255.0f);
|
||||
|
||||
return c;
|
||||
}
|
||||
|
||||
uint64_t Color::to_abgr64() const {
|
||||
uint64_t c = (uint16_t)Math::round(a * 65535.0f);
|
||||
c <<= 16;
|
||||
c |= (uint16_t)Math::round(b * 65535.0f);
|
||||
c <<= 16;
|
||||
c |= (uint16_t)Math::round(g * 65535.0f);
|
||||
c <<= 16;
|
||||
c |= (uint16_t)Math::round(r * 65535.0f);
|
||||
|
||||
return c;
|
||||
}
|
||||
|
||||
uint64_t Color::to_argb64() const {
|
||||
uint64_t c = (uint16_t)Math::round(a * 65535.0f);
|
||||
c <<= 16;
|
||||
c |= (uint16_t)Math::round(r * 65535.0f);
|
||||
c <<= 16;
|
||||
c |= (uint16_t)Math::round(g * 65535.0f);
|
||||
c <<= 16;
|
||||
c |= (uint16_t)Math::round(b * 65535.0f);
|
||||
|
||||
return c;
|
||||
}
|
||||
|
||||
uint64_t Color::to_rgba64() const {
|
||||
uint64_t c = (uint16_t)Math::round(r * 65535.0f);
|
||||
c <<= 16;
|
||||
c |= (uint16_t)Math::round(g * 65535.0f);
|
||||
c <<= 16;
|
||||
c |= (uint16_t)Math::round(b * 65535.0f);
|
||||
c <<= 16;
|
||||
c |= (uint16_t)Math::round(a * 65535.0f);
|
||||
|
||||
return c;
|
||||
}
|
||||
|
||||
String _to_hex(float p_val) {
|
||||
int v = Math::round(p_val * 255.0f);
|
||||
v = CLAMP(v, 0, 255);
|
||||
String ret;
|
||||
|
||||
for (int i = 0; i < 2; i++) {
|
||||
char32_t c[2] = { 0, 0 };
|
||||
int lv = v & 0xF;
|
||||
if (lv < 10) {
|
||||
c[0] = '0' + lv;
|
||||
} else {
|
||||
c[0] = 'a' + lv - 10;
|
||||
}
|
||||
|
||||
v >>= 4;
|
||||
String cs = (const char32_t *)c;
|
||||
ret = cs + ret;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
String Color::to_html(bool p_alpha) const {
|
||||
String txt;
|
||||
txt = txt + _to_hex(r);
|
||||
txt = txt + _to_hex(g);
|
||||
txt = txt + _to_hex(b);
|
||||
if (p_alpha) {
|
||||
txt = txt + _to_hex(a);
|
||||
}
|
||||
return txt;
|
||||
}
|
||||
|
||||
float Color::get_h() const {
|
||||
float min = Math::min(r, g);
|
||||
min = Math::min(min, b);
|
||||
float max = Math::max(r, g);
|
||||
max = Math::max(max, b);
|
||||
|
||||
float delta = max - min;
|
||||
|
||||
if (delta == 0.0f) {
|
||||
return 0.0f;
|
||||
}
|
||||
|
||||
float h;
|
||||
if (r == max) {
|
||||
h = (g - b) / delta; // between yellow & magenta
|
||||
} else if (g == max) {
|
||||
h = 2 + (b - r) / delta; // between cyan & yellow
|
||||
} else {
|
||||
h = 4 + (r - g) / delta; // between magenta & cyan
|
||||
}
|
||||
|
||||
h /= 6.0f;
|
||||
if (h < 0.0f) {
|
||||
h += 1.0f;
|
||||
}
|
||||
|
||||
return h;
|
||||
}
|
||||
|
||||
float Color::get_s() const {
|
||||
float min = Math::min(r, g);
|
||||
min = Math::min(min, b);
|
||||
float max = Math::max(r, g);
|
||||
max = Math::max(max, b);
|
||||
|
||||
float delta = max - min;
|
||||
|
||||
return (max != 0.0f) ? (delta / max) : 0.0f;
|
||||
}
|
||||
|
||||
float Color::get_v() const {
|
||||
float max = Math::max(r, g);
|
||||
max = Math::max(max, b);
|
||||
return max;
|
||||
}
|
||||
|
||||
void Color::set_hsv(float p_h, float p_s, float p_v, float p_alpha) {
|
||||
int i;
|
||||
float f, p, q, t;
|
||||
a = p_alpha;
|
||||
|
||||
if (p_s == 0.0f) {
|
||||
// Achromatic (grey)
|
||||
r = g = b = p_v;
|
||||
return;
|
||||
}
|
||||
|
||||
p_h *= 6.0f;
|
||||
p_h = Math::fmod(p_h, 6);
|
||||
i = Math::floor(p_h);
|
||||
|
||||
f = p_h - i;
|
||||
p = p_v * (1.0f - p_s);
|
||||
q = p_v * (1.0f - p_s * f);
|
||||
t = p_v * (1.0f - p_s * (1.0f - f));
|
||||
|
||||
switch (i) {
|
||||
case 0: // Red is the dominant color
|
||||
r = p_v;
|
||||
g = t;
|
||||
b = p;
|
||||
break;
|
||||
case 1: // Green is the dominant color
|
||||
r = q;
|
||||
g = p_v;
|
||||
b = p;
|
||||
break;
|
||||
case 2:
|
||||
r = p;
|
||||
g = p_v;
|
||||
b = t;
|
||||
break;
|
||||
case 3: // Blue is the dominant color
|
||||
r = p;
|
||||
g = q;
|
||||
b = p_v;
|
||||
break;
|
||||
case 4:
|
||||
r = t;
|
||||
g = p;
|
||||
b = p_v;
|
||||
break;
|
||||
default: // (5) Red is the dominant color
|
||||
r = p_v;
|
||||
g = p;
|
||||
b = q;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
bool Color::is_equal_approx(const Color &p_color) const {
|
||||
return Math::is_equal_approx(r, p_color.r) && Math::is_equal_approx(g, p_color.g) && Math::is_equal_approx(b, p_color.b) && Math::is_equal_approx(a, p_color.a);
|
||||
}
|
||||
|
||||
Color Color::clamp(const Color &p_min, const Color &p_max) const {
|
||||
return Color(
|
||||
CLAMP(r, p_min.r, p_max.r),
|
||||
CLAMP(g, p_min.g, p_max.g),
|
||||
CLAMP(b, p_min.b, p_max.b),
|
||||
CLAMP(a, p_min.a, p_max.a));
|
||||
}
|
||||
|
||||
void Color::invert() {
|
||||
r = 1.0f - r;
|
||||
g = 1.0f - g;
|
||||
b = 1.0f - b;
|
||||
}
|
||||
|
||||
Color Color::hex(uint32_t p_hex) {
|
||||
float a = (p_hex & 0xFF) / 255.0f;
|
||||
p_hex >>= 8;
|
||||
float b = (p_hex & 0xFF) / 255.0f;
|
||||
p_hex >>= 8;
|
||||
float g = (p_hex & 0xFF) / 255.0f;
|
||||
p_hex >>= 8;
|
||||
float r = (p_hex & 0xFF) / 255.0f;
|
||||
|
||||
return Color(r, g, b, a);
|
||||
}
|
||||
|
||||
Color Color::hex64(uint64_t p_hex) {
|
||||
float a = (p_hex & 0xFFFF) / 65535.0f;
|
||||
p_hex >>= 16;
|
||||
float b = (p_hex & 0xFFFF) / 65535.0f;
|
||||
p_hex >>= 16;
|
||||
float g = (p_hex & 0xFFFF) / 65535.0f;
|
||||
p_hex >>= 16;
|
||||
float r = (p_hex & 0xFFFF) / 65535.0f;
|
||||
|
||||
return Color(r, g, b, a);
|
||||
}
|
||||
|
||||
static int _parse_col4(const String &p_str, int p_ofs) {
|
||||
char character = p_str[p_ofs];
|
||||
|
||||
if (character >= '0' && character <= '9') {
|
||||
return character - '0';
|
||||
} else if (character >= 'a' && character <= 'f') {
|
||||
return character + (10 - 'a');
|
||||
} else if (character >= 'A' && character <= 'F') {
|
||||
return character + (10 - 'A');
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int _parse_col8(const String &p_str, int p_ofs) {
|
||||
return _parse_col4(p_str, p_ofs) * 16 + _parse_col4(p_str, p_ofs + 1);
|
||||
}
|
||||
|
||||
Color Color::inverted() const {
|
||||
Color c = *this;
|
||||
c.invert();
|
||||
return c;
|
||||
}
|
||||
|
||||
Color Color::html(const String &p_rgba) {
|
||||
String color = p_rgba;
|
||||
if (color.length() == 0) {
|
||||
return Color();
|
||||
}
|
||||
if (color[0] == '#') {
|
||||
color = color.substr(1);
|
||||
}
|
||||
|
||||
// If enabled, use 1 hex digit per channel instead of 2.
|
||||
// Other sizes aren't in the HTML/CSS spec but we could add them if desired.
|
||||
bool is_shorthand = color.length() < 5;
|
||||
bool alpha = false;
|
||||
|
||||
if (color.length() == 8) {
|
||||
alpha = true;
|
||||
} else if (color.length() == 6) {
|
||||
alpha = false;
|
||||
} else if (color.length() == 4) {
|
||||
alpha = true;
|
||||
} else if (color.length() == 3) {
|
||||
alpha = false;
|
||||
} else {
|
||||
ERR_FAIL_V_MSG(Color(), "Invalid color code: " + p_rgba + ".");
|
||||
}
|
||||
|
||||
float r, g, b, a = 1.0f;
|
||||
if (is_shorthand) {
|
||||
r = _parse_col4(color, 0) / 15.0f;
|
||||
g = _parse_col4(color, 1) / 15.0f;
|
||||
b = _parse_col4(color, 2) / 15.0f;
|
||||
if (alpha) {
|
||||
a = _parse_col4(color, 3) / 15.0f;
|
||||
}
|
||||
} else {
|
||||
r = _parse_col8(color, 0) / 255.0f;
|
||||
g = _parse_col8(color, 2) / 255.0f;
|
||||
b = _parse_col8(color, 4) / 255.0f;
|
||||
if (alpha) {
|
||||
a = _parse_col8(color, 6) / 255.0f;
|
||||
}
|
||||
}
|
||||
ERR_FAIL_COND_V_MSG(r < 0.0f, Color(), "Invalid color code: " + p_rgba + ".");
|
||||
ERR_FAIL_COND_V_MSG(g < 0.0f, Color(), "Invalid color code: " + p_rgba + ".");
|
||||
ERR_FAIL_COND_V_MSG(b < 0.0f, Color(), "Invalid color code: " + p_rgba + ".");
|
||||
ERR_FAIL_COND_V_MSG(a < 0.0f, Color(), "Invalid color code: " + p_rgba + ".");
|
||||
|
||||
return Color(r, g, b, a);
|
||||
}
|
||||
|
||||
bool Color::html_is_valid(const String &p_color) {
|
||||
String color = p_color;
|
||||
|
||||
if (color.length() == 0) {
|
||||
return false;
|
||||
}
|
||||
if (color[0] == '#') {
|
||||
color = color.substr(1);
|
||||
}
|
||||
|
||||
// Check if the amount of hex digits is valid.
|
||||
int len = color.length();
|
||||
if (!(len == 3 || len == 4 || len == 6 || len == 8)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check if each hex digit is valid.
|
||||
for (int i = 0; i < len; i++) {
|
||||
if (_parse_col4(color, i) == -1) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
Color Color::named(const String &p_name) {
|
||||
int idx = find_named_color(p_name);
|
||||
if (idx == -1) {
|
||||
ERR_FAIL_V_MSG(Color(), "Invalid color name: " + p_name + ".");
|
||||
return Color();
|
||||
}
|
||||
return named_colors[idx].color;
|
||||
}
|
||||
|
||||
Color Color::named(const String &p_name, const Color &p_default) {
|
||||
int idx = find_named_color(p_name);
|
||||
if (idx == -1) {
|
||||
return p_default;
|
||||
}
|
||||
return named_colors[idx].color;
|
||||
}
|
||||
|
||||
int Color::find_named_color(const String &p_name) {
|
||||
String name = p_name;
|
||||
// Normalize name
|
||||
name = name.replace(" ", "");
|
||||
name = name.replace("-", "");
|
||||
name = name.replace("_", "");
|
||||
name = name.replace("'", "");
|
||||
name = name.replace(".", "");
|
||||
name = name.to_upper();
|
||||
|
||||
int idx = 0;
|
||||
while (named_colors[idx].name != nullptr) {
|
||||
if (name == String(named_colors[idx].name).replace("_", "")) {
|
||||
return idx;
|
||||
}
|
||||
idx++;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
int Color::get_named_color_count() {
|
||||
int idx = 0;
|
||||
while (named_colors[idx].name != nullptr) {
|
||||
idx++;
|
||||
}
|
||||
return idx;
|
||||
}
|
||||
|
||||
String Color::get_named_color_name(int p_idx) {
|
||||
ERR_FAIL_INDEX_V(p_idx, get_named_color_count(), "");
|
||||
return named_colors[p_idx].name;
|
||||
}
|
||||
|
||||
Color Color::get_named_color(int p_idx) {
|
||||
ERR_FAIL_INDEX_V(p_idx, get_named_color_count(), Color());
|
||||
return named_colors[p_idx].color;
|
||||
}
|
||||
|
||||
// For a version that errors on invalid values instead of returning
|
||||
// a default color, use the Color(String) constructor instead.
|
||||
Color Color::from_string(const String &p_string, const Color &p_default) {
|
||||
if (html_is_valid(p_string)) {
|
||||
return html(p_string);
|
||||
} else {
|
||||
return named(p_string, p_default);
|
||||
}
|
||||
}
|
||||
|
||||
Color Color::from_hsv(float p_h, float p_s, float p_v, float p_alpha) {
|
||||
Color c;
|
||||
c.set_hsv(p_h, p_s, p_v, p_alpha);
|
||||
return c;
|
||||
}
|
||||
|
||||
Color Color::from_rgbe9995(uint32_t p_rgbe) {
|
||||
float r = p_rgbe & 0x1ff;
|
||||
float g = (p_rgbe >> 9) & 0x1ff;
|
||||
float b = (p_rgbe >> 18) & 0x1ff;
|
||||
float e = (p_rgbe >> 27);
|
||||
float m = Math::pow(2.0f, e - 15.0f - 9.0f);
|
||||
|
||||
float rd = r * m;
|
||||
float gd = g * m;
|
||||
float bd = b * m;
|
||||
|
||||
return Color(rd, gd, bd, 1.0f);
|
||||
}
|
||||
|
||||
Color::operator String() const {
|
||||
return "(" + String::num(r, 4) + ", " + String::num(g, 4) + ", " + String::num(b, 4) + ", " + String::num(a, 4) + ")";
|
||||
}
|
||||
|
||||
Color Color::operator+(const Color &p_color) const {
|
||||
return Color(
|
||||
r + p_color.r,
|
||||
g + p_color.g,
|
||||
b + p_color.b,
|
||||
a + p_color.a);
|
||||
}
|
||||
|
||||
void Color::operator+=(const Color &p_color) {
|
||||
r = r + p_color.r;
|
||||
g = g + p_color.g;
|
||||
b = b + p_color.b;
|
||||
a = a + p_color.a;
|
||||
}
|
||||
|
||||
Color Color::operator-(const Color &p_color) const {
|
||||
return Color(
|
||||
r - p_color.r,
|
||||
g - p_color.g,
|
||||
b - p_color.b,
|
||||
a - p_color.a);
|
||||
}
|
||||
|
||||
void Color::operator-=(const Color &p_color) {
|
||||
r = r - p_color.r;
|
||||
g = g - p_color.g;
|
||||
b = b - p_color.b;
|
||||
a = a - p_color.a;
|
||||
}
|
||||
|
||||
Color Color::operator*(const Color &p_color) const {
|
||||
return Color(
|
||||
r * p_color.r,
|
||||
g * p_color.g,
|
||||
b * p_color.b,
|
||||
a * p_color.a);
|
||||
}
|
||||
|
||||
Color Color::operator*(float p_scalar) const {
|
||||
return Color(
|
||||
r * p_scalar,
|
||||
g * p_scalar,
|
||||
b * p_scalar,
|
||||
a * p_scalar);
|
||||
}
|
||||
|
||||
void Color::operator*=(const Color &p_color) {
|
||||
r = r * p_color.r;
|
||||
g = g * p_color.g;
|
||||
b = b * p_color.b;
|
||||
a = a * p_color.a;
|
||||
}
|
||||
|
||||
void Color::operator*=(float p_scalar) {
|
||||
r = r * p_scalar;
|
||||
g = g * p_scalar;
|
||||
b = b * p_scalar;
|
||||
a = a * p_scalar;
|
||||
}
|
||||
|
||||
Color Color::operator/(const Color &p_color) const {
|
||||
return Color(
|
||||
r / p_color.r,
|
||||
g / p_color.g,
|
||||
b / p_color.b,
|
||||
a / p_color.a);
|
||||
}
|
||||
|
||||
Color Color::operator/(float p_scalar) const {
|
||||
return Color(
|
||||
r / p_scalar,
|
||||
g / p_scalar,
|
||||
b / p_scalar,
|
||||
a / p_scalar);
|
||||
}
|
||||
|
||||
void Color::operator/=(const Color &p_color) {
|
||||
r = r / p_color.r;
|
||||
g = g / p_color.g;
|
||||
b = b / p_color.b;
|
||||
a = a / p_color.a;
|
||||
}
|
||||
|
||||
void Color::operator/=(float p_scalar) {
|
||||
r = r / p_scalar;
|
||||
g = g / p_scalar;
|
||||
b = b / p_scalar;
|
||||
a = a / p_scalar;
|
||||
}
|
||||
|
||||
Color Color::operator-() const {
|
||||
return Color(
|
||||
1.0f - r,
|
||||
1.0f - g,
|
||||
1.0f - b,
|
||||
1.0f - a);
|
||||
}
|
||||
|
||||
} // namespace godot
|
230
lib/godot-cpp/src/variant/packed_arrays.cpp
Normal file
230
lib/godot-cpp/src/variant/packed_arrays.cpp
Normal file
@@ -0,0 +1,230 @@
|
||||
/**************************************************************************/
|
||||
/* packed_arrays.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. */
|
||||
/**************************************************************************/
|
||||
|
||||
// extra functions for packed arrays
|
||||
|
||||
#include <godot_cpp/godot.hpp>
|
||||
|
||||
#include <godot_cpp/variant/array.hpp>
|
||||
#include <godot_cpp/variant/dictionary.hpp>
|
||||
#include <godot_cpp/variant/packed_byte_array.hpp>
|
||||
#include <godot_cpp/variant/packed_color_array.hpp>
|
||||
#include <godot_cpp/variant/packed_float32_array.hpp>
|
||||
#include <godot_cpp/variant/packed_float64_array.hpp>
|
||||
#include <godot_cpp/variant/packed_int32_array.hpp>
|
||||
#include <godot_cpp/variant/packed_int64_array.hpp>
|
||||
#include <godot_cpp/variant/packed_string_array.hpp>
|
||||
#include <godot_cpp/variant/packed_vector2_array.hpp>
|
||||
#include <godot_cpp/variant/packed_vector3_array.hpp>
|
||||
|
||||
namespace godot {
|
||||
|
||||
const uint8_t &PackedByteArray::operator[](int p_index) const {
|
||||
return *internal::gde_interface->packed_byte_array_operator_index_const((GDExtensionTypePtr *)this, p_index);
|
||||
}
|
||||
|
||||
uint8_t &PackedByteArray::operator[](int p_index) {
|
||||
return *internal::gde_interface->packed_byte_array_operator_index((GDExtensionTypePtr *)this, p_index);
|
||||
}
|
||||
|
||||
const uint8_t *PackedByteArray::ptr() const {
|
||||
return internal::gde_interface->packed_byte_array_operator_index_const((GDExtensionTypePtr *)this, 0);
|
||||
}
|
||||
|
||||
uint8_t *PackedByteArray::ptrw() {
|
||||
return internal::gde_interface->packed_byte_array_operator_index((GDExtensionTypePtr *)this, 0);
|
||||
}
|
||||
|
||||
const Color &PackedColorArray::operator[](int p_index) const {
|
||||
const Color *color = (const Color *)internal::gde_interface->packed_color_array_operator_index_const((GDExtensionTypePtr *)this, p_index);
|
||||
return *color;
|
||||
}
|
||||
|
||||
Color &PackedColorArray::operator[](int p_index) {
|
||||
Color *color = (Color *)internal::gde_interface->packed_color_array_operator_index((GDExtensionTypePtr *)this, p_index);
|
||||
return *color;
|
||||
}
|
||||
|
||||
const Color *PackedColorArray::ptr() const {
|
||||
return (const Color *)internal::gde_interface->packed_color_array_operator_index_const((GDExtensionTypePtr *)this, 0);
|
||||
}
|
||||
|
||||
Color *PackedColorArray::ptrw() {
|
||||
return (Color *)internal::gde_interface->packed_color_array_operator_index((GDExtensionTypePtr *)this, 0);
|
||||
}
|
||||
|
||||
const float &PackedFloat32Array::operator[](int p_index) const {
|
||||
return *internal::gde_interface->packed_float32_array_operator_index_const((GDExtensionTypePtr *)this, p_index);
|
||||
}
|
||||
|
||||
float &PackedFloat32Array::operator[](int p_index) {
|
||||
return *internal::gde_interface->packed_float32_array_operator_index((GDExtensionTypePtr *)this, p_index);
|
||||
}
|
||||
|
||||
const float *PackedFloat32Array::ptr() const {
|
||||
return internal::gde_interface->packed_float32_array_operator_index_const((GDExtensionTypePtr *)this, 0);
|
||||
}
|
||||
|
||||
float *PackedFloat32Array::ptrw() {
|
||||
return internal::gde_interface->packed_float32_array_operator_index((GDExtensionTypePtr *)this, 0);
|
||||
}
|
||||
|
||||
const double &PackedFloat64Array::operator[](int p_index) const {
|
||||
return *internal::gde_interface->packed_float64_array_operator_index_const((GDExtensionTypePtr *)this, p_index);
|
||||
}
|
||||
|
||||
double &PackedFloat64Array::operator[](int p_index) {
|
||||
return *internal::gde_interface->packed_float64_array_operator_index((GDExtensionTypePtr *)this, p_index);
|
||||
}
|
||||
|
||||
const double *PackedFloat64Array::ptr() const {
|
||||
return internal::gde_interface->packed_float64_array_operator_index_const((GDExtensionTypePtr *)this, 0);
|
||||
}
|
||||
|
||||
double *PackedFloat64Array::ptrw() {
|
||||
return internal::gde_interface->packed_float64_array_operator_index((GDExtensionTypePtr *)this, 0);
|
||||
}
|
||||
|
||||
const int32_t &PackedInt32Array::operator[](int p_index) const {
|
||||
return *internal::gde_interface->packed_int32_array_operator_index_const((GDExtensionTypePtr *)this, p_index);
|
||||
}
|
||||
|
||||
int32_t &PackedInt32Array::operator[](int p_index) {
|
||||
return *internal::gde_interface->packed_int32_array_operator_index((GDExtensionTypePtr *)this, p_index);
|
||||
}
|
||||
|
||||
const int32_t *PackedInt32Array::ptr() const {
|
||||
return internal::gde_interface->packed_int32_array_operator_index_const((GDExtensionTypePtr *)this, 0);
|
||||
}
|
||||
|
||||
int32_t *PackedInt32Array::ptrw() {
|
||||
return internal::gde_interface->packed_int32_array_operator_index((GDExtensionTypePtr *)this, 0);
|
||||
}
|
||||
|
||||
const int64_t &PackedInt64Array::operator[](int p_index) const {
|
||||
return *internal::gde_interface->packed_int64_array_operator_index_const((GDExtensionTypePtr *)this, p_index);
|
||||
}
|
||||
|
||||
int64_t &PackedInt64Array::operator[](int p_index) {
|
||||
return *internal::gde_interface->packed_int64_array_operator_index((GDExtensionTypePtr *)this, p_index);
|
||||
}
|
||||
|
||||
const int64_t *PackedInt64Array::ptr() const {
|
||||
return internal::gde_interface->packed_int64_array_operator_index_const((GDExtensionTypePtr *)this, 0);
|
||||
}
|
||||
|
||||
int64_t *PackedInt64Array::ptrw() {
|
||||
return internal::gde_interface->packed_int64_array_operator_index((GDExtensionTypePtr *)this, 0);
|
||||
}
|
||||
|
||||
const String &PackedStringArray::operator[](int p_index) const {
|
||||
const String *string = (const String *)internal::gde_interface->packed_string_array_operator_index_const((GDExtensionTypePtr *)this, p_index);
|
||||
return *string;
|
||||
}
|
||||
|
||||
String &PackedStringArray::operator[](int p_index) {
|
||||
String *string = (String *)internal::gde_interface->packed_string_array_operator_index((GDExtensionTypePtr *)this, p_index);
|
||||
return *string;
|
||||
}
|
||||
|
||||
const String *PackedStringArray::ptr() const {
|
||||
return (const String *)internal::gde_interface->packed_string_array_operator_index_const((GDExtensionTypePtr *)this, 0);
|
||||
}
|
||||
|
||||
String *PackedStringArray::ptrw() {
|
||||
return (String *)internal::gde_interface->packed_string_array_operator_index((GDExtensionTypePtr *)this, 0);
|
||||
}
|
||||
|
||||
const Vector2 &PackedVector2Array::operator[](int p_index) const {
|
||||
const Vector2 *vec = (const Vector2 *)internal::gde_interface->packed_vector2_array_operator_index_const((GDExtensionTypePtr *)this, p_index);
|
||||
return *vec;
|
||||
}
|
||||
|
||||
Vector2 &PackedVector2Array::operator[](int p_index) {
|
||||
Vector2 *vec = (Vector2 *)internal::gde_interface->packed_vector2_array_operator_index((GDExtensionTypePtr *)this, p_index);
|
||||
return *vec;
|
||||
}
|
||||
|
||||
const Vector2 *PackedVector2Array::ptr() const {
|
||||
return (const Vector2 *)internal::gde_interface->packed_vector2_array_operator_index_const((GDExtensionTypePtr *)this, 0);
|
||||
}
|
||||
|
||||
Vector2 *PackedVector2Array::ptrw() {
|
||||
return (Vector2 *)internal::gde_interface->packed_vector2_array_operator_index((GDExtensionTypePtr *)this, 0);
|
||||
}
|
||||
|
||||
const Vector3 &PackedVector3Array::operator[](int p_index) const {
|
||||
const Vector3 *vec = (const Vector3 *)internal::gde_interface->packed_vector3_array_operator_index_const((GDExtensionTypePtr *)this, p_index);
|
||||
return *vec;
|
||||
}
|
||||
|
||||
Vector3 &PackedVector3Array::operator[](int p_index) {
|
||||
Vector3 *vec = (Vector3 *)internal::gde_interface->packed_vector3_array_operator_index((GDExtensionTypePtr *)this, p_index);
|
||||
return *vec;
|
||||
}
|
||||
|
||||
const Vector3 *PackedVector3Array::ptr() const {
|
||||
return (const Vector3 *)internal::gde_interface->packed_vector3_array_operator_index_const((GDExtensionTypePtr *)this, 0);
|
||||
}
|
||||
|
||||
Vector3 *PackedVector3Array::ptrw() {
|
||||
return (Vector3 *)internal::gde_interface->packed_vector3_array_operator_index((GDExtensionTypePtr *)this, 0);
|
||||
}
|
||||
|
||||
const Variant &Array::operator[](int p_index) const {
|
||||
const Variant *var = (const Variant *)internal::gde_interface->array_operator_index_const((GDExtensionTypePtr *)this, p_index);
|
||||
return *var;
|
||||
}
|
||||
|
||||
Variant &Array::operator[](int p_index) {
|
||||
Variant *var = (Variant *)internal::gde_interface->array_operator_index((GDExtensionTypePtr *)this, p_index);
|
||||
return *var;
|
||||
}
|
||||
|
||||
void Array::set_typed(uint32_t p_type, const StringName &p_class_name, const Variant &p_script) {
|
||||
// p_type is not Variant::Type so that header doesn't depend on <variant.hpp>.
|
||||
internal::gde_interface->array_set_typed((GDExtensionTypePtr *)this, (GDExtensionVariantType)p_type, (GDExtensionConstStringNamePtr)&p_class_name, (GDExtensionConstVariantPtr)&p_script);
|
||||
}
|
||||
|
||||
void Array::_ref(const Array &p_from) const {
|
||||
internal::gde_interface->array_ref((GDExtensionTypePtr *)this, (GDExtensionConstTypePtr *)&p_from);
|
||||
}
|
||||
|
||||
const Variant &Dictionary::operator[](const Variant &p_key) const {
|
||||
const Variant *var = (const Variant *)internal::gde_interface->dictionary_operator_index_const((GDExtensionTypePtr *)this, (GDExtensionVariantPtr)&p_key);
|
||||
return *var;
|
||||
}
|
||||
|
||||
Variant &Dictionary::operator[](const Variant &p_key) {
|
||||
Variant *var = (Variant *)internal::gde_interface->dictionary_operator_index((GDExtensionTypePtr *)this, (GDExtensionVariantPtr)&p_key);
|
||||
return *var;
|
||||
}
|
||||
|
||||
} // namespace godot
|
185
lib/godot-cpp/src/variant/plane.cpp
Normal file
185
lib/godot-cpp/src/variant/plane.cpp
Normal file
@@ -0,0 +1,185 @@
|
||||
/**************************************************************************/
|
||||
/* plane.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 <godot_cpp/variant/plane.hpp>
|
||||
|
||||
#include <godot_cpp/variant/string.hpp>
|
||||
#include <godot_cpp/variant/variant.hpp>
|
||||
|
||||
namespace godot {
|
||||
|
||||
void Plane::set_normal(const Vector3 &p_normal) {
|
||||
normal = p_normal;
|
||||
}
|
||||
|
||||
void Plane::normalize() {
|
||||
real_t l = normal.length();
|
||||
if (l == 0) {
|
||||
*this = Plane(0, 0, 0, 0);
|
||||
return;
|
||||
}
|
||||
normal /= l;
|
||||
d /= l;
|
||||
}
|
||||
|
||||
Plane Plane::normalized() const {
|
||||
Plane p = *this;
|
||||
p.normalize();
|
||||
return p;
|
||||
}
|
||||
|
||||
Vector3 Plane::get_any_perpendicular_normal() const {
|
||||
static const Vector3 p1 = Vector3(1, 0, 0);
|
||||
static const Vector3 p2 = Vector3(0, 1, 0);
|
||||
Vector3 p;
|
||||
|
||||
if (Math::abs(normal.dot(p1)) > 0.99f) { // if too similar to p1
|
||||
p = p2; // use p2
|
||||
} else {
|
||||
p = p1; // use p1
|
||||
}
|
||||
|
||||
p -= normal * normal.dot(p);
|
||||
p.normalize();
|
||||
|
||||
return p;
|
||||
}
|
||||
|
||||
/* intersections */
|
||||
|
||||
bool Plane::intersect_3(const Plane &p_plane1, const Plane &p_plane2, Vector3 *r_result) const {
|
||||
const Plane &p_plane0 = *this;
|
||||
Vector3 normal0 = p_plane0.normal;
|
||||
Vector3 normal1 = p_plane1.normal;
|
||||
Vector3 normal2 = p_plane2.normal;
|
||||
|
||||
real_t denom = vec3_cross(normal0, normal1).dot(normal2);
|
||||
|
||||
if (Math::is_zero_approx(denom)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (r_result) {
|
||||
*r_result = ((vec3_cross(normal1, normal2) * p_plane0.d) +
|
||||
(vec3_cross(normal2, normal0) * p_plane1.d) +
|
||||
(vec3_cross(normal0, normal1) * p_plane2.d)) /
|
||||
denom;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Plane::intersects_ray(const Vector3 &p_from, const Vector3 &p_dir, Vector3 *p_intersection) const {
|
||||
Vector3 segment = p_dir;
|
||||
real_t den = normal.dot(segment);
|
||||
|
||||
//printf("den is %i\n",den);
|
||||
if (Math::is_zero_approx(den)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
real_t dist = (normal.dot(p_from) - d) / den;
|
||||
//printf("dist is %i\n",dist);
|
||||
|
||||
if (dist > (real_t)CMP_EPSILON) { //this is a ray, before the emitting pos (p_from) doesn't exist
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
dist = -dist;
|
||||
*p_intersection = p_from + segment * dist;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Plane::intersects_segment(const Vector3 &p_begin, const Vector3 &p_end, Vector3 *p_intersection) const {
|
||||
Vector3 segment = p_begin - p_end;
|
||||
real_t den = normal.dot(segment);
|
||||
|
||||
//printf("den is %i\n",den);
|
||||
if (Math::is_zero_approx(den)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
real_t dist = (normal.dot(p_begin) - d) / den;
|
||||
//printf("dist is %i\n",dist);
|
||||
|
||||
if (dist < (real_t)-CMP_EPSILON || dist > (1.0f + (real_t)CMP_EPSILON)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
dist = -dist;
|
||||
*p_intersection = p_begin + segment * dist;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
Variant Plane::intersect_3_bind(const Plane &p_plane1, const Plane &p_plane2) const {
|
||||
Vector3 inters;
|
||||
if (intersect_3(p_plane1, p_plane2, &inters)) {
|
||||
return inters;
|
||||
} else {
|
||||
return Variant();
|
||||
}
|
||||
}
|
||||
|
||||
Variant Plane::intersects_ray_bind(const Vector3 &p_from, const Vector3 &p_dir) const {
|
||||
Vector3 inters;
|
||||
if (intersects_ray(p_from, p_dir, &inters)) {
|
||||
return inters;
|
||||
} else {
|
||||
return Variant();
|
||||
}
|
||||
}
|
||||
|
||||
Variant Plane::intersects_segment_bind(const Vector3 &p_begin, const Vector3 &p_end) const {
|
||||
Vector3 inters;
|
||||
if (intersects_segment(p_begin, p_end, &inters)) {
|
||||
return inters;
|
||||
} else {
|
||||
return Variant();
|
||||
}
|
||||
}
|
||||
|
||||
/* misc */
|
||||
|
||||
bool Plane::is_equal_approx_any_side(const Plane &p_plane) const {
|
||||
return (normal.is_equal_approx(p_plane.normal) && Math::is_equal_approx(d, p_plane.d)) || (normal.is_equal_approx(-p_plane.normal) && Math::is_equal_approx(d, -p_plane.d));
|
||||
}
|
||||
|
||||
bool Plane::is_equal_approx(const Plane &p_plane) const {
|
||||
return normal.is_equal_approx(p_plane.normal) && Math::is_equal_approx(d, p_plane.d);
|
||||
}
|
||||
|
||||
Plane::operator String() const {
|
||||
return "[N: " + normal.operator String() + ", D: " + String::num_real(d, false) + "]";
|
||||
}
|
||||
|
||||
} // namespace godot
|
941
lib/godot-cpp/src/variant/projection.cpp
Normal file
941
lib/godot-cpp/src/variant/projection.cpp
Normal file
@@ -0,0 +1,941 @@
|
||||
/**************************************************************************/
|
||||
/* projection.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 <godot_cpp/variant/projection.hpp>
|
||||
|
||||
#include <godot_cpp/variant/aabb.hpp>
|
||||
#include <godot_cpp/variant/plane.hpp>
|
||||
#include <godot_cpp/variant/rect2.hpp>
|
||||
#include <godot_cpp/variant/string.hpp>
|
||||
#include <godot_cpp/variant/transform3d.hpp>
|
||||
#include <godot_cpp/variant/variant.hpp>
|
||||
|
||||
namespace godot {
|
||||
|
||||
float Projection::determinant() const {
|
||||
return columns[0][3] * columns[1][2] * columns[2][1] * columns[3][0] - columns[0][2] * columns[1][3] * columns[2][1] * columns[3][0] -
|
||||
columns[0][3] * columns[1][1] * columns[2][2] * columns[3][0] + columns[0][1] * columns[1][3] * columns[2][2] * columns[3][0] +
|
||||
columns[0][2] * columns[1][1] * columns[2][3] * columns[3][0] - columns[0][1] * columns[1][2] * columns[2][3] * columns[3][0] -
|
||||
columns[0][3] * columns[1][2] * columns[2][0] * columns[3][1] + columns[0][2] * columns[1][3] * columns[2][0] * columns[3][1] +
|
||||
columns[0][3] * columns[1][0] * columns[2][2] * columns[3][1] - columns[0][0] * columns[1][3] * columns[2][2] * columns[3][1] -
|
||||
columns[0][2] * columns[1][0] * columns[2][3] * columns[3][1] + columns[0][0] * columns[1][2] * columns[2][3] * columns[3][1] +
|
||||
columns[0][3] * columns[1][1] * columns[2][0] * columns[3][2] - columns[0][1] * columns[1][3] * columns[2][0] * columns[3][2] -
|
||||
columns[0][3] * columns[1][0] * columns[2][1] * columns[3][2] + columns[0][0] * columns[1][3] * columns[2][1] * columns[3][2] +
|
||||
columns[0][1] * columns[1][0] * columns[2][3] * columns[3][2] - columns[0][0] * columns[1][1] * columns[2][3] * columns[3][2] -
|
||||
columns[0][2] * columns[1][1] * columns[2][0] * columns[3][3] + columns[0][1] * columns[1][2] * columns[2][0] * columns[3][3] +
|
||||
columns[0][2] * columns[1][0] * columns[2][1] * columns[3][3] - columns[0][0] * columns[1][2] * columns[2][1] * columns[3][3] -
|
||||
columns[0][1] * columns[1][0] * columns[2][2] * columns[3][3] + columns[0][0] * columns[1][1] * columns[2][2] * columns[3][3];
|
||||
}
|
||||
|
||||
void Projection::set_identity() {
|
||||
for (int i = 0; i < 4; i++) {
|
||||
for (int j = 0; j < 4; j++) {
|
||||
columns[i][j] = (i == j) ? 1 : 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Projection::set_zero() {
|
||||
for (int i = 0; i < 4; i++) {
|
||||
for (int j = 0; j < 4; j++) {
|
||||
columns[i][j] = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Plane Projection::xform4(const Plane &p_vec4) const {
|
||||
Plane ret;
|
||||
|
||||
ret.normal.x = columns[0][0] * p_vec4.normal.x + columns[1][0] * p_vec4.normal.y + columns[2][0] * p_vec4.normal.z + columns[3][0] * p_vec4.d;
|
||||
ret.normal.y = columns[0][1] * p_vec4.normal.x + columns[1][1] * p_vec4.normal.y + columns[2][1] * p_vec4.normal.z + columns[3][1] * p_vec4.d;
|
||||
ret.normal.z = columns[0][2] * p_vec4.normal.x + columns[1][2] * p_vec4.normal.y + columns[2][2] * p_vec4.normal.z + columns[3][2] * p_vec4.d;
|
||||
ret.d = columns[0][3] * p_vec4.normal.x + columns[1][3] * p_vec4.normal.y + columns[2][3] * p_vec4.normal.z + columns[3][3] * p_vec4.d;
|
||||
return ret;
|
||||
}
|
||||
|
||||
Vector4 Projection::xform(const Vector4 &p_vec4) const {
|
||||
return Vector4(
|
||||
columns[0][0] * p_vec4.x + columns[1][0] * p_vec4.y + columns[2][0] * p_vec4.z + columns[3][0] * p_vec4.w,
|
||||
columns[0][1] * p_vec4.x + columns[1][1] * p_vec4.y + columns[2][1] * p_vec4.z + columns[3][1] * p_vec4.w,
|
||||
columns[0][2] * p_vec4.x + columns[1][2] * p_vec4.y + columns[2][2] * p_vec4.z + columns[3][2] * p_vec4.w,
|
||||
columns[0][3] * p_vec4.x + columns[1][3] * p_vec4.y + columns[2][3] * p_vec4.z + columns[3][3] * p_vec4.w);
|
||||
}
|
||||
Vector4 Projection::xform_inv(const Vector4 &p_vec4) const {
|
||||
return Vector4(
|
||||
columns[0][0] * p_vec4.x + columns[0][1] * p_vec4.y + columns[0][2] * p_vec4.z + columns[0][3] * p_vec4.w,
|
||||
columns[1][0] * p_vec4.x + columns[1][1] * p_vec4.y + columns[1][2] * p_vec4.z + columns[1][3] * p_vec4.w,
|
||||
columns[2][0] * p_vec4.x + columns[2][1] * p_vec4.y + columns[2][2] * p_vec4.z + columns[2][3] * p_vec4.w,
|
||||
columns[3][0] * p_vec4.x + columns[3][1] * p_vec4.y + columns[3][2] * p_vec4.z + columns[3][3] * p_vec4.w);
|
||||
}
|
||||
|
||||
void Projection::adjust_perspective_znear(real_t p_new_znear) {
|
||||
real_t zfar = get_z_far();
|
||||
real_t znear = p_new_znear;
|
||||
|
||||
real_t deltaZ = zfar - znear;
|
||||
columns[2][2] = -(zfar + znear) / deltaZ;
|
||||
columns[3][2] = -2 * znear * zfar / deltaZ;
|
||||
}
|
||||
|
||||
Projection Projection::create_depth_correction(bool p_flip_y) {
|
||||
Projection proj;
|
||||
proj.set_depth_correction(p_flip_y);
|
||||
return proj;
|
||||
}
|
||||
|
||||
Projection Projection::create_light_atlas_rect(const Rect2 &p_rect) {
|
||||
Projection proj;
|
||||
proj.set_light_atlas_rect(p_rect);
|
||||
return proj;
|
||||
}
|
||||
|
||||
Projection Projection::create_perspective(real_t p_fovy_degrees, real_t p_aspect, real_t p_z_near, real_t p_z_far, bool p_flip_fov) {
|
||||
Projection proj;
|
||||
proj.set_perspective(p_fovy_degrees, p_aspect, p_z_near, p_z_far, p_flip_fov);
|
||||
return proj;
|
||||
}
|
||||
|
||||
Projection Projection::create_perspective_hmd(real_t p_fovy_degrees, real_t p_aspect, real_t p_z_near, real_t p_z_far, bool p_flip_fov, int p_eye, real_t p_intraocular_dist, real_t p_convergence_dist) {
|
||||
Projection proj;
|
||||
proj.set_perspective(p_fovy_degrees, p_aspect, p_z_near, p_z_far, p_flip_fov, p_eye, p_intraocular_dist, p_convergence_dist);
|
||||
return proj;
|
||||
}
|
||||
|
||||
Projection Projection::create_for_hmd(int p_eye, real_t p_aspect, real_t p_intraocular_dist, real_t p_display_width, real_t p_display_to_lens, real_t p_oversample, real_t p_z_near, real_t p_z_far) {
|
||||
Projection proj;
|
||||
proj.set_for_hmd(p_eye, p_aspect, p_intraocular_dist, p_display_width, p_display_to_lens, p_oversample, p_z_near, p_z_far);
|
||||
return proj;
|
||||
}
|
||||
|
||||
Projection Projection::create_orthogonal(real_t p_left, real_t p_right, real_t p_bottom, real_t p_top, real_t p_znear, real_t p_zfar) {
|
||||
Projection proj;
|
||||
proj.set_orthogonal(p_left, p_right, p_bottom, p_top, p_zfar, p_zfar);
|
||||
return proj;
|
||||
}
|
||||
|
||||
Projection Projection::create_orthogonal_aspect(real_t p_size, real_t p_aspect, real_t p_znear, real_t p_zfar, bool p_flip_fov) {
|
||||
Projection proj;
|
||||
proj.set_orthogonal(p_size, p_aspect, p_znear, p_zfar, p_flip_fov);
|
||||
return proj;
|
||||
}
|
||||
|
||||
Projection Projection::create_frustum(real_t p_left, real_t p_right, real_t p_bottom, real_t p_top, real_t p_near, real_t p_far) {
|
||||
Projection proj;
|
||||
proj.set_frustum(p_left, p_right, p_bottom, p_top, p_near, p_far);
|
||||
return proj;
|
||||
}
|
||||
|
||||
Projection Projection::create_frustum_aspect(real_t p_size, real_t p_aspect, Vector2 p_offset, real_t p_near, real_t p_far, bool p_flip_fov) {
|
||||
Projection proj;
|
||||
proj.set_frustum(p_size, p_aspect, p_offset, p_near, p_far, p_flip_fov);
|
||||
return proj;
|
||||
}
|
||||
|
||||
Projection Projection::create_fit_aabb(const AABB &p_aabb) {
|
||||
Projection proj;
|
||||
proj.scale_translate_to_fit(p_aabb);
|
||||
return proj;
|
||||
}
|
||||
|
||||
Projection Projection::perspective_znear_adjusted(real_t p_new_znear) const {
|
||||
Projection proj = *this;
|
||||
proj.adjust_perspective_znear(p_new_znear);
|
||||
return proj;
|
||||
}
|
||||
|
||||
Plane Projection::get_projection_plane(Planes p_plane) const {
|
||||
const real_t *matrix = (const real_t *)this->columns;
|
||||
|
||||
switch (p_plane) {
|
||||
case PLANE_NEAR: {
|
||||
Plane new_plane = Plane(matrix[3] + matrix[2],
|
||||
matrix[7] + matrix[6],
|
||||
matrix[11] + matrix[10],
|
||||
matrix[15] + matrix[14]);
|
||||
|
||||
new_plane.normal = -new_plane.normal;
|
||||
new_plane.normalize();
|
||||
return new_plane;
|
||||
}
|
||||
case PLANE_FAR: {
|
||||
Plane new_plane = Plane(matrix[3] - matrix[2],
|
||||
matrix[7] - matrix[6],
|
||||
matrix[11] - matrix[10],
|
||||
matrix[15] - matrix[14]);
|
||||
|
||||
new_plane.normal = -new_plane.normal;
|
||||
new_plane.normalize();
|
||||
return new_plane;
|
||||
}
|
||||
case PLANE_LEFT: {
|
||||
Plane new_plane = Plane(matrix[3] + matrix[0],
|
||||
matrix[7] + matrix[4],
|
||||
matrix[11] + matrix[8],
|
||||
matrix[15] + matrix[12]);
|
||||
|
||||
new_plane.normal = -new_plane.normal;
|
||||
new_plane.normalize();
|
||||
return new_plane;
|
||||
}
|
||||
case PLANE_TOP: {
|
||||
Plane new_plane = Plane(matrix[3] - matrix[1],
|
||||
matrix[7] - matrix[5],
|
||||
matrix[11] - matrix[9],
|
||||
matrix[15] - matrix[13]);
|
||||
|
||||
new_plane.normal = -new_plane.normal;
|
||||
new_plane.normalize();
|
||||
return new_plane;
|
||||
}
|
||||
case PLANE_RIGHT: {
|
||||
Plane new_plane = Plane(matrix[3] - matrix[0],
|
||||
matrix[7] - matrix[4],
|
||||
matrix[11] - matrix[8],
|
||||
matrix[15] - matrix[12]);
|
||||
|
||||
new_plane.normal = -new_plane.normal;
|
||||
new_plane.normalize();
|
||||
return new_plane;
|
||||
}
|
||||
case PLANE_BOTTOM: {
|
||||
Plane new_plane = Plane(matrix[3] + matrix[1],
|
||||
matrix[7] + matrix[5],
|
||||
matrix[11] + matrix[9],
|
||||
matrix[15] + matrix[13]);
|
||||
|
||||
new_plane.normal = -new_plane.normal;
|
||||
new_plane.normalize();
|
||||
return new_plane;
|
||||
}
|
||||
}
|
||||
|
||||
return Plane();
|
||||
}
|
||||
|
||||
Projection Projection::flipped_y() const {
|
||||
Projection proj = *this;
|
||||
proj.flip_y();
|
||||
return proj;
|
||||
}
|
||||
|
||||
Projection Projection ::jitter_offseted(const Vector2 &p_offset) const {
|
||||
Projection proj = *this;
|
||||
proj.add_jitter_offset(p_offset);
|
||||
return proj;
|
||||
}
|
||||
|
||||
void Projection::set_perspective(real_t p_fovy_degrees, real_t p_aspect, real_t p_z_near, real_t p_z_far, bool p_flip_fov) {
|
||||
if (p_flip_fov) {
|
||||
p_fovy_degrees = get_fovy(p_fovy_degrees, 1.0 / p_aspect);
|
||||
}
|
||||
|
||||
real_t sine, cotangent, deltaZ;
|
||||
real_t radians = Math::deg_to_rad(p_fovy_degrees / 2.0);
|
||||
|
||||
deltaZ = p_z_far - p_z_near;
|
||||
sine = Math::sin(radians);
|
||||
|
||||
if ((deltaZ == 0) || (sine == 0) || (p_aspect == 0)) {
|
||||
return;
|
||||
}
|
||||
cotangent = Math::cos(radians) / sine;
|
||||
|
||||
set_identity();
|
||||
|
||||
columns[0][0] = cotangent / p_aspect;
|
||||
columns[1][1] = cotangent;
|
||||
columns[2][2] = -(p_z_far + p_z_near) / deltaZ;
|
||||
columns[2][3] = -1;
|
||||
columns[3][2] = -2 * p_z_near * p_z_far / deltaZ;
|
||||
columns[3][3] = 0;
|
||||
}
|
||||
|
||||
void Projection::set_perspective(real_t p_fovy_degrees, real_t p_aspect, real_t p_z_near, real_t p_z_far, bool p_flip_fov, int p_eye, real_t p_intraocular_dist, real_t p_convergence_dist) {
|
||||
if (p_flip_fov) {
|
||||
p_fovy_degrees = get_fovy(p_fovy_degrees, 1.0 / p_aspect);
|
||||
}
|
||||
|
||||
real_t left, right, modeltranslation, ymax, xmax, frustumshift;
|
||||
|
||||
ymax = p_z_near * tan(Math::deg_to_rad(p_fovy_degrees / 2.0));
|
||||
xmax = ymax * p_aspect;
|
||||
frustumshift = (p_intraocular_dist / 2.0) * p_z_near / p_convergence_dist;
|
||||
|
||||
switch (p_eye) {
|
||||
case 1: { // left eye
|
||||
left = -xmax + frustumshift;
|
||||
right = xmax + frustumshift;
|
||||
modeltranslation = p_intraocular_dist / 2.0;
|
||||
} break;
|
||||
case 2: { // right eye
|
||||
left = -xmax - frustumshift;
|
||||
right = xmax - frustumshift;
|
||||
modeltranslation = -p_intraocular_dist / 2.0;
|
||||
} break;
|
||||
default: { // mono, should give the same result as set_perspective(p_fovy_degrees,p_aspect,p_z_near,p_z_far,p_flip_fov)
|
||||
left = -xmax;
|
||||
right = xmax;
|
||||
modeltranslation = 0.0;
|
||||
} break;
|
||||
}
|
||||
|
||||
set_frustum(left, right, -ymax, ymax, p_z_near, p_z_far);
|
||||
|
||||
// translate matrix by (modeltranslation, 0.0, 0.0)
|
||||
Projection cm;
|
||||
cm.set_identity();
|
||||
cm.columns[3][0] = modeltranslation;
|
||||
*this = *this * cm;
|
||||
}
|
||||
|
||||
void Projection::set_for_hmd(int p_eye, real_t p_aspect, real_t p_intraocular_dist, real_t p_display_width, real_t p_display_to_lens, real_t p_oversample, real_t p_z_near, real_t p_z_far) {
|
||||
// we first calculate our base frustum on our values without taking our lens magnification into account.
|
||||
real_t f1 = (p_intraocular_dist * 0.5) / p_display_to_lens;
|
||||
real_t f2 = ((p_display_width - p_intraocular_dist) * 0.5) / p_display_to_lens;
|
||||
real_t f3 = (p_display_width / 4.0) / p_display_to_lens;
|
||||
|
||||
// now we apply our oversample factor to increase our FOV. how much we oversample is always a balance we strike between performance and how much
|
||||
// we're willing to sacrifice in FOV.
|
||||
real_t add = ((f1 + f2) * (p_oversample - 1.0)) / 2.0;
|
||||
f1 += add;
|
||||
f2 += add;
|
||||
f3 *= p_oversample;
|
||||
|
||||
// always apply KEEP_WIDTH aspect ratio
|
||||
f3 /= p_aspect;
|
||||
|
||||
switch (p_eye) {
|
||||
case 1: { // left eye
|
||||
set_frustum(-f2 * p_z_near, f1 * p_z_near, -f3 * p_z_near, f3 * p_z_near, p_z_near, p_z_far);
|
||||
} break;
|
||||
case 2: { // right eye
|
||||
set_frustum(-f1 * p_z_near, f2 * p_z_near, -f3 * p_z_near, f3 * p_z_near, p_z_near, p_z_far);
|
||||
} break;
|
||||
default: { // mono, does not apply here!
|
||||
} break;
|
||||
}
|
||||
}
|
||||
|
||||
void Projection::set_orthogonal(real_t p_left, real_t p_right, real_t p_bottom, real_t p_top, real_t p_znear, real_t p_zfar) {
|
||||
set_identity();
|
||||
|
||||
columns[0][0] = 2.0 / (p_right - p_left);
|
||||
columns[3][0] = -((p_right + p_left) / (p_right - p_left));
|
||||
columns[1][1] = 2.0 / (p_top - p_bottom);
|
||||
columns[3][1] = -((p_top + p_bottom) / (p_top - p_bottom));
|
||||
columns[2][2] = -2.0 / (p_zfar - p_znear);
|
||||
columns[3][2] = -((p_zfar + p_znear) / (p_zfar - p_znear));
|
||||
columns[3][3] = 1.0;
|
||||
}
|
||||
|
||||
void Projection::set_orthogonal(real_t p_size, real_t p_aspect, real_t p_znear, real_t p_zfar, bool p_flip_fov) {
|
||||
if (!p_flip_fov) {
|
||||
p_size *= p_aspect;
|
||||
}
|
||||
|
||||
set_orthogonal(-p_size / 2, +p_size / 2, -p_size / p_aspect / 2, +p_size / p_aspect / 2, p_znear, p_zfar);
|
||||
}
|
||||
|
||||
void Projection::set_frustum(real_t p_left, real_t p_right, real_t p_bottom, real_t p_top, real_t p_near, real_t p_far) {
|
||||
ERR_FAIL_COND(p_right <= p_left);
|
||||
ERR_FAIL_COND(p_top <= p_bottom);
|
||||
ERR_FAIL_COND(p_far <= p_near);
|
||||
|
||||
real_t *te = &columns[0][0];
|
||||
real_t x = 2 * p_near / (p_right - p_left);
|
||||
real_t y = 2 * p_near / (p_top - p_bottom);
|
||||
|
||||
real_t a = (p_right + p_left) / (p_right - p_left);
|
||||
real_t b = (p_top + p_bottom) / (p_top - p_bottom);
|
||||
real_t c = -(p_far + p_near) / (p_far - p_near);
|
||||
real_t d = -2 * p_far * p_near / (p_far - p_near);
|
||||
|
||||
te[0] = x;
|
||||
te[1] = 0;
|
||||
te[2] = 0;
|
||||
te[3] = 0;
|
||||
te[4] = 0;
|
||||
te[5] = y;
|
||||
te[6] = 0;
|
||||
te[7] = 0;
|
||||
te[8] = a;
|
||||
te[9] = b;
|
||||
te[10] = c;
|
||||
te[11] = -1;
|
||||
te[12] = 0;
|
||||
te[13] = 0;
|
||||
te[14] = d;
|
||||
te[15] = 0;
|
||||
}
|
||||
|
||||
void Projection::set_frustum(real_t p_size, real_t p_aspect, Vector2 p_offset, real_t p_near, real_t p_far, bool p_flip_fov) {
|
||||
if (!p_flip_fov) {
|
||||
p_size *= p_aspect;
|
||||
}
|
||||
|
||||
set_frustum(-p_size / 2 + p_offset.x, +p_size / 2 + p_offset.x, -p_size / p_aspect / 2 + p_offset.y, +p_size / p_aspect / 2 + p_offset.y, p_near, p_far);
|
||||
}
|
||||
|
||||
real_t Projection::get_z_far() const {
|
||||
const real_t *matrix = (const real_t *)this->columns;
|
||||
Plane new_plane = Plane(matrix[3] - matrix[2],
|
||||
matrix[7] - matrix[6],
|
||||
matrix[11] - matrix[10],
|
||||
matrix[15] - matrix[14]);
|
||||
|
||||
new_plane.normal = -new_plane.normal;
|
||||
new_plane.normalize();
|
||||
|
||||
return new_plane.d;
|
||||
}
|
||||
|
||||
real_t Projection::get_z_near() const {
|
||||
const real_t *matrix = (const real_t *)this->columns;
|
||||
Plane new_plane = Plane(matrix[3] + matrix[2],
|
||||
matrix[7] + matrix[6],
|
||||
matrix[11] + matrix[10],
|
||||
-matrix[15] - matrix[14]);
|
||||
|
||||
new_plane.normalize();
|
||||
return new_plane.d;
|
||||
}
|
||||
|
||||
Vector2 Projection::get_viewport_half_extents() const {
|
||||
const real_t *matrix = (const real_t *)this->columns;
|
||||
///////--- Near Plane ---///////
|
||||
Plane near_plane = Plane(matrix[3] + matrix[2],
|
||||
matrix[7] + matrix[6],
|
||||
matrix[11] + matrix[10],
|
||||
-matrix[15] - matrix[14]);
|
||||
near_plane.normalize();
|
||||
|
||||
///////--- Right Plane ---///////
|
||||
Plane right_plane = Plane(matrix[3] - matrix[0],
|
||||
matrix[7] - matrix[4],
|
||||
matrix[11] - matrix[8],
|
||||
-matrix[15] + matrix[12]);
|
||||
right_plane.normalize();
|
||||
|
||||
Plane top_plane = Plane(matrix[3] - matrix[1],
|
||||
matrix[7] - matrix[5],
|
||||
matrix[11] - matrix[9],
|
||||
-matrix[15] + matrix[13]);
|
||||
top_plane.normalize();
|
||||
|
||||
Vector3 res;
|
||||
near_plane.intersect_3(right_plane, top_plane, &res);
|
||||
|
||||
return Vector2(res.x, res.y);
|
||||
}
|
||||
|
||||
Vector2 Projection::get_far_plane_half_extents() const {
|
||||
const real_t *matrix = (const real_t *)this->columns;
|
||||
///////--- Far Plane ---///////
|
||||
Plane far_plane = Plane(matrix[3] - matrix[2],
|
||||
matrix[7] - matrix[6],
|
||||
matrix[11] - matrix[10],
|
||||
-matrix[15] + matrix[14]);
|
||||
far_plane.normalize();
|
||||
|
||||
///////--- Right Plane ---///////
|
||||
Plane right_plane = Plane(matrix[3] - matrix[0],
|
||||
matrix[7] - matrix[4],
|
||||
matrix[11] - matrix[8],
|
||||
-matrix[15] + matrix[12]);
|
||||
right_plane.normalize();
|
||||
|
||||
Plane top_plane = Plane(matrix[3] - matrix[1],
|
||||
matrix[7] - matrix[5],
|
||||
matrix[11] - matrix[9],
|
||||
-matrix[15] + matrix[13]);
|
||||
top_plane.normalize();
|
||||
|
||||
Vector3 res;
|
||||
far_plane.intersect_3(right_plane, top_plane, &res);
|
||||
|
||||
return Vector2(res.x, res.y);
|
||||
}
|
||||
|
||||
bool Projection::get_endpoints(const Transform3D &p_transform, Vector3 *p_8points) const {
|
||||
Array planes = get_projection_planes(Transform3D());
|
||||
const Planes intersections[8][3] = {
|
||||
{ PLANE_FAR, PLANE_LEFT, PLANE_TOP },
|
||||
{ PLANE_FAR, PLANE_LEFT, PLANE_BOTTOM },
|
||||
{ PLANE_FAR, PLANE_RIGHT, PLANE_TOP },
|
||||
{ PLANE_FAR, PLANE_RIGHT, PLANE_BOTTOM },
|
||||
{ PLANE_NEAR, PLANE_LEFT, PLANE_TOP },
|
||||
{ PLANE_NEAR, PLANE_LEFT, PLANE_BOTTOM },
|
||||
{ PLANE_NEAR, PLANE_RIGHT, PLANE_TOP },
|
||||
{ PLANE_NEAR, PLANE_RIGHT, PLANE_BOTTOM },
|
||||
};
|
||||
|
||||
for (int i = 0; i < 8; i++) {
|
||||
Vector3 point;
|
||||
Plane a = planes[intersections[i][0]];
|
||||
Plane b = planes[intersections[i][1]];
|
||||
Plane c = planes[intersections[i][2]];
|
||||
bool res = a.intersect_3(b, c, &point);
|
||||
ERR_FAIL_COND_V(!res, false);
|
||||
p_8points[i] = p_transform.xform(point);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
Array Projection::get_projection_planes(const Transform3D &p_transform) const {
|
||||
/** Fast Plane Extraction from combined modelview/projection matrices.
|
||||
* References:
|
||||
* https://web.archive.org/web/20011221205252/https://www.markmorley.com/opengl/frustumculling.html
|
||||
* https://web.archive.org/web/20061020020112/https://www2.ravensoft.com/users/ggribb/plane%20extraction.pdf
|
||||
*/
|
||||
|
||||
Array planes;
|
||||
planes.resize(6);
|
||||
|
||||
const real_t *matrix = (const real_t *)this->columns;
|
||||
|
||||
Plane new_plane;
|
||||
|
||||
///////--- Near Plane ---///////
|
||||
new_plane = Plane(matrix[3] + matrix[2],
|
||||
matrix[7] + matrix[6],
|
||||
matrix[11] + matrix[10],
|
||||
matrix[15] + matrix[14]);
|
||||
|
||||
new_plane.normal = -new_plane.normal;
|
||||
new_plane.normalize();
|
||||
|
||||
planes[0] = p_transform.xform(new_plane);
|
||||
|
||||
///////--- Far Plane ---///////
|
||||
new_plane = Plane(matrix[3] - matrix[2],
|
||||
matrix[7] - matrix[6],
|
||||
matrix[11] - matrix[10],
|
||||
matrix[15] - matrix[14]);
|
||||
|
||||
new_plane.normal = -new_plane.normal;
|
||||
new_plane.normalize();
|
||||
|
||||
planes[1] = p_transform.xform(new_plane);
|
||||
|
||||
///////--- Left Plane ---///////
|
||||
new_plane = Plane(matrix[3] + matrix[0],
|
||||
matrix[7] + matrix[4],
|
||||
matrix[11] + matrix[8],
|
||||
matrix[15] + matrix[12]);
|
||||
|
||||
new_plane.normal = -new_plane.normal;
|
||||
new_plane.normalize();
|
||||
|
||||
planes[2] = p_transform.xform(new_plane);
|
||||
|
||||
///////--- Top Plane ---///////
|
||||
new_plane = Plane(matrix[3] - matrix[1],
|
||||
matrix[7] - matrix[5],
|
||||
matrix[11] - matrix[9],
|
||||
matrix[15] - matrix[13]);
|
||||
|
||||
new_plane.normal = -new_plane.normal;
|
||||
new_plane.normalize();
|
||||
|
||||
planes[3] = p_transform.xform(new_plane);
|
||||
|
||||
///////--- Right Plane ---///////
|
||||
new_plane = Plane(matrix[3] - matrix[0],
|
||||
matrix[7] - matrix[4],
|
||||
matrix[11] - matrix[8],
|
||||
matrix[15] - matrix[12]);
|
||||
|
||||
new_plane.normal = -new_plane.normal;
|
||||
new_plane.normalize();
|
||||
|
||||
planes[4] = p_transform.xform(new_plane);
|
||||
|
||||
///////--- Bottom Plane ---///////
|
||||
new_plane = Plane(matrix[3] + matrix[1],
|
||||
matrix[7] + matrix[5],
|
||||
matrix[11] + matrix[9],
|
||||
matrix[15] + matrix[13]);
|
||||
|
||||
new_plane.normal = -new_plane.normal;
|
||||
new_plane.normalize();
|
||||
|
||||
planes[5] = p_transform.xform(new_plane);
|
||||
|
||||
return planes;
|
||||
}
|
||||
|
||||
Projection Projection::inverse() const {
|
||||
Projection cm = *this;
|
||||
cm.invert();
|
||||
return cm;
|
||||
}
|
||||
|
||||
void Projection::invert() {
|
||||
int i, j, k;
|
||||
int pvt_i[4], pvt_j[4]; /* Locations of pivot matrix */
|
||||
real_t pvt_val; /* Value of current pivot element */
|
||||
real_t hold; /* Temporary storage */
|
||||
real_t determinant = 1.0f;
|
||||
for (k = 0; k < 4; k++) {
|
||||
/** Locate k'th pivot element **/
|
||||
pvt_val = columns[k][k]; /** Initialize for search **/
|
||||
pvt_i[k] = k;
|
||||
pvt_j[k] = k;
|
||||
for (i = k; i < 4; i++) {
|
||||
for (j = k; j < 4; j++) {
|
||||
if (Math::abs(columns[i][j]) > Math::abs(pvt_val)) {
|
||||
pvt_i[k] = i;
|
||||
pvt_j[k] = j;
|
||||
pvt_val = columns[i][j];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** Product of pivots, gives determinant when finished **/
|
||||
determinant *= pvt_val;
|
||||
if (Math::is_zero_approx(determinant)) {
|
||||
return; /** Matrix is singular (zero determinant). **/
|
||||
}
|
||||
|
||||
/** "Interchange" rows (with sign change stuff) **/
|
||||
i = pvt_i[k];
|
||||
if (i != k) { /** If rows are different **/
|
||||
for (j = 0; j < 4; j++) {
|
||||
hold = -columns[k][j];
|
||||
columns[k][j] = columns[i][j];
|
||||
columns[i][j] = hold;
|
||||
}
|
||||
}
|
||||
|
||||
/** "Interchange" columns **/
|
||||
j = pvt_j[k];
|
||||
if (j != k) { /** If columns are different **/
|
||||
for (i = 0; i < 4; i++) {
|
||||
hold = -columns[i][k];
|
||||
columns[i][k] = columns[i][j];
|
||||
columns[i][j] = hold;
|
||||
}
|
||||
}
|
||||
|
||||
/** Divide column by minus pivot value **/
|
||||
for (i = 0; i < 4; i++) {
|
||||
if (i != k) {
|
||||
columns[i][k] /= (-pvt_val);
|
||||
}
|
||||
}
|
||||
|
||||
/** Reduce the matrix **/
|
||||
for (i = 0; i < 4; i++) {
|
||||
hold = columns[i][k];
|
||||
for (j = 0; j < 4; j++) {
|
||||
if (i != k && j != k) {
|
||||
columns[i][j] += hold * columns[k][j];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** Divide row by pivot **/
|
||||
for (j = 0; j < 4; j++) {
|
||||
if (j != k) {
|
||||
columns[k][j] /= pvt_val;
|
||||
}
|
||||
}
|
||||
|
||||
/** Replace pivot by reciprocal (at last we can touch it). **/
|
||||
columns[k][k] = 1.0 / pvt_val;
|
||||
}
|
||||
|
||||
/* That was most of the work, one final pass of row/column interchange */
|
||||
/* to finish */
|
||||
for (k = 4 - 2; k >= 0; k--) { /* Don't need to work with 1 by 1 corner*/
|
||||
i = pvt_j[k]; /* Rows to swap correspond to pivot COLUMN */
|
||||
if (i != k) { /* If rows are different */
|
||||
for (j = 0; j < 4; j++) {
|
||||
hold = columns[k][j];
|
||||
columns[k][j] = -columns[i][j];
|
||||
columns[i][j] = hold;
|
||||
}
|
||||
}
|
||||
|
||||
j = pvt_i[k]; /* Columns to swap correspond to pivot ROW */
|
||||
if (j != k) { /* If columns are different */
|
||||
for (i = 0; i < 4; i++) {
|
||||
hold = columns[i][k];
|
||||
columns[i][k] = -columns[i][j];
|
||||
columns[i][j] = hold;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Projection::flip_y() {
|
||||
for (int i = 0; i < 4; i++) {
|
||||
columns[1][i] = -columns[1][i];
|
||||
}
|
||||
}
|
||||
|
||||
Projection::Projection() {
|
||||
set_identity();
|
||||
}
|
||||
|
||||
Projection Projection::operator*(const Projection &p_matrix) const {
|
||||
Projection new_matrix;
|
||||
|
||||
for (int j = 0; j < 4; j++) {
|
||||
for (int i = 0; i < 4; i++) {
|
||||
real_t ab = 0;
|
||||
for (int k = 0; k < 4; k++) {
|
||||
ab += columns[k][i] * p_matrix.columns[j][k];
|
||||
}
|
||||
new_matrix.columns[j][i] = ab;
|
||||
}
|
||||
}
|
||||
|
||||
return new_matrix;
|
||||
}
|
||||
|
||||
void Projection::set_depth_correction(bool p_flip_y) {
|
||||
real_t *m = &columns[0][0];
|
||||
|
||||
m[0] = 1;
|
||||
m[1] = 0.0;
|
||||
m[2] = 0.0;
|
||||
m[3] = 0.0;
|
||||
m[4] = 0.0;
|
||||
m[5] = p_flip_y ? -1 : 1;
|
||||
m[6] = 0.0;
|
||||
m[7] = 0.0;
|
||||
m[8] = 0.0;
|
||||
m[9] = 0.0;
|
||||
m[10] = 0.5;
|
||||
m[11] = 0.0;
|
||||
m[12] = 0.0;
|
||||
m[13] = 0.0;
|
||||
m[14] = 0.5;
|
||||
m[15] = 1.0;
|
||||
}
|
||||
|
||||
void Projection::set_light_bias() {
|
||||
real_t *m = &columns[0][0];
|
||||
|
||||
m[0] = 0.5;
|
||||
m[1] = 0.0;
|
||||
m[2] = 0.0;
|
||||
m[3] = 0.0;
|
||||
m[4] = 0.0;
|
||||
m[5] = 0.5;
|
||||
m[6] = 0.0;
|
||||
m[7] = 0.0;
|
||||
m[8] = 0.0;
|
||||
m[9] = 0.0;
|
||||
m[10] = 0.5;
|
||||
m[11] = 0.0;
|
||||
m[12] = 0.5;
|
||||
m[13] = 0.5;
|
||||
m[14] = 0.5;
|
||||
m[15] = 1.0;
|
||||
}
|
||||
|
||||
void Projection::set_light_atlas_rect(const Rect2 &p_rect) {
|
||||
real_t *m = &columns[0][0];
|
||||
|
||||
m[0] = p_rect.size.width;
|
||||
m[1] = 0.0;
|
||||
m[2] = 0.0;
|
||||
m[3] = 0.0;
|
||||
m[4] = 0.0;
|
||||
m[5] = p_rect.size.height;
|
||||
m[6] = 0.0;
|
||||
m[7] = 0.0;
|
||||
m[8] = 0.0;
|
||||
m[9] = 0.0;
|
||||
m[10] = 1.0;
|
||||
m[11] = 0.0;
|
||||
m[12] = p_rect.position.x;
|
||||
m[13] = p_rect.position.y;
|
||||
m[14] = 0.0;
|
||||
m[15] = 1.0;
|
||||
}
|
||||
|
||||
Projection::operator String() const {
|
||||
String str;
|
||||
for (int i = 0; i < 4; i++) {
|
||||
for (int j = 0; j < 4; j++) {
|
||||
str = str + String((j > 0) ? ", " : "\n") + rtos(columns[i][j]);
|
||||
}
|
||||
}
|
||||
|
||||
return str;
|
||||
}
|
||||
|
||||
real_t Projection::get_aspect() const {
|
||||
Vector2 vp_he = get_viewport_half_extents();
|
||||
return vp_he.x / vp_he.y;
|
||||
}
|
||||
|
||||
int Projection::get_pixels_per_meter(int p_for_pixel_width) const {
|
||||
Vector3 result = xform(Vector3(1, 0, -1));
|
||||
|
||||
return int((result.x * 0.5 + 0.5) * p_for_pixel_width);
|
||||
}
|
||||
|
||||
bool Projection::is_orthogonal() const {
|
||||
return columns[3][3] == 1.0;
|
||||
}
|
||||
|
||||
real_t Projection::get_fov() const {
|
||||
const real_t *matrix = (const real_t *)this->columns;
|
||||
|
||||
Plane right_plane = Plane(matrix[3] - matrix[0],
|
||||
matrix[7] - matrix[4],
|
||||
matrix[11] - matrix[8],
|
||||
-matrix[15] + matrix[12]);
|
||||
right_plane.normalize();
|
||||
|
||||
if ((matrix[8] == 0) && (matrix[9] == 0)) {
|
||||
return Math::rad_to_deg(Math::acos(Math::abs(right_plane.normal.x))) * 2.0;
|
||||
} else {
|
||||
// our frustum is asymmetrical need to calculate the left planes angle separately..
|
||||
Plane left_plane = Plane(matrix[3] + matrix[0],
|
||||
matrix[7] + matrix[4],
|
||||
matrix[11] + matrix[8],
|
||||
matrix[15] + matrix[12]);
|
||||
left_plane.normalize();
|
||||
|
||||
return Math::rad_to_deg(Math::acos(Math::abs(left_plane.normal.x))) + Math::rad_to_deg(Math::acos(Math::abs(right_plane.normal.x)));
|
||||
}
|
||||
}
|
||||
|
||||
float Projection::get_lod_multiplier() const {
|
||||
if (is_orthogonal()) {
|
||||
return get_viewport_half_extents().x;
|
||||
} else {
|
||||
float zn = get_z_near();
|
||||
float width = get_viewport_half_extents().x * 2.0;
|
||||
return 1.0 / (zn / width);
|
||||
}
|
||||
|
||||
// Usage is lod_size / (lod_distance * multiplier) < threshold
|
||||
}
|
||||
|
||||
void Projection::make_scale(const Vector3 &p_scale) {
|
||||
set_identity();
|
||||
columns[0][0] = p_scale.x;
|
||||
columns[1][1] = p_scale.y;
|
||||
columns[2][2] = p_scale.z;
|
||||
}
|
||||
|
||||
void Projection::scale_translate_to_fit(const AABB &p_aabb) {
|
||||
Vector3 min = p_aabb.position;
|
||||
Vector3 max = p_aabb.position + p_aabb.size;
|
||||
|
||||
columns[0][0] = 2 / (max.x - min.x);
|
||||
columns[1][0] = 0;
|
||||
columns[2][0] = 0;
|
||||
columns[3][0] = -(max.x + min.x) / (max.x - min.x);
|
||||
|
||||
columns[0][1] = 0;
|
||||
columns[1][1] = 2 / (max.y - min.y);
|
||||
columns[2][1] = 0;
|
||||
columns[3][1] = -(max.y + min.y) / (max.y - min.y);
|
||||
|
||||
columns[0][2] = 0;
|
||||
columns[1][2] = 0;
|
||||
columns[2][2] = 2 / (max.z - min.z);
|
||||
columns[3][2] = -(max.z + min.z) / (max.z - min.z);
|
||||
|
||||
columns[0][3] = 0;
|
||||
columns[1][3] = 0;
|
||||
columns[2][3] = 0;
|
||||
columns[3][3] = 1;
|
||||
}
|
||||
|
||||
void Projection::add_jitter_offset(const Vector2 &p_offset) {
|
||||
columns[3][0] += p_offset.x;
|
||||
columns[3][1] += p_offset.y;
|
||||
}
|
||||
|
||||
Projection::operator Transform3D() const {
|
||||
Transform3D tr;
|
||||
const real_t *m = &columns[0][0];
|
||||
|
||||
tr.basis.rows[0][0] = m[0];
|
||||
tr.basis.rows[1][0] = m[1];
|
||||
tr.basis.rows[2][0] = m[2];
|
||||
|
||||
tr.basis.rows[0][1] = m[4];
|
||||
tr.basis.rows[1][1] = m[5];
|
||||
tr.basis.rows[2][1] = m[6];
|
||||
|
||||
tr.basis.rows[0][2] = m[8];
|
||||
tr.basis.rows[1][2] = m[9];
|
||||
tr.basis.rows[2][2] = m[10];
|
||||
|
||||
tr.origin.x = m[12];
|
||||
tr.origin.y = m[13];
|
||||
tr.origin.z = m[14];
|
||||
|
||||
return tr;
|
||||
}
|
||||
|
||||
Projection::Projection(const Vector4 &p_x, const Vector4 &p_y, const Vector4 &p_z, const Vector4 &p_w) {
|
||||
columns[0] = p_x;
|
||||
columns[1] = p_y;
|
||||
columns[2] = p_z;
|
||||
columns[3] = p_w;
|
||||
}
|
||||
|
||||
Projection::Projection(const Transform3D &p_transform) {
|
||||
const Transform3D &tr = p_transform;
|
||||
real_t *m = &columns[0][0];
|
||||
|
||||
m[0] = tr.basis.rows[0][0];
|
||||
m[1] = tr.basis.rows[1][0];
|
||||
m[2] = tr.basis.rows[2][0];
|
||||
m[3] = 0.0;
|
||||
m[4] = tr.basis.rows[0][1];
|
||||
m[5] = tr.basis.rows[1][1];
|
||||
m[6] = tr.basis.rows[2][1];
|
||||
m[7] = 0.0;
|
||||
m[8] = tr.basis.rows[0][2];
|
||||
m[9] = tr.basis.rows[1][2];
|
||||
m[10] = tr.basis.rows[2][2];
|
||||
m[11] = 0.0;
|
||||
m[12] = tr.origin.x;
|
||||
m[13] = tr.origin.y;
|
||||
m[14] = tr.origin.z;
|
||||
m[15] = 1.0;
|
||||
}
|
||||
|
||||
Projection::~Projection() {
|
||||
}
|
||||
|
||||
} // namespace godot
|
353
lib/godot-cpp/src/variant/quaternion.cpp
Normal file
353
lib/godot-cpp/src/variant/quaternion.cpp
Normal file
@@ -0,0 +1,353 @@
|
||||
/**************************************************************************/
|
||||
/* quaternion.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 <godot_cpp/variant/quaternion.hpp>
|
||||
|
||||
#include <godot_cpp/variant/basis.hpp>
|
||||
#include <godot_cpp/variant/string.hpp>
|
||||
|
||||
namespace godot {
|
||||
|
||||
real_t Quaternion::angle_to(const Quaternion &p_to) const {
|
||||
real_t d = dot(p_to);
|
||||
return Math::acos(CLAMP(d * d * 2 - 1, -1, 1));
|
||||
}
|
||||
|
||||
// get_euler_xyz returns a vector containing the Euler angles in the format
|
||||
// (ax,ay,az), where ax is the angle of rotation around x axis,
|
||||
// and similar for other axes.
|
||||
// This implementation uses XYZ convention (Z is the first rotation).
|
||||
Vector3 Quaternion::get_euler_xyz() const {
|
||||
Basis m(*this);
|
||||
return m.get_euler(EULER_ORDER_XYZ);
|
||||
}
|
||||
|
||||
// get_euler_yxz returns a vector containing the Euler angles in the format
|
||||
// (ax,ay,az), where ax is the angle of rotation around x axis,
|
||||
// and similar for other axes.
|
||||
// This implementation uses YXZ convention (Z is the first rotation).
|
||||
Vector3 Quaternion::get_euler_yxz() const {
|
||||
#ifdef MATH_CHECKS
|
||||
ERR_FAIL_COND_V_MSG(!is_normalized(), Vector3(0, 0, 0), "The quaternion must be normalized.");
|
||||
#endif
|
||||
Basis m(*this);
|
||||
return m.get_euler(EULER_ORDER_YXZ);
|
||||
}
|
||||
|
||||
void Quaternion::operator*=(const Quaternion &p_q) {
|
||||
real_t xx = w * p_q.x + x * p_q.w + y * p_q.z - z * p_q.y;
|
||||
real_t yy = w * p_q.y + y * p_q.w + z * p_q.x - x * p_q.z;
|
||||
real_t zz = w * p_q.z + z * p_q.w + x * p_q.y - y * p_q.x;
|
||||
w = w * p_q.w - x * p_q.x - y * p_q.y - z * p_q.z;
|
||||
x = xx;
|
||||
y = yy;
|
||||
z = zz;
|
||||
}
|
||||
|
||||
Quaternion Quaternion::operator*(const Quaternion &p_q) const {
|
||||
Quaternion r = *this;
|
||||
r *= p_q;
|
||||
return r;
|
||||
}
|
||||
|
||||
bool Quaternion::is_equal_approx(const Quaternion &p_quaternion) const {
|
||||
return Math::is_equal_approx(x, p_quaternion.x) && Math::is_equal_approx(y, p_quaternion.y) && Math::is_equal_approx(z, p_quaternion.z) && Math::is_equal_approx(w, p_quaternion.w);
|
||||
}
|
||||
|
||||
real_t Quaternion::length() const {
|
||||
return Math::sqrt(length_squared());
|
||||
}
|
||||
|
||||
void Quaternion::normalize() {
|
||||
*this /= length();
|
||||
}
|
||||
|
||||
Quaternion Quaternion::normalized() const {
|
||||
return *this / length();
|
||||
}
|
||||
|
||||
bool Quaternion::is_normalized() const {
|
||||
return Math::is_equal_approx(length_squared(), 1, (real_t)UNIT_EPSILON); //use less epsilon
|
||||
}
|
||||
|
||||
Quaternion Quaternion::inverse() const {
|
||||
#ifdef MATH_CHECKS
|
||||
ERR_FAIL_COND_V_MSG(!is_normalized(), Quaternion(), "The quaternion must be normalized.");
|
||||
#endif
|
||||
return Quaternion(-x, -y, -z, w);
|
||||
}
|
||||
|
||||
Quaternion Quaternion::log() const {
|
||||
Quaternion src = *this;
|
||||
Vector3 src_v = src.get_axis() * src.get_angle();
|
||||
return Quaternion(src_v.x, src_v.y, src_v.z, 0);
|
||||
}
|
||||
|
||||
Quaternion Quaternion::exp() const {
|
||||
Quaternion src = *this;
|
||||
Vector3 src_v = Vector3(src.x, src.y, src.z);
|
||||
real_t theta = src_v.length();
|
||||
src_v = src_v.normalized();
|
||||
if (theta < CMP_EPSILON || !src_v.is_normalized()) {
|
||||
return Quaternion(0, 0, 0, 1);
|
||||
}
|
||||
return Quaternion(src_v, theta);
|
||||
}
|
||||
|
||||
Quaternion Quaternion::slerp(const Quaternion &p_to, const real_t &p_weight) const {
|
||||
#ifdef MATH_CHECKS
|
||||
ERR_FAIL_COND_V_MSG(!is_normalized(), Quaternion(), "The start quaternion must be normalized.");
|
||||
ERR_FAIL_COND_V_MSG(!p_to.is_normalized(), Quaternion(), "The end quaternion must be normalized.");
|
||||
#endif
|
||||
Quaternion to1;
|
||||
real_t omega, cosom, sinom, scale0, scale1;
|
||||
|
||||
// calc cosine
|
||||
cosom = dot(p_to);
|
||||
|
||||
// adjust signs (if necessary)
|
||||
if (cosom < 0.0f) {
|
||||
cosom = -cosom;
|
||||
to1 = -p_to;
|
||||
} else {
|
||||
to1 = p_to;
|
||||
}
|
||||
|
||||
// calculate coefficients
|
||||
|
||||
if ((1.0f - cosom) > (real_t)CMP_EPSILON) {
|
||||
// standard case (slerp)
|
||||
omega = Math::acos(cosom);
|
||||
sinom = Math::sin(omega);
|
||||
scale0 = Math::sin((1.0 - p_weight) * omega) / sinom;
|
||||
scale1 = Math::sin(p_weight * omega) / sinom;
|
||||
} else {
|
||||
// "from" and "to" quaternions are very close
|
||||
// ... so we can do a linear interpolation
|
||||
scale0 = 1.0f - p_weight;
|
||||
scale1 = p_weight;
|
||||
}
|
||||
// calculate final values
|
||||
return Quaternion(
|
||||
scale0 * x + scale1 * to1.x,
|
||||
scale0 * y + scale1 * to1.y,
|
||||
scale0 * z + scale1 * to1.z,
|
||||
scale0 * w + scale1 * to1.w);
|
||||
}
|
||||
|
||||
Quaternion Quaternion::slerpni(const Quaternion &p_to, const real_t &p_weight) const {
|
||||
#ifdef MATH_CHECKS
|
||||
ERR_FAIL_COND_V_MSG(!is_normalized(), Quaternion(), "The start quaternion must be normalized.");
|
||||
ERR_FAIL_COND_V_MSG(!p_to.is_normalized(), Quaternion(), "The end quaternion must be normalized.");
|
||||
#endif
|
||||
const Quaternion &from = *this;
|
||||
|
||||
real_t dot = from.dot(p_to);
|
||||
|
||||
if (Math::absf(dot) > 0.9999f) {
|
||||
return from;
|
||||
}
|
||||
|
||||
real_t theta = Math::acos(dot),
|
||||
sinT = 1.0f / Math::sin(theta),
|
||||
newFactor = Math::sin(p_weight * theta) * sinT,
|
||||
invFactor = Math::sin((1.0f - p_weight) * theta) * sinT;
|
||||
|
||||
return Quaternion(invFactor * from.x + newFactor * p_to.x,
|
||||
invFactor * from.y + newFactor * p_to.y,
|
||||
invFactor * from.z + newFactor * p_to.z,
|
||||
invFactor * from.w + newFactor * p_to.w);
|
||||
}
|
||||
|
||||
Quaternion Quaternion::spherical_cubic_interpolate(const Quaternion &p_b, const Quaternion &p_pre_a, const Quaternion &p_post_b, const real_t &p_weight) const {
|
||||
#ifdef MATH_CHECKS
|
||||
ERR_FAIL_COND_V_MSG(!is_normalized(), Quaternion(), "The start quaternion must be normalized.");
|
||||
ERR_FAIL_COND_V_MSG(!p_b.is_normalized(), Quaternion(), "The end quaternion must be normalized.");
|
||||
#endif
|
||||
Quaternion from_q = *this;
|
||||
Quaternion pre_q = p_pre_a;
|
||||
Quaternion to_q = p_b;
|
||||
Quaternion post_q = p_post_b;
|
||||
|
||||
// Align flip phases.
|
||||
from_q = Basis(from_q).get_rotation_quaternion();
|
||||
pre_q = Basis(pre_q).get_rotation_quaternion();
|
||||
to_q = Basis(to_q).get_rotation_quaternion();
|
||||
post_q = Basis(post_q).get_rotation_quaternion();
|
||||
|
||||
// Flip quaternions to shortest path if necessary.
|
||||
bool flip1 = Math::sign(from_q.dot(pre_q));
|
||||
pre_q = flip1 ? -pre_q : pre_q;
|
||||
bool flip2 = Math::sign(from_q.dot(to_q));
|
||||
to_q = flip2 ? -to_q : to_q;
|
||||
bool flip3 = flip2 ? to_q.dot(post_q) <= 0 : Math::sign(to_q.dot(post_q));
|
||||
post_q = flip3 ? -post_q : post_q;
|
||||
|
||||
// Calc by Expmap in from_q space.
|
||||
Quaternion ln_from = Quaternion(0, 0, 0, 0);
|
||||
Quaternion ln_to = (from_q.inverse() * to_q).log();
|
||||
Quaternion ln_pre = (from_q.inverse() * pre_q).log();
|
||||
Quaternion ln_post = (from_q.inverse() * post_q).log();
|
||||
Quaternion ln = Quaternion(0, 0, 0, 0);
|
||||
ln.x = Math::cubic_interpolate(ln_from.x, ln_to.x, ln_pre.x, ln_post.x, p_weight);
|
||||
ln.y = Math::cubic_interpolate(ln_from.y, ln_to.y, ln_pre.y, ln_post.y, p_weight);
|
||||
ln.z = Math::cubic_interpolate(ln_from.z, ln_to.z, ln_pre.z, ln_post.z, p_weight);
|
||||
Quaternion q1 = from_q * ln.exp();
|
||||
|
||||
// Calc by Expmap in to_q space.
|
||||
ln_from = (to_q.inverse() * from_q).log();
|
||||
ln_to = Quaternion(0, 0, 0, 0);
|
||||
ln_pre = (to_q.inverse() * pre_q).log();
|
||||
ln_post = (to_q.inverse() * post_q).log();
|
||||
ln = Quaternion(0, 0, 0, 0);
|
||||
ln.x = Math::cubic_interpolate(ln_from.x, ln_to.x, ln_pre.x, ln_post.x, p_weight);
|
||||
ln.y = Math::cubic_interpolate(ln_from.y, ln_to.y, ln_pre.y, ln_post.y, p_weight);
|
||||
ln.z = Math::cubic_interpolate(ln_from.z, ln_to.z, ln_pre.z, ln_post.z, p_weight);
|
||||
Quaternion q2 = to_q * ln.exp();
|
||||
|
||||
// To cancel error made by Expmap ambiguity, do blends.
|
||||
return q1.slerp(q2, p_weight);
|
||||
}
|
||||
|
||||
Quaternion Quaternion::spherical_cubic_interpolate_in_time(const Quaternion &p_b, const Quaternion &p_pre_a, const Quaternion &p_post_b, const real_t &p_weight,
|
||||
const real_t &p_b_t, const real_t &p_pre_a_t, const real_t &p_post_b_t) const {
|
||||
#ifdef MATH_CHECKS
|
||||
ERR_FAIL_COND_V_MSG(!is_normalized(), Quaternion(), "The start quaternion must be normalized.");
|
||||
ERR_FAIL_COND_V_MSG(!p_b.is_normalized(), Quaternion(), "The end quaternion must be normalized.");
|
||||
#endif
|
||||
Quaternion from_q = *this;
|
||||
Quaternion pre_q = p_pre_a;
|
||||
Quaternion to_q = p_b;
|
||||
Quaternion post_q = p_post_b;
|
||||
|
||||
// Align flip phases.
|
||||
from_q = Basis(from_q).get_rotation_quaternion();
|
||||
pre_q = Basis(pre_q).get_rotation_quaternion();
|
||||
to_q = Basis(to_q).get_rotation_quaternion();
|
||||
post_q = Basis(post_q).get_rotation_quaternion();
|
||||
|
||||
// Flip quaternions to shortest path if necessary.
|
||||
bool flip1 = Math::sign(from_q.dot(pre_q));
|
||||
pre_q = flip1 ? -pre_q : pre_q;
|
||||
bool flip2 = Math::sign(from_q.dot(to_q));
|
||||
to_q = flip2 ? -to_q : to_q;
|
||||
bool flip3 = flip2 ? to_q.dot(post_q) <= 0 : Math::sign(to_q.dot(post_q));
|
||||
post_q = flip3 ? -post_q : post_q;
|
||||
|
||||
// Calc by Expmap in from_q space.
|
||||
Quaternion ln_from = Quaternion(0, 0, 0, 0);
|
||||
Quaternion ln_to = (from_q.inverse() * to_q).log();
|
||||
Quaternion ln_pre = (from_q.inverse() * pre_q).log();
|
||||
Quaternion ln_post = (from_q.inverse() * post_q).log();
|
||||
Quaternion ln = Quaternion(0, 0, 0, 0);
|
||||
ln.x = Math::cubic_interpolate_in_time(ln_from.x, ln_to.x, ln_pre.x, ln_post.x, p_weight, p_b_t, p_pre_a_t, p_post_b_t);
|
||||
ln.y = Math::cubic_interpolate_in_time(ln_from.y, ln_to.y, ln_pre.y, ln_post.y, p_weight, p_b_t, p_pre_a_t, p_post_b_t);
|
||||
ln.z = Math::cubic_interpolate_in_time(ln_from.z, ln_to.z, ln_pre.z, ln_post.z, p_weight, p_b_t, p_pre_a_t, p_post_b_t);
|
||||
Quaternion q1 = from_q * ln.exp();
|
||||
|
||||
// Calc by Expmap in to_q space.
|
||||
ln_from = (to_q.inverse() * from_q).log();
|
||||
ln_to = Quaternion(0, 0, 0, 0);
|
||||
ln_pre = (to_q.inverse() * pre_q).log();
|
||||
ln_post = (to_q.inverse() * post_q).log();
|
||||
ln = Quaternion(0, 0, 0, 0);
|
||||
ln.x = Math::cubic_interpolate_in_time(ln_from.x, ln_to.x, ln_pre.x, ln_post.x, p_weight, p_b_t, p_pre_a_t, p_post_b_t);
|
||||
ln.y = Math::cubic_interpolate_in_time(ln_from.y, ln_to.y, ln_pre.y, ln_post.y, p_weight, p_b_t, p_pre_a_t, p_post_b_t);
|
||||
ln.z = Math::cubic_interpolate_in_time(ln_from.z, ln_to.z, ln_pre.z, ln_post.z, p_weight, p_b_t, p_pre_a_t, p_post_b_t);
|
||||
Quaternion q2 = to_q * ln.exp();
|
||||
|
||||
// To cancel error made by Expmap ambiguity, do blends.
|
||||
return q1.slerp(q2, p_weight);
|
||||
}
|
||||
|
||||
Quaternion::operator String() const {
|
||||
return "(" + String::num_real(x, false) + ", " + String::num_real(y, false) + ", " + String::num_real(z, false) + ", " + String::num_real(w, false) + ")";
|
||||
}
|
||||
|
||||
Vector3 Quaternion::get_axis() const {
|
||||
if (Math::abs(w) > 1 - CMP_EPSILON) {
|
||||
return Vector3(x, y, z);
|
||||
}
|
||||
real_t r = ((real_t)1) / Math::sqrt(1 - w * w);
|
||||
return Vector3(x * r, y * r, z * r);
|
||||
}
|
||||
|
||||
real_t Quaternion::get_angle() const {
|
||||
return 2 * Math::acos(w);
|
||||
}
|
||||
|
||||
Quaternion::Quaternion(const Vector3 &p_axis, real_t p_angle) {
|
||||
#ifdef MATH_CHECKS
|
||||
ERR_FAIL_COND_MSG(!p_axis.is_normalized(), "The axis Vector3 must be normalized.");
|
||||
#endif
|
||||
real_t d = p_axis.length();
|
||||
if (d == 0) {
|
||||
x = 0;
|
||||
y = 0;
|
||||
z = 0;
|
||||
w = 0;
|
||||
} else {
|
||||
real_t sin_angle = Math::sin(p_angle * 0.5f);
|
||||
real_t cos_angle = Math::cos(p_angle * 0.5f);
|
||||
real_t s = sin_angle / d;
|
||||
x = p_axis.x * s;
|
||||
y = p_axis.y * s;
|
||||
z = p_axis.z * s;
|
||||
w = cos_angle;
|
||||
}
|
||||
}
|
||||
|
||||
// Euler constructor expects a vector containing the Euler angles in the format
|
||||
// (ax, ay, az), where ax is the angle of rotation around x axis,
|
||||
// and similar for other axes.
|
||||
// This implementation uses YXZ convention (Z is the first rotation).
|
||||
Quaternion::Quaternion(const Vector3 &p_euler) {
|
||||
real_t half_a1 = p_euler.y * 0.5f;
|
||||
real_t half_a2 = p_euler.x * 0.5f;
|
||||
real_t half_a3 = p_euler.z * 0.5f;
|
||||
|
||||
// R = Y(a1).X(a2).Z(a3) convention for Euler angles.
|
||||
// Conversion to quaternion as listed in https://ntrs.nasa.gov/archive/nasa/casi.ntrs.nasa.gov/19770024290.pdf (page A-6)
|
||||
// a3 is the angle of the first rotation, following the notation in this reference.
|
||||
|
||||
real_t cos_a1 = Math::cos(half_a1);
|
||||
real_t sin_a1 = Math::sin(half_a1);
|
||||
real_t cos_a2 = Math::cos(half_a2);
|
||||
real_t sin_a2 = Math::sin(half_a2);
|
||||
real_t cos_a3 = Math::cos(half_a3);
|
||||
real_t sin_a3 = Math::sin(half_a3);
|
||||
|
||||
x = sin_a1 * cos_a2 * sin_a3 + cos_a1 * sin_a2 * cos_a3;
|
||||
y = sin_a1 * cos_a2 * cos_a3 - cos_a1 * sin_a2 * sin_a3;
|
||||
z = -sin_a1 * sin_a2 * cos_a3 + cos_a1 * cos_a2 * sin_a3;
|
||||
w = sin_a1 * sin_a2 * sin_a3 + cos_a1 * cos_a2 * cos_a3;
|
||||
}
|
||||
|
||||
} // namespace godot
|
291
lib/godot-cpp/src/variant/rect2.cpp
Normal file
291
lib/godot-cpp/src/variant/rect2.cpp
Normal file
@@ -0,0 +1,291 @@
|
||||
/**************************************************************************/
|
||||
/* rect2.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 <godot_cpp/variant/rect2.hpp>
|
||||
|
||||
#include <godot_cpp/variant/rect2i.hpp>
|
||||
#include <godot_cpp/variant/string.hpp>
|
||||
#include <godot_cpp/variant/transform2d.hpp>
|
||||
|
||||
namespace godot {
|
||||
|
||||
bool Rect2::is_equal_approx(const Rect2 &p_rect) const {
|
||||
return position.is_equal_approx(p_rect.position) && size.is_equal_approx(p_rect.size);
|
||||
}
|
||||
|
||||
bool Rect2::intersects_segment(const Point2 &p_from, const Point2 &p_to, Point2 *r_pos, Point2 *r_normal) const {
|
||||
#ifdef MATH_CHECKS
|
||||
if (unlikely(size.x < 0 || size.y < 0)) {
|
||||
ERR_PRINT("Rect2 size is negative, this is not supported. Use Rect2.abs() to get a Rect2 with a positive size.");
|
||||
}
|
||||
#endif
|
||||
real_t min = 0, max = 1;
|
||||
int axis = 0;
|
||||
real_t sign = 0;
|
||||
|
||||
for (int i = 0; i < 2; i++) {
|
||||
real_t seg_from = p_from[i];
|
||||
real_t seg_to = p_to[i];
|
||||
real_t box_begin = position[i];
|
||||
real_t box_end = box_begin + size[i];
|
||||
real_t cmin, cmax;
|
||||
real_t csign;
|
||||
|
||||
if (seg_from < seg_to) {
|
||||
if (seg_from > box_end || seg_to < box_begin) {
|
||||
return false;
|
||||
}
|
||||
real_t length = seg_to - seg_from;
|
||||
cmin = (seg_from < box_begin) ? ((box_begin - seg_from) / length) : 0;
|
||||
cmax = (seg_to > box_end) ? ((box_end - seg_from) / length) : 1;
|
||||
csign = -1.0;
|
||||
|
||||
} else {
|
||||
if (seg_to > box_end || seg_from < box_begin) {
|
||||
return false;
|
||||
}
|
||||
real_t length = seg_to - seg_from;
|
||||
cmin = (seg_from > box_end) ? (box_end - seg_from) / length : 0;
|
||||
cmax = (seg_to < box_begin) ? (box_begin - seg_from) / length : 1;
|
||||
csign = 1.0;
|
||||
}
|
||||
|
||||
if (cmin > min) {
|
||||
min = cmin;
|
||||
axis = i;
|
||||
sign = csign;
|
||||
}
|
||||
if (cmax < max) {
|
||||
max = cmax;
|
||||
}
|
||||
if (max < min) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
Vector2 rel = p_to - p_from;
|
||||
|
||||
if (r_normal) {
|
||||
Vector2 normal;
|
||||
normal[axis] = sign;
|
||||
*r_normal = normal;
|
||||
}
|
||||
|
||||
if (r_pos) {
|
||||
*r_pos = p_from + rel * min;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Rect2::intersects_transformed(const Transform2D &p_xform, const Rect2 &p_rect) const {
|
||||
#ifdef MATH_CHECKS
|
||||
if (unlikely(size.x < 0 || size.y < 0 || p_rect.size.x < 0 || p_rect.size.y < 0)) {
|
||||
ERR_PRINT("Rect2 size is negative, this is not supported. Use Rect2.abs() to get a Rect2 with a positive size.");
|
||||
}
|
||||
#endif
|
||||
//SAT intersection between local and transformed rect2
|
||||
|
||||
Vector2 xf_points[4] = {
|
||||
p_xform.xform(p_rect.position),
|
||||
p_xform.xform(Vector2(p_rect.position.x + p_rect.size.x, p_rect.position.y)),
|
||||
p_xform.xform(Vector2(p_rect.position.x, p_rect.position.y + p_rect.size.y)),
|
||||
p_xform.xform(Vector2(p_rect.position.x + p_rect.size.x, p_rect.position.y + p_rect.size.y)),
|
||||
};
|
||||
|
||||
real_t low_limit;
|
||||
|
||||
//base rect2 first (faster)
|
||||
|
||||
if (xf_points[0].y > position.y) {
|
||||
goto next1;
|
||||
}
|
||||
if (xf_points[1].y > position.y) {
|
||||
goto next1;
|
||||
}
|
||||
if (xf_points[2].y > position.y) {
|
||||
goto next1;
|
||||
}
|
||||
if (xf_points[3].y > position.y) {
|
||||
goto next1;
|
||||
}
|
||||
|
||||
return false;
|
||||
|
||||
next1:
|
||||
|
||||
low_limit = position.y + size.y;
|
||||
|
||||
if (xf_points[0].y < low_limit) {
|
||||
goto next2;
|
||||
}
|
||||
if (xf_points[1].y < low_limit) {
|
||||
goto next2;
|
||||
}
|
||||
if (xf_points[2].y < low_limit) {
|
||||
goto next2;
|
||||
}
|
||||
if (xf_points[3].y < low_limit) {
|
||||
goto next2;
|
||||
}
|
||||
|
||||
return false;
|
||||
|
||||
next2:
|
||||
|
||||
if (xf_points[0].x > position.x) {
|
||||
goto next3;
|
||||
}
|
||||
if (xf_points[1].x > position.x) {
|
||||
goto next3;
|
||||
}
|
||||
if (xf_points[2].x > position.x) {
|
||||
goto next3;
|
||||
}
|
||||
if (xf_points[3].x > position.x) {
|
||||
goto next3;
|
||||
}
|
||||
|
||||
return false;
|
||||
|
||||
next3:
|
||||
|
||||
low_limit = position.x + size.x;
|
||||
|
||||
if (xf_points[0].x < low_limit) {
|
||||
goto next4;
|
||||
}
|
||||
if (xf_points[1].x < low_limit) {
|
||||
goto next4;
|
||||
}
|
||||
if (xf_points[2].x < low_limit) {
|
||||
goto next4;
|
||||
}
|
||||
if (xf_points[3].x < low_limit) {
|
||||
goto next4;
|
||||
}
|
||||
|
||||
return false;
|
||||
|
||||
next4:
|
||||
|
||||
Vector2 xf_points2[4] = {
|
||||
position,
|
||||
Vector2(position.x + size.x, position.y),
|
||||
Vector2(position.x, position.y + size.y),
|
||||
Vector2(position.x + size.x, position.y + size.y),
|
||||
};
|
||||
|
||||
real_t maxa = p_xform.columns[0].dot(xf_points2[0]);
|
||||
real_t mina = maxa;
|
||||
|
||||
real_t dp = p_xform.columns[0].dot(xf_points2[1]);
|
||||
maxa = Math::max(dp, maxa);
|
||||
mina = Math::min(dp, mina);
|
||||
|
||||
dp = p_xform.columns[0].dot(xf_points2[2]);
|
||||
maxa = Math::max(dp, maxa);
|
||||
mina = Math::min(dp, mina);
|
||||
|
||||
dp = p_xform.columns[0].dot(xf_points2[3]);
|
||||
maxa = Math::max(dp, maxa);
|
||||
mina = Math::min(dp, mina);
|
||||
|
||||
real_t maxb = p_xform.columns[0].dot(xf_points[0]);
|
||||
real_t minb = maxb;
|
||||
|
||||
dp = p_xform.columns[0].dot(xf_points[1]);
|
||||
maxb = Math::max(dp, maxb);
|
||||
minb = Math::min(dp, minb);
|
||||
|
||||
dp = p_xform.columns[0].dot(xf_points[2]);
|
||||
maxb = Math::max(dp, maxb);
|
||||
minb = Math::min(dp, minb);
|
||||
|
||||
dp = p_xform.columns[0].dot(xf_points[3]);
|
||||
maxb = Math::max(dp, maxb);
|
||||
minb = Math::min(dp, minb);
|
||||
|
||||
if (mina > maxb) {
|
||||
return false;
|
||||
}
|
||||
if (minb > maxa) {
|
||||
return false;
|
||||
}
|
||||
|
||||
maxa = p_xform.columns[1].dot(xf_points2[0]);
|
||||
mina = maxa;
|
||||
|
||||
dp = p_xform.columns[1].dot(xf_points2[1]);
|
||||
maxa = Math::max(dp, maxa);
|
||||
mina = Math::min(dp, mina);
|
||||
|
||||
dp = p_xform.columns[1].dot(xf_points2[2]);
|
||||
maxa = Math::max(dp, maxa);
|
||||
mina = Math::min(dp, mina);
|
||||
|
||||
dp = p_xform.columns[1].dot(xf_points2[3]);
|
||||
maxa = Math::max(dp, maxa);
|
||||
mina = Math::min(dp, mina);
|
||||
|
||||
maxb = p_xform.columns[1].dot(xf_points[0]);
|
||||
minb = maxb;
|
||||
|
||||
dp = p_xform.columns[1].dot(xf_points[1]);
|
||||
maxb = Math::max(dp, maxb);
|
||||
minb = Math::min(dp, minb);
|
||||
|
||||
dp = p_xform.columns[1].dot(xf_points[2]);
|
||||
maxb = Math::max(dp, maxb);
|
||||
minb = Math::min(dp, minb);
|
||||
|
||||
dp = p_xform.columns[1].dot(xf_points[3]);
|
||||
maxb = Math::max(dp, maxb);
|
||||
minb = Math::min(dp, minb);
|
||||
|
||||
if (mina > maxb) {
|
||||
return false;
|
||||
}
|
||||
if (minb > maxa) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
Rect2::operator String() const {
|
||||
return "[P: " + position.operator String() + ", S: " + size + "]";
|
||||
}
|
||||
|
||||
Rect2::operator Rect2i() const {
|
||||
return Rect2i(position, size);
|
||||
}
|
||||
|
||||
} // namespace godot
|
46
lib/godot-cpp/src/variant/rect2i.cpp
Normal file
46
lib/godot-cpp/src/variant/rect2i.cpp
Normal file
@@ -0,0 +1,46 @@
|
||||
/**************************************************************************/
|
||||
/* rect2i.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 <godot_cpp/variant/rect2i.hpp>
|
||||
|
||||
#include <godot_cpp/variant/rect2.hpp>
|
||||
#include <godot_cpp/variant/string.hpp>
|
||||
|
||||
namespace godot {
|
||||
|
||||
Rect2i::operator String() const {
|
||||
return "[P: " + position.operator String() + ", S: " + size + "]";
|
||||
}
|
||||
|
||||
Rect2i::operator Rect2() const {
|
||||
return Rect2(position, size);
|
||||
}
|
||||
|
||||
} // namespace godot
|
323
lib/godot-cpp/src/variant/transform2d.cpp
Normal file
323
lib/godot-cpp/src/variant/transform2d.cpp
Normal file
@@ -0,0 +1,323 @@
|
||||
/**************************************************************************/
|
||||
/* transform2d.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 <godot_cpp/variant/transform2d.hpp>
|
||||
|
||||
#include <godot_cpp/variant/string.hpp>
|
||||
|
||||
namespace godot {
|
||||
|
||||
void Transform2D::invert() {
|
||||
// FIXME: this function assumes the basis is a rotation matrix, with no scaling.
|
||||
// Transform2D::affine_inverse can handle matrices with scaling, so GDScript should eventually use that.
|
||||
SWAP(columns[0][1], columns[1][0]);
|
||||
columns[2] = basis_xform(-columns[2]);
|
||||
}
|
||||
|
||||
Transform2D Transform2D::inverse() const {
|
||||
Transform2D inv = *this;
|
||||
inv.invert();
|
||||
return inv;
|
||||
}
|
||||
|
||||
void Transform2D::affine_invert() {
|
||||
real_t det = basis_determinant();
|
||||
#ifdef MATH_CHECKS
|
||||
ERR_FAIL_COND(det == 0);
|
||||
#endif
|
||||
real_t idet = 1.0f / det;
|
||||
|
||||
SWAP(columns[0][0], columns[1][1]);
|
||||
columns[0] *= Vector2(idet, -idet);
|
||||
columns[1] *= Vector2(-idet, idet);
|
||||
|
||||
columns[2] = basis_xform(-columns[2]);
|
||||
}
|
||||
|
||||
Transform2D Transform2D::affine_inverse() const {
|
||||
Transform2D inv = *this;
|
||||
inv.affine_invert();
|
||||
return inv;
|
||||
}
|
||||
|
||||
void Transform2D::rotate(const real_t p_angle) {
|
||||
*this = Transform2D(p_angle, Vector2()) * (*this);
|
||||
}
|
||||
|
||||
real_t Transform2D::get_skew() const {
|
||||
real_t det = basis_determinant();
|
||||
return Math::acos(columns[0].normalized().dot(SIGN(det) * columns[1].normalized())) - (real_t)Math_PI * 0.5f;
|
||||
}
|
||||
|
||||
void Transform2D::set_skew(const real_t p_angle) {
|
||||
real_t det = basis_determinant();
|
||||
columns[1] = SIGN(det) * columns[0].rotated(((real_t)Math_PI * 0.5f + p_angle)).normalized() * columns[1].length();
|
||||
}
|
||||
|
||||
real_t Transform2D::get_rotation() const {
|
||||
return Math::atan2(columns[0].y, columns[0].x);
|
||||
}
|
||||
|
||||
void Transform2D::set_rotation(const real_t p_rot) {
|
||||
Size2 scale = get_scale();
|
||||
real_t cr = Math::cos(p_rot);
|
||||
real_t sr = Math::sin(p_rot);
|
||||
columns[0][0] = cr;
|
||||
columns[0][1] = sr;
|
||||
columns[1][0] = -sr;
|
||||
columns[1][1] = cr;
|
||||
set_scale(scale);
|
||||
}
|
||||
|
||||
Transform2D::Transform2D(const real_t p_rot, const Vector2 &p_pos) {
|
||||
real_t cr = Math::cos(p_rot);
|
||||
real_t sr = Math::sin(p_rot);
|
||||
columns[0][0] = cr;
|
||||
columns[0][1] = sr;
|
||||
columns[1][0] = -sr;
|
||||
columns[1][1] = cr;
|
||||
columns[2] = p_pos;
|
||||
}
|
||||
|
||||
Transform2D::Transform2D(const real_t p_rot, const Size2 &p_scale, const real_t p_skew, const Vector2 &p_pos) {
|
||||
columns[0][0] = Math::cos(p_rot) * p_scale.x;
|
||||
columns[1][1] = Math::cos(p_rot + p_skew) * p_scale.y;
|
||||
columns[1][0] = -Math::sin(p_rot + p_skew) * p_scale.y;
|
||||
columns[0][1] = Math::sin(p_rot) * p_scale.x;
|
||||
columns[2] = p_pos;
|
||||
}
|
||||
|
||||
Size2 Transform2D::get_scale() const {
|
||||
real_t det_sign = Math::sign(basis_determinant());
|
||||
return Size2(columns[0].length(), det_sign * columns[1].length());
|
||||
}
|
||||
|
||||
void Transform2D::set_scale(const Size2 &p_scale) {
|
||||
columns[0].normalize();
|
||||
columns[1].normalize();
|
||||
columns[0] *= p_scale.x;
|
||||
columns[1] *= p_scale.y;
|
||||
}
|
||||
|
||||
void Transform2D::scale(const Size2 &p_scale) {
|
||||
scale_basis(p_scale);
|
||||
columns[2] *= p_scale;
|
||||
}
|
||||
|
||||
void Transform2D::scale_basis(const Size2 &p_scale) {
|
||||
columns[0][0] *= p_scale.x;
|
||||
columns[0][1] *= p_scale.y;
|
||||
columns[1][0] *= p_scale.x;
|
||||
columns[1][1] *= p_scale.y;
|
||||
}
|
||||
|
||||
void Transform2D::translate_local(const real_t p_tx, const real_t p_ty) {
|
||||
translate_local(Vector2(p_tx, p_ty));
|
||||
}
|
||||
|
||||
void Transform2D::translate_local(const Vector2 &p_translation) {
|
||||
columns[2] += basis_xform(p_translation);
|
||||
}
|
||||
|
||||
void Transform2D::orthonormalize() {
|
||||
// Gram-Schmidt Process
|
||||
|
||||
Vector2 x = columns[0];
|
||||
Vector2 y = columns[1];
|
||||
|
||||
x.normalize();
|
||||
y = (y - x * (x.dot(y)));
|
||||
y.normalize();
|
||||
|
||||
columns[0] = x;
|
||||
columns[1] = y;
|
||||
}
|
||||
|
||||
Transform2D Transform2D::orthonormalized() const {
|
||||
Transform2D on = *this;
|
||||
on.orthonormalize();
|
||||
return on;
|
||||
}
|
||||
|
||||
bool Transform2D::is_equal_approx(const Transform2D &p_transform) const {
|
||||
return columns[0].is_equal_approx(p_transform.columns[0]) && columns[1].is_equal_approx(p_transform.columns[1]) && columns[2].is_equal_approx(p_transform.columns[2]);
|
||||
}
|
||||
|
||||
Transform2D Transform2D::looking_at(const Vector2 &p_target) const {
|
||||
Transform2D return_trans = Transform2D(get_rotation(), get_origin());
|
||||
Vector2 target_position = affine_inverse().xform(p_target);
|
||||
return_trans.set_rotation(return_trans.get_rotation() + (target_position * get_scale()).angle());
|
||||
return return_trans;
|
||||
}
|
||||
|
||||
bool Transform2D::operator==(const Transform2D &p_transform) const {
|
||||
for (int i = 0; i < 3; i++) {
|
||||
if (columns[i] != p_transform.columns[i]) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Transform2D::operator!=(const Transform2D &p_transform) const {
|
||||
for (int i = 0; i < 3; i++) {
|
||||
if (columns[i] != p_transform.columns[i]) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void Transform2D::operator*=(const Transform2D &p_transform) {
|
||||
columns[2] = xform(p_transform.columns[2]);
|
||||
|
||||
real_t x0, x1, y0, y1;
|
||||
|
||||
x0 = tdotx(p_transform.columns[0]);
|
||||
x1 = tdoty(p_transform.columns[0]);
|
||||
y0 = tdotx(p_transform.columns[1]);
|
||||
y1 = tdoty(p_transform.columns[1]);
|
||||
|
||||
columns[0][0] = x0;
|
||||
columns[0][1] = x1;
|
||||
columns[1][0] = y0;
|
||||
columns[1][1] = y1;
|
||||
}
|
||||
|
||||
Transform2D Transform2D::operator*(const Transform2D &p_transform) const {
|
||||
Transform2D t = *this;
|
||||
t *= p_transform;
|
||||
return t;
|
||||
}
|
||||
|
||||
Transform2D Transform2D::basis_scaled(const Size2 &p_scale) const {
|
||||
Transform2D copy = *this;
|
||||
copy.scale_basis(p_scale);
|
||||
return copy;
|
||||
}
|
||||
|
||||
Transform2D Transform2D::scaled(const Size2 &p_scale) const {
|
||||
// Equivalent to left multiplication
|
||||
Transform2D copy = *this;
|
||||
copy.scale(p_scale);
|
||||
return copy;
|
||||
}
|
||||
|
||||
Transform2D Transform2D::scaled_local(const Size2 &p_scale) const {
|
||||
// Equivalent to right multiplication
|
||||
return Transform2D(columns[0] * p_scale.x, columns[1] * p_scale.y, columns[2]);
|
||||
}
|
||||
|
||||
Transform2D Transform2D::untranslated() const {
|
||||
Transform2D copy = *this;
|
||||
copy.columns[2] = Vector2();
|
||||
return copy;
|
||||
}
|
||||
|
||||
Transform2D Transform2D::translated(const Vector2 &p_offset) const {
|
||||
// Equivalent to left multiplication
|
||||
return Transform2D(columns[0], columns[1], columns[2] + p_offset);
|
||||
}
|
||||
|
||||
Transform2D Transform2D::translated_local(const Vector2 &p_offset) const {
|
||||
// Equivalent to right multiplication
|
||||
return Transform2D(columns[0], columns[1], columns[2] + basis_xform(p_offset));
|
||||
}
|
||||
|
||||
Transform2D Transform2D::rotated(const real_t p_angle) const {
|
||||
// Equivalent to left multiplication
|
||||
return Transform2D(p_angle, Vector2()) * (*this);
|
||||
}
|
||||
|
||||
Transform2D Transform2D::rotated_local(const real_t p_angle) const {
|
||||
// Equivalent to right multiplication
|
||||
return (*this) * Transform2D(p_angle, Vector2()); // Could be optimized, because origin transform can be skipped.
|
||||
}
|
||||
|
||||
real_t Transform2D::basis_determinant() const {
|
||||
return columns[0].x * columns[1].y - columns[0].y * columns[1].x;
|
||||
}
|
||||
|
||||
Transform2D Transform2D::interpolate_with(const Transform2D &p_transform, const real_t p_c) const {
|
||||
//extract parameters
|
||||
Vector2 p1 = get_origin();
|
||||
Vector2 p2 = p_transform.get_origin();
|
||||
|
||||
real_t r1 = get_rotation();
|
||||
real_t r2 = p_transform.get_rotation();
|
||||
|
||||
Size2 s1 = get_scale();
|
||||
Size2 s2 = p_transform.get_scale();
|
||||
|
||||
//slerp rotation
|
||||
Vector2 v1(Math::cos(r1), Math::sin(r1));
|
||||
Vector2 v2(Math::cos(r2), Math::sin(r2));
|
||||
|
||||
real_t dot = v1.dot(v2);
|
||||
|
||||
dot = Math::clamp(dot, (real_t)-1.0, (real_t)1.0);
|
||||
|
||||
Vector2 v;
|
||||
|
||||
if (dot > 0.9995f) {
|
||||
v = v1.lerp(v2, p_c).normalized(); //linearly interpolate to avoid numerical precision issues
|
||||
} else {
|
||||
real_t angle = p_c * Math::acos(dot);
|
||||
Vector2 v3 = (v2 - v1 * dot).normalized();
|
||||
v = v1 * Math::cos(angle) + v3 * Math::sin(angle);
|
||||
}
|
||||
|
||||
//construct matrix
|
||||
Transform2D res(v.angle(), p1.lerp(p2, p_c));
|
||||
res.scale_basis(s1.lerp(s2, p_c));
|
||||
return res;
|
||||
}
|
||||
|
||||
void Transform2D::operator*=(const real_t p_val) {
|
||||
columns[0] *= p_val;
|
||||
columns[1] *= p_val;
|
||||
columns[2] *= p_val;
|
||||
}
|
||||
|
||||
Transform2D Transform2D::operator*(const real_t p_val) const {
|
||||
Transform2D ret(*this);
|
||||
ret *= p_val;
|
||||
return ret;
|
||||
}
|
||||
|
||||
Transform2D::operator String() const {
|
||||
return "[X: " + columns[0].operator String() +
|
||||
", Y: " + columns[1].operator String() +
|
||||
", O: " + columns[2].operator String() + "]";
|
||||
}
|
||||
|
||||
} // namespace godot
|
232
lib/godot-cpp/src/variant/transform3d.cpp
Normal file
232
lib/godot-cpp/src/variant/transform3d.cpp
Normal file
@@ -0,0 +1,232 @@
|
||||
/**************************************************************************/
|
||||
/* transform3d.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 <godot_cpp/variant/transform3d.hpp>
|
||||
|
||||
#include <godot_cpp/variant/string.hpp>
|
||||
|
||||
namespace godot {
|
||||
|
||||
void Transform3D::affine_invert() {
|
||||
basis.invert();
|
||||
origin = basis.xform(-origin);
|
||||
}
|
||||
|
||||
Transform3D Transform3D::affine_inverse() const {
|
||||
Transform3D ret = *this;
|
||||
ret.affine_invert();
|
||||
return ret;
|
||||
}
|
||||
|
||||
void Transform3D::invert() {
|
||||
basis.transpose();
|
||||
origin = basis.xform(-origin);
|
||||
}
|
||||
|
||||
Transform3D Transform3D::inverse() const {
|
||||
// FIXME: this function assumes the basis is a rotation matrix, with no scaling.
|
||||
// Transform3D::affine_inverse can handle matrices with scaling, so GDScript should eventually use that.
|
||||
Transform3D ret = *this;
|
||||
ret.invert();
|
||||
return ret;
|
||||
}
|
||||
|
||||
void Transform3D::rotate(const Vector3 &p_axis, real_t p_angle) {
|
||||
*this = rotated(p_axis, p_angle);
|
||||
}
|
||||
|
||||
Transform3D Transform3D::rotated(const Vector3 &p_axis, real_t p_angle) const {
|
||||
// Equivalent to left multiplication
|
||||
Basis p_basis(p_axis, p_angle);
|
||||
return Transform3D(p_basis * basis, p_basis.xform(origin));
|
||||
}
|
||||
|
||||
Transform3D Transform3D::rotated_local(const Vector3 &p_axis, real_t p_angle) const {
|
||||
// Equivalent to right multiplication
|
||||
Basis p_basis(p_axis, p_angle);
|
||||
return Transform3D(basis * p_basis, origin);
|
||||
}
|
||||
|
||||
void Transform3D::rotate_basis(const Vector3 &p_axis, real_t p_angle) {
|
||||
basis.rotate(p_axis, p_angle);
|
||||
}
|
||||
|
||||
Transform3D Transform3D::looking_at(const Vector3 &p_target, const Vector3 &p_up) const {
|
||||
#ifdef MATH_CHECKS
|
||||
ERR_FAIL_COND_V_MSG(origin.is_equal_approx(p_target), Transform3D(), "The transform's origin and target can't be equal.");
|
||||
#endif
|
||||
Transform3D t = *this;
|
||||
t.basis = Basis::looking_at(p_target - origin, p_up);
|
||||
return t;
|
||||
}
|
||||
|
||||
void Transform3D::set_look_at(const Vector3 &p_eye, const Vector3 &p_target, const Vector3 &p_up) {
|
||||
#ifdef MATH_CHECKS
|
||||
ERR_FAIL_COND_MSG(p_eye.is_equal_approx(p_target), "The eye and target vectors can't be equal.");
|
||||
#endif
|
||||
basis = Basis::looking_at(p_target - p_eye, p_up);
|
||||
origin = p_eye;
|
||||
}
|
||||
|
||||
Transform3D Transform3D::interpolate_with(const Transform3D &p_transform, real_t p_c) const {
|
||||
Transform3D interp;
|
||||
|
||||
Vector3 src_scale = basis.get_scale();
|
||||
Quaternion src_rot = basis.get_rotation_quaternion();
|
||||
Vector3 src_loc = origin;
|
||||
|
||||
Vector3 dst_scale = p_transform.basis.get_scale();
|
||||
Quaternion dst_rot = p_transform.basis.get_rotation_quaternion();
|
||||
Vector3 dst_loc = p_transform.origin;
|
||||
|
||||
interp.basis.set_quaternion_scale(src_rot.slerp(dst_rot, p_c).normalized(), src_scale.lerp(dst_scale, p_c));
|
||||
interp.origin = src_loc.lerp(dst_loc, p_c);
|
||||
|
||||
return interp;
|
||||
}
|
||||
|
||||
void Transform3D::scale(const Vector3 &p_scale) {
|
||||
basis.scale(p_scale);
|
||||
origin *= p_scale;
|
||||
}
|
||||
|
||||
Transform3D Transform3D::scaled(const Vector3 &p_scale) const {
|
||||
// Equivalent to left multiplication
|
||||
return Transform3D(basis.scaled(p_scale), origin * p_scale);
|
||||
}
|
||||
|
||||
Transform3D Transform3D::scaled_local(const Vector3 &p_scale) const {
|
||||
// Equivalent to right multiplication
|
||||
return Transform3D(basis.scaled_local(p_scale), origin);
|
||||
}
|
||||
|
||||
void Transform3D::scale_basis(const Vector3 &p_scale) {
|
||||
basis.scale(p_scale);
|
||||
}
|
||||
|
||||
void Transform3D::translate_local(real_t p_tx, real_t p_ty, real_t p_tz) {
|
||||
translate_local(Vector3(p_tx, p_ty, p_tz));
|
||||
}
|
||||
|
||||
void Transform3D::translate_local(const Vector3 &p_translation) {
|
||||
for (int i = 0; i < 3; i++) {
|
||||
origin[i] += basis[i].dot(p_translation);
|
||||
}
|
||||
}
|
||||
|
||||
Transform3D Transform3D::translated(const Vector3 &p_translation) const {
|
||||
// Equivalent to left multiplication
|
||||
return Transform3D(basis, origin + p_translation);
|
||||
}
|
||||
|
||||
Transform3D Transform3D::translated_local(const Vector3 &p_translation) const {
|
||||
// Equivalent to right multiplication
|
||||
return Transform3D(basis, origin + basis.xform(p_translation));
|
||||
}
|
||||
|
||||
void Transform3D::orthonormalize() {
|
||||
basis.orthonormalize();
|
||||
}
|
||||
|
||||
Transform3D Transform3D::orthonormalized() const {
|
||||
Transform3D _copy = *this;
|
||||
_copy.orthonormalize();
|
||||
return _copy;
|
||||
}
|
||||
|
||||
void Transform3D::orthogonalize() {
|
||||
basis.orthogonalize();
|
||||
}
|
||||
|
||||
Transform3D Transform3D::orthogonalized() const {
|
||||
Transform3D _copy = *this;
|
||||
_copy.orthogonalize();
|
||||
return _copy;
|
||||
}
|
||||
|
||||
bool Transform3D::is_equal_approx(const Transform3D &p_transform) const {
|
||||
return basis.is_equal_approx(p_transform.basis) && origin.is_equal_approx(p_transform.origin);
|
||||
}
|
||||
|
||||
bool Transform3D::operator==(const Transform3D &p_transform) const {
|
||||
return (basis == p_transform.basis && origin == p_transform.origin);
|
||||
}
|
||||
|
||||
bool Transform3D::operator!=(const Transform3D &p_transform) const {
|
||||
return (basis != p_transform.basis || origin != p_transform.origin);
|
||||
}
|
||||
|
||||
void Transform3D::operator*=(const Transform3D &p_transform) {
|
||||
origin = xform(p_transform.origin);
|
||||
basis *= p_transform.basis;
|
||||
}
|
||||
|
||||
Transform3D Transform3D::operator*(const Transform3D &p_transform) const {
|
||||
Transform3D t = *this;
|
||||
t *= p_transform;
|
||||
return t;
|
||||
}
|
||||
|
||||
void Transform3D::operator*=(const real_t p_val) {
|
||||
origin *= p_val;
|
||||
basis *= p_val;
|
||||
}
|
||||
|
||||
Transform3D Transform3D::operator*(const real_t p_val) const {
|
||||
Transform3D ret(*this);
|
||||
ret *= p_val;
|
||||
return ret;
|
||||
}
|
||||
|
||||
Transform3D::operator String() const {
|
||||
return "[X: " + basis.get_column(0).operator String() +
|
||||
", Y: " + basis.get_column(1).operator String() +
|
||||
", Z: " + basis.get_column(2).operator String() +
|
||||
", O: " + origin.operator String() + "]";
|
||||
}
|
||||
|
||||
Transform3D::Transform3D(const Basis &p_basis, const Vector3 &p_origin) :
|
||||
basis(p_basis),
|
||||
origin(p_origin) {
|
||||
}
|
||||
|
||||
Transform3D::Transform3D(const Vector3 &p_x, const Vector3 &p_y, const Vector3 &p_z, const Vector3 &p_origin) :
|
||||
origin(p_origin) {
|
||||
basis.set_column(0, p_x);
|
||||
basis.set_column(1, p_y);
|
||||
basis.set_column(2, p_z);
|
||||
}
|
||||
|
||||
Transform3D::Transform3D(real_t xx, real_t xy, real_t xz, real_t yx, real_t yy, real_t yz, real_t zx, real_t zy, real_t zz, real_t ox, real_t oy, real_t oz) {
|
||||
basis = Basis(xx, xy, xz, yx, yy, yz, zx, zy, zz);
|
||||
origin = Vector3(ox, oy, oz);
|
||||
}
|
||||
|
||||
} // namespace godot
|
783
lib/godot-cpp/src/variant/variant.cpp
Normal file
783
lib/godot-cpp/src/variant/variant.cpp
Normal file
@@ -0,0 +1,783 @@
|
||||
/**************************************************************************/
|
||||
/* variant.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 <godot_cpp/variant/variant.hpp>
|
||||
|
||||
#include <godot_cpp/godot.hpp>
|
||||
|
||||
#include <godot_cpp/core/binder_common.hpp>
|
||||
#include <godot_cpp/core/defs.hpp>
|
||||
|
||||
#include <utility>
|
||||
|
||||
namespace godot {
|
||||
|
||||
GDExtensionVariantFromTypeConstructorFunc Variant::from_type_constructor[Variant::VARIANT_MAX]{};
|
||||
GDExtensionTypeFromVariantConstructorFunc Variant::to_type_constructor[Variant::VARIANT_MAX]{};
|
||||
|
||||
void Variant::init_bindings() {
|
||||
// Start from 1 to skip NIL.
|
||||
for (int i = 1; i < VARIANT_MAX; i++) {
|
||||
from_type_constructor[i] = internal::gde_interface->get_variant_from_type_constructor((GDExtensionVariantType)i);
|
||||
to_type_constructor[i] = internal::gde_interface->get_variant_to_type_constructor((GDExtensionVariantType)i);
|
||||
}
|
||||
|
||||
StringName::init_bindings();
|
||||
String::init_bindings();
|
||||
NodePath::init_bindings();
|
||||
RID::init_bindings();
|
||||
Callable::init_bindings();
|
||||
Signal::init_bindings();
|
||||
Dictionary::init_bindings();
|
||||
Array::init_bindings();
|
||||
PackedByteArray::init_bindings();
|
||||
PackedInt32Array::init_bindings();
|
||||
PackedInt64Array::init_bindings();
|
||||
PackedFloat32Array::init_bindings();
|
||||
PackedFloat64Array::init_bindings();
|
||||
PackedStringArray::init_bindings();
|
||||
PackedVector2Array::init_bindings();
|
||||
PackedVector3Array::init_bindings();
|
||||
PackedColorArray::init_bindings();
|
||||
}
|
||||
|
||||
Variant::Variant() {
|
||||
internal::gde_interface->variant_new_nil(_native_ptr());
|
||||
}
|
||||
|
||||
Variant::Variant(GDExtensionConstVariantPtr native_ptr) {
|
||||
internal::gde_interface->variant_new_copy(_native_ptr(), native_ptr);
|
||||
}
|
||||
|
||||
Variant::Variant(const Variant &other) {
|
||||
internal::gde_interface->variant_new_copy(_native_ptr(), other._native_ptr());
|
||||
}
|
||||
|
||||
Variant::Variant(Variant &&other) {
|
||||
std::swap(opaque, other.opaque);
|
||||
}
|
||||
|
||||
Variant::Variant(bool v) {
|
||||
GDExtensionBool encoded;
|
||||
PtrToArg<bool>::encode(v, &encoded);
|
||||
from_type_constructor[BOOL](_native_ptr(), &encoded);
|
||||
}
|
||||
|
||||
Variant::Variant(int64_t v) {
|
||||
GDExtensionInt encoded;
|
||||
PtrToArg<int64_t>::encode(v, &encoded);
|
||||
from_type_constructor[INT](_native_ptr(), &encoded);
|
||||
}
|
||||
|
||||
Variant::Variant(double v) {
|
||||
double encoded;
|
||||
PtrToArg<double>::encode(v, &encoded);
|
||||
from_type_constructor[FLOAT](_native_ptr(), &encoded);
|
||||
}
|
||||
|
||||
Variant::Variant(const String &v) {
|
||||
from_type_constructor[STRING](_native_ptr(), v._native_ptr());
|
||||
}
|
||||
|
||||
Variant::Variant(const Vector2 &v) {
|
||||
from_type_constructor[VECTOR2](_native_ptr(), (GDExtensionTypePtr)&v);
|
||||
}
|
||||
|
||||
Variant::Variant(const Vector2i &v) {
|
||||
from_type_constructor[VECTOR2I](_native_ptr(), (GDExtensionTypePtr)&v);
|
||||
}
|
||||
|
||||
Variant::Variant(const Rect2 &v) {
|
||||
from_type_constructor[RECT2](_native_ptr(), (GDExtensionTypePtr)&v);
|
||||
}
|
||||
|
||||
Variant::Variant(const Rect2i &v) {
|
||||
from_type_constructor[RECT2I](_native_ptr(), (GDExtensionTypePtr)&v);
|
||||
}
|
||||
|
||||
Variant::Variant(const Vector3 &v) {
|
||||
from_type_constructor[VECTOR3](_native_ptr(), (GDExtensionTypePtr)&v);
|
||||
}
|
||||
|
||||
Variant::Variant(const Vector3i &v) {
|
||||
from_type_constructor[VECTOR3I](_native_ptr(), (GDExtensionTypePtr)&v);
|
||||
}
|
||||
|
||||
Variant::Variant(const Transform2D &v) {
|
||||
from_type_constructor[TRANSFORM2D](_native_ptr(), (GDExtensionTypePtr)&v);
|
||||
}
|
||||
|
||||
Variant::Variant(const Vector4 &v) {
|
||||
from_type_constructor[VECTOR4](_native_ptr(), (GDExtensionTypePtr)&v);
|
||||
}
|
||||
|
||||
Variant::Variant(const Vector4i &v) {
|
||||
from_type_constructor[VECTOR4I](_native_ptr(), (GDExtensionTypePtr)&v);
|
||||
}
|
||||
|
||||
Variant::Variant(const Plane &v) {
|
||||
from_type_constructor[PLANE](_native_ptr(), (GDExtensionTypePtr)&v);
|
||||
}
|
||||
|
||||
Variant::Variant(const Quaternion &v) {
|
||||
from_type_constructor[QUATERNION](_native_ptr(), (GDExtensionTypePtr)&v);
|
||||
}
|
||||
|
||||
Variant::Variant(const godot::AABB &v) {
|
||||
from_type_constructor[AABB](_native_ptr(), (GDExtensionTypePtr)&v);
|
||||
}
|
||||
|
||||
Variant::Variant(const Basis &v) {
|
||||
from_type_constructor[BASIS](_native_ptr(), (GDExtensionTypePtr)&v);
|
||||
}
|
||||
|
||||
Variant::Variant(const Transform3D &v) {
|
||||
from_type_constructor[TRANSFORM3D](_native_ptr(), (GDExtensionTypePtr)&v);
|
||||
}
|
||||
|
||||
Variant::Variant(const Projection &v) {
|
||||
from_type_constructor[PROJECTION](_native_ptr(), (GDExtensionTypePtr)&v);
|
||||
}
|
||||
|
||||
Variant::Variant(const Color &v) {
|
||||
from_type_constructor[COLOR](_native_ptr(), (GDExtensionTypePtr)&v);
|
||||
}
|
||||
|
||||
Variant::Variant(const StringName &v) {
|
||||
from_type_constructor[STRING_NAME](_native_ptr(), v._native_ptr());
|
||||
}
|
||||
|
||||
Variant::Variant(const NodePath &v) {
|
||||
from_type_constructor[NODE_PATH](_native_ptr(), v._native_ptr());
|
||||
}
|
||||
|
||||
Variant::Variant(const godot::RID &v) {
|
||||
from_type_constructor[RID](_native_ptr(), v._native_ptr());
|
||||
}
|
||||
|
||||
Variant::Variant(const Object *v) {
|
||||
if (v) {
|
||||
from_type_constructor[OBJECT](_native_ptr(), const_cast<GodotObject **>(&v->_owner));
|
||||
} else {
|
||||
GodotObject *nullobject = nullptr;
|
||||
from_type_constructor[OBJECT](_native_ptr(), &nullobject);
|
||||
}
|
||||
}
|
||||
|
||||
Variant::Variant(const ObjectID &p_id) :
|
||||
Variant(p_id.operator uint64_t()) {
|
||||
}
|
||||
|
||||
Variant::Variant(const Callable &v) {
|
||||
from_type_constructor[CALLABLE](_native_ptr(), v._native_ptr());
|
||||
}
|
||||
|
||||
Variant::Variant(const Signal &v) {
|
||||
from_type_constructor[SIGNAL](_native_ptr(), v._native_ptr());
|
||||
}
|
||||
|
||||
Variant::Variant(const Dictionary &v) {
|
||||
from_type_constructor[DICTIONARY](_native_ptr(), v._native_ptr());
|
||||
}
|
||||
|
||||
Variant::Variant(const Array &v) {
|
||||
from_type_constructor[ARRAY](_native_ptr(), v._native_ptr());
|
||||
}
|
||||
|
||||
Variant::Variant(const PackedByteArray &v) {
|
||||
from_type_constructor[PACKED_BYTE_ARRAY](_native_ptr(), v._native_ptr());
|
||||
}
|
||||
|
||||
Variant::Variant(const PackedInt32Array &v) {
|
||||
from_type_constructor[PACKED_INT32_ARRAY](_native_ptr(), v._native_ptr());
|
||||
}
|
||||
|
||||
Variant::Variant(const PackedInt64Array &v) {
|
||||
from_type_constructor[PACKED_INT64_ARRAY](_native_ptr(), v._native_ptr());
|
||||
}
|
||||
|
||||
Variant::Variant(const PackedFloat32Array &v) {
|
||||
from_type_constructor[PACKED_FLOAT32_ARRAY](_native_ptr(), v._native_ptr());
|
||||
}
|
||||
|
||||
Variant::Variant(const PackedFloat64Array &v) {
|
||||
from_type_constructor[PACKED_FLOAT64_ARRAY](_native_ptr(), v._native_ptr());
|
||||
}
|
||||
|
||||
Variant::Variant(const PackedStringArray &v) {
|
||||
from_type_constructor[PACKED_STRING_ARRAY](_native_ptr(), v._native_ptr());
|
||||
}
|
||||
|
||||
Variant::Variant(const PackedVector2Array &v) {
|
||||
from_type_constructor[PACKED_VECTOR2_ARRAY](_native_ptr(), v._native_ptr());
|
||||
}
|
||||
|
||||
Variant::Variant(const PackedVector3Array &v) {
|
||||
from_type_constructor[PACKED_VECTOR3_ARRAY](_native_ptr(), v._native_ptr());
|
||||
}
|
||||
|
||||
Variant::Variant(const PackedColorArray &v) {
|
||||
from_type_constructor[PACKED_COLOR_ARRAY](_native_ptr(), v._native_ptr());
|
||||
}
|
||||
|
||||
Variant::~Variant() {
|
||||
internal::gde_interface->variant_destroy(_native_ptr());
|
||||
}
|
||||
|
||||
Variant::operator bool() const {
|
||||
GDExtensionBool result;
|
||||
to_type_constructor[BOOL](&result, _native_ptr());
|
||||
return PtrToArg<bool>::convert(&result);
|
||||
}
|
||||
|
||||
Variant::operator int64_t() const {
|
||||
GDExtensionInt result;
|
||||
to_type_constructor[INT](&result, _native_ptr());
|
||||
return PtrToArg<int64_t>::convert(&result);
|
||||
}
|
||||
|
||||
Variant::operator int32_t() const {
|
||||
return static_cast<int32_t>(operator int64_t());
|
||||
}
|
||||
|
||||
Variant::operator uint64_t() const {
|
||||
return static_cast<uint64_t>(operator int64_t());
|
||||
}
|
||||
|
||||
Variant::operator uint32_t() const {
|
||||
return static_cast<uint32_t>(operator int64_t());
|
||||
}
|
||||
|
||||
Variant::operator double() const {
|
||||
double result;
|
||||
to_type_constructor[FLOAT](&result, _native_ptr());
|
||||
return PtrToArg<double>::convert(&result);
|
||||
}
|
||||
|
||||
Variant::operator float() const {
|
||||
return static_cast<float>(operator double());
|
||||
}
|
||||
|
||||
Variant::operator String() const {
|
||||
String result;
|
||||
to_type_constructor[STRING](result._native_ptr(), _native_ptr());
|
||||
return result;
|
||||
}
|
||||
|
||||
Variant::operator Vector2() const {
|
||||
Vector2 result;
|
||||
to_type_constructor[VECTOR2]((GDExtensionTypePtr)&result, _native_ptr());
|
||||
return result;
|
||||
}
|
||||
|
||||
Variant::operator Vector2i() const {
|
||||
Vector2i result;
|
||||
to_type_constructor[VECTOR2I]((GDExtensionTypePtr)&result, _native_ptr());
|
||||
return result;
|
||||
}
|
||||
|
||||
Variant::operator Rect2() const {
|
||||
Rect2 result;
|
||||
to_type_constructor[RECT2]((GDExtensionTypePtr)&result, _native_ptr());
|
||||
return result;
|
||||
}
|
||||
|
||||
Variant::operator Rect2i() const {
|
||||
Rect2i result;
|
||||
to_type_constructor[RECT2I]((GDExtensionTypePtr)&result, _native_ptr());
|
||||
return result;
|
||||
}
|
||||
|
||||
Variant::operator Vector3() const {
|
||||
Vector3 result;
|
||||
to_type_constructor[VECTOR3]((GDExtensionTypePtr)&result, _native_ptr());
|
||||
return result;
|
||||
}
|
||||
|
||||
Variant::operator Vector3i() const {
|
||||
Vector3i result;
|
||||
to_type_constructor[VECTOR3I]((GDExtensionTypePtr)&result, _native_ptr());
|
||||
return result;
|
||||
}
|
||||
|
||||
Variant::operator Transform2D() const {
|
||||
Transform2D result;
|
||||
to_type_constructor[TRANSFORM2D]((GDExtensionTypePtr)&result, _native_ptr());
|
||||
return result;
|
||||
}
|
||||
|
||||
Variant::operator Vector4() const {
|
||||
Vector4 result;
|
||||
to_type_constructor[VECTOR4]((GDExtensionTypePtr)&result, _native_ptr());
|
||||
return result;
|
||||
}
|
||||
|
||||
Variant::operator Vector4i() const {
|
||||
Vector4i result;
|
||||
to_type_constructor[VECTOR4I]((GDExtensionTypePtr)&result, _native_ptr());
|
||||
return result;
|
||||
}
|
||||
|
||||
Variant::operator Plane() const {
|
||||
Plane result;
|
||||
to_type_constructor[PLANE]((GDExtensionTypePtr)&result, _native_ptr());
|
||||
return result;
|
||||
}
|
||||
|
||||
Variant::operator Quaternion() const {
|
||||
Quaternion result;
|
||||
to_type_constructor[QUATERNION]((GDExtensionTypePtr)&result, _native_ptr());
|
||||
return result;
|
||||
}
|
||||
|
||||
Variant::operator godot::AABB() const {
|
||||
godot::AABB result;
|
||||
to_type_constructor[AABB]((GDExtensionTypePtr)&result, _native_ptr());
|
||||
return result;
|
||||
}
|
||||
|
||||
Variant::operator Basis() const {
|
||||
Basis result;
|
||||
to_type_constructor[BASIS]((GDExtensionTypePtr)&result, _native_ptr());
|
||||
return result;
|
||||
}
|
||||
|
||||
Variant::operator Transform3D() const {
|
||||
Transform3D result;
|
||||
to_type_constructor[TRANSFORM3D]((GDExtensionTypePtr)&result, _native_ptr());
|
||||
return result;
|
||||
}
|
||||
|
||||
Variant::operator Projection() const {
|
||||
Projection result;
|
||||
to_type_constructor[PROJECTION]((GDExtensionTypePtr)&result, _native_ptr());
|
||||
return result;
|
||||
}
|
||||
|
||||
Variant::operator Color() const {
|
||||
Color result;
|
||||
to_type_constructor[COLOR]((GDExtensionTypePtr)&result, _native_ptr());
|
||||
return result;
|
||||
}
|
||||
|
||||
Variant::operator StringName() const {
|
||||
StringName result;
|
||||
to_type_constructor[STRING_NAME](result._native_ptr(), _native_ptr());
|
||||
return result;
|
||||
}
|
||||
|
||||
Variant::operator NodePath() const {
|
||||
NodePath result;
|
||||
to_type_constructor[NODE_PATH](result._native_ptr(), _native_ptr());
|
||||
return result;
|
||||
}
|
||||
|
||||
Variant::operator godot::RID() const {
|
||||
godot::RID result;
|
||||
to_type_constructor[RID](result._native_ptr(), _native_ptr());
|
||||
return result;
|
||||
}
|
||||
|
||||
Variant::operator Object *() const {
|
||||
GodotObject *obj;
|
||||
to_type_constructor[OBJECT](&obj, _native_ptr());
|
||||
if (obj == nullptr) {
|
||||
return nullptr;
|
||||
}
|
||||
return reinterpret_cast<Object *>(internal::gde_interface->object_get_instance_binding(obj, internal::token, &Object::___binding_callbacks));
|
||||
}
|
||||
|
||||
Variant::operator ObjectID() const {
|
||||
if (get_type() == Type::INT) {
|
||||
return ObjectID(operator uint64_t());
|
||||
} else if (get_type() == Type::OBJECT) {
|
||||
Object *obj = operator Object *();
|
||||
if (obj != nullptr) {
|
||||
return ObjectID(obj->get_instance_id());
|
||||
} else {
|
||||
return ObjectID();
|
||||
}
|
||||
} else {
|
||||
return ObjectID();
|
||||
}
|
||||
}
|
||||
|
||||
Variant::operator Callable() const {
|
||||
Callable result;
|
||||
to_type_constructor[CALLABLE](result._native_ptr(), _native_ptr());
|
||||
return result;
|
||||
}
|
||||
|
||||
Variant::operator Signal() const {
|
||||
Signal result;
|
||||
to_type_constructor[SIGNAL](result._native_ptr(), _native_ptr());
|
||||
return result;
|
||||
}
|
||||
|
||||
Variant::operator Dictionary() const {
|
||||
Dictionary result;
|
||||
to_type_constructor[DICTIONARY](result._native_ptr(), _native_ptr());
|
||||
return result;
|
||||
}
|
||||
|
||||
Variant::operator Array() const {
|
||||
Array result;
|
||||
to_type_constructor[ARRAY](result._native_ptr(), _native_ptr());
|
||||
return result;
|
||||
}
|
||||
|
||||
Variant::operator PackedByteArray() const {
|
||||
PackedByteArray result;
|
||||
to_type_constructor[PACKED_BYTE_ARRAY](result._native_ptr(), _native_ptr());
|
||||
return result;
|
||||
}
|
||||
|
||||
Variant::operator PackedInt32Array() const {
|
||||
PackedInt32Array result;
|
||||
to_type_constructor[PACKED_INT32_ARRAY](result._native_ptr(), _native_ptr());
|
||||
return result;
|
||||
}
|
||||
|
||||
Variant::operator PackedInt64Array() const {
|
||||
PackedInt64Array result;
|
||||
to_type_constructor[PACKED_INT64_ARRAY](result._native_ptr(), _native_ptr());
|
||||
return result;
|
||||
}
|
||||
|
||||
Variant::operator PackedFloat32Array() const {
|
||||
PackedFloat32Array result;
|
||||
to_type_constructor[PACKED_FLOAT32_ARRAY](result._native_ptr(), _native_ptr());
|
||||
return result;
|
||||
}
|
||||
|
||||
Variant::operator PackedFloat64Array() const {
|
||||
PackedFloat64Array result;
|
||||
to_type_constructor[PACKED_FLOAT64_ARRAY](result._native_ptr(), _native_ptr());
|
||||
return result;
|
||||
}
|
||||
|
||||
Variant::operator PackedStringArray() const {
|
||||
PackedStringArray result;
|
||||
to_type_constructor[PACKED_STRING_ARRAY](result._native_ptr(), _native_ptr());
|
||||
return result;
|
||||
}
|
||||
|
||||
Variant::operator PackedVector2Array() const {
|
||||
PackedVector2Array result;
|
||||
to_type_constructor[PACKED_VECTOR2_ARRAY](result._native_ptr(), _native_ptr());
|
||||
return result;
|
||||
}
|
||||
|
||||
Variant::operator PackedVector3Array() const {
|
||||
PackedVector3Array result;
|
||||
to_type_constructor[PACKED_VECTOR3_ARRAY](result._native_ptr(), _native_ptr());
|
||||
return result;
|
||||
}
|
||||
|
||||
Variant::operator PackedColorArray() const {
|
||||
PackedColorArray result;
|
||||
to_type_constructor[PACKED_COLOR_ARRAY](result._native_ptr(), _native_ptr());
|
||||
return result;
|
||||
}
|
||||
|
||||
Variant &Variant::operator=(const Variant &other) {
|
||||
clear();
|
||||
internal::gde_interface->variant_new_copy(_native_ptr(), other._native_ptr());
|
||||
return *this;
|
||||
}
|
||||
|
||||
Variant &Variant::operator=(Variant &&other) {
|
||||
std::swap(opaque, other.opaque);
|
||||
return *this;
|
||||
}
|
||||
|
||||
bool Variant::operator==(const Variant &other) const {
|
||||
if (get_type() != other.get_type()) {
|
||||
return false;
|
||||
}
|
||||
bool valid = false;
|
||||
Variant result;
|
||||
evaluate(OP_EQUAL, *this, other, result, valid);
|
||||
return result.operator bool();
|
||||
}
|
||||
|
||||
bool Variant::operator!=(const Variant &other) const {
|
||||
if (get_type() != other.get_type()) {
|
||||
return true;
|
||||
}
|
||||
bool valid = false;
|
||||
Variant result;
|
||||
evaluate(OP_NOT_EQUAL, *this, other, result, valid);
|
||||
return result.operator bool();
|
||||
}
|
||||
|
||||
bool Variant::operator<(const Variant &other) const {
|
||||
if (get_type() != other.get_type()) {
|
||||
return get_type() < other.get_type();
|
||||
}
|
||||
bool valid = false;
|
||||
Variant result;
|
||||
evaluate(OP_LESS, *this, other, result, valid);
|
||||
return result.operator bool();
|
||||
}
|
||||
|
||||
void Variant::call(const StringName &method, const Variant **args, int argcount, Variant &r_ret, GDExtensionCallError &r_error) {
|
||||
internal::gde_interface->variant_call(_native_ptr(), method._native_ptr(), reinterpret_cast<GDExtensionConstVariantPtr *>(args), argcount, r_ret._native_ptr(), &r_error);
|
||||
}
|
||||
|
||||
void Variant::call_static(Variant::Type type, const StringName &method, const Variant **args, int argcount, Variant &r_ret, GDExtensionCallError &r_error) {
|
||||
internal::gde_interface->variant_call_static(static_cast<GDExtensionVariantType>(type), method._native_ptr(), reinterpret_cast<GDExtensionConstVariantPtr *>(args), argcount, r_ret._native_ptr(), &r_error);
|
||||
}
|
||||
|
||||
void Variant::evaluate(const Operator &op, const Variant &a, const Variant &b, Variant &r_ret, bool &r_valid) {
|
||||
GDExtensionBool valid;
|
||||
internal::gde_interface->variant_evaluate(static_cast<GDExtensionVariantOperator>(op), a._native_ptr(), b._native_ptr(), r_ret._native_ptr(), &valid);
|
||||
r_valid = PtrToArg<bool>::convert(&valid);
|
||||
}
|
||||
|
||||
void Variant::set(const Variant &key, const Variant &value, bool *r_valid) {
|
||||
GDExtensionBool valid;
|
||||
internal::gde_interface->variant_set(_native_ptr(), key._native_ptr(), value._native_ptr(), &valid);
|
||||
if (r_valid) {
|
||||
*r_valid = PtrToArg<bool>::convert(&valid);
|
||||
}
|
||||
}
|
||||
|
||||
void Variant::set_named(const StringName &name, const Variant &value, bool &r_valid) {
|
||||
GDExtensionBool valid;
|
||||
internal::gde_interface->variant_set_named(_native_ptr(), name._native_ptr(), value._native_ptr(), &valid);
|
||||
r_valid = PtrToArg<bool>::convert(&valid);
|
||||
}
|
||||
|
||||
void Variant::set_indexed(int64_t index, const Variant &value, bool &r_valid, bool &r_oob) {
|
||||
GDExtensionBool valid, oob;
|
||||
internal::gde_interface->variant_set_indexed(_native_ptr(), index, value._native_ptr(), &valid, &oob);
|
||||
r_valid = PtrToArg<bool>::convert(&valid);
|
||||
r_oob = PtrToArg<bool>::convert(&oob);
|
||||
}
|
||||
|
||||
void Variant::set_keyed(const Variant &key, const Variant &value, bool &r_valid) {
|
||||
GDExtensionBool valid;
|
||||
internal::gde_interface->variant_set_keyed(_native_ptr(), key._native_ptr(), value._native_ptr(), &valid);
|
||||
r_valid = PtrToArg<bool>::convert(&valid);
|
||||
}
|
||||
|
||||
Variant Variant::get(const Variant &key, bool *r_valid) const {
|
||||
Variant result;
|
||||
GDExtensionBool valid;
|
||||
internal::gde_interface->variant_get(_native_ptr(), key._native_ptr(), result._native_ptr(), &valid);
|
||||
if (r_valid) {
|
||||
*r_valid = PtrToArg<bool>::convert(&valid);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
Variant Variant::get_named(const StringName &name, bool &r_valid) const {
|
||||
Variant result;
|
||||
GDExtensionBool valid;
|
||||
internal::gde_interface->variant_get_named(_native_ptr(), name._native_ptr(), result._native_ptr(), &valid);
|
||||
r_valid = PtrToArg<bool>::convert(&valid);
|
||||
return result;
|
||||
}
|
||||
|
||||
Variant Variant::get_indexed(int64_t index, bool &r_valid, bool &r_oob) const {
|
||||
Variant result;
|
||||
GDExtensionBool valid;
|
||||
GDExtensionBool oob;
|
||||
internal::gde_interface->variant_get_indexed(_native_ptr(), index, result._native_ptr(), &valid, &oob);
|
||||
r_valid = PtrToArg<bool>::convert(&valid);
|
||||
r_oob = PtrToArg<bool>::convert(&oob);
|
||||
return result;
|
||||
}
|
||||
|
||||
Variant Variant::get_keyed(const Variant &key, bool &r_valid) const {
|
||||
Variant result;
|
||||
GDExtensionBool valid;
|
||||
internal::gde_interface->variant_get_keyed(_native_ptr(), key._native_ptr(), result._native_ptr(), &valid);
|
||||
r_valid = PtrToArg<bool>::convert(&valid);
|
||||
return result;
|
||||
}
|
||||
|
||||
bool Variant::in(const Variant &index, bool *r_valid) const {
|
||||
Variant result;
|
||||
bool valid;
|
||||
evaluate(OP_IN, *this, index, result, valid);
|
||||
if (r_valid) {
|
||||
*r_valid = valid;
|
||||
}
|
||||
return result.operator bool();
|
||||
}
|
||||
|
||||
bool Variant::iter_init(Variant &r_iter, bool &r_valid) const {
|
||||
GDExtensionBool valid;
|
||||
internal::gde_interface->variant_iter_init(_native_ptr(), r_iter._native_ptr(), &valid);
|
||||
return PtrToArg<bool>::convert(&valid);
|
||||
}
|
||||
|
||||
bool Variant::iter_next(Variant &r_iter, bool &r_valid) const {
|
||||
GDExtensionBool valid;
|
||||
internal::gde_interface->variant_iter_next(_native_ptr(), r_iter._native_ptr(), &valid);
|
||||
return PtrToArg<bool>::convert(&valid);
|
||||
}
|
||||
|
||||
Variant Variant::iter_get(const Variant &r_iter, bool &r_valid) const {
|
||||
Variant result;
|
||||
GDExtensionBool valid;
|
||||
internal::gde_interface->variant_iter_get(_native_ptr(), r_iter._native_ptr(), result._native_ptr(), &valid);
|
||||
r_valid = PtrToArg<bool>::convert(&valid);
|
||||
return result;
|
||||
}
|
||||
|
||||
Variant::Type Variant::get_type() const {
|
||||
return static_cast<Variant::Type>(internal::gde_interface->variant_get_type(_native_ptr()));
|
||||
}
|
||||
|
||||
bool Variant::has_method(const StringName &method) const {
|
||||
GDExtensionBool has = internal::gde_interface->variant_has_method(_native_ptr(), method._native_ptr());
|
||||
return PtrToArg<bool>::convert(&has);
|
||||
}
|
||||
|
||||
bool Variant::has_key(const Variant &key, bool *r_valid) const {
|
||||
GDExtensionBool valid;
|
||||
GDExtensionBool has = internal::gde_interface->variant_has_key(_native_ptr(), key._native_ptr(), &valid);
|
||||
if (r_valid) {
|
||||
*r_valid = PtrToArg<bool>::convert(&valid);
|
||||
}
|
||||
return PtrToArg<bool>::convert(&has);
|
||||
}
|
||||
|
||||
bool Variant::has_member(Variant::Type type, const StringName &member) {
|
||||
GDExtensionBool has = internal::gde_interface->variant_has_member(static_cast<GDExtensionVariantType>(type), member._native_ptr());
|
||||
return PtrToArg<bool>::convert(&has);
|
||||
}
|
||||
|
||||
uint32_t Variant::hash() const {
|
||||
GDExtensionInt hash = internal::gde_interface->variant_hash(_native_ptr());
|
||||
return PtrToArg<uint32_t>::convert(&hash);
|
||||
}
|
||||
|
||||
uint32_t Variant::recursive_hash(int recursion_count) const {
|
||||
GDExtensionInt hash = internal::gde_interface->variant_recursive_hash(_native_ptr(), recursion_count);
|
||||
return PtrToArg<uint32_t>::convert(&hash);
|
||||
}
|
||||
|
||||
bool Variant::hash_compare(const Variant &variant) const {
|
||||
GDExtensionBool compare = internal::gde_interface->variant_hash_compare(_native_ptr(), variant._native_ptr());
|
||||
return PtrToArg<bool>::convert(&compare);
|
||||
}
|
||||
|
||||
bool Variant::booleanize() const {
|
||||
GDExtensionBool booleanized = internal::gde_interface->variant_booleanize(_native_ptr());
|
||||
return PtrToArg<bool>::convert(&booleanized);
|
||||
}
|
||||
|
||||
String Variant::stringify() const {
|
||||
String result;
|
||||
internal::gde_interface->variant_stringify(_native_ptr(), result._native_ptr());
|
||||
return result;
|
||||
}
|
||||
|
||||
Variant Variant::duplicate(bool deep) const {
|
||||
Variant result;
|
||||
GDExtensionBool _deep;
|
||||
PtrToArg<bool>::encode(deep, &_deep);
|
||||
internal::gde_interface->variant_duplicate(_native_ptr(), result._native_ptr(), _deep);
|
||||
return result;
|
||||
}
|
||||
|
||||
String Variant::get_type_name(Variant::Type type) {
|
||||
String result;
|
||||
internal::gde_interface->variant_get_type_name(static_cast<GDExtensionVariantType>(type), result._native_ptr());
|
||||
return result;
|
||||
}
|
||||
|
||||
bool Variant::can_convert(Variant::Type from, Variant::Type to) {
|
||||
GDExtensionBool can = internal::gde_interface->variant_can_convert(static_cast<GDExtensionVariantType>(from), static_cast<GDExtensionVariantType>(to));
|
||||
return PtrToArg<bool>::convert(&can);
|
||||
}
|
||||
|
||||
bool Variant::can_convert_strict(Variant::Type from, Variant::Type to) {
|
||||
GDExtensionBool can = internal::gde_interface->variant_can_convert_strict(static_cast<GDExtensionVariantType>(from), static_cast<GDExtensionVariantType>(to));
|
||||
return PtrToArg<bool>::convert(&can);
|
||||
}
|
||||
|
||||
void Variant::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, // TRANSFORM3D,
|
||||
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,
|
||||
};
|
||||
|
||||
if (unlikely(needs_deinit[get_type()])) { // Make it fast for types that don't need deinit.
|
||||
internal::gde_interface->variant_destroy(_native_ptr());
|
||||
}
|
||||
internal::gde_interface->variant_new_nil(_native_ptr());
|
||||
}
|
||||
|
||||
} // namespace godot
|
199
lib/godot-cpp/src/variant/vector2.cpp
Normal file
199
lib/godot-cpp/src/variant/vector2.cpp
Normal file
@@ -0,0 +1,199 @@
|
||||
/**************************************************************************/
|
||||
/* vector2.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 <godot_cpp/variant/vector2.hpp>
|
||||
|
||||
#include <godot_cpp/variant/string.hpp>
|
||||
#include <godot_cpp/variant/vector2i.hpp>
|
||||
|
||||
namespace godot {
|
||||
|
||||
real_t Vector2::angle() const {
|
||||
return Math::atan2(y, x);
|
||||
}
|
||||
|
||||
Vector2 Vector2::from_angle(const real_t p_angle) {
|
||||
return Vector2(Math::cos(p_angle), Math::sin(p_angle));
|
||||
}
|
||||
|
||||
real_t Vector2::length() const {
|
||||
return Math::sqrt(x * x + y * y);
|
||||
}
|
||||
|
||||
real_t Vector2::length_squared() const {
|
||||
return x * x + y * y;
|
||||
}
|
||||
|
||||
void Vector2::normalize() {
|
||||
real_t l = x * x + y * y;
|
||||
if (l != 0) {
|
||||
l = Math::sqrt(l);
|
||||
x /= l;
|
||||
y /= l;
|
||||
}
|
||||
}
|
||||
|
||||
Vector2 Vector2::normalized() const {
|
||||
Vector2 v = *this;
|
||||
v.normalize();
|
||||
return v;
|
||||
}
|
||||
|
||||
bool Vector2::is_normalized() const {
|
||||
// use length_squared() instead of length() to avoid sqrt(), makes it more stringent.
|
||||
return Math::is_equal_approx(length_squared(), 1, (real_t)UNIT_EPSILON);
|
||||
}
|
||||
|
||||
real_t Vector2::distance_to(const Vector2 &p_vector2) const {
|
||||
return Math::sqrt((x - p_vector2.x) * (x - p_vector2.x) + (y - p_vector2.y) * (y - p_vector2.y));
|
||||
}
|
||||
|
||||
real_t Vector2::distance_squared_to(const Vector2 &p_vector2) const {
|
||||
return (x - p_vector2.x) * (x - p_vector2.x) + (y - p_vector2.y) * (y - p_vector2.y);
|
||||
}
|
||||
|
||||
real_t Vector2::angle_to(const Vector2 &p_vector2) const {
|
||||
return Math::atan2(cross(p_vector2), dot(p_vector2));
|
||||
}
|
||||
|
||||
real_t Vector2::angle_to_point(const Vector2 &p_vector2) const {
|
||||
return (p_vector2 - *this).angle();
|
||||
}
|
||||
|
||||
real_t Vector2::dot(const Vector2 &p_other) const {
|
||||
return x * p_other.x + y * p_other.y;
|
||||
}
|
||||
|
||||
real_t Vector2::cross(const Vector2 &p_other) const {
|
||||
return x * p_other.y - y * p_other.x;
|
||||
}
|
||||
|
||||
Vector2 Vector2::sign() const {
|
||||
return Vector2(SIGN(x), SIGN(y));
|
||||
}
|
||||
|
||||
Vector2 Vector2::floor() const {
|
||||
return Vector2(Math::floor(x), Math::floor(y));
|
||||
}
|
||||
|
||||
Vector2 Vector2::ceil() const {
|
||||
return Vector2(Math::ceil(x), Math::ceil(y));
|
||||
}
|
||||
|
||||
Vector2 Vector2::round() const {
|
||||
return Vector2(Math::round(x), Math::round(y));
|
||||
}
|
||||
|
||||
Vector2 Vector2::rotated(const real_t p_by) const {
|
||||
real_t sine = Math::sin(p_by);
|
||||
real_t cosi = Math::cos(p_by);
|
||||
return Vector2(
|
||||
x * cosi - y * sine,
|
||||
x * sine + y * cosi);
|
||||
}
|
||||
|
||||
Vector2 Vector2::posmod(const real_t p_mod) const {
|
||||
return Vector2(Math::fposmod(x, p_mod), Math::fposmod(y, p_mod));
|
||||
}
|
||||
|
||||
Vector2 Vector2::posmodv(const Vector2 &p_modv) const {
|
||||
return Vector2(Math::fposmod(x, p_modv.x), Math::fposmod(y, p_modv.y));
|
||||
}
|
||||
|
||||
Vector2 Vector2::project(const Vector2 &p_to) const {
|
||||
return p_to * (dot(p_to) / p_to.length_squared());
|
||||
}
|
||||
|
||||
Vector2 Vector2::clamp(const Vector2 &p_min, const Vector2 &p_max) const {
|
||||
return Vector2(
|
||||
CLAMP(x, p_min.x, p_max.x),
|
||||
CLAMP(y, p_min.y, p_max.y));
|
||||
}
|
||||
|
||||
Vector2 Vector2::snapped(const Vector2 &p_step) const {
|
||||
return Vector2(
|
||||
Math::snapped(x, p_step.x),
|
||||
Math::snapped(y, p_step.y));
|
||||
}
|
||||
|
||||
Vector2 Vector2::limit_length(const real_t p_len) const {
|
||||
const real_t l = length();
|
||||
Vector2 v = *this;
|
||||
if (l > 0 && p_len < l) {
|
||||
v /= l;
|
||||
v *= p_len;
|
||||
}
|
||||
|
||||
return v;
|
||||
}
|
||||
|
||||
Vector2 Vector2::move_toward(const Vector2 &p_to, const real_t p_delta) const {
|
||||
Vector2 v = *this;
|
||||
Vector2 vd = p_to - v;
|
||||
real_t len = vd.length();
|
||||
return len <= p_delta || len < (real_t)CMP_EPSILON ? p_to : v + vd / len * p_delta;
|
||||
}
|
||||
|
||||
// slide returns the component of the vector along the given plane, specified by its normal vector.
|
||||
Vector2 Vector2::slide(const Vector2 &p_normal) const {
|
||||
#ifdef MATH_CHECKS
|
||||
ERR_FAIL_COND_V_MSG(!p_normal.is_normalized(), Vector2(), "The normal Vector2 must be normalized.");
|
||||
#endif
|
||||
return *this - p_normal * this->dot(p_normal);
|
||||
}
|
||||
|
||||
Vector2 Vector2::bounce(const Vector2 &p_normal) const {
|
||||
return -reflect(p_normal);
|
||||
}
|
||||
|
||||
Vector2 Vector2::reflect(const Vector2 &p_normal) const {
|
||||
#ifdef MATH_CHECKS
|
||||
ERR_FAIL_COND_V_MSG(!p_normal.is_normalized(), Vector2(), "The normal Vector2 must be normalized.");
|
||||
#endif
|
||||
return 2.0f * p_normal * this->dot(p_normal) - *this;
|
||||
}
|
||||
|
||||
bool Vector2::is_equal_approx(const Vector2 &p_v) const {
|
||||
return Math::is_equal_approx(x, p_v.x) && Math::is_equal_approx(y, p_v.y);
|
||||
}
|
||||
|
||||
bool Vector2::is_zero_approx() const {
|
||||
return Math::is_zero_approx(x) && Math::is_zero_approx(y);
|
||||
}
|
||||
|
||||
Vector2::operator String() const {
|
||||
return "(" + String::num_real(x, false) + ", " + String::num_real(y, false) + ")";
|
||||
}
|
||||
|
||||
Vector2::operator Vector2i() const {
|
||||
return Vector2i(x, y);
|
||||
}
|
||||
|
||||
} // namespace godot
|
129
lib/godot-cpp/src/variant/vector2i.cpp
Normal file
129
lib/godot-cpp/src/variant/vector2i.cpp
Normal file
@@ -0,0 +1,129 @@
|
||||
/**************************************************************************/
|
||||
/* vector2i.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 <godot_cpp/variant/vector2i.hpp>
|
||||
|
||||
#include <godot_cpp/variant/string.hpp>
|
||||
#include <godot_cpp/variant/vector2.hpp>
|
||||
|
||||
namespace godot {
|
||||
|
||||
Vector2i Vector2i::clamp(const Vector2i &p_min, const Vector2i &p_max) const {
|
||||
return Vector2i(
|
||||
CLAMP(x, p_min.x, p_max.x),
|
||||
CLAMP(y, p_min.y, p_max.y));
|
||||
}
|
||||
|
||||
int64_t Vector2i::length_squared() const {
|
||||
return x * (int64_t)x + y * (int64_t)y;
|
||||
}
|
||||
|
||||
double Vector2i::length() const {
|
||||
return Math::sqrt((double)length_squared());
|
||||
}
|
||||
|
||||
Vector2i Vector2i::operator+(const Vector2i &p_v) const {
|
||||
return Vector2i(x + p_v.x, y + p_v.y);
|
||||
}
|
||||
|
||||
void Vector2i::operator+=(const Vector2i &p_v) {
|
||||
x += p_v.x;
|
||||
y += p_v.y;
|
||||
}
|
||||
|
||||
Vector2i Vector2i::operator-(const Vector2i &p_v) const {
|
||||
return Vector2i(x - p_v.x, y - p_v.y);
|
||||
}
|
||||
|
||||
void Vector2i::operator-=(const Vector2i &p_v) {
|
||||
x -= p_v.x;
|
||||
y -= p_v.y;
|
||||
}
|
||||
|
||||
Vector2i Vector2i::operator*(const Vector2i &p_v1) const {
|
||||
return Vector2i(x * p_v1.x, y * p_v1.y);
|
||||
}
|
||||
|
||||
Vector2i Vector2i::operator*(const int32_t &rvalue) const {
|
||||
return Vector2i(x * rvalue, y * rvalue);
|
||||
}
|
||||
|
||||
void Vector2i::operator*=(const int32_t &rvalue) {
|
||||
x *= rvalue;
|
||||
y *= rvalue;
|
||||
}
|
||||
|
||||
Vector2i Vector2i::operator/(const Vector2i &p_v1) const {
|
||||
return Vector2i(x / p_v1.x, y / p_v1.y);
|
||||
}
|
||||
|
||||
Vector2i Vector2i::operator/(const int32_t &rvalue) const {
|
||||
return Vector2i(x / rvalue, y / rvalue);
|
||||
}
|
||||
|
||||
void Vector2i::operator/=(const int32_t &rvalue) {
|
||||
x /= rvalue;
|
||||
y /= rvalue;
|
||||
}
|
||||
|
||||
Vector2i Vector2i::operator%(const Vector2i &p_v1) const {
|
||||
return Vector2i(x % p_v1.x, y % p_v1.y);
|
||||
}
|
||||
|
||||
Vector2i Vector2i::operator%(const int32_t &rvalue) const {
|
||||
return Vector2i(x % rvalue, y % rvalue);
|
||||
}
|
||||
|
||||
void Vector2i::operator%=(const int32_t &rvalue) {
|
||||
x %= rvalue;
|
||||
y %= rvalue;
|
||||
}
|
||||
|
||||
Vector2i Vector2i::operator-() const {
|
||||
return Vector2i(-x, -y);
|
||||
}
|
||||
|
||||
bool Vector2i::operator==(const Vector2i &p_vec2) const {
|
||||
return x == p_vec2.x && y == p_vec2.y;
|
||||
}
|
||||
|
||||
bool Vector2i::operator!=(const Vector2i &p_vec2) const {
|
||||
return x != p_vec2.x || y != p_vec2.y;
|
||||
}
|
||||
|
||||
Vector2i::operator String() const {
|
||||
return "(" + itos(x) + ", " + itos(y) + ")";
|
||||
}
|
||||
|
||||
Vector2i::operator Vector2() const {
|
||||
return Vector2((int32_t)x, (int32_t)y);
|
||||
}
|
||||
|
||||
} // namespace godot
|
152
lib/godot-cpp/src/variant/vector3.cpp
Normal file
152
lib/godot-cpp/src/variant/vector3.cpp
Normal file
@@ -0,0 +1,152 @@
|
||||
/**************************************************************************/
|
||||
/* vector3.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 <godot_cpp/variant/vector3.hpp>
|
||||
|
||||
#include <godot_cpp/variant/basis.hpp>
|
||||
#include <godot_cpp/variant/string.hpp>
|
||||
#include <godot_cpp/variant/vector2.hpp>
|
||||
#include <godot_cpp/variant/vector3i.hpp>
|
||||
|
||||
namespace godot {
|
||||
|
||||
void Vector3::rotate(const Vector3 &p_axis, const real_t p_angle) {
|
||||
*this = Basis(p_axis, p_angle).xform(*this);
|
||||
}
|
||||
|
||||
Vector3 Vector3::rotated(const Vector3 &p_axis, const real_t p_angle) const {
|
||||
Vector3 r = *this;
|
||||
r.rotate(p_axis, p_angle);
|
||||
return r;
|
||||
}
|
||||
|
||||
Vector3 Vector3::clamp(const Vector3 &p_min, const Vector3 &p_max) const {
|
||||
return Vector3(
|
||||
CLAMP(x, p_min.x, p_max.x),
|
||||
CLAMP(y, p_min.y, p_max.y),
|
||||
CLAMP(z, p_min.z, p_max.z));
|
||||
}
|
||||
|
||||
void Vector3::snap(const Vector3 p_step) {
|
||||
x = Math::snapped(x, p_step.x);
|
||||
y = Math::snapped(y, p_step.y);
|
||||
z = Math::snapped(z, p_step.z);
|
||||
}
|
||||
|
||||
Vector3 Vector3::snapped(const Vector3 p_step) const {
|
||||
Vector3 v = *this;
|
||||
v.snap(p_step);
|
||||
return v;
|
||||
}
|
||||
|
||||
Vector3 Vector3::limit_length(const real_t p_len) const {
|
||||
const real_t l = length();
|
||||
Vector3 v = *this;
|
||||
if (l > 0 && p_len < l) {
|
||||
v /= l;
|
||||
v *= p_len;
|
||||
}
|
||||
|
||||
return v;
|
||||
}
|
||||
|
||||
Vector3 Vector3::move_toward(const Vector3 &p_to, const real_t p_delta) const {
|
||||
Vector3 v = *this;
|
||||
Vector3 vd = p_to - v;
|
||||
real_t len = vd.length();
|
||||
return len <= p_delta || len < (real_t)CMP_EPSILON ? p_to : v + vd / len * p_delta;
|
||||
}
|
||||
|
||||
Vector2 Vector3::octahedron_encode() const {
|
||||
Vector3 n = *this;
|
||||
n /= Math::abs(n.x) + Math::abs(n.y) + Math::abs(n.z);
|
||||
Vector2 o;
|
||||
if (n.z >= 0.0f) {
|
||||
o.x = n.x;
|
||||
o.y = n.y;
|
||||
} else {
|
||||
o.x = (1.0f - Math::abs(n.y)) * (n.x >= 0.0f ? 1.0f : -1.0f);
|
||||
o.y = (1.0f - Math::abs(n.x)) * (n.y >= 0.0f ? 1.0f : -1.0f);
|
||||
}
|
||||
o.x = o.x * 0.5f + 0.5f;
|
||||
o.y = o.y * 0.5f + 0.5f;
|
||||
return o;
|
||||
}
|
||||
|
||||
Vector3 Vector3::octahedron_decode(const Vector2 &p_oct) {
|
||||
Vector2 f(p_oct.x * 2.0f - 1.0f, p_oct.y * 2.0f - 1.0f);
|
||||
Vector3 n(f.x, f.y, 1.0f - Math::abs(f.x) - Math::abs(f.y));
|
||||
float t = CLAMP(-n.z, 0.0f, 1.0f);
|
||||
n.x += n.x >= 0 ? -t : t;
|
||||
n.y += n.y >= 0 ? -t : t;
|
||||
return n.normalized();
|
||||
}
|
||||
|
||||
Vector2 Vector3::octahedron_tangent_encode(const float sign) const {
|
||||
Vector2 res = this->octahedron_encode();
|
||||
res.y = res.y * 0.5f + 0.5f;
|
||||
res.y = sign >= 0.0f ? res.y : 1 - res.y;
|
||||
return res;
|
||||
}
|
||||
|
||||
Vector3 Vector3::octahedron_tangent_decode(const Vector2 &p_oct, float *sign) {
|
||||
Vector2 oct_compressed = p_oct;
|
||||
oct_compressed.y = oct_compressed.y * 2 - 1;
|
||||
*sign = oct_compressed.y >= 0.0f ? 1.0f : -1.0f;
|
||||
oct_compressed.y = Math::abs(oct_compressed.y);
|
||||
Vector3 res = Vector3::octahedron_decode(oct_compressed);
|
||||
return res;
|
||||
}
|
||||
|
||||
Basis Vector3::outer(const Vector3 &p_with) const {
|
||||
Basis basis;
|
||||
basis.rows[0] = Vector3(x * p_with.x, x * p_with.y, x * p_with.z);
|
||||
basis.rows[1] = Vector3(y * p_with.x, y * p_with.y, y * p_with.z);
|
||||
basis.rows[2] = Vector3(z * p_with.x, z * p_with.y, z * p_with.z);
|
||||
return basis;
|
||||
}
|
||||
|
||||
bool Vector3::is_equal_approx(const Vector3 &p_v) const {
|
||||
return Math::is_equal_approx(x, p_v.x) && Math::is_equal_approx(y, p_v.y) && Math::is_equal_approx(z, p_v.z);
|
||||
}
|
||||
|
||||
bool Vector3::is_zero_approx() const {
|
||||
return Math::is_zero_approx(x) && Math::is_zero_approx(y) && Math::is_zero_approx(z);
|
||||
}
|
||||
|
||||
Vector3::operator String() const {
|
||||
return "(" + String::num_real(x, false) + ", " + String::num_real(y, false) + ", " + String::num_real(z, false) + ")";
|
||||
}
|
||||
|
||||
Vector3::operator Vector3i() const {
|
||||
return Vector3i(x, y, z);
|
||||
}
|
||||
|
||||
} // namespace godot
|
61
lib/godot-cpp/src/variant/vector3i.cpp
Normal file
61
lib/godot-cpp/src/variant/vector3i.cpp
Normal file
@@ -0,0 +1,61 @@
|
||||
/**************************************************************************/
|
||||
/* vector3i.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 <godot_cpp/variant/vector3i.hpp>
|
||||
|
||||
#include <godot_cpp/variant/string.hpp>
|
||||
#include <godot_cpp/variant/vector3.hpp>
|
||||
|
||||
namespace godot {
|
||||
|
||||
Vector3i::Axis Vector3i::min_axis_index() const {
|
||||
return x < y ? (x < z ? Vector3i::AXIS_X : Vector3i::AXIS_Z) : (y < z ? Vector3i::AXIS_Y : Vector3i::AXIS_Z);
|
||||
}
|
||||
|
||||
Vector3i::Axis Vector3i::max_axis_index() const {
|
||||
return x < y ? (y < z ? Vector3i::AXIS_Z : Vector3i::AXIS_Y) : (x < z ? Vector3i::AXIS_Z : Vector3i::AXIS_X);
|
||||
}
|
||||
|
||||
Vector3i Vector3i::clamp(const Vector3i &p_min, const Vector3i &p_max) const {
|
||||
return Vector3i(
|
||||
CLAMP(x, p_min.x, p_max.x),
|
||||
CLAMP(y, p_min.y, p_max.y),
|
||||
CLAMP(z, p_min.z, p_max.z));
|
||||
}
|
||||
|
||||
Vector3i::operator String() const {
|
||||
return "(" + itos(x) + ", " + itos(y) + ", " + itos(z) + ")";
|
||||
}
|
||||
|
||||
Vector3i::operator Vector3() const {
|
||||
return Vector3(x, y, z);
|
||||
}
|
||||
|
||||
} // namespace godot
|
196
lib/godot-cpp/src/variant/vector4.cpp
Normal file
196
lib/godot-cpp/src/variant/vector4.cpp
Normal file
@@ -0,0 +1,196 @@
|
||||
/**************************************************************************/
|
||||
/* vector4.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 <godot_cpp/variant/vector4.hpp>
|
||||
|
||||
#include <godot_cpp/variant/string.hpp>
|
||||
#include <godot_cpp/variant/vector4i.hpp>
|
||||
|
||||
namespace godot {
|
||||
|
||||
Vector4::Axis Vector4::min_axis_index() const {
|
||||
uint32_t min_index = 0;
|
||||
real_t min_value = x;
|
||||
for (uint32_t i = 1; i < 4; i++) {
|
||||
if (operator[](i) <= min_value) {
|
||||
min_index = i;
|
||||
min_value = operator[](i);
|
||||
}
|
||||
}
|
||||
return Vector4::Axis(min_index);
|
||||
}
|
||||
|
||||
Vector4::Axis Vector4::max_axis_index() const {
|
||||
uint32_t max_index = 0;
|
||||
real_t max_value = x;
|
||||
for (uint32_t i = 1; i < 4; i++) {
|
||||
if (operator[](i) > max_value) {
|
||||
max_index = i;
|
||||
max_value = operator[](i);
|
||||
}
|
||||
}
|
||||
return Vector4::Axis(max_index);
|
||||
}
|
||||
|
||||
bool Vector4::is_equal_approx(const Vector4 &p_vec4) const {
|
||||
return Math::is_equal_approx(x, p_vec4.x) && Math::is_equal_approx(y, p_vec4.y) && Math::is_equal_approx(z, p_vec4.z) && Math::is_equal_approx(w, p_vec4.w);
|
||||
}
|
||||
|
||||
bool Vector4::is_zero_approx() const {
|
||||
return Math::is_zero_approx(x) && Math::is_zero_approx(y) && Math::is_zero_approx(z) && Math::is_zero_approx(w);
|
||||
}
|
||||
|
||||
real_t Vector4::length() const {
|
||||
return Math::sqrt(length_squared());
|
||||
}
|
||||
|
||||
void Vector4::normalize() {
|
||||
real_t lengthsq = length_squared();
|
||||
if (lengthsq == 0) {
|
||||
x = y = z = w = 0;
|
||||
} else {
|
||||
real_t length = Math::sqrt(lengthsq);
|
||||
x /= length;
|
||||
y /= length;
|
||||
z /= length;
|
||||
w /= length;
|
||||
}
|
||||
}
|
||||
|
||||
Vector4 Vector4::normalized() const {
|
||||
Vector4 v = *this;
|
||||
v.normalize();
|
||||
return v;
|
||||
}
|
||||
|
||||
bool Vector4::is_normalized() const {
|
||||
return Math::is_equal_approx(length_squared(), (real_t)1, (real_t)UNIT_EPSILON);
|
||||
}
|
||||
|
||||
real_t Vector4::distance_to(const Vector4 &p_to) const {
|
||||
return (p_to - *this).length();
|
||||
}
|
||||
|
||||
real_t Vector4::distance_squared_to(const Vector4 &p_to) const {
|
||||
return (p_to - *this).length_squared();
|
||||
}
|
||||
|
||||
Vector4 Vector4::direction_to(const Vector4 &p_to) const {
|
||||
Vector4 ret(p_to.x - x, p_to.y - y, p_to.z - z, p_to.w - w);
|
||||
ret.normalize();
|
||||
return ret;
|
||||
}
|
||||
|
||||
Vector4 Vector4::abs() const {
|
||||
return Vector4(Math::abs(x), Math::abs(y), Math::abs(z), Math::abs(w));
|
||||
}
|
||||
|
||||
Vector4 Vector4::sign() const {
|
||||
return Vector4(Math::sign(x), Math::sign(y), Math::sign(z), Math::sign(w));
|
||||
}
|
||||
|
||||
Vector4 Vector4::floor() const {
|
||||
return Vector4(Math::floor(x), Math::floor(y), Math::floor(z), Math::floor(w));
|
||||
}
|
||||
|
||||
Vector4 Vector4::ceil() const {
|
||||
return Vector4(Math::ceil(x), Math::ceil(y), Math::ceil(z), Math::ceil(w));
|
||||
}
|
||||
|
||||
Vector4 Vector4::round() const {
|
||||
return Vector4(Math::round(x), Math::round(y), Math::round(z), Math::round(w));
|
||||
}
|
||||
|
||||
Vector4 Vector4::lerp(const Vector4 &p_to, const real_t p_weight) const {
|
||||
return Vector4(
|
||||
x + (p_weight * (p_to.x - x)),
|
||||
y + (p_weight * (p_to.y - y)),
|
||||
z + (p_weight * (p_to.z - z)),
|
||||
w + (p_weight * (p_to.w - w)));
|
||||
}
|
||||
|
||||
Vector4 Vector4::cubic_interpolate(const Vector4 &p_b, const Vector4 &p_pre_a, const Vector4 &p_post_b, const real_t p_weight) const {
|
||||
Vector4 res = *this;
|
||||
res.x = Math::cubic_interpolate(res.x, p_b.x, p_pre_a.x, p_post_b.x, p_weight);
|
||||
res.y = Math::cubic_interpolate(res.y, p_b.y, p_pre_a.y, p_post_b.y, p_weight);
|
||||
res.z = Math::cubic_interpolate(res.z, p_b.z, p_pre_a.z, p_post_b.z, p_weight);
|
||||
res.w = Math::cubic_interpolate(res.w, p_b.w, p_pre_a.w, p_post_b.w, p_weight);
|
||||
return res;
|
||||
}
|
||||
|
||||
Vector4 Vector4::cubic_interpolate_in_time(const Vector4 &p_b, const Vector4 &p_pre_a, const Vector4 &p_post_b, const real_t p_weight, const real_t &p_b_t, const real_t &p_pre_a_t, const real_t &p_post_b_t) const {
|
||||
Vector4 res = *this;
|
||||
res.x = Math::cubic_interpolate_in_time(res.x, p_b.x, p_pre_a.x, p_post_b.x, p_weight, p_b_t, p_pre_a_t, p_post_b_t);
|
||||
res.y = Math::cubic_interpolate_in_time(res.y, p_b.y, p_pre_a.y, p_post_b.y, p_weight, p_b_t, p_pre_a_t, p_post_b_t);
|
||||
res.z = Math::cubic_interpolate_in_time(res.z, p_b.z, p_pre_a.z, p_post_b.z, p_weight, p_b_t, p_pre_a_t, p_post_b_t);
|
||||
res.w = Math::cubic_interpolate_in_time(res.w, p_b.w, p_pre_a.w, p_post_b.w, p_weight, p_b_t, p_pre_a_t, p_post_b_t);
|
||||
return res;
|
||||
}
|
||||
|
||||
Vector4 Vector4::posmod(const real_t p_mod) const {
|
||||
return Vector4(Math::fposmod(x, p_mod), Math::fposmod(y, p_mod), Math::fposmod(z, p_mod), Math::fposmod(w, p_mod));
|
||||
}
|
||||
|
||||
Vector4 Vector4::posmodv(const Vector4 &p_modv) const {
|
||||
return Vector4(Math::fposmod(x, p_modv.x), Math::fposmod(y, p_modv.y), Math::fposmod(z, p_modv.z), Math::fposmod(w, p_modv.w));
|
||||
}
|
||||
|
||||
void Vector4::snap(const Vector4 &p_step) {
|
||||
x = Math::snapped(x, p_step.x);
|
||||
y = Math::snapped(y, p_step.y);
|
||||
z = Math::snapped(z, p_step.z);
|
||||
w = Math::snapped(w, p_step.w);
|
||||
}
|
||||
|
||||
Vector4 Vector4::snapped(const Vector4 &p_step) const {
|
||||
Vector4 v = *this;
|
||||
v.snap(p_step);
|
||||
return v;
|
||||
}
|
||||
|
||||
Vector4 Vector4::inverse() const {
|
||||
return Vector4(1.0f / x, 1.0f / y, 1.0f / z, 1.0f / w);
|
||||
}
|
||||
|
||||
Vector4 Vector4::clamp(const Vector4 &p_min, const Vector4 &p_max) const {
|
||||
return Vector4(
|
||||
CLAMP(x, p_min.x, p_max.x),
|
||||
CLAMP(y, p_min.y, p_max.y),
|
||||
CLAMP(z, p_min.z, p_max.z),
|
||||
CLAMP(w, p_min.w, p_max.w));
|
||||
}
|
||||
|
||||
Vector4::operator String() const {
|
||||
return "(" + String::num_real(x, false) + ", " + String::num_real(y, false) + ", " + String::num_real(z, false) + ", " + String::num_real(w, false) + ")";
|
||||
}
|
||||
|
||||
static_assert(sizeof(Vector4) == 4 * sizeof(real_t));
|
||||
|
||||
} // namespace godot
|
87
lib/godot-cpp/src/variant/vector4i.cpp
Normal file
87
lib/godot-cpp/src/variant/vector4i.cpp
Normal file
@@ -0,0 +1,87 @@
|
||||
/**************************************************************************/
|
||||
/* vector4i.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 <godot_cpp/variant/vector4i.hpp>
|
||||
|
||||
#include <godot_cpp/variant/string.hpp>
|
||||
#include <godot_cpp/variant/vector4.hpp>
|
||||
|
||||
namespace godot {
|
||||
|
||||
Vector4i::Axis Vector4i::min_axis_index() const {
|
||||
uint32_t min_index = 0;
|
||||
int32_t min_value = x;
|
||||
for (uint32_t i = 1; i < 4; i++) {
|
||||
if (operator[](i) <= min_value) {
|
||||
min_index = i;
|
||||
min_value = operator[](i);
|
||||
}
|
||||
}
|
||||
return Vector4i::Axis(min_index);
|
||||
}
|
||||
|
||||
Vector4i::Axis Vector4i::max_axis_index() const {
|
||||
uint32_t max_index = 0;
|
||||
int32_t max_value = x;
|
||||
for (uint32_t i = 1; i < 4; i++) {
|
||||
if (operator[](i) > max_value) {
|
||||
max_index = i;
|
||||
max_value = operator[](i);
|
||||
}
|
||||
}
|
||||
return Vector4i::Axis(max_index);
|
||||
}
|
||||
|
||||
Vector4i Vector4i::clamp(const Vector4i &p_min, const Vector4i &p_max) const {
|
||||
return Vector4i(
|
||||
CLAMP(x, p_min.x, p_max.x),
|
||||
CLAMP(y, p_min.y, p_max.y),
|
||||
CLAMP(z, p_min.z, p_max.z),
|
||||
CLAMP(w, p_min.w, p_max.w));
|
||||
}
|
||||
|
||||
Vector4i::operator String() const {
|
||||
return "(" + itos(x) + ", " + itos(y) + ", " + itos(z) + ", " + itos(w) + ")";
|
||||
}
|
||||
|
||||
Vector4i::operator Vector4() const {
|
||||
return Vector4(x, y, z, w);
|
||||
}
|
||||
|
||||
Vector4i::Vector4i(const Vector4 &p_vec4) {
|
||||
x = (int32_t)p_vec4.x;
|
||||
y = (int32_t)p_vec4.y;
|
||||
z = (int32_t)p_vec4.z;
|
||||
w = (int32_t)p_vec4.w;
|
||||
}
|
||||
|
||||
static_assert(sizeof(Vector4i) == 4 * sizeof(int32_t));
|
||||
|
||||
} // namespace godot
|
Reference in New Issue
Block a user