diff options
Diffstat (limited to 'src/variant/callable_custom.cpp')
-rw-r--r-- | src/variant/callable_custom.cpp | 113 |
1 files changed, 113 insertions, 0 deletions
diff --git a/src/variant/callable_custom.cpp b/src/variant/callable_custom.cpp new file mode 100644 index 0000000..e0540fa --- /dev/null +++ b/src/variant/callable_custom.cpp @@ -0,0 +1,113 @@ +/**************************************************************************/ +/* callable_custom.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/callable_custom.hpp> + +#include <godot_cpp/core/object.hpp> +#include <godot_cpp/variant/callable.hpp> + +namespace godot { + +static void callable_custom_call(void *p_userdata, const GDExtensionConstVariantPtr *p_args, GDExtensionInt p_argument_count, GDExtensionVariantPtr r_return, GDExtensionCallError *r_error) { + CallableCustom *callable_custom = (CallableCustom *)p_userdata; + callable_custom->call((const Variant **)p_args, p_argument_count, *(Variant *)r_return, *r_error); +} + +static GDExtensionBool callable_custom_is_valid(void *p_userdata) { + CallableCustom *callable_custom = (CallableCustom *)p_userdata; + return callable_custom->is_valid(); +} + +static void callable_custom_free(void *p_userdata) { + CallableCustom *callable_custom = (CallableCustom *)p_userdata; + memdelete(callable_custom); +} + +static uint32_t callable_custom_hash(void *p_userdata) { + CallableCustom *callable_custom = (CallableCustom *)p_userdata; + return callable_custom->hash(); +} + +static void callable_custom_to_string(void *p_userdata, GDExtensionBool *r_is_valid, GDExtensionStringPtr r_out) { + CallableCustom *callable_custom = (CallableCustom *)p_userdata; + *((String *)r_out) = callable_custom->get_as_text(); + *r_is_valid = true; +} + +static GDExtensionBool callable_custom_equal_func(void *p_a, void *p_b) { + CallableCustom *a = (CallableCustom *)p_a; + CallableCustom *b = (CallableCustom *)p_b; + CallableCustom::CompareEqualFunc func_a = a->get_compare_equal_func(); + CallableCustom::CompareEqualFunc func_b = b->get_compare_equal_func(); + if (func_a != func_b) { + return false; + } + return func_a(a, b); +} + +static GDExtensionBool callable_custom_less_than_func(void *p_a, void *p_b) { + CallableCustom *a = (CallableCustom *)p_a; + CallableCustom *b = (CallableCustom *)p_b; + CallableCustom::CompareEqualFunc func_a = a->get_compare_less_func(); + CallableCustom::CompareEqualFunc func_b = b->get_compare_less_func(); + if (func_a != func_b) { + // Just compare the addresses. + return p_a < p_b; + } + return func_a(a, b); +} + +bool CallableCustom::is_valid() const { + // The same default implementation as in Godot. + return ObjectDB::get_instance(get_object()); +} + +Callable::Callable(CallableCustom *p_callable_custom) { + GDExtensionCallableCustomInfo info = {}; + info.callable_userdata = p_callable_custom; + info.token = internal::token; + info.object_id = p_callable_custom->get_object(); + info.call_func = &callable_custom_call; + info.is_valid_func = &callable_custom_is_valid; + info.free_func = &callable_custom_free; + info.hash_func = &callable_custom_hash; + info.equal_func = &callable_custom_equal_func; + info.less_than_func = &callable_custom_less_than_func; + info.to_string_func = &callable_custom_to_string; + + ::godot::internal::gdextension_interface_callable_custom_create(_native_ptr(), &info); +} + +CallableCustom *Callable::get_custom() const { + CallableCustomBase *callable_custom = (CallableCustomBase *)::godot::internal::gdextension_interface_callable_custom_get_userdata(_native_ptr(), internal::token); + return dynamic_cast<CallableCustom *>(callable_custom); +} + +} // namespace godot |