Merge pull request #49744 from reduz/implement-native-extensions
Implement native extension system
This commit is contained in:
commit
56dafe9164
|
@ -186,6 +186,7 @@ SConscript("io/SCsub")
|
|||
SConscript("debugger/SCsub")
|
||||
SConscript("input/SCsub")
|
||||
SConscript("variant/SCsub")
|
||||
SConscript("extension/SCsub")
|
||||
SConscript("object/SCsub")
|
||||
SConscript("templates/SCsub")
|
||||
SConscript("string/SCsub")
|
||||
|
|
|
@ -236,9 +236,10 @@ Engine::Engine() {
|
|||
singleton = this;
|
||||
}
|
||||
|
||||
Engine::Singleton::Singleton(const StringName &p_name, Object *p_ptr) :
|
||||
Engine::Singleton::Singleton(const StringName &p_name, Object *p_ptr, const StringName &p_class_name) :
|
||||
name(p_name),
|
||||
ptr(p_ptr) {
|
||||
ptr(p_ptr),
|
||||
class_name(p_class_name) {
|
||||
#ifdef DEBUG_ENABLED
|
||||
RefCounted *rc = Object::cast_to<RefCounted>(p_ptr);
|
||||
if (rc && !rc->is_referenced()) {
|
||||
|
|
|
@ -41,7 +41,8 @@ public:
|
|||
struct Singleton {
|
||||
StringName name;
|
||||
Object *ptr;
|
||||
Singleton(const StringName &p_name = StringName(), Object *p_ptr = nullptr);
|
||||
StringName class_name; //used for binding generation hinting
|
||||
Singleton(const StringName &p_name = StringName(), Object *p_ptr = nullptr, const StringName &p_class_name = StringName());
|
||||
};
|
||||
|
||||
private:
|
||||
|
|
|
@ -0,0 +1,7 @@
|
|||
#!/usr/bin/env python
|
||||
|
||||
Import("env")
|
||||
|
||||
env_extension = env.Clone()
|
||||
|
||||
env_extension.add_source_files(env.core_sources, "*.cpp")
|
|
@ -0,0 +1,805 @@
|
|||
/*************************************************************************/
|
||||
/* extension_api_dump.cpp */
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* https://godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
|
||||
/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
|
||||
/* */
|
||||
/* 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 "extension_api_dump.h"
|
||||
#include "core/config/engine.h"
|
||||
#include "core/core_constants.h"
|
||||
#include "core/io/file_access.h"
|
||||
#include "core/io/json.h"
|
||||
#include "core/templates/pair.h"
|
||||
#include "core/version.h"
|
||||
|
||||
#ifdef TOOLS_ENABLED
|
||||
|
||||
Dictionary NativeExtensionAPIDump::generate_extension_api() {
|
||||
Dictionary api_dump;
|
||||
|
||||
{
|
||||
//header
|
||||
Dictionary header;
|
||||
header["version_major"] = VERSION_MAJOR;
|
||||
header["version_minor"] = VERSION_MINOR;
|
||||
#if VERSION_PATCH
|
||||
header["version_patch"] = VERSION_PATCH;
|
||||
#else
|
||||
header["version_patch"] = 0;
|
||||
#endif
|
||||
header["version_status"] = VERSION_STATUS;
|
||||
header["version_build"] = VERSION_BUILD;
|
||||
header["version_full_name"] = VERSION_FULL_NAME;
|
||||
|
||||
api_dump["header"] = header;
|
||||
}
|
||||
|
||||
const uint32_t vec3_elems = 3;
|
||||
const uint32_t ptrsize_32 = 4;
|
||||
const uint32_t ptrsize_64 = 4;
|
||||
static const char *build_config_name[4] = { "float_32", "float_64", "double_32", "double_64" };
|
||||
|
||||
{
|
||||
//type sizes
|
||||
struct {
|
||||
Variant::Type type;
|
||||
uint32_t size_32_bits_real_float;
|
||||
uint32_t size_64_bits_real_float;
|
||||
uint32_t size_32_bits_real_double;
|
||||
uint32_t size_64_bits_real_double;
|
||||
} type_size_array[Variant::VARIANT_MAX + 1] = {
|
||||
{ Variant::NIL, 0, 0, 0, 0 },
|
||||
{ Variant::BOOL, sizeof(uint32_t), sizeof(uint32_t), sizeof(uint32_t), sizeof(uint32_t) },
|
||||
{ Variant::INT, sizeof(int64_t), sizeof(int64_t), sizeof(int64_t), sizeof(int64_t) },
|
||||
{ Variant::FLOAT, sizeof(double), sizeof(double), sizeof(double), sizeof(double) },
|
||||
{ Variant::STRING, ptrsize_32, ptrsize_64, ptrsize_32, ptrsize_64 },
|
||||
{ Variant::VECTOR2, 2 * sizeof(float), 2 * sizeof(float), 2 * sizeof(double), 2 * sizeof(double) },
|
||||
{ Variant::VECTOR2I, 2 * sizeof(int32_t), 2 * sizeof(int32_t), 2 * sizeof(int32_t), 2 * sizeof(int32_t) },
|
||||
{ Variant::RECT2, 4 * sizeof(float), 4 * sizeof(float), 4 * sizeof(double), 4 * sizeof(double) },
|
||||
{ Variant::RECT2I, 4 * sizeof(int32_t), 4 * sizeof(int32_t), 4 * sizeof(int32_t), 4 * sizeof(int32_t) },
|
||||
{ Variant::VECTOR3, vec3_elems * sizeof(float), vec3_elems * sizeof(float), vec3_elems * sizeof(double), vec3_elems * sizeof(double) },
|
||||
{ Variant::VECTOR3I, 3 * sizeof(int32_t), 3 * sizeof(int32_t), 3 * sizeof(int32_t), 3 * sizeof(int32_t) },
|
||||
{ Variant::TRANSFORM2D, 6 * sizeof(float), 6 * sizeof(float), 6 * sizeof(double), 6 * sizeof(double) },
|
||||
{ Variant::PLANE, (vec3_elems + 1) * sizeof(float), (vec3_elems + 1) * sizeof(float), (vec3_elems + 1) * sizeof(double), (vec3_elems + 1) * sizeof(double) },
|
||||
{ Variant::QUATERNION, 4 * sizeof(float), 4 * sizeof(float), 4 * sizeof(double), 4 * sizeof(double) },
|
||||
{ Variant::AABB, (vec3_elems * 2) * sizeof(float), (vec3_elems * 2) * sizeof(float), (vec3_elems * 2) * sizeof(double), (vec3_elems * 2) * sizeof(double) },
|
||||
{ Variant::BASIS, (vec3_elems * 3) * sizeof(float), (vec3_elems * 3) * sizeof(float), (vec3_elems * 3) * sizeof(double), (vec3_elems * 3) * sizeof(double) },
|
||||
{ Variant::TRANSFORM3D, (vec3_elems * 4) * sizeof(float), (vec3_elems * 4) * sizeof(float), (vec3_elems * 4) * sizeof(double), (vec3_elems * 4) * sizeof(double) },
|
||||
{ Variant::COLOR, 4 * sizeof(float), 4 * sizeof(float), 4 * sizeof(float), 4 * sizeof(float) },
|
||||
{ Variant::STRING_NAME, ptrsize_32, ptrsize_64, ptrsize_32, ptrsize_64 },
|
||||
{ Variant::NODE_PATH, ptrsize_32, ptrsize_64, ptrsize_32, ptrsize_64 },
|
||||
{ Variant::RID, sizeof(uint64_t), sizeof(uint64_t), sizeof(uint64_t), sizeof(uint64_t) },
|
||||
{ Variant::OBJECT, ptrsize_32, ptrsize_64, ptrsize_32, ptrsize_64 },
|
||||
{ Variant::CALLABLE, sizeof(Callable), sizeof(Callable), sizeof(Callable), sizeof(Callable) }, //harcoded align
|
||||
{ Variant::SIGNAL, sizeof(Signal), sizeof(Signal), sizeof(Signal), sizeof(Signal) }, //harcoded align
|
||||
{ Variant::DICTIONARY, ptrsize_32, ptrsize_64, ptrsize_32, ptrsize_64 },
|
||||
{ Variant::ARRAY, ptrsize_32, ptrsize_64, ptrsize_32, ptrsize_64 },
|
||||
{ Variant::PACKED_BYTE_ARRAY, ptrsize_32, ptrsize_64, ptrsize_32, ptrsize_64 },
|
||||
{ Variant::PACKED_INT32_ARRAY, ptrsize_32, ptrsize_64, ptrsize_32, ptrsize_64 },
|
||||
{ Variant::PACKED_INT64_ARRAY, ptrsize_32, ptrsize_64, ptrsize_32, ptrsize_64 },
|
||||
{ Variant::PACKED_FLOAT32_ARRAY, ptrsize_32, ptrsize_64, ptrsize_32, ptrsize_64 },
|
||||
{ Variant::PACKED_FLOAT64_ARRAY, ptrsize_32, ptrsize_64, ptrsize_32, ptrsize_64 },
|
||||
{ Variant::PACKED_STRING_ARRAY, ptrsize_32, ptrsize_64, ptrsize_32, ptrsize_64 },
|
||||
{ Variant::PACKED_VECTOR2_ARRAY, ptrsize_32, ptrsize_64, ptrsize_32, ptrsize_64 },
|
||||
{ Variant::PACKED_VECTOR3_ARRAY, ptrsize_32, ptrsize_64, ptrsize_32, ptrsize_64 },
|
||||
{ Variant::PACKED_COLOR_ARRAY, ptrsize_32, ptrsize_64, ptrsize_32, ptrsize_64 },
|
||||
{ Variant::VARIANT_MAX, sizeof(uint64_t) + sizeof(float) * 4, sizeof(uint64_t) + sizeof(float) * 4, sizeof(uint64_t) + sizeof(double) * 4, sizeof(uint64_t) + sizeof(double) * 4 },
|
||||
};
|
||||
|
||||
Array core_type_sizes;
|
||||
|
||||
for (int i = 0; i < 4; i++) {
|
||||
Dictionary d;
|
||||
d["build_configuration"] = build_config_name[i];
|
||||
Array sizes;
|
||||
for (int j = 0; j < Variant::VARIANT_MAX; j++) {
|
||||
Variant::Type t = type_size_array[j].type;
|
||||
String name = t == Variant::VARIANT_MAX ? String("Variant") : Variant::get_type_name(t);
|
||||
Dictionary d2;
|
||||
d2["name"] = name;
|
||||
uint32_t size;
|
||||
switch (i) {
|
||||
case 0:
|
||||
size = type_size_array[j].size_32_bits_real_float;
|
||||
break;
|
||||
case 1:
|
||||
size = type_size_array[j].size_64_bits_real_float;
|
||||
break;
|
||||
case 2:
|
||||
size = type_size_array[j].size_32_bits_real_double;
|
||||
break;
|
||||
case 3:
|
||||
size = type_size_array[j].size_64_bits_real_double;
|
||||
break;
|
||||
}
|
||||
d2["size"] = size;
|
||||
sizes.push_back(d2);
|
||||
}
|
||||
d["sizes"] = sizes;
|
||||
core_type_sizes.push_back(d);
|
||||
}
|
||||
api_dump["builtin_class_sizes"] = core_type_sizes;
|
||||
}
|
||||
|
||||
{
|
||||
//member offsets sizes
|
||||
struct {
|
||||
Variant::Type type;
|
||||
const char *member;
|
||||
uint32_t offset_32_bits_real_float;
|
||||
uint32_t offset_64_bits_real_float;
|
||||
uint32_t offset_32_bits_real_double;
|
||||
uint32_t offset_64_bits_real_double;
|
||||
} member_offset_array[] = {
|
||||
{ Variant::VECTOR2, "x", 0, 0, 0, 0 },
|
||||
{ Variant::VECTOR2, "y", sizeof(float), sizeof(float), sizeof(double), sizeof(double) },
|
||||
{ Variant::VECTOR2I, "x", 0, 0, 0, 0 },
|
||||
{ Variant::VECTOR2I, "y", sizeof(int32_t), sizeof(int32_t), sizeof(int32_t), sizeof(int32_t) },
|
||||
{ Variant::RECT2, "position", 0, 0, 0, 0 },
|
||||
{ Variant::RECT2, "size", 2 * sizeof(Vector2), 2 * sizeof(float), 2 * sizeof(double), 2 * sizeof(double) },
|
||||
{ Variant::RECT2I, "position", 0, 0, 0, 0 },
|
||||
{ Variant::RECT2I, "size", 2 * sizeof(int32_t), 2 * sizeof(int32_t), 2 * sizeof(int32_t), 2 * sizeof(int32_t) },
|
||||
{ Variant::VECTOR3, "x", 0, 0, 0, 0 },
|
||||
{ Variant::VECTOR3, "y", sizeof(float), sizeof(float), sizeof(double), sizeof(double) },
|
||||
{ Variant::VECTOR3, "z", 2 * sizeof(float), 2 * sizeof(float), 2 * sizeof(double), 2 * sizeof(double) },
|
||||
{ Variant::VECTOR3I, "x", 0, 0, 0, 0 },
|
||||
{ Variant::VECTOR3I, "y", sizeof(int32_t), sizeof(int32_t), sizeof(int32_t), sizeof(int32_t) },
|
||||
{ Variant::VECTOR3I, "z", 2 * sizeof(int32_t), 2 * sizeof(int32_t), 2 * sizeof(int32_t), 2 * sizeof(int32_t) },
|
||||
{ Variant::TRANSFORM2D, "x", 0, 0, 0, 0 },
|
||||
{ Variant::TRANSFORM2D, "y", 2 * sizeof(float), 2 * sizeof(float), 2 * sizeof(double), 2 * sizeof(double) },
|
||||
{ Variant::TRANSFORM2D, "origin", 4 * sizeof(float), 4 * sizeof(float), 4 * sizeof(double), 4 * sizeof(double) },
|
||||
{ Variant::PLANE, "normal", 0, 0, 0, 0 },
|
||||
{ Variant::PLANE, "d", vec3_elems * sizeof(float), vec3_elems * sizeof(float), vec3_elems * sizeof(double), vec3_elems * sizeof(double) },
|
||||
{ Variant::QUATERNION, "x", 0, 0, 0, 0 },
|
||||
{ Variant::QUATERNION, "y", sizeof(float), sizeof(float), sizeof(double), sizeof(double) },
|
||||
{ Variant::QUATERNION, "z", 2 * sizeof(float), 2 * sizeof(float), 2 * sizeof(double), 2 * sizeof(double) },
|
||||
{ Variant::QUATERNION, "w", 3 * sizeof(float), 3 * sizeof(float), 3 * sizeof(double), 3 * sizeof(double) },
|
||||
{ Variant::AABB, "position", 0, 0, 0, 0 },
|
||||
{ Variant::AABB, "size", vec3_elems * sizeof(float), vec3_elems * sizeof(float), vec3_elems * sizeof(double), vec3_elems * sizeof(double) },
|
||||
//rememer that basis vectors are flipped!
|
||||
{ Variant::BASIS, "x", 0, 0, 0, 0 },
|
||||
{ Variant::BASIS, "y", vec3_elems * sizeof(float), vec3_elems * sizeof(float), vec3_elems * sizeof(double), vec3_elems * sizeof(double) },
|
||||
{ Variant::BASIS, "z", vec3_elems * 2 * sizeof(float), vec3_elems * 2 * sizeof(float), vec3_elems * 2 * sizeof(double), vec3_elems * 2 * sizeof(double) },
|
||||
{ Variant::TRANSFORM3D, "basis", 0, 0, 0, 0 },
|
||||
{ Variant::TRANSFORM3D, "origin", (vec3_elems * 3) * sizeof(float), (vec3_elems * 3) * sizeof(float), (vec3_elems * 3) * sizeof(double), (vec3_elems * 3) * sizeof(double) },
|
||||
{ Variant::COLOR, "x", 0, 0, 0, 0 },
|
||||
{ Variant::COLOR, "y", sizeof(float), sizeof(float), sizeof(float), sizeof(float) },
|
||||
{ Variant::COLOR, "z", 2 * sizeof(float), 2 * sizeof(float), 2 * sizeof(float), 2 * sizeof(float) },
|
||||
{ Variant::COLOR, "w", 3 * sizeof(float), 3 * sizeof(float), 3 * sizeof(float), 3 * sizeof(float) },
|
||||
{ Variant::NIL, nullptr, 0, 0, 0, 0 },
|
||||
};
|
||||
|
||||
Array core_type_member_offsets;
|
||||
|
||||
for (int i = 0; i < 4; i++) {
|
||||
Dictionary d;
|
||||
d["build_configuration"] = build_config_name[i];
|
||||
Array type_offsets;
|
||||
uint32_t idx = 0;
|
||||
|
||||
Variant::Type last_type = Variant::NIL;
|
||||
|
||||
Dictionary d2;
|
||||
Array members;
|
||||
|
||||
while (true) {
|
||||
Variant::Type t = member_offset_array[idx].type;
|
||||
if (t != last_type) {
|
||||
if (last_type != Variant::NIL) {
|
||||
d2["members"] = members;
|
||||
type_offsets.push_back(d2);
|
||||
}
|
||||
if (t == Variant::NIL) {
|
||||
break;
|
||||
}
|
||||
|
||||
String name = t == Variant::VARIANT_MAX ? String("Variant") : Variant::get_type_name(t);
|
||||
d2 = Dictionary();
|
||||
members = Array();
|
||||
d2["name"] = name;
|
||||
last_type = t;
|
||||
}
|
||||
Dictionary d3;
|
||||
uint32_t offset;
|
||||
switch (i) {
|
||||
case 0:
|
||||
offset = member_offset_array[idx].offset_32_bits_real_float;
|
||||
break;
|
||||
case 1:
|
||||
offset = member_offset_array[idx].offset_64_bits_real_float;
|
||||
break;
|
||||
case 2:
|
||||
offset = member_offset_array[idx].offset_32_bits_real_double;
|
||||
break;
|
||||
case 3:
|
||||
offset = member_offset_array[idx].offset_64_bits_real_double;
|
||||
break;
|
||||
}
|
||||
d3["member"] = member_offset_array[idx].member;
|
||||
d3["offset"] = offset;
|
||||
members.push_back(d3);
|
||||
idx++;
|
||||
}
|
||||
d["classes"] = type_offsets;
|
||||
core_type_member_offsets.push_back(d);
|
||||
}
|
||||
api_dump["builtin_class_member_offsets"] = core_type_member_offsets;
|
||||
}
|
||||
|
||||
{
|
||||
// global enums and constants
|
||||
Array constants;
|
||||
Map<String, List<Pair<String, int>>> enum_list;
|
||||
|
||||
for (int i = 0; i < CoreConstants::get_global_constant_count(); i++) {
|
||||
int value = CoreConstants::get_global_constant_value(i);
|
||||
String enum_name = CoreConstants::get_global_constant_enum(i);
|
||||
String name = CoreConstants::get_global_constant_name(i);
|
||||
if (enum_name != String()) {
|
||||
enum_list[enum_name].push_back(Pair<String, int>(name, value));
|
||||
} else {
|
||||
Dictionary d;
|
||||
d["name"] = name;
|
||||
d["value"] = value;
|
||||
constants.push_back(d);
|
||||
}
|
||||
}
|
||||
|
||||
api_dump["global_constants"] = constants;
|
||||
|
||||
Array enums;
|
||||
for (Map<String, List<Pair<String, int>>>::Element *E = enum_list.front(); E; E = E->next()) {
|
||||
Dictionary d1;
|
||||
d1["name"] = E->key();
|
||||
Array values;
|
||||
for (List<Pair<String, int>>::Element *F = E->get().front(); F; F = F->next()) {
|
||||
Dictionary d2;
|
||||
d2["name"] = F->get().first;
|
||||
d2["value"] = F->get().second;
|
||||
values.push_back(d2);
|
||||
}
|
||||
d1["values"] = values;
|
||||
enums.push_back(d1);
|
||||
}
|
||||
|
||||
api_dump["global_enums"] = enums;
|
||||
}
|
||||
{
|
||||
Array utility_funcs;
|
||||
|
||||
List<StringName> utility_func_names;
|
||||
Variant::get_utility_function_list(&utility_func_names);
|
||||
|
||||
for (List<StringName>::Element *E = utility_func_names.front(); E; E = E->next()) {
|
||||
StringName name = E->get();
|
||||
Dictionary func;
|
||||
func["name"] = String(name);
|
||||
if (Variant::has_utility_function_return_value(name)) {
|
||||
Variant::Type rt = Variant::get_utility_function_return_type(name);
|
||||
func["return_type"] = rt == Variant::NIL ? String("Variant") : Variant::get_type_name(rt);
|
||||
}
|
||||
switch (Variant::get_utility_function_type(name)) {
|
||||
case Variant::UTILITY_FUNC_TYPE_MATH:
|
||||
func["category"] = "math";
|
||||
break;
|
||||
case Variant::UTILITY_FUNC_TYPE_RANDOM:
|
||||
func["category"] = "random";
|
||||
break;
|
||||
case Variant::UTILITY_FUNC_TYPE_GENERAL:
|
||||
func["category"] = "general";
|
||||
break;
|
||||
}
|
||||
bool vararg = Variant::is_utility_function_vararg(name);
|
||||
func["is_vararg"] = Variant::is_utility_function_vararg(name);
|
||||
func["hash"] = Variant::get_utility_function_hash(name);
|
||||
Array arguments;
|
||||
int argcount = Variant::get_utility_function_argument_count(name);
|
||||
for (int i = 0; i < argcount; i++) {
|
||||
Dictionary arg;
|
||||
String argname = vararg ? "arg" + itos(i + 1) : Variant::get_utility_function_argument_name(name, i);
|
||||
arg["name"] = argname;
|
||||
Variant::Type argtype = Variant::get_utility_function_argument_type(name, i);
|
||||
arg["type"] = argtype == Variant::NIL ? String("Variant") : Variant::get_type_name(argtype);
|
||||
//no default value support in utility functions
|
||||
arguments.push_back(arg);
|
||||
}
|
||||
|
||||
if (arguments.size()) {
|
||||
func["arguments"] = arguments;
|
||||
}
|
||||
|
||||
utility_funcs.push_back(func);
|
||||
}
|
||||
|
||||
api_dump["utility_functions"] = utility_funcs;
|
||||
}
|
||||
|
||||
{
|
||||
// builtin types
|
||||
|
||||
Array builtins;
|
||||
|
||||
for (int i = 0; i < Variant::VARIANT_MAX; i++) {
|
||||
if (i == Variant::OBJECT) {
|
||||
continue;
|
||||
}
|
||||
|
||||
Variant::Type type = Variant::Type(i);
|
||||
|
||||
Dictionary d;
|
||||
d["name"] = Variant::get_type_name(type);
|
||||
if (Variant::has_indexing(type)) {
|
||||
Variant::Type index_type = Variant::get_indexed_element_type(type);
|
||||
d["indexing_return_type"] = index_type == Variant::NIL ? String("Variant") : Variant::get_type_name(index_type);
|
||||
}
|
||||
|
||||
{
|
||||
//members
|
||||
Array members;
|
||||
|
||||
List<StringName> member_names;
|
||||
Variant::get_member_list(type, &member_names);
|
||||
for (List<StringName>::Element *E = member_names.front(); E; E = E->next()) {
|
||||
StringName member_name = E->get();
|
||||
Dictionary d2;
|
||||
d2["name"] = String(member_name);
|
||||
d2["type"] = Variant::get_type_name(Variant::get_member_type(type, member_name));
|
||||
members.push_back(d2);
|
||||
}
|
||||
if (members.size()) {
|
||||
d["members"] = members;
|
||||
}
|
||||
}
|
||||
{
|
||||
//constants
|
||||
Array constants;
|
||||
|
||||
List<StringName> constant_names;
|
||||
Variant::get_constants_for_type(type, &constant_names);
|
||||
for (List<StringName>::Element *E = constant_names.front(); E; E = E->next()) {
|
||||
StringName constant_name = E->get();
|
||||
Dictionary d2;
|
||||
d2["name"] = String(constant_name);
|
||||
Variant constant = Variant::get_constant_value(type, constant_name);
|
||||
d2["type"] = Variant::get_type_name(constant.get_type());
|
||||
d2["value"] = constant.get_construct_string();
|
||||
constants.push_back(d2);
|
||||
}
|
||||
if (constants.size()) {
|
||||
d["constants"] = constants;
|
||||
}
|
||||
}
|
||||
{
|
||||
//operators
|
||||
Array operators;
|
||||
|
||||
for (int j = 0; j < Variant::VARIANT_MAX; j++) {
|
||||
for (int k = 0; k < Variant::OP_MAX; k++) {
|
||||
Variant::Type rt = Variant::get_operator_return_type(Variant::Operator(k), type, Variant::Type(j));
|
||||
if (rt != Variant::NIL) {
|
||||
Dictionary d2;
|
||||
d2["name"] = Variant::get_operator_name(Variant::Operator(k));
|
||||
if (k != Variant::OP_NEGATE && k != Variant::OP_POSITIVE && k != Variant::OP_NOT && k != Variant::OP_BIT_NEGATE) {
|
||||
d2["right_type"] = Variant::get_type_name(Variant::Type(j));
|
||||
}
|
||||
operators.push_back(d2);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (operators.size()) {
|
||||
d["operators"] = operators;
|
||||
}
|
||||
}
|
||||
{
|
||||
//methods
|
||||
Array methods;
|
||||
|
||||
List<StringName> method_names;
|
||||
Variant::get_builtin_method_list(type, &method_names);
|
||||
for (List<StringName>::Element *E = method_names.front(); E; E = E->next()) {
|
||||
StringName method_name = E->get();
|
||||
Dictionary d2;
|
||||
d2["name"] = String(method_name);
|
||||
if (Variant::has_builtin_method_return_value(type, method_name)) {
|
||||
Variant::Type ret_type = Variant::get_builtin_method_return_type(type, method_name);
|
||||
d2["return_type"] = ret_type == Variant::NIL ? String("Variant") : Variant::get_type_name(ret_type);
|
||||
}
|
||||
d2["is_vararg"] = Variant::is_builtin_method_vararg(type, method_name);
|
||||
d2["is_const"] = Variant::is_builtin_method_const(type, method_name);
|
||||
d2["is_static"] = Variant::is_builtin_method_static(type, method_name);
|
||||
d2["hash"] = Variant::get_builtin_method_hash(type, method_name);
|
||||
|
||||
Vector<Variant> default_args = Variant::get_builtin_method_default_arguments(type, method_name);
|
||||
|
||||
Array arguments;
|
||||
int argcount = Variant::get_builtin_method_argument_count(type, method_name);
|
||||
for (int j = 0; j < argcount; j++) {
|
||||
Dictionary d3;
|
||||
d3["name"] = Variant::get_builtin_method_argument_name(type, method_name, j);
|
||||
Variant::Type argtype = Variant::get_builtin_method_argument_type(type, method_name, j);
|
||||
d3["type"] = argtype == Variant::NIL ? String("Variant") : Variant::get_type_name(argtype);
|
||||
|
||||
if (j >= (argcount - default_args.size())) {
|
||||
int dargidx = j - (argcount - default_args.size());
|
||||
d3["default_value"] = default_args[dargidx].get_construct_string();
|
||||
}
|
||||
arguments.push_back(d3);
|
||||
}
|
||||
|
||||
if (arguments.size()) {
|
||||
d2["arguments"] = arguments;
|
||||
}
|
||||
|
||||
methods.push_back(d2);
|
||||
}
|
||||
if (methods.size()) {
|
||||
d["methods"] = methods;
|
||||
}
|
||||
}
|
||||
{
|
||||
//constructors
|
||||
Array constructors;
|
||||
|
||||
for (int j = 0; j < Variant::get_constructor_count(type); j++) {
|
||||
Dictionary d2;
|
||||
d2["index"] = j;
|
||||
|
||||
Array arguments;
|
||||
int argcount = Variant::get_constructor_argument_count(type, j);
|
||||
for (int k = 0; k < argcount; k++) {
|
||||
Dictionary d3;
|
||||
d3["name"] = Variant::get_constructor_argument_name(type, j, k);
|
||||
d3["type"] = Variant::get_type_name(Variant::get_constructor_argument_type(type, j, k));
|
||||
arguments.push_back(d3);
|
||||
}
|
||||
if (arguments.size()) {
|
||||
d2["arguments"] = arguments;
|
||||
}
|
||||
constructors.push_back(d2);
|
||||
}
|
||||
|
||||
if (constructors.size()) {
|
||||
d["constructors"] = constructors;
|
||||
}
|
||||
}
|
||||
|
||||
builtins.push_back(d);
|
||||
}
|
||||
|
||||
api_dump["builtin_classes"] = builtins;
|
||||
}
|
||||
|
||||
{
|
||||
// classes
|
||||
Array classes;
|
||||
|
||||
List<StringName> class_list;
|
||||
|
||||
ClassDB::get_class_list(&class_list);
|
||||
|
||||
class_list.sort_custom<StringName::AlphCompare>();
|
||||
|
||||
for (List<StringName>::Element *E = class_list.front(); E; E = E->next()) {
|
||||
Dictionary d;
|
||||
StringName class_name = E->get();
|
||||
d["name"] = String(class_name);
|
||||
d["is_refcounted"] = ClassDB::is_parent_class(class_name, "RefCounted");
|
||||
d["is_instantiable"] = ClassDB::can_instantiate(class_name);
|
||||
StringName parent_class = ClassDB::get_parent_class(class_name);
|
||||
if (parent_class != StringName()) {
|
||||
d["inherits"] = String(parent_class);
|
||||
}
|
||||
|
||||
{
|
||||
ClassDB::APIType api = ClassDB::get_api_type(class_name);
|
||||
static const char *api_type[5] = { "core", "editor", "extension", "editor_extension" };
|
||||
d["api_type"] = api_type[api];
|
||||
}
|
||||
|
||||
{
|
||||
//constants
|
||||
Array constants;
|
||||
List<String> constant_list;
|
||||
ClassDB::get_integer_constant_list(class_name, &constant_list, true);
|
||||
for (List<String>::Element *F = constant_list.front(); F; F = F->next()) {
|
||||
StringName enum_name = ClassDB::get_integer_constant_enum(class_name, F->get());
|
||||
if (enum_name != StringName()) {
|
||||
continue; //enums will be handled on their own
|
||||
}
|
||||
|
||||
Dictionary d2;
|
||||
d2["name"] = String(F->get());
|
||||
d2["value"] = ClassDB::get_integer_constant(class_name, F->get());
|
||||
|
||||
constants.push_back(d2);
|
||||
}
|
||||
|
||||
if (constants.size()) {
|
||||
d["constants"] = constants;
|
||||
}
|
||||
}
|
||||
{
|
||||
//enum
|
||||
Array enums;
|
||||
List<StringName> enum_list;
|
||||
ClassDB::get_enum_list(class_name, &enum_list, true);
|
||||
for (List<StringName>::Element *F = enum_list.front(); F; F = F->next()) {
|
||||
Dictionary d2;
|
||||
d2["name"] = String(F->get());
|
||||
|
||||
Array values;
|
||||
List<StringName> enum_constant_list;
|
||||
ClassDB::get_enum_constants(class_name, F->get(), &enum_constant_list, true);
|
||||
for (List<StringName>::Element *G = enum_constant_list.front(); G; G = G->next()) {
|
||||
Dictionary d3;
|
||||
d3["name"] = String(G->get());
|
||||
d3["value"] = ClassDB::get_integer_constant(class_name, G->get());
|
||||
values.push_back(d3);
|
||||
}
|
||||
|
||||
d2["values"] = values;
|
||||
|
||||
enums.push_back(d2);
|
||||
}
|
||||
|
||||
if (enums.size()) {
|
||||
d["enums"] = enums;
|
||||
}
|
||||
}
|
||||
{
|
||||
//methods
|
||||
Array methods;
|
||||
List<MethodInfo> method_list;
|
||||
ClassDB::get_method_list(class_name, &method_list, true);
|
||||
for (List<MethodInfo>::Element *F = method_list.front(); F; F = F->next()) {
|
||||
StringName method_name = F->get().name;
|
||||
if (F->get().flags & METHOD_FLAG_VIRTUAL) {
|
||||
//virtual method
|
||||
const MethodInfo &mi = F->get();
|
||||
Dictionary d2;
|
||||
d2["name"] = String(method_name);
|
||||
d2["is_const"] = (F->get().flags & METHOD_FLAG_CONST) ? true : false;
|
||||
d2["is_vararg"] = false;
|
||||
d2["is_virtual"] = true;
|
||||
// virtual functions have no hash since no MethodBind is involved
|
||||
bool has_return = mi.return_val.type != Variant::NIL || (mi.return_val.usage & PROPERTY_USAGE_NIL_IS_VARIANT);
|
||||
Array arguments;
|
||||
for (int i = (has_return ? -1 : 0); i < mi.arguments.size(); i++) {
|
||||
PropertyInfo pinfo = i == -1 ? mi.return_val : mi.arguments[i];
|
||||
Dictionary d3;
|
||||
|
||||
if (i >= 0) {
|
||||
d3["name"] = pinfo.name;
|
||||
}
|
||||
if (pinfo.class_name != StringName()) {
|
||||
d3["type"] = String(pinfo.class_name);
|
||||
} else {
|
||||
Variant::Type type = pinfo.type;
|
||||
if (type == Variant::NIL) {
|
||||
d3["type"] = "Variant";
|
||||
} else {
|
||||
d3["type"] = Variant::get_type_name(type);
|
||||
}
|
||||
}
|
||||
|
||||
if (i == -1) {
|
||||
d2["return_value"] = d3;
|
||||
} else {
|
||||
arguments.push_back(d3);
|
||||
}
|
||||
}
|
||||
|
||||
if (arguments.size()) {
|
||||
d2["arguments"] = arguments;
|
||||
}
|
||||
|
||||
methods.push_back(d2);
|
||||
|
||||
} else if (F->get().name.begins_with("_")) {
|
||||
//hidden method, ignore
|
||||
|
||||
} else {
|
||||
Dictionary d2;
|
||||
d2["name"] = String(method_name);
|
||||
|
||||
MethodBind *method = ClassDB::get_method(class_name, method_name);
|
||||
if (!method) {
|
||||
continue;
|
||||
}
|
||||
|
||||
d2["is_const"] = method->is_const();
|
||||
d2["is_vararg"] = method->is_vararg();
|
||||
d2["is_virtual"] = false;
|
||||
d2["hash"] = method->get_hash();
|
||||
|
||||
Vector<Variant> default_args = method->get_default_arguments();
|
||||
|
||||
Array arguments;
|
||||
for (int i = (method->has_return() ? -1 : 0); i < method->get_argument_count(); i++) {
|
||||
PropertyInfo pinfo = i == -1 ? method->get_return_info() : method->get_argument_info(i);
|
||||
Dictionary d3;
|
||||
|
||||
if (i >= 0) {
|
||||
d3["name"] = pinfo.name;
|
||||
}
|
||||
if (pinfo.class_name != StringName()) {
|
||||
d3["type"] = String(pinfo.class_name);
|
||||
} else {
|
||||
Variant::Type type = pinfo.type;
|
||||
if (type == Variant::NIL) {
|
||||
d3["type"] = "Variant";
|
||||
} else {
|
||||
d3["type"] = Variant::get_type_name(type);
|
||||
}
|
||||
}
|
||||
|
||||
if (method->get_argument_meta(i) > 0) {
|
||||
static const char *argmeta[11] = { "none", "int8", "int16", "int32", "int64", "uint8", "uint16", "uint32", "uint64", "float", "double" };
|
||||
d3["meta"] = argmeta[method->get_argument_meta(i)];
|
||||
}
|
||||
|
||||
if (i >= 0 && i >= (method->get_argument_count() - default_args.size())) {
|
||||
int dargidx = i - (method->get_argument_count() - default_args.size());
|
||||
d3["default_value"] = default_args[dargidx].get_construct_string();
|
||||
}
|
||||
|
||||
if (i == -1) {
|
||||
d2["return_value"] = d3;
|
||||
} else {
|
||||
arguments.push_back(d3);
|
||||
}
|
||||
}
|
||||
|
||||
if (arguments.size()) {
|
||||
d2["arguments"] = arguments;
|
||||
}
|
||||
|
||||
methods.push_back(d2);
|
||||
}
|
||||
}
|
||||
|
||||
if (methods.size()) {
|
||||
d["methods"] = methods;
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
//signals
|
||||
Array signals;
|
||||
List<MethodInfo> signal_list;
|
||||
ClassDB::get_signal_list(class_name, &signal_list, true);
|
||||
for (List<MethodInfo>::Element *F = signal_list.front(); F; F = F->next()) {
|
||||
StringName signal_name = F->get().name;
|
||||
Dictionary d2;
|
||||
d2["name"] = String(signal_name);
|
||||
|
||||
Array arguments;
|
||||
|
||||
for (int i = 0; i < F->get().arguments.size(); i++) {
|
||||
Dictionary d3;
|
||||
d3["name"] = F->get().arguments[i].name;
|
||||
Variant::Type type = F->get().arguments[i].type;
|
||||
if (F->get().arguments[i].class_name != StringName()) {
|
||||
d3["type"] = String(F->get().arguments[i].class_name);
|
||||
} else if (type == Variant::NIL) {
|
||||
d3["type"] = "Variant";
|
||||
} else {
|
||||
d3["type"] = Variant::get_type_name(type);
|
||||
}
|
||||
arguments.push_back(d3);
|
||||
}
|
||||
if (arguments.size()) {
|
||||
d2["arguments"] = arguments;
|
||||
}
|
||||
|
||||
signals.push_back(d2);
|
||||
}
|
||||
|
||||
if (signals.size()) {
|
||||
d["signals"] = signals;
|
||||
}
|
||||
}
|
||||
{
|
||||
//properties
|
||||
Array properties;
|
||||
List<PropertyInfo> property_list;
|
||||
ClassDB::get_property_list(class_name, &property_list, true);
|
||||
for (List<PropertyInfo>::Element *F = property_list.front(); F; F = F->next()) {
|
||||
if (F->get().usage & PROPERTY_USAGE_CATEGORY || F->get().usage & PROPERTY_USAGE_GROUP || F->get().usage & PROPERTY_USAGE_SUBGROUP) {
|
||||
continue; //not real properties
|
||||
}
|
||||
if (F->get().name.begins_with("_")) {
|
||||
continue; //hidden property
|
||||
}
|
||||
StringName property_name = F->get().name;
|
||||
Dictionary d2;
|
||||
d2["name"] = String(property_name);
|
||||
|
||||
if (F->get().class_name != StringName()) {
|
||||
d2["type"] = String(F->get().class_name);
|
||||
} else if (F->get().type == Variant::NIL && F->get().usage & PROPERTY_USAGE_NIL_IS_VARIANT) {
|
||||
d2["type"] = "Variant";
|
||||
} else {
|
||||
d2["type"] = Variant::get_type_name(F->get().type);
|
||||
}
|
||||
|
||||
d2["setter"] = ClassDB::get_property_setter(class_name, F->get().name);
|
||||
d2["getter"] = ClassDB::get_property_getter(class_name, F->get().name);
|
||||
d2["index"] = ClassDB::get_property_index(class_name, F->get().name);
|
||||
properties.push_back(d2);
|
||||
}
|
||||
|
||||
if (properties.size()) {
|
||||
d["properties"] = properties;
|
||||
}
|
||||
}
|
||||
|
||||
classes.push_back(d);
|
||||
}
|
||||
|
||||
api_dump["classes"] = classes;
|
||||
}
|
||||
|
||||
{
|
||||
// singletons
|
||||
|
||||
Array singletons;
|
||||
List<Engine::Singleton> singleton_list;
|
||||
Engine::get_singleton()->get_singletons(&singleton_list);
|
||||
|
||||
for (List<Engine::Singleton>::Element *E = singleton_list.front(); E; E = E->next()) {
|
||||
const Engine::Singleton &s = E->get();
|
||||
Dictionary d;
|
||||
d["name"] = s.name;
|
||||
if (s.class_name != StringName()) {
|
||||
d["type"] = String(s.class_name);
|
||||
} else {
|
||||
d["type"] = String(s.ptr->get_class());
|
||||
}
|
||||
singletons.push_back(d);
|
||||
}
|
||||
|
||||
if (singletons.size()) {
|
||||
api_dump["singletons"] = singletons;
|
||||
}
|
||||
}
|
||||
|
||||
return api_dump;
|
||||
}
|
||||
|
||||
void NativeExtensionAPIDump::generate_extension_json_file(const String &p_path) {
|
||||
Dictionary api = generate_extension_api();
|
||||
Ref<JSON> json;
|
||||
json.instantiate();
|
||||
|
||||
String text = json->stringify(api, "\t", false);
|
||||
FileAccessRef fa = FileAccess::open(p_path, FileAccess::WRITE);
|
||||
CharString cs = text.ascii();
|
||||
fa->store_buffer((const uint8_t *)cs.ptr(), cs.length());
|
||||
fa->close();
|
||||
}
|
||||
#endif
|
|
@ -0,0 +1,45 @@
|
|||
/*************************************************************************/
|
||||
/* extension_api_dump.h */
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* https://godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
|
||||
/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
|
||||
/* */
|
||||
/* Permission is hereby granted, free of charge, to any person obtaining */
|
||||
/* a copy of this software and associated documentation files (the */
|
||||
/* "Software"), to deal in the Software without restriction, including */
|
||||
/* without limitation the rights to use, copy, modify, merge, publish, */
|
||||
/* distribute, sublicense, and/or sell copies of the Software, and to */
|
||||
/* permit persons to whom the Software is furnished to do so, subject to */
|
||||
/* the following conditions: */
|
||||
/* */
|
||||
/* The above copyright notice and this permission notice shall be */
|
||||
/* included in all copies or substantial portions of the Software. */
|
||||
/* */
|
||||
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
|
||||
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
|
||||
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
|
||||
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
|
||||
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
|
||||
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
||||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
/*************************************************************************/
|
||||
|
||||
#ifndef API_DUMP_H
|
||||
#define API_DUMP_H
|
||||
|
||||
#include "core/extension/native_extension.h"
|
||||
|
||||
#ifdef TOOLS_ENABLED
|
||||
|
||||
class NativeExtensionAPIDump {
|
||||
public:
|
||||
static Dictionary generate_extension_api();
|
||||
static void generate_extension_json_file(const String &p_path);
|
||||
};
|
||||
#endif
|
||||
|
||||
#endif // API_DUMP_H
|
|
@ -0,0 +1,688 @@
|
|||
/*************************************************************************/
|
||||
/* gdnative_interface.cpp */
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* https://godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
|
||||
/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
|
||||
/* */
|
||||
/* 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 "gdnative_interface.h"
|
||||
|
||||
#include "core/config/engine.h"
|
||||
#include "core/object/class_db.h"
|
||||
#include "core/os/memory.h"
|
||||
#include "core/variant/variant.h"
|
||||
#include "core/version.h"
|
||||
|
||||
// Memory Functions
|
||||
static void *gdnative_alloc(size_t p_size) {
|
||||
return memalloc(p_size);
|
||||
}
|
||||
|
||||
static void *gdnative_realloc(void *p_mem, size_t p_size) {
|
||||
return memrealloc(p_mem, p_size);
|
||||
}
|
||||
|
||||
static void gdnative_free(void *p_mem) {
|
||||
memfree(p_mem);
|
||||
}
|
||||
|
||||
// Helper print functions.
|
||||
static void gdnative_print_error(const char *p_description, const char *p_function, const char *p_file, int32_t p_line) {
|
||||
_err_print_error(p_function, p_file, p_line, p_description, ERR_HANDLER_ERROR);
|
||||
}
|
||||
static void gdnative_print_warning(const char *p_description, const char *p_function, const char *p_file, int32_t p_line) {
|
||||
_err_print_error(p_function, p_file, p_line, p_description, ERR_HANDLER_WARNING);
|
||||
}
|
||||
static void gdnative_print_script_error(const char *p_description, const char *p_function, const char *p_file, int32_t p_line) {
|
||||
_err_print_error(p_function, p_file, p_line, p_description, ERR_HANDLER_SCRIPT);
|
||||
}
|
||||
|
||||
// Variant functions
|
||||
|
||||
static void gdnative_variant_new_copy(GDNativeVariantPtr r_dest, const GDNativeVariantPtr p_src) {
|
||||
memnew_placement(reinterpret_cast<Variant *>(r_dest), Variant(*reinterpret_cast<Variant *>(p_src)));
|
||||
}
|
||||
static void gdnative_variant_new_nil(GDNativeVariantPtr r_dest) {
|
||||
memnew_placement(reinterpret_cast<Variant *>(r_dest), Variant);
|
||||
}
|
||||
static void gdnative_variant_destroy(GDNativeVariantPtr p_self) {
|
||||
reinterpret_cast<Variant *>(p_self)->~Variant();
|
||||
}
|
||||
|
||||
// variant type
|
||||
|
||||
#define memnew_placement_custom(m_placement, m_class, m_constr) _post_initialize(new (m_placement, sizeof(m_class), "") m_constr)
|
||||
|
||||
static void gdnative_variant_call(GDNativeVariantPtr p_self, const GDNativeStringNamePtr p_method, const GDNativeVariantPtr *p_args, const GDNativeInt p_argcount, GDNativeVariantPtr r_return, GDNativeCallError *r_error) {
|
||||
Variant *self = (Variant *)p_self;
|
||||
const StringName *method = (const StringName *)p_method;
|
||||
const Variant **args = (const Variant **)p_args;
|
||||
Variant ret;
|
||||
Callable::CallError error;
|
||||
self->call(*method, args, p_argcount, ret, error);
|
||||
memnew_placement_custom(r_return, Variant, Variant(ret));
|
||||
|
||||
if (r_error) {
|
||||
r_error->error = (GDNativeCallErrorType)(error.error);
|
||||
r_error->argument = error.argument;
|
||||
r_error->expected = error.expected;
|
||||
}
|
||||
}
|
||||
|
||||
static void gdnative_variant_call_static(GDNativeVariantType p_type, const GDNativeStringNamePtr p_method, const GDNativeVariantPtr *p_args, const GDNativeInt p_argcount, GDNativeVariantPtr r_return, GDNativeCallError *r_error) {
|
||||
Variant::Type type = (Variant::Type)p_type;
|
||||
const StringName *method = (const StringName *)p_method;
|
||||
const Variant **args = (const Variant **)p_args;
|
||||
Variant ret;
|
||||
Callable::CallError error;
|
||||
Variant::call_static(type, *method, args, p_argcount, ret, error);
|
||||
memnew_placement_custom(r_return, Variant, Variant(ret));
|
||||
|
||||
if (r_error) {
|
||||
r_error->error = (GDNativeCallErrorType)error.error;
|
||||
r_error->argument = error.argument;
|
||||
r_error->expected = error.expected;
|
||||
}
|
||||
}
|
||||
|
||||
static void gdnative_variant_evaluate(GDNativeVariantOperator p_op, const GDNativeVariantPtr p_a, const GDNativeVariantPtr p_b, GDNativeVariantPtr r_return, GDNativeBool *r_valid) {
|
||||
Variant::Operator op = (Variant::Operator)p_op;
|
||||
const Variant *a = (const Variant *)p_a;
|
||||
const Variant *b = (const Variant *)p_b;
|
||||
Variant *ret = (Variant *)r_return;
|
||||
bool valid;
|
||||
Variant::evaluate(op, *a, *b, *ret, valid);
|
||||
*r_valid = valid;
|
||||
}
|
||||
|
||||
static void gdnative_variant_set(GDNativeVariantPtr p_self, const GDNativeVariantPtr p_key, const GDNativeVariantPtr p_value, GDNativeBool *r_valid) {
|
||||
Variant *self = (Variant *)p_self;
|
||||
const Variant *key = (const Variant *)p_key;
|
||||
const Variant *value = (const Variant *)p_value;
|
||||
|
||||
bool valid;
|
||||
self->set(*key, *value, &valid);
|
||||
*r_valid = valid;
|
||||
}
|
||||
|
||||
static void gdnative_variant_set_named(GDNativeVariantPtr p_self, const GDNativeStringNamePtr p_key, const GDNativeVariantPtr p_value, GDNativeBool *r_valid) {
|
||||
Variant *self = (Variant *)p_self;
|
||||
const StringName *key = (const StringName *)p_key;
|
||||
const Variant *value = (const Variant *)p_value;
|
||||
|
||||
bool valid;
|
||||
self->set_named(*key, *value, valid);
|
||||
*r_valid = valid;
|
||||
}
|
||||
|
||||
static void gdnative_variant_set_keyed(GDNativeVariantPtr p_self, const GDNativeVariantPtr p_key, const GDNativeVariantPtr p_value, GDNativeBool *r_valid) {
|
||||
Variant *self = (Variant *)p_self;
|
||||
const Variant *key = (const Variant *)p_key;
|
||||
const Variant *value = (const Variant *)p_value;
|
||||
|
||||
bool valid;
|
||||
self->set_keyed(*key, *value, valid);
|
||||
*r_valid = valid;
|
||||
}
|
||||
|
||||
static void gdnative_variant_set_indexed(GDNativeVariantPtr p_self, GDNativeInt p_index, const GDNativeVariantPtr p_value, GDNativeBool *r_valid, GDNativeBool *r_oob) {
|
||||
Variant *self = (Variant *)p_self;
|
||||
const Variant *value = (const Variant *)p_value;
|
||||
|
||||
bool valid;
|
||||
bool oob;
|
||||
self->set_indexed(p_index, value, valid, oob);
|
||||
*r_valid = valid;
|
||||
*r_oob = oob;
|
||||
}
|
||||
|
||||
static void gdnative_variant_get(const GDNativeVariantPtr p_self, const GDNativeVariantPtr p_key, GDNativeVariantPtr r_ret, GDNativeBool *r_valid) {
|
||||
const Variant *self = (const Variant *)p_self;
|
||||
const Variant *key = (const Variant *)p_key;
|
||||
|
||||
bool valid;
|
||||
memnew_placement_custom(r_ret, Variant, Variant(self->get(*key, &valid)));
|
||||
*r_valid = valid;
|
||||
}
|
||||
|
||||
static void gdnative_variant_get_named(const GDNativeVariantPtr p_self, const GDNativeStringNamePtr p_key, GDNativeVariantPtr r_ret, GDNativeBool *r_valid) {
|
||||
const Variant *self = (const Variant *)p_self;
|
||||
const StringName *key = (const StringName *)p_key;
|
||||
|
||||
bool valid;
|
||||
memnew_placement_custom(r_ret, Variant, Variant(self->get_named(*key, valid)));
|
||||
*r_valid = valid;
|
||||
}
|
||||
|
||||
static void gdnative_variant_get_keyed(const GDNativeVariantPtr p_self, const GDNativeVariantPtr p_key, GDNativeVariantPtr r_ret, GDNativeBool *r_valid) {
|
||||
const Variant *self = (const Variant *)p_self;
|
||||
const Variant *key = (const Variant *)p_key;
|
||||
|
||||
bool valid;
|
||||
memnew_placement_custom(r_ret, Variant, Variant(self->get_keyed(*key, valid)));
|
||||
*r_valid = valid;
|
||||
}
|
||||
|
||||
static void gdnative_variant_get_indexed(const GDNativeVariantPtr p_self, GDNativeInt p_index, GDNativeVariantPtr r_ret, GDNativeBool *r_valid, GDNativeBool *r_oob) {
|
||||
const Variant *self = (const Variant *)p_self;
|
||||
|
||||
bool valid;
|
||||
bool oob;
|
||||
memnew_placement_custom(r_ret, Variant, Variant(self->get_indexed(p_index, valid, oob)));
|
||||
*r_valid = valid;
|
||||
*r_oob = oob;
|
||||
}
|
||||
|
||||
/// Iteration.
|
||||
static GDNativeBool gdnative_variant_iter_init(const GDNativeVariantPtr p_self, GDNativeVariantPtr r_iter, GDNativeBool *r_valid) {
|
||||
const Variant *self = (const Variant *)p_self;
|
||||
Variant *iter = (Variant *)r_iter;
|
||||
|
||||
bool valid;
|
||||
bool ret = self->iter_init(*iter, valid);
|
||||
*r_valid = valid;
|
||||
return ret;
|
||||
}
|
||||
|
||||
static GDNativeBool gdnative_variant_iter_next(const GDNativeVariantPtr p_self, GDNativeVariantPtr r_iter, GDNativeBool *r_valid) {
|
||||
const Variant *self = (const Variant *)p_self;
|
||||
Variant *iter = (Variant *)r_iter;
|
||||
|
||||
bool valid;
|
||||
bool ret = self->iter_next(*iter, valid);
|
||||
*r_valid = valid;
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void gdnative_variant_iter_get(const GDNativeVariantPtr p_self, GDNativeVariantPtr r_iter, GDNativeVariantPtr r_ret, GDNativeBool *r_valid) {
|
||||
const Variant *self = (const Variant *)p_self;
|
||||
Variant *iter = (Variant *)r_iter;
|
||||
|
||||
bool valid;
|
||||
memnew_placement_custom(r_ret, Variant, Variant(self->iter_next(*iter, valid)));
|
||||
*r_valid = valid;
|
||||
}
|
||||
|
||||
/// Variant functions.
|
||||
static GDNativeBool gdnative_variant_hash_compare(const GDNativeVariantPtr p_self, const GDNativeVariantPtr p_other) {
|
||||
const Variant *self = (const Variant *)p_self;
|
||||
const Variant *other = (const Variant *)p_other;
|
||||
return self->hash_compare(*other);
|
||||
}
|
||||
|
||||
static GDNativeBool gdnative_variant_booleanize(const GDNativeVariantPtr p_self) {
|
||||
const Variant *self = (const Variant *)p_self;
|
||||
return self->booleanize();
|
||||
}
|
||||
|
||||
static void gdnative_variant_blend(const GDNativeVariantPtr p_a, const GDNativeVariantPtr p_b, float p_c, GDNativeVariantPtr r_dst) {
|
||||
const Variant *a = (const Variant *)p_a;
|
||||
const Variant *b = (const Variant *)p_b;
|
||||
memnew_placement(r_dst, Variant);
|
||||
Variant::blend(*a, *b, p_c, *(Variant *)r_dst);
|
||||
}
|
||||
|
||||
static void gdnative_variant_interpolate(const GDNativeVariantPtr p_a, const GDNativeVariantPtr p_b, float p_c, GDNativeVariantPtr r_dst) {
|
||||
const Variant *a = (const Variant *)p_a;
|
||||
const Variant *b = (const Variant *)p_b;
|
||||
memnew_placement(r_dst, Variant);
|
||||
Variant::interpolate(*a, *b, p_c, *(Variant *)r_dst);
|
||||
}
|
||||
|
||||
static void gdnative_variant_duplicate(const GDNativeVariantPtr p_self, GDNativeVariantPtr r_ret, GDNativeBool p_deep) {
|
||||
const Variant *self = (const Variant *)p_self;
|
||||
memnew_placement_custom(r_ret, Variant, Variant(self->duplicate(p_deep)));
|
||||
}
|
||||
|
||||
static void gdnative_variant_stringify(const GDNativeVariantPtr p_self, GDNativeStringPtr r_ret) {
|
||||
const Variant *self = (const Variant *)p_self;
|
||||
memnew_placement_custom(r_ret, String, String(*self));
|
||||
}
|
||||
|
||||
static GDNativeVariantType gdnative_variant_get_type(const GDNativeVariantPtr p_self) {
|
||||
const Variant *self = (const Variant *)p_self;
|
||||
return (GDNativeVariantType)self->get_type();
|
||||
}
|
||||
|
||||
static GDNativeBool gdnative_variant_has_method(const GDNativeVariantPtr p_self, const GDNativeStringNamePtr p_method) {
|
||||
const Variant *self = (const Variant *)p_self;
|
||||
const StringName *method = (const StringName *)p_method;
|
||||
return self->has_method(*method);
|
||||
}
|
||||
|
||||
static GDNativeBool gdnative_variant_has_member(GDNativeVariantType p_type, const GDNativeStringNamePtr p_member) {
|
||||
return Variant::has_member((Variant::Type)p_type, *((const StringName *)p_member));
|
||||
}
|
||||
|
||||
static GDNativeBool gdnative_variant_has_key(const GDNativeVariantPtr p_self, const GDNativeVariantPtr p_key, GDNativeBool *r_valid) {
|
||||
const Variant *self = (const Variant *)p_self;
|
||||
const Variant *key = (const Variant *)p_key;
|
||||
bool valid;
|
||||
return self->has_key(*key, valid);
|
||||
*r_valid = valid;
|
||||
}
|
||||
|
||||
static void gdnative_variant_get_type_name(GDNativeVariantType p_type, GDNativeStringPtr r_ret) {
|
||||
String name = Variant::get_type_name((Variant::Type)p_type);
|
||||
memnew_placement_custom(r_ret, String, String(name));
|
||||
}
|
||||
|
||||
static GDNativeBool gdnative_variant_can_convert(GDNativeVariantType p_from, GDNativeVariantType p_to) {
|
||||
return Variant::can_convert((Variant::Type)p_from, (Variant::Type)p_to);
|
||||
}
|
||||
|
||||
static GDNativeBool gdnative_variant_can_convert_strict(GDNativeVariantType p_from, GDNativeVariantType p_to) {
|
||||
return Variant::can_convert_strict((Variant::Type)p_from, (Variant::Type)p_to);
|
||||
}
|
||||
|
||||
// ptrcalls
|
||||
static GDNativePtrOperatorEvaluator gdnative_variant_get_ptr_operator_evaluator(GDNativeVariantOperator p_operator, GDNativeVariantType p_type_a, GDNativeVariantType p_type_b) {
|
||||
return (GDNativePtrOperatorEvaluator)Variant::get_ptr_operator_evaluator(Variant::Operator(p_operator), Variant::Type(p_type_a), Variant::Type(p_type_b));
|
||||
}
|
||||
static GDNativePtrBuiltInMethod gdnative_variant_get_ptr_builtin_method(GDNativeVariantType p_type, const char *p_method, GDNativeInt p_hash) {
|
||||
StringName method = p_method;
|
||||
uint32_t hash = Variant::get_builtin_method_hash(Variant::Type(p_type), method);
|
||||
if (hash != p_hash) {
|
||||
ERR_PRINT_ONCE("Error getting method " + String(method) + ", hash mismatch.");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return (GDNativePtrBuiltInMethod)Variant::get_ptr_builtin_method(Variant::Type(p_type), method);
|
||||
}
|
||||
static GDNativePtrConstructor gdnative_variant_get_ptr_constructor(GDNativeVariantType p_type, int32_t p_constructor) {
|
||||
return (GDNativePtrConstructor)Variant::get_ptr_constructor(Variant::Type(p_type), p_constructor);
|
||||
}
|
||||
static void gdnative_variant_construct(GDNativeVariantType p_type, GDNativeVariantPtr p_base, const GDNativeVariantPtr *p_args, int32_t p_argument_count, GDNativeCallError *r_error) {
|
||||
memnew_placement(p_base, Variant);
|
||||
|
||||
Callable::CallError error;
|
||||
Variant::construct(Variant::Type(p_type), *(Variant *)p_base, (const Variant **)p_args, p_argument_count, error);
|
||||
|
||||
if (r_error) {
|
||||
r_error->error = (GDNativeCallErrorType)(error.error);
|
||||
r_error->argument = error.argument;
|
||||
r_error->expected = error.expected;
|
||||
}
|
||||
}
|
||||
static GDNativePtrSetter gdnative_variant_get_ptr_setter(GDNativeVariantType p_type, const char *p_member) {
|
||||
return (GDNativePtrSetter)Variant::get_member_ptr_setter(Variant::Type(p_type), p_member);
|
||||
}
|
||||
static GDNativePtrGetter gdnative_variant_get_ptr_getter(GDNativeVariantType p_type, const char *p_member) {
|
||||
return (GDNativePtrGetter)Variant::get_member_ptr_getter(Variant::Type(p_type), p_member);
|
||||
}
|
||||
static GDNativePtrIndexedSetter gdnative_variant_get_ptr_indexed_setter(GDNativeVariantType p_type) {
|
||||
return (GDNativePtrIndexedSetter)Variant::get_member_ptr_indexed_setter(Variant::Type(p_type));
|
||||
}
|
||||
static GDNativePtrIndexedGetter gdnative_variant_get_ptr_indexed_getter(GDNativeVariantType p_type) {
|
||||
return (GDNativePtrIndexedGetter)Variant::get_member_ptr_indexed_getter(Variant::Type(p_type));
|
||||
}
|
||||
static GDNativePtrKeyedSetter gdnative_variant_get_ptr_keyed_setter(GDNativeVariantType p_type) {
|
||||
return (GDNativePtrKeyedSetter)Variant::get_member_ptr_keyed_setter(Variant::Type(p_type));
|
||||
}
|
||||
static GDNativePtrKeyedGetter gdnative_variant_get_ptr_keyed_getter(GDNativeVariantType p_type) {
|
||||
return (GDNativePtrKeyedGetter)Variant::get_member_ptr_keyed_getter(Variant::Type(p_type));
|
||||
}
|
||||
static GDNativePtrKeyedChecker gdnative_variant_get_ptr_keyed_checker(GDNativeVariantType p_type) {
|
||||
return (GDNativePtrKeyedChecker)Variant::get_member_ptr_keyed_checker(Variant::Type(p_type));
|
||||
}
|
||||
static void gdnative_variant_get_constant_value(GDNativeVariantType p_type, const char *p_constant, GDNativeVariantPtr r_ret) {
|
||||
memnew_placement_custom(r_ret, Variant, Variant(Variant::get_constant_value(Variant::Type(p_type), p_constant)));
|
||||
}
|
||||
static GDNativePtrUtilityFunction gdnative_variant_get_ptr_utility_function(const char *p_function, GDNativeInt p_hash) {
|
||||
StringName function = p_function;
|
||||
uint32_t hash = Variant::get_utility_function_hash(function);
|
||||
if (hash != p_hash) {
|
||||
ERR_PRINT_ONCE("Error getting utility function " + String(function) + ", hash mismatch.");
|
||||
return nullptr;
|
||||
}
|
||||
return (GDNativePtrUtilityFunction)Variant::get_ptr_utility_function(function);
|
||||
}
|
||||
|
||||
//string helpers
|
||||
|
||||
static void gdnative_string_new_with_latin1_chars(GDNativeStringPtr r_dest, const char *p_contents) {
|
||||
String *dest = (String *)r_dest;
|
||||
memnew_placement(dest, String);
|
||||
*dest = String(p_contents);
|
||||
}
|
||||
|
||||
static void gdnative_string_new_with_utf8_chars(GDNativeStringPtr r_dest, const char *p_contents) {
|
||||
String *dest = (String *)r_dest;
|
||||
memnew_placement(dest, String);
|
||||
dest->parse_utf8(p_contents);
|
||||
}
|
||||
|
||||
static void gdnative_string_new_with_utf16_chars(GDNativeStringPtr r_dest, const char16_t *p_contents) {
|
||||
String *dest = (String *)r_dest;
|
||||
memnew_placement(dest, String);
|
||||
dest->parse_utf16(p_contents);
|
||||
}
|
||||
|
||||
static void gdnative_string_new_with_utf32_chars(GDNativeStringPtr r_dest, const char32_t *p_contents) {
|
||||
String *dest = (String *)r_dest;
|
||||
memnew_placement(dest, String);
|
||||
*dest = String((const char32_t *)p_contents);
|
||||
}
|
||||
|
||||
static void gdnative_string_new_with_wide_chars(GDNativeStringPtr r_dest, const wchar_t *p_contents) {
|
||||
String *dest = (String *)r_dest;
|
||||
if (sizeof(wchar_t) == 2) {
|
||||
// wchar_t is 16 bit, parse.
|
||||
memnew_placement(dest, String);
|
||||
dest->parse_utf16((const char16_t *)p_contents);
|
||||
} else {
|
||||
// wchar_t is 32 bit, copy.
|
||||
memnew_placement(dest, String);
|
||||
*dest = String((const char32_t *)p_contents);
|
||||
}
|
||||
}
|
||||
|
||||
static void gdnative_string_new_with_latin1_chars_and_len(GDNativeStringPtr r_dest, const char *p_contents, const GDNativeInt p_size) {
|
||||
String *dest = (String *)r_dest;
|
||||
memnew_placement(dest, String);
|
||||
*dest = String(p_contents, p_size);
|
||||
}
|
||||
|
||||
static void gdnative_string_new_with_utf8_chars_and_len(GDNativeStringPtr r_dest, const char *p_contents, const GDNativeInt p_size) {
|
||||
String *dest = (String *)r_dest;
|
||||
memnew_placement(dest, String);
|
||||
dest->parse_utf8(p_contents, p_size);
|
||||
}
|
||||
|
||||
static void gdnative_string_new_with_utf16_chars_and_len(GDNativeStringPtr r_dest, const char16_t *p_contents, const GDNativeInt p_size) {
|
||||
String *dest = (String *)r_dest;
|
||||
memnew_placement(dest, String);
|
||||
dest->parse_utf16(p_contents, p_size);
|
||||
}
|
||||
|
||||
static void gdnative_string_new_with_utf32_chars_and_len(GDNativeStringPtr r_dest, const char32_t *p_contents, const GDNativeInt p_size) {
|
||||
String *dest = (String *)r_dest;
|
||||
memnew_placement(dest, String);
|
||||
*dest = String((const char32_t *)p_contents, p_size);
|
||||
}
|
||||
|
||||
static void gdnative_string_new_with_wide_chars_and_len(GDNativeStringPtr r_dest, const wchar_t *p_contents, const GDNativeInt p_size) {
|
||||
String *dest = (String *)r_dest;
|
||||
if (sizeof(wchar_t) == 2) {
|
||||
// wchar_t is 16 bit, parse.
|
||||
memnew_placement(dest, String);
|
||||
dest->parse_utf16((const char16_t *)p_contents, p_size);
|
||||
} else {
|
||||
// wchar_t is 32 bit, copy.
|
||||
memnew_placement(dest, String);
|
||||
*dest = String((const char32_t *)p_contents, p_size);
|
||||
}
|
||||
}
|
||||
|
||||
static GDNativeInt gdnative_string_to_latin1_chars(const GDNativeStringPtr p_self, char *r_text, GDNativeInt p_max_write_length) {
|
||||
String *self = (String *)p_self;
|
||||
CharString cs = self->ascii(true);
|
||||
GDNativeInt len = cs.length();
|
||||
if (r_text) {
|
||||
const char *s_text = cs.ptr();
|
||||
for (GDNativeInt i = 0; i < MIN(len, p_max_write_length); i++) {
|
||||
r_text[i] = s_text[i];
|
||||
}
|
||||
}
|
||||
return len;
|
||||
}
|
||||
static GDNativeInt gdnative_string_to_utf8_chars(const GDNativeStringPtr p_self, char *r_text, GDNativeInt p_max_write_length) {
|
||||
String *self = (String *)p_self;
|
||||
CharString cs = self->utf8();
|
||||
GDNativeInt len = cs.length();
|
||||
if (r_text) {
|
||||
const char *s_text = cs.ptr();
|
||||
for (GDNativeInt i = 0; i < MIN(len, p_max_write_length); i++) {
|
||||
r_text[i] = s_text[i];
|
||||
}
|
||||
}
|
||||
return len;
|
||||
}
|
||||
static GDNativeInt gdnative_string_to_utf16_chars(const GDNativeStringPtr p_self, char16_t *r_text, GDNativeInt p_max_write_length) {
|
||||
String *self = (String *)p_self;
|
||||
Char16String cs = self->utf16();
|
||||
GDNativeInt len = cs.length();
|
||||
if (r_text) {
|
||||
const char16_t *s_text = cs.ptr();
|
||||
for (GDNativeInt i = 0; i < MIN(len, p_max_write_length); i++) {
|
||||
r_text[i] = s_text[i];
|
||||
}
|
||||
}
|
||||
return len;
|
||||
}
|
||||
static GDNativeInt gdnative_string_to_utf32_chars(const GDNativeStringPtr p_self, char32_t *r_text, GDNativeInt p_max_write_length) {
|
||||
String *self = (String *)p_self;
|
||||
GDNativeInt len = self->length();
|
||||
if (r_text) {
|
||||
const char32_t *s_text = self->ptr();
|
||||
for (GDNativeInt i = 0; i < MIN(len, p_max_write_length); i++) {
|
||||
r_text[i] = s_text[i];
|
||||
}
|
||||
}
|
||||
return len;
|
||||
}
|
||||
static GDNativeInt gdnative_string_to_wide_chars(const GDNativeStringPtr p_self, wchar_t *r_text, GDNativeInt p_max_write_length) {
|
||||
if (sizeof(wchar_t) == 4) {
|
||||
return gdnative_string_to_utf32_chars(p_self, (char32_t *)r_text, p_max_write_length);
|
||||
} else {
|
||||
return gdnative_string_to_utf16_chars(p_self, (char16_t *)r_text, p_max_write_length);
|
||||
}
|
||||
}
|
||||
|
||||
static char32_t *gdnative_string_operator_index(GDNativeStringPtr p_self, GDNativeInt p_index) {
|
||||
String *self = (String *)p_self;
|
||||
ERR_FAIL_INDEX_V(p_index, self->length() + 1, nullptr);
|
||||
return &self->ptrw()[p_index];
|
||||
}
|
||||
|
||||
static const char32_t *gdnative_string_operator_index_const(const GDNativeStringPtr p_self, GDNativeInt p_index) {
|
||||
const String *self = (const String *)p_self;
|
||||
ERR_FAIL_INDEX_V(p_index, self->length() + 1, nullptr);
|
||||
return &self->ptr()[p_index];
|
||||
}
|
||||
|
||||
/* OBJECT API */
|
||||
|
||||
static void gdnative_object_method_bind_ptrcall(GDNativeMethodBindPtr p_method_bind, GDNativeObjectPtr p_instance, const GDNativeTypePtr *p_args, GDNativeTypePtr p_ret) {
|
||||
MethodBind *mb = (MethodBind *)p_method_bind;
|
||||
Object *o = (Object *)p_instance;
|
||||
mb->ptrcall(o, (const void **)p_args, p_ret);
|
||||
}
|
||||
|
||||
static void gdnative_object_destroy(GDNativeObjectPtr p_o) {
|
||||
memdelete((Object *)p_o);
|
||||
}
|
||||
|
||||
static GDNativeObjectPtr gdnative_global_get_singleton(const char *p_name) {
|
||||
return (GDNativeObjectPtr)Engine::get_singleton()->get_singleton_object(String(p_name));
|
||||
}
|
||||
|
||||
static GDNativeObjectPtr gdnative_object_get_instance_from_id(GDObjectInstanceID p_instance_id) {
|
||||
return (GDNativeObjectPtr)ObjectDB::get_instance(ObjectID(p_instance_id));
|
||||
}
|
||||
|
||||
static GDNativeObjectPtr gdnative_object_cast_to(const GDNativeObjectPtr p_object, void *p_class_tag) {
|
||||
if (!p_object) {
|
||||
return nullptr;
|
||||
}
|
||||
Object *o = (Object *)p_object;
|
||||
|
||||
return o->is_class_ptr(p_class_tag) ? (GDNativeObjectPtr)o : (GDNativeObjectPtr) nullptr;
|
||||
}
|
||||
|
||||
static GDObjectInstanceID gdnative_object_get_instance_id(const GDNativeObjectPtr p_object) {
|
||||
const Object *o = (const Object *)p_object;
|
||||
return (GDObjectInstanceID)o->get_instance_id();
|
||||
}
|
||||
|
||||
static GDNativeMethodBindPtr gdnative_classdb_get_method_bind(const char *p_classname, const char *p_methodname, GDNativeInt p_hash) {
|
||||
MethodBind *mb = ClassDB::get_method(StringName(p_classname), StringName(p_methodname));
|
||||
ERR_FAIL_COND_V(!mb, nullptr);
|
||||
if (mb->get_hash() != p_hash) {
|
||||
ERR_PRINT_ONCE("Hash mismatch for method '" + String(p_classname) + "." + String(p_methodname) + "'.");
|
||||
return nullptr;
|
||||
}
|
||||
// MethodBind *mb = ClassDB::get_method("Node", "get_name");
|
||||
return (GDNativeMethodBindPtr)mb;
|
||||
}
|
||||
|
||||
static GDNativeClassConstructor gdnative_classdb_get_constructor(const char *p_classname) {
|
||||
ClassDB::ClassInfo *class_info = ClassDB::classes.getptr(StringName(p_classname));
|
||||
if (class_info) {
|
||||
return (GDNativeClassConstructor)class_info->creation_func;
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
static void *gdnative_classdb_get_class_tag(const char *p_classname) {
|
||||
ClassDB::ClassInfo *class_info = ClassDB::classes.getptr(p_classname);
|
||||
return class_info ? class_info->class_ptr : nullptr;
|
||||
}
|
||||
|
||||
void gdnative_setup_interface(GDNativeInterface *p_interface) {
|
||||
GDNativeInterface &gdni = *p_interface;
|
||||
|
||||
gdni.version_major = VERSION_MAJOR;
|
||||
gdni.version_minor = VERSION_MINOR;
|
||||
#if VERSION_PATCH
|
||||
gdni.version_patch = VERSION_PATCH;
|
||||
#else
|
||||
gdni.version_patch = 0;
|
||||
#endif
|
||||
gdni.version_string = VERSION_FULL_NAME;
|
||||
|
||||
/* GODOT CORE */
|
||||
|
||||
gdni.mem_alloc = gdnative_alloc;
|
||||
gdni.mem_realloc = gdnative_realloc;
|
||||
gdni.mem_free = gdnative_free;
|
||||
|
||||
gdni.print_error = gdnative_print_error;
|
||||
gdni.print_warning = gdnative_print_warning;
|
||||
gdni.print_script_error = gdnative_print_script_error;
|
||||
|
||||
/* GODOT VARIANT */
|
||||
|
||||
// variant general
|
||||
gdni.variant_new_copy = gdnative_variant_new_copy;
|
||||
gdni.variant_new_nil = gdnative_variant_new_nil;
|
||||
gdni.variant_destroy = gdnative_variant_destroy;
|
||||
|
||||
gdni.variant_call = gdnative_variant_call;
|
||||
gdni.variant_call_static = gdnative_variant_call_static;
|
||||
gdni.variant_evaluate = gdnative_variant_evaluate;
|
||||
gdni.variant_set = gdnative_variant_set;
|
||||
gdni.variant_set_named = gdnative_variant_set_named;
|
||||
gdni.variant_set_keyed = gdnative_variant_set_keyed;
|
||||
gdni.variant_set_indexed = gdnative_variant_set_indexed;
|
||||
gdni.variant_get = gdnative_variant_get;
|
||||
gdni.variant_get_named = gdnative_variant_get_named;
|
||||
gdni.variant_get_keyed = gdnative_variant_get_keyed;
|
||||
gdni.variant_get_indexed = gdnative_variant_get_indexed;
|
||||
gdni.variant_iter_init = gdnative_variant_iter_init;
|
||||
gdni.variant_iter_next = gdnative_variant_iter_next;
|
||||
gdni.variant_iter_get = gdnative_variant_iter_get;
|
||||
gdni.variant_hash_compare = gdnative_variant_hash_compare;
|
||||
gdni.variant_booleanize = gdnative_variant_booleanize;
|
||||
gdni.variant_blend = gdnative_variant_blend;
|
||||
gdni.variant_interpolate = gdnative_variant_interpolate;
|
||||
gdni.variant_duplicate = gdnative_variant_duplicate;
|
||||
gdni.variant_stringify = gdnative_variant_stringify;
|
||||
|
||||
gdni.variant_get_type = gdnative_variant_get_type;
|
||||
gdni.variant_has_method = gdnative_variant_has_method;
|
||||
gdni.variant_has_member = gdnative_variant_has_member;
|
||||
gdni.variant_has_key = gdnative_variant_has_key;
|
||||
gdni.variant_get_type_name = gdnative_variant_get_type_name;
|
||||
gdni.variant_can_convert = gdnative_variant_can_convert;
|
||||
gdni.variant_can_convert_strict = gdnative_variant_can_convert_strict;
|
||||
|
||||
//ptrcalls
|
||||
#if 0
|
||||
GDNativeVariantFromTypeConstructorFunc (*get_variant_from_type_constructor)(GDNativeVariantType p_type);
|
||||
GDNativeTypeFromVariantConstructorFunc (*get_variant_to_type_constructor)(GDNativeVariantType p_type);
|
||||
#endif
|
||||
|
||||
gdni.variant_get_ptr_operator_evaluator = gdnative_variant_get_ptr_operator_evaluator;
|
||||
gdni.variant_get_ptr_builtin_method = gdnative_variant_get_ptr_builtin_method;
|
||||
gdni.variant_get_ptr_constructor = gdnative_variant_get_ptr_constructor;
|
||||
gdni.variant_construct = gdnative_variant_construct;
|
||||
gdni.variant_get_ptr_setter = gdnative_variant_get_ptr_setter;
|
||||
gdni.variant_get_ptr_getter = gdnative_variant_get_ptr_getter;
|
||||
gdni.variant_get_ptr_indexed_setter = gdnative_variant_get_ptr_indexed_setter;
|
||||
gdni.variant_get_ptr_indexed_getter = gdnative_variant_get_ptr_indexed_getter;
|
||||
gdni.variant_get_ptr_keyed_setter = gdnative_variant_get_ptr_keyed_setter;
|
||||
gdni.variant_get_ptr_keyed_getter = gdnative_variant_get_ptr_keyed_getter;
|
||||
gdni.variant_get_ptr_keyed_checker = gdnative_variant_get_ptr_keyed_checker;
|
||||
gdni.variant_get_constant_value = gdnative_variant_get_constant_value;
|
||||
gdni.variant_get_ptr_utility_function = gdnative_variant_get_ptr_utility_function;
|
||||
|
||||
// extra utilities
|
||||
|
||||
gdni.string_new_with_latin1_chars = gdnative_string_new_with_latin1_chars;
|
||||
gdni.string_new_with_utf8_chars = gdnative_string_new_with_utf8_chars;
|
||||
gdni.string_new_with_utf16_chars = gdnative_string_new_with_utf16_chars;
|
||||
gdni.string_new_with_utf32_chars = gdnative_string_new_with_utf32_chars;
|
||||
gdni.string_new_with_wide_chars = gdnative_string_new_with_wide_chars;
|
||||
gdni.string_new_with_latin1_chars_and_len = gdnative_string_new_with_latin1_chars_and_len;
|
||||
gdni.string_new_with_utf8_chars_and_len = gdnative_string_new_with_utf8_chars_and_len;
|
||||
gdni.string_new_with_utf16_chars_and_len = gdnative_string_new_with_utf16_chars_and_len;
|
||||
gdni.string_new_with_utf32_chars_and_len = gdnative_string_new_with_utf32_chars_and_len;
|
||||
gdni.string_new_with_wide_chars_and_len = gdnative_string_new_with_wide_chars_and_len;
|
||||
gdni.string_to_latin1_chars = gdnative_string_to_latin1_chars;
|
||||
gdni.string_to_utf8_chars = gdnative_string_to_utf8_chars;
|
||||
gdni.string_to_utf16_chars = gdnative_string_to_utf16_chars;
|
||||
gdni.string_to_utf32_chars = gdnative_string_to_utf32_chars;
|
||||
gdni.string_to_wide_chars = gdnative_string_to_wide_chars;
|
||||
gdni.string_operator_index = gdnative_string_operator_index;
|
||||
gdni.string_operator_index_const = gdnative_string_operator_index_const;
|
||||
|
||||
/* OBJECT */
|
||||
|
||||
gdni.object_method_bind_ptrcall = gdnative_object_method_bind_ptrcall;
|
||||
gdni.object_destroy = gdnative_object_destroy;
|
||||
gdni.global_get_singleton = gdnative_global_get_singleton;
|
||||
|
||||
gdni.object_cast_to = gdnative_object_cast_to;
|
||||
gdni.object_get_instance_from_id = gdnative_object_get_instance_from_id;
|
||||
gdni.object_get_instance_id = gdnative_object_get_instance_id;
|
||||
|
||||
/* CLASSDB */
|
||||
|
||||
gdni.classdb_get_constructor = gdnative_classdb_get_constructor;
|
||||
gdni.classdb_get_method_bind = gdnative_classdb_get_method_bind;
|
||||
gdni.classdb_get_class_tag = gdnative_classdb_get_class_tag;
|
||||
|
||||
/* CLASSDB EXTENSION */
|
||||
|
||||
//these are filled by implementation, since it will want to keep track of registered classes
|
||||
gdni.classdb_register_extension_class = nullptr;
|
||||
gdni.classdb_register_extension_class_method = nullptr;
|
||||
gdni.classdb_register_extension_class_integer_constant = nullptr;
|
||||
gdni.classdb_register_extension_class_property = nullptr;
|
||||
gdni.classdb_register_extension_class_signal = nullptr;
|
||||
gdni.classdb_unregister_extension_class = nullptr;
|
||||
}
|
|
@ -0,0 +1,427 @@
|
|||
/*************************************************************************/
|
||||
/* gdnative_interface.h */
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* https://godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
|
||||
/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
|
||||
/* */
|
||||
/* Permission is hereby granted, free of charge, to any person obtaining */
|
||||
/* a copy of this software and associated documentation files (the */
|
||||
/* "Software"), to deal in the Software without restriction, including */
|
||||
/* without limitation the rights to use, copy, modify, merge, publish, */
|
||||
/* distribute, sublicense, and/or sell copies of the Software, and to */
|
||||
/* permit persons to whom the Software is furnished to do so, subject to */
|
||||
/* the following conditions: */
|
||||
/* */
|
||||
/* The above copyright notice and this permission notice shall be */
|
||||
/* included in all copies or substantial portions of the Software. */
|
||||
/* */
|
||||
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
|
||||
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
|
||||
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
|
||||
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
|
||||
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
|
||||
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
||||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
/*************************************************************************/
|
||||
|
||||
#ifndef GDNATIVE_INTERFACE_H
|
||||
#define GDNATIVE_INTERFACE_H
|
||||
|
||||
/* This is a C class header, you can copy it and use it directly in your own binders.
|
||||
* Together with the JSON file, you should be able to generate any binder.
|
||||
*/
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* VARIANT TYPES */
|
||||
|
||||
typedef enum {
|
||||
GDNATIVE_VARIANT_TYPE_NIL,
|
||||
|
||||
/* atomic types */
|
||||
GDNATIVE_VARIANT_TYPE_BOOL,
|
||||
GDNATIVE_VARIANT_TYPE_INT,
|
||||
GDNATIVE_VARIANT_TYPE_FLOAT,
|
||||
GDNATIVE_VARIANT_TYPE_STRING,
|
||||
|
||||
/* math types */
|
||||
GDNATIVE_VARIANT_TYPE_VECTOR2,
|
||||
GDNATIVE_VARIANT_TYPE_VECTOR2I,
|
||||
GDNATIVE_VARIANT_TYPE_RECT2,
|
||||
GDNATIVE_VARIANT_TYPE_RECT2I,
|
||||
GDNATIVE_VARIANT_TYPE_VECTOR3,
|
||||
GDNATIVE_VARIANT_TYPE_VECTOR3I,
|
||||
GDNATIVE_VARIANT_TYPE_TRANSFORM2D,
|
||||
GDNATIVE_VARIANT_TYPE_PLANE,
|
||||
GDNATIVE_VARIANT_TYPE_QUATERNION,
|
||||
GDNATIVE_VARIANT_TYPE_AABB,
|
||||
GDNATIVE_VARIANT_TYPE_BASIS,
|
||||
GDNATIVE_VARIANT_TYPE_TRANSFORM3D,
|
||||
|
||||
/* misc types */
|
||||
GDNATIVE_VARIANT_TYPE_COLOR,
|
||||
GDNATIVE_VARIANT_TYPE_STRING_NAME,
|
||||
GDNATIVE_VARIANT_TYPE_NODE_PATH,
|
||||
GDNATIVE_VARIANT_TYPE_RID,
|
||||
GDNATIVE_VARIANT_TYPE_OBJECT,
|
||||
GDNATIVE_VARIANT_TYPE_CALLABLE,
|
||||
GDNATIVE_VARIANT_TYPE_SIGNAL,
|
||||
GDNATIVE_VARIANT_TYPE_DICTIONARY,
|
||||
GDNATIVE_VARIANT_TYPE_ARRAY,
|
||||
|
||||
/* typed arrays */
|
||||
GDNATIVE_VARIANT_TYPE_PACKED_BYTE_ARRAY,
|
||||
GDNATIVE_VARIANT_TYPE_PACKED_INT32_ARRAY,
|
||||
GDNATIVE_VARIANT_TYPE_PACKED_INT64_ARRAY,
|
||||
GDNATIVE_VARIANT_TYPE_PACKED_FLOAT32_ARRAY,
|
||||
GDNATIVE_VARIANT_TYPE_PACKED_FLOAT64_ARRAY,
|
||||
GDNATIVE_VARIANT_TYPE_PACKED_STRING_ARRAY,
|
||||
GDNATIVE_VARIANT_TYPE_PACKED_VECTOR2_ARRAY,
|
||||
GDNATIVE_VARIANT_TYPE_PACKED_VECTOR3_ARRAY,
|
||||
GDNATIVE_VARIANT_TYPE_PACKED_COLOR_ARRAY,
|
||||
|
||||
GDNATIVE_VARIANT_TYPE_VARIANT_MAX
|
||||
} GDNativeVariantType;
|
||||
|
||||
typedef enum {
|
||||
/* comparison */
|
||||
GDNATIVE_VARIANT_OP_EQUAL,
|
||||
GDNATIVE_VARIANT_OP_NOT_EQUAL,
|
||||
GDNATIVE_VARIANT_OP_LESS,
|
||||
GDNATIVE_VARIANT_OP_LESS_EQUAL,
|
||||
GDNATIVE_VARIANT_OP_GREATER,
|
||||
GDNATIVE_VARIANT_OP_GREATER_EQUAL,
|
||||
/* mathematic */
|
||||
GDNATIVE_VARIANT_OP_ADD,
|
||||
GDNATIVE_VARIANT_OP_SUBTRACT,
|
||||
GDNATIVE_VARIANT_OP_MULTIPLY,
|
||||
GDNATIVE_VARIANT_OP_DIVIDE,
|
||||
GDNATIVE_VARIANT_OP_NEGATE,
|
||||
GDNATIVE_VARIANT_OP_POSITIVE,
|
||||
GDNATIVE_VARIANT_OP_MODULE,
|
||||
/* bitwise */
|
||||
GDNATIVE_VARIANT_OP_SHIFT_LEFT,
|
||||
GDNATIVE_VARIANT_OP_SHIFT_RIGHT,
|
||||
GDNATIVE_VARIANT_OP_BIT_AND,
|
||||
GDNATIVE_VARIANT_OP_BIT_OR,
|
||||
GDNATIVE_VARIANT_OP_BIT_XOR,
|
||||
GDNATIVE_VARIANT_OP_BIT_NEGATE,
|
||||
/* logic */
|
||||
GDNATIVE_VARIANT_OP_AND,
|
||||
GDNATIVE_VARIANT_OP_OR,
|
||||
GDNATIVE_VARIANT_OP_XOR,
|
||||
GDNATIVE_VARIANT_OP_NOT,
|
||||
/* containment */
|
||||
GDNATIVE_VARIANT_OP_IN,
|
||||
GDNATIVE_VARIANT_OP_MAX
|
||||
|
||||
} GDNativeVariantOperator;
|
||||
|
||||
typedef void *GDNativeVariantPtr;
|
||||
typedef void *GDNativeStringNamePtr;
|
||||
typedef void *GDNativeStringPtr;
|
||||
typedef void *GDNativeObjectPtr;
|
||||
typedef void *GDNativeTypePtr;
|
||||
typedef void *GDNativeMethodBindPtr;
|
||||
typedef int64_t GDNativeInt;
|
||||
typedef uint32_t GDNativeBool;
|
||||
typedef uint64_t GDObjectInstanceID;
|
||||
|
||||
/* VARIANT DATA I/O */
|
||||
|
||||
typedef enum {
|
||||
NATIVE_CALL_OK,
|
||||
NATIVE_CALL_ERROR_INVALID_METHOD,
|
||||
NATIVE_CALL_ERROR_INVALID_ARGUMENT, /* expected is variant type */
|
||||
NATIVE_CALL_ERROR_TOO_MANY_ARGUMENTS, /* expected is number of arguments */
|
||||
NATIVE_CALL_ERROR_TOO_FEW_ARGUMENTS, /* expected is number of arguments */
|
||||
NATIVE_CALL_ERROR_INSTANCE_IS_NULL,
|
||||
|
||||
} GDNativeCallErrorType;
|
||||
|
||||
typedef struct {
|
||||
GDNativeCallErrorType error;
|
||||
int32_t argument;
|
||||
int32_t expected;
|
||||
} GDNativeCallError;
|
||||
|
||||
typedef void (*GDNativeVariantFromTypeConstructorFunc)(GDNativeVariantPtr, GDNativeTypePtr);
|
||||
typedef void (*GDNativeTypeFromVariantConstructorFunc)(GDNativeTypePtr, GDNativeVariantPtr);
|
||||
typedef void (*GDNativePtrOperatorEvaluator)(const GDNativeTypePtr p_left, const GDNativeTypePtr p_right, GDNativeTypePtr r_result);
|
||||
typedef void (*GDNativePtrBuiltInMethod)(GDNativeTypePtr p_base, const GDNativeTypePtr *p_args, GDNativeTypePtr r_return, int p_argument_count);
|
||||
typedef void (*GDNativePtrConstructor)(GDNativeTypePtr p_base, const GDNativeTypePtr *p_args);
|
||||
typedef void (*GDNativePtrSetter)(GDNativeTypePtr p_base, const GDNativeTypePtr p_value);
|
||||
typedef void (*GDNativePtrGetter)(const GDNativeTypePtr p_base, GDNativeTypePtr r_value);
|
||||
typedef void (*GDNativePtrIndexedSetter)(GDNativeTypePtr p_base, GDNativeInt p_index, const GDNativeTypePtr p_value);
|
||||
typedef void (*GDNativePtrIndexedGetter)(const GDNativeTypePtr p_base, GDNativeInt p_index, GDNativeTypePtr r_value);
|
||||
typedef void (*GDNativePtrKeyedSetter)(GDNativeTypePtr p_base, const GDNativeTypePtr p_key, const GDNativeTypePtr p_value);
|
||||
typedef void (*GDNativePtrKeyedGetter)(const GDNativeTypePtr p_base, const GDNativeTypePtr p_key, GDNativeTypePtr r_value);
|
||||
typedef uint32_t (*GDNativePtrKeyedChecker)(const GDNativeVariantPtr p_base, const GDNativeVariantPtr p_key);
|
||||
typedef void (*GDNativePtrUtilityFunction)(GDNativeTypePtr r_return, const GDNativeTypePtr *p_arguments, int p_argument_count);
|
||||
|
||||
typedef GDNativeObjectPtr (*GDNativeClassConstructor)();
|
||||
|
||||
/* EXTENSION CLASSES */
|
||||
|
||||
typedef void *GDExtensionClassInstancePtr;
|
||||
|
||||
typedef GDNativeBool (*GDNativeExtensionClassSet)(GDExtensionClassInstancePtr p_instance, const GDNativeStringNamePtr p_name, const GDNativeVariantPtr p_value);
|
||||
typedef GDNativeBool (*GDNativeExtensionClassGet)(GDExtensionClassInstancePtr p_instance, const GDNativeStringNamePtr p_name, GDNativeVariantPtr r_ret);
|
||||
|
||||
typedef struct {
|
||||
uint32_t type;
|
||||
const char *name;
|
||||
const char *class_name;
|
||||
uint32_t hint;
|
||||
const char *hint_string;
|
||||
uint32_t usage;
|
||||
} GDNativePropertyInfo;
|
||||
|
||||
typedef const GDNativePropertyInfo *(*GDNativeExtensionClassGetPropertyList)(GDExtensionClassInstancePtr p_instance, uint32_t *r_count);
|
||||
typedef void (*GDNativeExtensionClassFreePropertyList)(GDExtensionClassInstancePtr p_instance, const GDNativePropertyInfo *p_list);
|
||||
typedef void (*GDNativeExtensionClassNotification)(GDExtensionClassInstancePtr p_instance, int32_t p_what);
|
||||
typedef const char *(*GDNativeExtensionClassToString)(GDExtensionClassInstancePtr p_instance);
|
||||
typedef void (*GDNativeExtensionClassReference)(GDExtensionClassInstancePtr p_instance);
|
||||
typedef void (*GDNativeExtensionClassUnreference)(GDExtensionClassInstancePtr p_instance);
|
||||
typedef void (*GDNativeExtensionClassCallVirtual)(GDExtensionClassInstancePtr p_instance, const GDNativeTypePtr *p_args, GDNativeTypePtr r_ret);
|
||||
typedef GDExtensionClassInstancePtr (*GDNativeExtensionClassCreateInstance)(void *p_userdata);
|
||||
typedef void (*GDNativeExtensionClassFreeInstance)(void *p_userdata, GDExtensionClassInstancePtr p_instance);
|
||||
typedef GDNativeExtensionClassCallVirtual (*GDNativeExtensionClassGetVirtual)(void *p_userdata, const char *p_name);
|
||||
|
||||
typedef struct {
|
||||
GDNativeExtensionClassSet set_func;
|
||||
GDNativeExtensionClassGet get_func;
|
||||
GDNativeExtensionClassGetPropertyList get_property_list_func;
|
||||
GDNativeExtensionClassFreePropertyList free_property_list_func;
|
||||
GDNativeExtensionClassNotification notification_func;
|
||||
GDNativeExtensionClassToString to_string_func;
|
||||
GDNativeExtensionClassReference reference_func;
|
||||
GDNativeExtensionClassUnreference unreference_func;
|
||||
GDNativeExtensionClassCreateInstance create_instance_func; /* this one is mandatory */
|
||||
GDNativeExtensionClassFreeInstance free_instance_func; /* this one is mandatory */
|
||||
GDNativeExtensionClassGetVirtual get_firtual_func;
|
||||
void *class_userdata;
|
||||
} GDNativeExtensionClassCreationInfo;
|
||||
|
||||
typedef void *GDNativeExtensionClassLibraryPtr;
|
||||
|
||||
typedef const GDNativePropertyInfo *(*GDNativeExtensionClassGetPropertyList)(GDExtensionClassInstancePtr p_instance, uint32_t *r_count);
|
||||
|
||||
/* Method */
|
||||
|
||||
typedef enum {
|
||||
GDNATIVE_EXTENSION_METHOD_FLAG_NORMAL = 1,
|
||||
GDNATIVE_EXTENSION_METHOD_FLAG_EDITOR = 2,
|
||||
GDNATIVE_EXTENSION_METHOD_FLAG_NOSCRIPT = 4,
|
||||
GDNATIVE_EXTENSION_METHOD_FLAG_CONST = 8,
|
||||
GDNATIVE_EXTENSION_METHOD_FLAG_REVERSE = 16, /* used for events */
|
||||
GDNATIVE_EXTENSION_METHOD_FLAG_VIRTUAL = 32,
|
||||
GDNATIVE_EXTENSION_METHOD_FLAG_FROM_SCRIPT = 64,
|
||||
GDNATIVE_EXTENSION_METHOD_FLAG_VARARG = 128,
|
||||
GDNATIVE_EXTENSION_METHOD_FLAG_STATIC = 256,
|
||||
GDNATIVE_EXTENSION_METHOD_FLAGS_DEFAULT = GDNATIVE_EXTENSION_METHOD_FLAG_NORMAL,
|
||||
} GDNativeExtensionClassMethodFlags;
|
||||
|
||||
typedef enum {
|
||||
GDNATIVE_EXTENSION_METHOD_ARGUMENT_METADATA_NONE,
|
||||
GDNATIVE_EXTENSION_METHOD_ARGUMENT_METADATA_INT_IS_INT8,
|
||||
GDNATIVE_EXTENSION_METHOD_ARGUMENT_METADATA_INT_IS_INT16,
|
||||
GDNATIVE_EXTENSION_METHOD_ARGUMENT_METADATA_INT_IS_INT32,
|
||||
GDNATIVE_EXTENSION_METHOD_ARGUMENT_METADATA_INT_IS_INT64,
|
||||
GDNATIVE_EXTENSION_METHOD_ARGUMENT_METADATA_INT_IS_UINT8,
|
||||
GDNATIVE_EXTENSION_METHOD_ARGUMENT_METADATA_INT_IS_UINT16,
|
||||
GDNATIVE_EXTENSION_METHOD_ARGUMENT_METADATA_INT_IS_UINT32,
|
||||
GDNATIVE_EXTENSION_METHOD_ARGUMENT_METADATA_INT_IS_UINT64,
|
||||
GDNATIVE_EXTENSION_METHOD_ARGUMENT_METADATA_REAL_IS_FLOAT,
|
||||
GDNATIVE_EXTENSION_METHOD_ARGUMENT_METADATA_REAL_IS_DOUBLE
|
||||
} GDNativeExtensionClassMethodArgumentMetadata;
|
||||
|
||||
typedef void (*GDNativeExtensionClassMethodCall)(GDExtensionClassInstancePtr p_instance, const GDNativeVariantPtr *p_args, const GDNativeInt p_argument_count, GDNativeVariantPtr r_return, GDNativeCallError *r_error);
|
||||
typedef void (*GDNativeExtensionClassMethodPtrCall)(GDExtensionClassInstancePtr p_instance, const GDNativeTypePtr *p_args, GDNativeTypePtr r_ret);
|
||||
|
||||
/* passing -1 as argument in the following functions refers to the return type */
|
||||
typedef GDNativeVariantType (*GDNativeExtensionClassMethodGetArgumentType)(void *p_method_userdata, int32_t p_argument);
|
||||
typedef void (*GDNativeExtensionClassMethodGetArgumentInfo)(void *p_method_userdata, int32_t p_argument, GDNativePropertyInfo *r_info);
|
||||
typedef GDNativeExtensionClassMethodArgumentMetadata (*GDNativeExtensionClassMethodGetArgumentMetadata)(void *p_method_userdata, int32_t p_argument);
|
||||
|
||||
typedef struct {
|
||||
const char *name;
|
||||
void *method_userdata;
|
||||
GDNativeExtensionClassMethodCall call_func;
|
||||
GDNativeExtensionClassMethodPtrCall ptrcall_func;
|
||||
uint32_t method_flags; /* GDNativeExtensionClassMethodFlags */
|
||||
uint32_t argument_count;
|
||||
GDNativeBool has_return_value;
|
||||
GDNativeExtensionClassMethodGetArgumentType get_argument_type_func;
|
||||
GDNativeExtensionClassMethodGetArgumentInfo get_argument_info_func; /* name and hint information for the argument can be omitted in release builds. Class name should always be present if it applies. */
|
||||
GDNativeExtensionClassMethodGetArgumentMetadata get_argument_metadata_func;
|
||||
uint32_t default_argument_count;
|
||||
GDNativeVariantPtr *default_arguments;
|
||||
} GDNativeExtensionClassMethodInfo;
|
||||
|
||||
/* INTERFACE */
|
||||
|
||||
typedef struct {
|
||||
uint32_t version_major;
|
||||
uint32_t version_minor;
|
||||
uint32_t version_patch;
|
||||
const char *version_string;
|
||||
|
||||
/* GODOT CORE */
|
||||
void *(*mem_alloc)(size_t p_bytes);
|
||||
void *(*mem_realloc)(void *p_ptr, size_t p_bytes);
|
||||
void (*mem_free)(void *p_ptr);
|
||||
|
||||
void (*print_error)(const char *p_description, const char *p_function, const char *p_file, int32_t p_line);
|
||||
void (*print_warning)(const char *p_description, const char *p_function, const char *p_file, int32_t p_line);
|
||||
void (*print_script_error)(const char *p_description, const char *p_function, const char *p_file, int32_t p_line);
|
||||
|
||||
/* GODOT VARIANT */
|
||||
|
||||
/* variant general */
|
||||
void (*variant_new_copy)(GDNativeVariantPtr r_dest, const GDNativeVariantPtr p_src);
|
||||
void (*variant_new_nil)(GDNativeVariantPtr r_dest);
|
||||
void (*variant_destroy)(GDNativeVariantPtr p_self);
|
||||
|
||||
/* variant type */
|
||||
void (*variant_call)(GDNativeVariantPtr p_self, const GDNativeStringNamePtr p_method, const GDNativeVariantPtr *p_args, const GDNativeInt p_argument_count, GDNativeVariantPtr r_return, GDNativeCallError *r_error);
|
||||
void (*variant_call_static)(GDNativeVariantType p_type, const GDNativeStringNamePtr p_method, const GDNativeVariantPtr *p_args, const GDNativeInt p_argument_count, GDNativeVariantPtr r_return, GDNativeCallError *r_error);
|
||||
void (*variant_evaluate)(GDNativeVariantOperator p_op, const GDNativeVariantPtr p_a, const GDNativeVariantPtr p_b, GDNativeVariantPtr r_return, GDNativeBool *r_valid);
|
||||
void (*variant_set)(GDNativeVariantPtr p_self, const GDNativeVariantPtr p_key, const GDNativeVariantPtr p_value, GDNativeBool *r_valid);
|
||||
void (*variant_set_named)(GDNativeVariantPtr p_self, const GDNativeStringNamePtr p_key, const GDNativeVariantPtr p_value, GDNativeBool *r_valid);
|
||||
void (*variant_set_keyed)(GDNativeVariantPtr p_self, const GDNativeVariantPtr p_key, const GDNativeVariantPtr p_value, GDNativeBool *r_valid);
|
||||
void (*variant_set_indexed)(GDNativeVariantPtr p_self, GDNativeInt p_index, const GDNativeVariantPtr p_value, GDNativeBool *r_valid, GDNativeBool *r_oob);
|
||||
void (*variant_get)(const GDNativeVariantPtr p_self, const GDNativeVariantPtr p_key, GDNativeVariantPtr r_ret, GDNativeBool *r_valid);
|
||||
void (*variant_get_named)(const GDNativeVariantPtr p_self, const GDNativeStringNamePtr p_key, GDNativeVariantPtr r_ret, GDNativeBool *r_valid);
|
||||
void (*variant_get_keyed)(const GDNativeVariantPtr p_self, const GDNativeVariantPtr p_key, GDNativeVariantPtr r_ret, GDNativeBool *r_valid);
|
||||
void (*variant_get_indexed)(const GDNativeVariantPtr p_self, GDNativeInt p_index, GDNativeVariantPtr r_ret, GDNativeBool *r_valid, GDNativeBool *r_oob);
|
||||
GDNativeBool (*variant_iter_init)(const GDNativeVariantPtr p_self, GDNativeVariantPtr r_iter, GDNativeBool *r_valid);
|
||||
GDNativeBool (*variant_iter_next)(const GDNativeVariantPtr p_self, GDNativeVariantPtr r_iter, GDNativeBool *r_valid);
|
||||
void (*variant_iter_get)(const GDNativeVariantPtr p_self, GDNativeVariantPtr r_iter, GDNativeVariantPtr r_ret, GDNativeBool *r_valid);
|
||||
GDNativeBool (*variant_hash_compare)(const GDNativeVariantPtr p_self, const GDNativeVariantPtr p_other);
|
||||
GDNativeBool (*variant_booleanize)(const GDNativeVariantPtr p_self);
|
||||
void (*variant_blend)(const GDNativeVariantPtr p_a, const GDNativeVariantPtr p_b, float p_c, GDNativeVariantPtr r_dst);
|
||||
void (*variant_interpolate)(const GDNativeVariantPtr p_a, const GDNativeVariantPtr p_b, float p_c, GDNativeVariantPtr r_dst);
|
||||
void (*variant_duplicate)(const GDNativeVariantPtr p_self, GDNativeVariantPtr r_ret, GDNativeBool p_deep);
|
||||
void (*variant_stringify)(const GDNativeVariantPtr p_self, GDNativeStringPtr r_ret);
|
||||
|
||||
GDNativeVariantType (*variant_get_type)(const GDNativeVariantPtr p_self);
|
||||
GDNativeBool (*variant_has_method)(const GDNativeVariantPtr p_self, const GDNativeStringNamePtr p_method);
|
||||
GDNativeBool (*variant_has_member)(GDNativeVariantType p_type, const GDNativeStringNamePtr p_member);
|
||||
GDNativeBool (*variant_has_key)(const GDNativeVariantPtr p_self, const GDNativeVariantPtr p_key, GDNativeBool *r_valid);
|
||||
void (*variant_get_type_name)(GDNativeVariantType p_type, GDNativeStringPtr r_name);
|
||||
GDNativeBool (*variant_can_convert)(GDNativeVariantType p_from, GDNativeVariantType p_to);
|
||||
GDNativeBool (*variant_can_convert_strict)(GDNativeVariantType p_from, GDNativeVariantType p_to);
|
||||
|
||||
/* ptrcalls */
|
||||
GDNativeVariantFromTypeConstructorFunc (*get_variant_from_type_constructor)(GDNativeVariantType p_type);
|
||||
GDNativeTypeFromVariantConstructorFunc (*get_variant_to_type_constructor)(GDNativeVariantType p_type);
|
||||
GDNativePtrOperatorEvaluator (*variant_get_ptr_operator_evaluator)(GDNativeVariantOperator p_operator, GDNativeVariantType p_type_a, GDNativeVariantType p_type_b);
|
||||
GDNativePtrBuiltInMethod (*variant_get_ptr_builtin_method)(GDNativeVariantType p_type, const char *p_method, GDNativeInt p_hash);
|
||||
GDNativePtrConstructor (*variant_get_ptr_constructor)(GDNativeVariantType p_type, int32_t p_constructor);
|
||||
void (*variant_construct)(GDNativeVariantType p_type, GDNativeVariantPtr p_base, const GDNativeVariantPtr *p_args, int32_t p_argument_count, GDNativeCallError *r_error);
|
||||
GDNativePtrSetter (*variant_get_ptr_setter)(GDNativeVariantType p_type, const char *p_member);
|
||||
GDNativePtrGetter (*variant_get_ptr_getter)(GDNativeVariantType p_type, const char *p_member);
|
||||
GDNativePtrIndexedSetter (*variant_get_ptr_indexed_setter)(GDNativeVariantType p_type);
|
||||
GDNativePtrIndexedGetter (*variant_get_ptr_indexed_getter)(GDNativeVariantType p_type);
|
||||
GDNativePtrKeyedSetter (*variant_get_ptr_keyed_setter)(GDNativeVariantType p_type);
|
||||
GDNativePtrKeyedGetter (*variant_get_ptr_keyed_getter)(GDNativeVariantType p_type);
|
||||
GDNativePtrKeyedChecker (*variant_get_ptr_keyed_checker)(GDNativeVariantType p_type);
|
||||
void (*variant_get_constant_value)(GDNativeVariantType p_type, const char *p_constant, GDNativeVariantPtr r_ret);
|
||||
GDNativePtrUtilityFunction (*variant_get_ptr_utility_function)(const char *p_function, GDNativeInt p_hash);
|
||||
|
||||
/* extra utilities */
|
||||
|
||||
void (*string_new_with_latin1_chars)(GDNativeStringPtr r_dest, const char *p_contents);
|
||||
void (*string_new_with_utf8_chars)(GDNativeStringPtr r_dest, const char *p_contents);
|
||||
void (*string_new_with_utf16_chars)(GDNativeStringPtr r_dest, const char16_t *p_contents);
|
||||
void (*string_new_with_utf32_chars)(GDNativeStringPtr r_dest, const char32_t *p_contents);
|
||||
void (*string_new_with_wide_chars)(GDNativeStringPtr r_dest, const wchar_t *p_contents);
|
||||
void (*string_new_with_latin1_chars_and_len)(GDNativeStringPtr r_dest, const char *p_contents, const GDNativeInt p_size);
|
||||
void (*string_new_with_utf8_chars_and_len)(GDNativeStringPtr r_dest, const char *p_contents, const GDNativeInt p_size);
|
||||
void (*string_new_with_utf16_chars_and_len)(GDNativeStringPtr r_dest, const char16_t *p_contents, const GDNativeInt p_size);
|
||||
void (*string_new_with_utf32_chars_and_len)(GDNativeStringPtr r_dest, const char32_t *p_contents, const GDNativeInt p_size);
|
||||
void (*string_new_with_wide_chars_and_len)(GDNativeStringPtr r_dest, const wchar_t *p_contents, const GDNativeInt p_size);
|
||||
/* Information about the following functions:
|
||||
* - The return value is the resulting encoded string length.
|
||||
* - The length returned is in characters, not in bytes. It also does not include a trailing zero.
|
||||
* - These functions also do not write trailing zero, If you need it, write it yourself at the position indicated by the length (and make sure to allocate it).
|
||||
* - Passing NULL in r_text means only the length is computed (again, without including trailing zero).
|
||||
* - p_max_write_length argument is in characters, not bytes. It will be ignored if r_text is NULL.
|
||||
* - p_max_write_length argument does not affect the return value, it's only to cap write length.
|
||||
*/
|
||||
GDNativeInt (*string_to_latin1_chars)(const GDNativeStringPtr p_self, char *r_text, GDNativeInt p_max_write_length);
|
||||
GDNativeInt (*string_to_utf8_chars)(const GDNativeStringPtr p_self, char *r_text, GDNativeInt p_max_write_length);
|
||||
GDNativeInt (*string_to_utf16_chars)(const GDNativeStringPtr p_self, char16_t *r_text, GDNativeInt p_max_write_length);
|
||||
GDNativeInt (*string_to_utf32_chars)(const GDNativeStringPtr p_self, char32_t *r_text, GDNativeInt p_max_write_length);
|
||||
GDNativeInt (*string_to_wide_chars)(const GDNativeStringPtr p_self, wchar_t *r_text, GDNativeInt p_max_write_length);
|
||||
char32_t *(*string_operator_index)(GDNativeStringPtr p_self, GDNativeInt p_index);
|
||||
const char32_t *(*string_operator_index_const)(const GDNativeStringPtr p_self, GDNativeInt p_index);
|
||||
|
||||
/* OBJECT */
|
||||
|
||||
void (*object_method_bind_ptrcall)(GDNativeMethodBindPtr p_method_bind, GDNativeObjectPtr p_instance, const GDNativeTypePtr *p_args, GDNativeTypePtr r_ret);
|
||||
void (*object_destroy)(GDNativeObjectPtr p_o);
|
||||
GDNativeObjectPtr (*global_get_singleton)(const char *p_name);
|
||||
|
||||
GDNativeObjectPtr (*object_cast_to)(const GDNativeObjectPtr p_object, void *p_class_tag);
|
||||
GDNativeObjectPtr (*object_get_instance_from_id)(GDObjectInstanceID p_instance_id);
|
||||
GDObjectInstanceID (*object_get_instance_id)(const GDNativeObjectPtr p_object);
|
||||
|
||||
/* CLASSDB */
|
||||
|
||||
GDNativeClassConstructor (*classdb_get_constructor)(const char *p_classname);
|
||||
GDNativeMethodBindPtr (*classdb_get_method_bind)(const char *p_classname, const char *p_methodname, GDNativeInt p_hash);
|
||||
void *(*classdb_get_class_tag)(const char *p_classname);
|
||||
|
||||
/* CLASSDB EXTENSION */
|
||||
|
||||
void (*classdb_register_extension_class)(const GDNativeExtensionClassLibraryPtr p_library, const char *p_class_name, const char *p_parent_class_name, const GDNativeExtensionClassCreationInfo *p_extension_funcs);
|
||||
void (*classdb_register_extension_class_method)(const GDNativeExtensionClassLibraryPtr p_library, const char *p_class_name, const GDNativeExtensionClassMethodInfo *p_method_info);
|
||||
void (*classdb_register_extension_class_integer_constant)(const GDNativeExtensionClassLibraryPtr p_library, const char *p_enum_name, const char *p_class_name, const char *p_constant_name, uint32_t p_constant_value);
|
||||
void (*classdb_register_extension_class_property)(const GDNativeExtensionClassLibraryPtr p_library, const char *p_class_name, const GDNativePropertyInfo *p_info, const char *p_setter, const char *p_getter);
|
||||
void (*classdb_register_extension_class_signal)(const GDNativeExtensionClassLibraryPtr p_library, const char *p_class_name, const char *p_signal_name, const GDNativePropertyInfo *p_argument_info, GDNativeInt p_argument_count);
|
||||
void (*classdb_unregister_extension_class)(const GDNativeExtensionClassLibraryPtr p_library, const char *p_class_name); /* Unregistering a parent class before a class that inherits it will result in failure. Inheritors must be unregistered first. */
|
||||
} GDNativeInterface;
|
||||
|
||||
/* INITIALIZATION */
|
||||
|
||||
typedef enum {
|
||||
GDNATIVE_INITIALIZATION_CORE,
|
||||
GDNATIVE_INITIALIZATION_SERVERS,
|
||||
GDNATIVE_INITIALIZATION_SCENE,
|
||||
GDNATIVE_INITIALIZATION_EDITOR,
|
||||
} GDNativeInitializationLevel;
|
||||
|
||||
typedef struct {
|
||||
/* Minimum initialization level required.
|
||||
* If Core or Servers, the extension needs editor or game restart to take effect */
|
||||
GDNativeInitializationLevel minimum_initialization_level;
|
||||
/* Up to the user to supply when initializing */
|
||||
void *userdata;
|
||||
/* This function will be called multiple times for each initialization level. */
|
||||
void (*initialize)(void *userdata, GDNativeInitializationLevel p_level);
|
||||
void (*deinitialize)(void *userdata, GDNativeInitializationLevel p_level);
|
||||
} GDNativeInitialization;
|
||||
|
||||
/* Define a C function prototype that implements the function below and expose it to dlopen() (or similar).
|
||||
* It will be called on initialization. The name must be an unique one specified in the .gdextension config file.
|
||||
*/
|
||||
|
||||
typedef GDNativeBool (*GDNativeInitializationFunction)(const GDNativeInterface *p_interface, const GDNativeExtensionClassLibraryPtr p_library, GDNativeInitialization *r_initialization);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
|
@ -0,0 +1,411 @@
|
|||
/*************************************************************************/
|
||||
/* native_extension.cpp */
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* https://godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
|
||||
/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
|
||||
/* */
|
||||
/* 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 "native_extension.h"
|
||||
#include "core/io/config_file.h"
|
||||
#include "core/object/class_db.h"
|
||||
#include "core/object/method_bind.h"
|
||||
#include "core/os/os.h"
|
||||
|
||||
class NativeExtensionMethodBind : public MethodBind {
|
||||
GDNativeExtensionClassMethodCall call_func;
|
||||
GDNativeExtensionClassMethodPtrCall ptrcall_func;
|
||||
GDNativeExtensionClassMethodGetArgumentType get_argument_type_func;
|
||||
GDNativeExtensionClassMethodGetArgumentInfo get_argument_info_func;
|
||||
GDNativeExtensionClassMethodGetArgumentMetadata get_argument_metadata_func;
|
||||
void *method_userdata;
|
||||
bool vararg;
|
||||
|
||||
protected:
|
||||
virtual Variant::Type _gen_argument_type(int p_arg) const {
|
||||
return Variant::Type(get_argument_type_func(method_userdata, p_arg));
|
||||
}
|
||||
virtual PropertyInfo _gen_argument_type_info(int p_arg) const {
|
||||
GDNativePropertyInfo pinfo;
|
||||
get_argument_info_func(method_userdata, p_arg, &pinfo);
|
||||
PropertyInfo ret;
|
||||
ret.type = Variant::Type(pinfo.type);
|
||||
ret.name = pinfo.name;
|
||||
ret.class_name = pinfo.class_name;
|
||||
ret.hint = PropertyHint(pinfo.hint);
|
||||
ret.usage = pinfo.usage;
|
||||
ret.class_name = pinfo.class_name;
|
||||
return ret;
|
||||
}
|
||||
|
||||
public:
|
||||
virtual GodotTypeInfo::Metadata get_argument_meta(int p_arg) const {
|
||||
return GodotTypeInfo::Metadata(get_argument_metadata_func(method_userdata, p_arg));
|
||||
}
|
||||
|
||||
virtual Variant call(Object *p_object, const Variant **p_args, int p_arg_count, Callable::CallError &r_error) {
|
||||
Variant ret;
|
||||
GDExtensionClassInstancePtr extension_instance = p_object->_get_extension_instance();
|
||||
GDNativeCallError ce;
|
||||
call_func(extension_instance, (const GDNativeVariantPtr *)p_args, p_arg_count, (GDNativeVariantPtr)&ret, &ce);
|
||||
r_error.error = Callable::CallError::Error(ce.error);
|
||||
r_error.argument = ce.argument;
|
||||
r_error.expected = ce.expected;
|
||||
return ret;
|
||||
}
|
||||
virtual void ptrcall(Object *p_object, const void **p_args, void *r_ret) {
|
||||
ERR_FAIL_COND_MSG(vararg, "Vararg methods don't have ptrcall support. This is most likely an engine bug.");
|
||||
GDExtensionClassInstancePtr extension_instance = p_object->_get_extension_instance();
|
||||
ptrcall_func(extension_instance, (const GDNativeTypePtr *)p_args, (GDNativeTypePtr)r_ret);
|
||||
}
|
||||
|
||||
virtual bool is_vararg() const {
|
||||
return false;
|
||||
}
|
||||
NativeExtensionMethodBind(const GDNativeExtensionClassMethodInfo *p_method_info) {
|
||||
method_userdata = p_method_info->method_userdata;
|
||||
call_func = p_method_info->call_func;
|
||||
ptrcall_func = p_method_info->ptrcall_func;
|
||||
get_argument_type_func = p_method_info->get_argument_type_func;
|
||||
get_argument_info_func = p_method_info->get_argument_info_func;
|
||||
get_argument_metadata_func = p_method_info->get_argument_metadata_func;
|
||||
|
||||
vararg = p_method_info->method_flags & GDNATIVE_EXTENSION_METHOD_FLAG_VARARG;
|
||||
|
||||
_set_returns(p_method_info->has_return_value);
|
||||
_set_const(p_method_info->method_flags & GDNATIVE_EXTENSION_METHOD_FLAG_CONST);
|
||||
#ifdef DEBUG_METHODS_ENABLED
|
||||
_generate_argument_types(p_method_info->argument_count);
|
||||
#endif
|
||||
set_argument_count(p_method_info->argument_count);
|
||||
}
|
||||
};
|
||||
|
||||
static GDNativeInterface gdnative_interface;
|
||||
|
||||
void NativeExtension::_register_extension_class(const GDNativeExtensionClassLibraryPtr p_library, const char *p_class_name, const char *p_parent_class_name, const GDNativeExtensionClassCreationInfo *p_extension_funcs) {
|
||||
NativeExtension *self = (NativeExtension *)p_library;
|
||||
|
||||
StringName class_name = p_class_name;
|
||||
ERR_FAIL_COND_MSG(String(class_name).is_valid_identifier(), "Attempt to register extension clas '" + class_name + "', which is not a valid class identifier.");
|
||||
ERR_FAIL_COND_MSG(ClassDB::class_exists(class_name), "Attempt to register extension class '" + class_name + "', which appears to be already registered.");
|
||||
|
||||
Extension *parent_extension = nullptr;
|
||||
StringName parent_class_name = p_parent_class_name;
|
||||
|
||||
if (self->extension_classes.has(parent_class_name)) {
|
||||
parent_extension = &self->extension_classes[parent_class_name];
|
||||
} else if (ClassDB::class_exists(parent_class_name)) {
|
||||
if (ClassDB::get_api_type(parent_class_name) == ClassDB::API_EXTENSION || ClassDB::get_api_type(parent_class_name) == ClassDB::API_EDITOR_EXTENSION) {
|
||||
ERR_PRINT("Unimplemented yet");
|
||||
//inheriting from another extension
|
||||
} else {
|
||||
//inheriting from engine class
|
||||
}
|
||||
} else {
|
||||
ERR_FAIL_MSG("Attempt to register an extension class '" + String(class_name) + "' using non-existing parent class '" + String(parent_class_name) + "'");
|
||||
}
|
||||
|
||||
self->extension_classes[class_name] = Extension();
|
||||
|
||||
Extension *extension = &self->extension_classes[class_name];
|
||||
|
||||
if (parent_extension) {
|
||||
extension->native_extension.parent = &parent_extension->native_extension;
|
||||
parent_extension->native_extension.children.push_back(&extension->native_extension);
|
||||
}
|
||||
|
||||
extension->native_extension.parent_class_name = parent_class_name;
|
||||
extension->native_extension.class_name = class_name;
|
||||
extension->native_extension.editor_class = self->level_initialized == INITIALIZATION_LEVEL_EDITOR;
|
||||
extension->native_extension.set = p_extension_funcs->set_func;
|
||||
extension->native_extension.get = p_extension_funcs->get_func;
|
||||
extension->native_extension.get_property_list = p_extension_funcs->get_property_list_func;
|
||||
extension->native_extension.free_property_list = p_extension_funcs->free_property_list_func;
|
||||
extension->native_extension.notification = p_extension_funcs->notification_func;
|
||||
extension->native_extension.to_string = p_extension_funcs->to_string_func;
|
||||
extension->native_extension.reference = p_extension_funcs->reference_func;
|
||||
extension->native_extension.unreference = p_extension_funcs->unreference_func;
|
||||
extension->native_extension.class_userdata = p_extension_funcs->class_userdata;
|
||||
extension->native_extension.create_instance = p_extension_funcs->create_instance_func;
|
||||
extension->native_extension.free_instance = p_extension_funcs->free_instance_func;
|
||||
|
||||
ClassDB::register_extension_class(&extension->native_extension);
|
||||
}
|
||||
void NativeExtension::_register_extension_class_method(const GDNativeExtensionClassLibraryPtr p_library, const char *p_class_name, const GDNativeExtensionClassMethodInfo *p_method_info) {
|
||||
NativeExtension *self = (NativeExtension *)p_library;
|
||||
|
||||
StringName class_name = p_class_name;
|
||||
StringName method_name = p_method_info->name;
|
||||
ERR_FAIL_COND_MSG(self->extension_classes.has(class_name), "Attempt to register extension method '" + String(method_name) + "' for unexisting class '" + class_name + "'.");
|
||||
|
||||
//Extension *extension = &self->extension_classes[class_name];
|
||||
|
||||
NativeExtensionMethodBind *method = memnew(NativeExtensionMethodBind(p_method_info));
|
||||
|
||||
ClassDB::bind_method_custom(class_name, method);
|
||||
}
|
||||
void NativeExtension::_register_extension_class_integer_constant(const GDNativeExtensionClassLibraryPtr p_library, const char *p_class_name, const char *p_enum_name, const char *p_constant_name, uint32_t p_constant_value) {
|
||||
NativeExtension *self = (NativeExtension *)p_library;
|
||||
|
||||
StringName class_name = p_class_name;
|
||||
ERR_FAIL_COND_MSG(self->extension_classes.has(class_name), "Attempt to register extension constant '" + String(p_constant_name) + "' for unexisting class '" + class_name + "'.");
|
||||
|
||||
//Extension *extension = &self->extension_classes[class_name];
|
||||
|
||||
ClassDB::bind_integer_constant(class_name, p_enum_name, p_constant_name, p_constant_value);
|
||||
}
|
||||
void NativeExtension::_register_extension_class_property(const GDNativeExtensionClassLibraryPtr p_library, const char *p_class_name, const GDNativePropertyInfo *p_info, const char *p_setter, const char *p_getter) {
|
||||
NativeExtension *self = (NativeExtension *)p_library;
|
||||
|
||||
StringName class_name = p_class_name;
|
||||
ERR_FAIL_COND_MSG(self->extension_classes.has(class_name), "Attempt to register extension class property '" + String(p_info->name) + "' for unexisting class '" + class_name + "'.");
|
||||
|
||||
//Extension *extension = &self->extension_classes[class_name];
|
||||
PropertyInfo pinfo;
|
||||
pinfo.type = Variant::Type(p_info->type);
|
||||
pinfo.name = p_info->name;
|
||||
pinfo.class_name = p_info->class_name;
|
||||
pinfo.hint = PropertyHint(p_info->hint);
|
||||
pinfo.hint_string = p_info->hint_string;
|
||||
pinfo.usage = p_info->usage;
|
||||
|
||||
ClassDB::add_property(class_name, pinfo, p_setter, p_getter);
|
||||
}
|
||||
|
||||
void NativeExtension::_register_extension_class_signal(const GDNativeExtensionClassLibraryPtr p_library, const char *p_class_name, const char *p_signal_name, const GDNativePropertyInfo *p_argument_info, GDNativeInt p_argument_count) {
|
||||
NativeExtension *self = (NativeExtension *)p_library;
|
||||
|
||||
StringName class_name = p_class_name;
|
||||
ERR_FAIL_COND_MSG(self->extension_classes.has(class_name), "Attempt to register extension class signal '" + String(p_signal_name) + "' for unexisting class '" + class_name + "'.");
|
||||
|
||||
MethodInfo s;
|
||||
s.name = p_signal_name;
|
||||
for (int i = 0; i < p_argument_count; i++) {
|
||||
PropertyInfo arg;
|
||||
arg.type = Variant::Type(p_argument_info[i].type);
|
||||
arg.name = p_argument_info[i].name;
|
||||
arg.class_name = p_argument_info[i].class_name;
|
||||
arg.hint = PropertyHint(p_argument_info[i].hint);
|
||||
arg.hint_string = p_argument_info[i].hint_string;
|
||||
arg.usage = p_argument_info[i].usage;
|
||||
s.arguments.push_back(arg);
|
||||
}
|
||||
ClassDB::add_signal(class_name, s);
|
||||
}
|
||||
|
||||
void NativeExtension::_unregister_extension_class(const GDNativeExtensionClassLibraryPtr p_library, const char *p_class_name) {
|
||||
NativeExtension *self = (NativeExtension *)p_library;
|
||||
|
||||
StringName class_name = p_class_name;
|
||||
ERR_FAIL_COND_MSG(self->extension_classes.has(class_name), "Attempt to unregister unexisting extension class '" + class_name + "'.");
|
||||
Extension *ext = &self->extension_classes[class_name];
|
||||
ERR_FAIL_COND_MSG(ext->native_extension.children.size(), "Attempt to unregister class '" + class_name + "' while other extension classes inherit from it.");
|
||||
|
||||
ClassDB::unregister_extension_class(class_name);
|
||||
if (ext->native_extension.parent != nullptr) {
|
||||
ext->native_extension.parent->children.erase(&ext->native_extension);
|
||||
}
|
||||
self->extension_classes.erase(class_name);
|
||||
}
|
||||
|
||||
Error NativeExtension::open_library(const String &p_path, const String &p_entry_symbol) {
|
||||
Error err = OS::get_singleton()->open_dynamic_library(p_path, library, true);
|
||||
if (err != OK) {
|
||||
return err;
|
||||
}
|
||||
|
||||
void *entry_funcptr = nullptr;
|
||||
|
||||
err = OS::get_singleton()->get_dynamic_library_symbol_handle(library, p_entry_symbol, entry_funcptr, false);
|
||||
|
||||
if (err != OK) {
|
||||
OS::get_singleton()->close_dynamic_library(library);
|
||||
return err;
|
||||
}
|
||||
|
||||
GDNativeInitializationFunction initialization_function = (GDNativeInitializationFunction)entry_funcptr;
|
||||
|
||||
initialization_function(&gdnative_interface, this, &initialization);
|
||||
level_initialized = -1;
|
||||
return OK;
|
||||
}
|
||||
|
||||
void NativeExtension::close_library() {
|
||||
ERR_FAIL_COND(library == nullptr);
|
||||
OS::get_singleton()->close_dynamic_library(library);
|
||||
|
||||
library = nullptr;
|
||||
}
|
||||
|
||||
bool NativeExtension::is_library_open() const {
|
||||
return library != nullptr;
|
||||
}
|
||||
|
||||
NativeExtension::InitializationLevel NativeExtension::get_minimum_library_initialization_level() const {
|
||||
ERR_FAIL_COND_V(library == nullptr, INITIALIZATION_LEVEL_CORE);
|
||||
return InitializationLevel(initialization.minimum_initialization_level);
|
||||
}
|
||||
void NativeExtension::initialize_library(InitializationLevel p_level) {
|
||||
ERR_FAIL_COND(library == nullptr);
|
||||
ERR_FAIL_COND(p_level <= int32_t(level_initialized));
|
||||
|
||||
level_initialized = int32_t(p_level);
|
||||
|
||||
ERR_FAIL_COND(initialization.initialize == nullptr);
|
||||
|
||||
initialization.initialize(initialization.userdata, GDNativeInitializationLevel(p_level));
|
||||
}
|
||||
void NativeExtension::deinitialize_library(InitializationLevel p_level) {
|
||||
ERR_FAIL_COND(library == nullptr);
|
||||
ERR_FAIL_COND(p_level > int32_t(level_initialized));
|
||||
|
||||
level_initialized = int32_t(p_level) - 1;
|
||||
initialization.deinitialize(initialization.userdata, GDNativeInitializationLevel(p_level));
|
||||
}
|
||||
|
||||
void NativeExtension::_bind_methods() {
|
||||
ClassDB::bind_method(D_METHOD("open_library", "path", "entry_symbol"), &NativeExtension::open_library);
|
||||
ClassDB::bind_method(D_METHOD("close_library"), &NativeExtension::close_library);
|
||||
ClassDB::bind_method(D_METHOD("is_library_open"), &NativeExtension::is_library_open);
|
||||
|
||||
ClassDB::bind_method(D_METHOD("get_minimum_library_initialization_level"), &NativeExtension::get_minimum_library_initialization_level);
|
||||
ClassDB::bind_method(D_METHOD("initialize_library", "level"), &NativeExtension::initialize_library);
|
||||
|
||||
BIND_ENUM_CONSTANT(INITIALIZATION_LEVEL_CORE);
|
||||
BIND_ENUM_CONSTANT(INITIALIZATION_LEVEL_SERVERS);
|
||||
BIND_ENUM_CONSTANT(INITIALIZATION_LEVEL_SCENE);
|
||||
BIND_ENUM_CONSTANT(INITIALIZATION_LEVEL_EDITOR);
|
||||
}
|
||||
|
||||
NativeExtension::NativeExtension() {
|
||||
}
|
||||
|
||||
NativeExtension::~NativeExtension() {
|
||||
if (library != nullptr) {
|
||||
close_library();
|
||||
}
|
||||
}
|
||||
|
||||
extern void gdnative_setup_interface(GDNativeInterface *p_interface);
|
||||
|
||||
void NativeExtension::initialize_native_extensions() {
|
||||
gdnative_setup_interface(&gdnative_interface);
|
||||
|
||||
gdnative_interface.classdb_register_extension_class = _register_extension_class;
|
||||
gdnative_interface.classdb_register_extension_class_method = _register_extension_class_method;
|
||||
gdnative_interface.classdb_register_extension_class_integer_constant = _register_extension_class_integer_constant;
|
||||
gdnative_interface.classdb_register_extension_class_property = _register_extension_class_property;
|
||||
gdnative_interface.classdb_register_extension_class_signal = _register_extension_class_signal;
|
||||
gdnative_interface.classdb_unregister_extension_class = _unregister_extension_class;
|
||||
}
|
||||
|
||||
RES NativeExtensionResourceLoader::load(const String &p_path, const String &p_original_path, Error *r_error, bool p_use_sub_threads, float *r_progress, CacheMode p_cache_mode) {
|
||||
Ref<ConfigFile> config;
|
||||
config.instantiate();
|
||||
|
||||
Error err = config->load(p_path);
|
||||
|
||||
if (r_error) {
|
||||
*r_error = err;
|
||||
}
|
||||
|
||||
if (err != OK) {
|
||||
return RES();
|
||||
}
|
||||
|
||||
if (!config->has_section_key("configuration", "entry_symbol")) {
|
||||
if (r_error) {
|
||||
*r_error = ERR_INVALID_DATA;
|
||||
}
|
||||
return RES();
|
||||
}
|
||||
|
||||
String entry_symbol = config->get_value("configuration", "entry_symbol");
|
||||
|
||||
List<String> libraries;
|
||||
|
||||
config->get_section_keys("libraries", &libraries);
|
||||
|
||||
String library_path;
|
||||
|
||||
for (List<String>::Element *E = libraries.front(); E; E = E->next()) {
|
||||
Vector<String> tags = E->get().split(".");
|
||||
bool all_tags_met = true;
|
||||
for (int i = 0; i < tags.size(); i++) {
|
||||
String tag = tags[i].strip_edges();
|
||||
if (!OS::get_singleton()->has_feature(tag)) {
|
||||
all_tags_met = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (all_tags_met) {
|
||||
library_path = config->get_value("libraries", E->get());
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (library_path != String()) {
|
||||
if (r_error) {
|
||||
*r_error = ERR_FILE_NOT_FOUND;
|
||||
}
|
||||
return RES();
|
||||
}
|
||||
|
||||
if (!library_path.is_resource_file()) {
|
||||
library_path = p_path.get_base_dir().plus_file(library_path);
|
||||
}
|
||||
|
||||
Ref<NativeExtension> lib;
|
||||
lib.instantiate();
|
||||
err = lib->open_library(library_path, entry_symbol);
|
||||
|
||||
if (r_error) {
|
||||
*r_error = err;
|
||||
}
|
||||
|
||||
if (err != OK) {
|
||||
return RES();
|
||||
}
|
||||
|
||||
return lib;
|
||||
}
|
||||
|
||||
void NativeExtensionResourceLoader::get_recognized_extensions(List<String> *p_extensions) const {
|
||||
p_extensions->push_back("gdextension");
|
||||
}
|
||||
|
||||
bool NativeExtensionResourceLoader::handles_type(const String &p_type) const {
|
||||
return p_type == "NativeExtension";
|
||||
}
|
||||
|
||||
String NativeExtensionResourceLoader::get_resource_type(const String &p_path) const {
|
||||
String el = p_path.get_extension().to_lower();
|
||||
if (el == "gdextension") {
|
||||
return "NativeExtension";
|
||||
}
|
||||
return "";
|
||||
}
|
|
@ -0,0 +1,94 @@
|
|||
/*************************************************************************/
|
||||
/* native_extension.h */
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* https://godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
|
||||
/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
|
||||
/* */
|
||||
/* Permission is hereby granted, free of charge, to any person obtaining */
|
||||
/* a copy of this software and associated documentation files (the */
|
||||
/* "Software"), to deal in the Software without restriction, including */
|
||||
/* without limitation the rights to use, copy, modify, merge, publish, */
|
||||
/* distribute, sublicense, and/or sell copies of the Software, and to */
|
||||
/* permit persons to whom the Software is furnished to do so, subject to */
|
||||
/* the following conditions: */
|
||||
/* */
|
||||
/* The above copyright notice and this permission notice shall be */
|
||||
/* included in all copies or substantial portions of the Software. */
|
||||
/* */
|
||||
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
|
||||
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
|
||||
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
|
||||
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
|
||||
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
|
||||
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
||||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
/*************************************************************************/
|
||||
|
||||
#ifndef NATIVE_EXTENSION_H
|
||||
#define NATIVE_EXTENSION_H
|
||||
|
||||
#include "core/extension/gdnative_interface.h"
|
||||
#include "core/io/resource_loader.h"
|
||||
#include "core/object/ref_counted.h"
|
||||
|
||||
class NativeExtension : public RefCounted {
|
||||
GDCLASS(NativeExtension, RefCounted)
|
||||
|
||||
void *library = nullptr; // pointer if valid,
|
||||
|
||||
struct Extension {
|
||||
ObjectNativeExtension native_extension;
|
||||
};
|
||||
|
||||
Map<StringName, Extension> extension_classes;
|
||||
|
||||
static void _register_extension_class(const GDNativeExtensionClassLibraryPtr p_library, const char *p_class_name, const char *p_parent_class_name, const GDNativeExtensionClassCreationInfo *p_extension_funcs);
|
||||
static void _register_extension_class_method(const GDNativeExtensionClassLibraryPtr p_library, const char *p_class_name, const GDNativeExtensionClassMethodInfo *p_method_info);
|
||||
static void _register_extension_class_integer_constant(const GDNativeExtensionClassLibraryPtr p_library, const char *p_class_name, const char *p_enum_name, const char *p_constant_name, uint32_t p_constant_value);
|
||||
static void _register_extension_class_property(const GDNativeExtensionClassLibraryPtr p_library, const char *p_class_name, const GDNativePropertyInfo *p_info, const char *p_setter, const char *p_getter);
|
||||
static void _register_extension_class_signal(const GDNativeExtensionClassLibraryPtr p_library, const char *p_class_name, const char *p_signal_name, const GDNativePropertyInfo *p_argument_info, GDNativeInt p_argument_count);
|
||||
static void _unregister_extension_class(const GDNativeExtensionClassLibraryPtr p_library, const char *p_class_name);
|
||||
|
||||
GDNativeInitialization initialization;
|
||||
int32_t level_initialized = -1;
|
||||
|
||||
protected:
|
||||
static void _bind_methods();
|
||||
|
||||
public:
|
||||
Error open_library(const String &p_path, const String &p_entry_symbol);
|
||||
void close_library();
|
||||
|
||||
enum InitializationLevel {
|
||||
INITIALIZATION_LEVEL_CORE,
|
||||
INITIALIZATION_LEVEL_SERVERS,
|
||||
INITIALIZATION_LEVEL_SCENE,
|
||||
INITIALIZATION_LEVEL_EDITOR,
|
||||
};
|
||||
|
||||
bool is_library_open() const;
|
||||
|
||||
InitializationLevel get_minimum_library_initialization_level() const;
|
||||
void initialize_library(InitializationLevel p_level);
|
||||
void deinitialize_library(InitializationLevel p_level);
|
||||
|
||||
static void initialize_native_extensions();
|
||||
NativeExtension();
|
||||
~NativeExtension();
|
||||
};
|
||||
|
||||
VARIANT_ENUM_CAST(NativeExtension::InitializationLevel)
|
||||
|
||||
class NativeExtensionResourceLoader : public ResourceFormatLoader {
|
||||
public:
|
||||
virtual RES load(const String &p_path, const String &p_original_path, Error *r_error, bool p_use_sub_threads = false, float *r_progress = nullptr, CacheMode p_cache_mode = CACHE_MODE_REUSE);
|
||||
virtual void get_recognized_extensions(List<String> *p_extensions) const;
|
||||
virtual bool handles_type(const String &p_type) const;
|
||||
virtual String get_resource_type(const String &p_path) const;
|
||||
};
|
||||
|
||||
#endif // NATIVEEXTENSION_H
|
|
@ -0,0 +1,130 @@
|
|||
/*************************************************************************/
|
||||
/* native_extension_manager.cpp */
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* https://godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
|
||||
/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
|
||||
/* */
|
||||
/* 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 "native_extension_manager.h"
|
||||
|
||||
NativeExtensionManager::LoadStatus NativeExtensionManager::load_extension(const String &p_path) {
|
||||
if (native_extension_map.has(p_path)) {
|
||||
return LOAD_STATUS_ALREADY_LOADED;
|
||||
}
|
||||
Ref<NativeExtension> extension = ResourceLoader::load(p_path);
|
||||
if (extension.is_null()) {
|
||||
return LOAD_STATUS_FAILED;
|
||||
}
|
||||
|
||||
if (level >= 0) { //already initialized up to some level
|
||||
int32_t minimum_level = extension->get_minimum_library_initialization_level();
|
||||
if (minimum_level < MIN(level, NativeExtension::INITIALIZATION_LEVEL_SCENE)) {
|
||||
return LOAD_STATUS_NEEDS_RESTART;
|
||||
}
|
||||
//initialize up to current level
|
||||
for (int32_t i = minimum_level; i < level; i++) {
|
||||
extension->initialize_library(NativeExtension::InitializationLevel(level));
|
||||
}
|
||||
}
|
||||
native_extension_map[p_path] = extension;
|
||||
return LOAD_STATUS_OK;
|
||||
}
|
||||
|
||||
NativeExtensionManager::LoadStatus NativeExtensionManager::reload_extension(const String &p_path) {
|
||||
return LOAD_STATUS_OK; //TODO
|
||||
}
|
||||
NativeExtensionManager::LoadStatus NativeExtensionManager::unload_extension(const String &p_path) {
|
||||
if (!native_extension_map.has(p_path)) {
|
||||
return LOAD_STATUS_NOT_LOADED;
|
||||
}
|
||||
|
||||
Ref<NativeExtension> extension = native_extension_map[p_path];
|
||||
|
||||
if (level >= 0) { //already initialized up to some level
|
||||
int32_t minimum_level = extension->get_minimum_library_initialization_level();
|
||||
if (minimum_level < MIN(level, NativeExtension::INITIALIZATION_LEVEL_SCENE)) {
|
||||
return LOAD_STATUS_NEEDS_RESTART;
|
||||
}
|
||||
//initialize up to current level
|
||||
for (int32_t i = level; i >= minimum_level; i--) {
|
||||
extension->deinitialize_library(NativeExtension::InitializationLevel(level));
|
||||
}
|
||||
}
|
||||
native_extension_map.erase(p_path);
|
||||
return LOAD_STATUS_OK;
|
||||
}
|
||||
Vector<String> NativeExtensionManager::get_loaded_extensions() const {
|
||||
Vector<String> ret;
|
||||
for (const Map<String, Ref<NativeExtension>>::Element *E = native_extension_map.front(); E; E = E->next()) {
|
||||
ret.push_back(E->key());
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
Ref<NativeExtension> NativeExtensionManager::get_extension(const String &p_path) {
|
||||
Map<String, Ref<NativeExtension>>::Element *E = native_extension_map.find(p_path);
|
||||
ERR_FAIL_COND_V(!E, Ref<NativeExtension>());
|
||||
return E->get();
|
||||
}
|
||||
|
||||
void NativeExtensionManager::initialize_extensions(NativeExtension::InitializationLevel p_level) {
|
||||
ERR_FAIL_COND(int32_t(p_level) - 1 != level);
|
||||
for (Map<String, Ref<NativeExtension>>::Element *E = native_extension_map.front(); E; E = E->next()) {
|
||||
E->get()->initialize_library(p_level);
|
||||
}
|
||||
level = p_level;
|
||||
}
|
||||
|
||||
void NativeExtensionManager::deinitialize_extensions(NativeExtension::InitializationLevel p_level) {
|
||||
ERR_FAIL_COND(int32_t(p_level) != level);
|
||||
for (Map<String, Ref<NativeExtension>>::Element *E = native_extension_map.front(); E; E = E->next()) {
|
||||
E->get()->deinitialize_library(p_level);
|
||||
}
|
||||
level = int32_t(p_level) - 1;
|
||||
}
|
||||
|
||||
NativeExtensionManager *NativeExtensionManager::get_singleton() {
|
||||
return singleton;
|
||||
}
|
||||
void NativeExtensionManager::_bind_methods() {
|
||||
ClassDB::bind_method(D_METHOD("load_extension", "path"), &NativeExtensionManager::load_extension);
|
||||
ClassDB::bind_method(D_METHOD("reload_extension", "path"), &NativeExtensionManager::reload_extension);
|
||||
ClassDB::bind_method(D_METHOD("unload_extension", "path"), &NativeExtensionManager::unload_extension);
|
||||
ClassDB::bind_method(D_METHOD("get_loaded_extensions"), &NativeExtensionManager::get_loaded_extensions);
|
||||
ClassDB::bind_method(D_METHOD("get_extension", "path"), &NativeExtensionManager::get_extension);
|
||||
|
||||
BIND_ENUM_CONSTANT(LOAD_STATUS_OK);
|
||||
BIND_ENUM_CONSTANT(LOAD_STATUS_FAILED);
|
||||
BIND_ENUM_CONSTANT(LOAD_STATUS_ALREADY_LOADED);
|
||||
BIND_ENUM_CONSTANT(LOAD_STATUS_NOT_LOADED);
|
||||
BIND_ENUM_CONSTANT(LOAD_STATUS_NEEDS_RESTART);
|
||||
}
|
||||
|
||||
NativeExtensionManager *NativeExtensionManager::singleton = nullptr;
|
||||
|
||||
NativeExtensionManager::NativeExtensionManager() {
|
||||
ERR_FAIL_COND(singleton != nullptr);
|
||||
singleton = this;
|
||||
}
|
|
@ -0,0 +1,71 @@
|
|||
/*************************************************************************/
|
||||
/* native_extension_manager.h */
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* https://godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
|
||||
/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
|
||||
/* */
|
||||
/* Permission is hereby granted, free of charge, to any person obtaining */
|
||||
/* a copy of this software and associated documentation files (the */
|
||||
/* "Software"), to deal in the Software without restriction, including */
|
||||
/* without limitation the rights to use, copy, modify, merge, publish, */
|
||||
/* distribute, sublicense, and/or sell copies of the Software, and to */
|
||||
/* permit persons to whom the Software is furnished to do so, subject to */
|
||||
/* the following conditions: */
|
||||
/* */
|
||||
/* The above copyright notice and this permission notice shall be */
|
||||
/* included in all copies or substantial portions of the Software. */
|
||||
/* */
|
||||
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
|
||||
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
|
||||
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
|
||||
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
|
||||
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
|
||||
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
||||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
/*************************************************************************/
|
||||
|
||||
#ifndef NATIVE_EXTENSION_MANAGER_H
|
||||
#define NATIVE_EXTENSION_MANAGER_H
|
||||
|
||||
#include "core/extension/native_extension.h"
|
||||
|
||||
class NativeExtensionManager : public Object {
|
||||
GDCLASS(NativeExtensionManager, Object);
|
||||
|
||||
int32_t level = -1;
|
||||
Map<String, Ref<NativeExtension>> native_extension_map;
|
||||
|
||||
static void _bind_methods();
|
||||
|
||||
static NativeExtensionManager *singleton;
|
||||
|
||||
public:
|
||||
enum LoadStatus {
|
||||
LOAD_STATUS_OK,
|
||||
LOAD_STATUS_FAILED,
|
||||
LOAD_STATUS_ALREADY_LOADED,
|
||||
LOAD_STATUS_NOT_LOADED,
|
||||
LOAD_STATUS_NEEDS_RESTART,
|
||||
};
|
||||
|
||||
LoadStatus load_extension(const String &p_path);
|
||||
LoadStatus reload_extension(const String &p_path);
|
||||
LoadStatus unload_extension(const String &p_path);
|
||||
Vector<String> get_loaded_extensions() const;
|
||||
Ref<NativeExtension> get_extension(const String &p_path);
|
||||
|
||||
void initialize_extensions(NativeExtension::InitializationLevel p_level);
|
||||
void deinitialize_extensions(NativeExtension::InitializationLevel p_level);
|
||||
|
||||
static NativeExtensionManager *get_singleton();
|
||||
|
||||
NativeExtensionManager();
|
||||
};
|
||||
|
||||
VARIANT_ENUM_CAST(NativeExtensionManager::LoadStatus)
|
||||
|
||||
#endif // NATIVEEXTENSIONMANAGER_H
|
|
@ -2,6 +2,11 @@
|
|||
|
||||
Import("env")
|
||||
|
||||
import make_virtuals
|
||||
from platform_methods import run_in_subprocess
|
||||
|
||||
env.CommandNoCache(["gdvirtual.gen.inc"], "make_virtuals.py", run_in_subprocess(make_virtuals.run))
|
||||
|
||||
env_object = env.Clone()
|
||||
|
||||
env_object.add_source_files(env.core_sources, "*.cpp")
|
||||
|
|
|
@ -503,9 +503,9 @@ void ClassDB::add_compatibility_class(const StringName &p_class, const StringNam
|
|||
|
||||
thread_local bool initializing_with_extension = false;
|
||||
thread_local ObjectNativeExtension *initializing_extension = nullptr;
|
||||
thread_local void *initializing_extension_instance = nullptr;
|
||||
thread_local GDExtensionClassInstancePtr initializing_extension_instance = nullptr;
|
||||
|
||||
void ClassDB::instance_get_native_extension_data(ObjectNativeExtension **r_extension, void **r_extension_instance) {
|
||||
void ClassDB::instance_get_native_extension_data(ObjectNativeExtension **r_extension, GDExtensionClassInstancePtr *r_extension_instance) {
|
||||
if (initializing_with_extension) {
|
||||
*r_extension = initializing_extension;
|
||||
*r_extension_instance = initializing_extension_instance;
|
||||
|
@ -539,7 +539,7 @@ Object *ClassDB::instantiate(const StringName &p_class) {
|
|||
if (ti->native_extension) {
|
||||
initializing_with_extension = true;
|
||||
initializing_extension = ti->native_extension;
|
||||
initializing_extension_instance = ti->native_extension->create_instance(ti->native_extension->create_instance_userdata);
|
||||
initializing_extension_instance = ti->native_extension->create_instance(ti->native_extension->class_userdata);
|
||||
}
|
||||
return ti->creation_func();
|
||||
}
|
||||
|
@ -1603,6 +1603,11 @@ void ClassDB::register_extension_class(ObjectNativeExtension *p_extension) {
|
|||
classes[p_extension->class_name] = c;
|
||||
}
|
||||
|
||||
void ClassDB::unregister_extension_class(const StringName &p_class) {
|
||||
ERR_FAIL_COND(!classes.has(p_class));
|
||||
classes.erase(p_class);
|
||||
}
|
||||
|
||||
RWLock ClassDB::lock;
|
||||
|
||||
void ClassDB::cleanup_defaults() {
|
||||
|
|
|
@ -204,6 +204,7 @@ public:
|
|||
}
|
||||
|
||||
static void register_extension_class(ObjectNativeExtension *p_extension);
|
||||
static void unregister_extension_class(const StringName &p_class);
|
||||
|
||||
template <class T>
|
||||
static Object *_create_ptr_func() {
|
||||
|
@ -232,7 +233,8 @@ public:
|
|||
static bool is_parent_class(const StringName &p_class, const StringName &p_inherits);
|
||||
static bool can_instantiate(const StringName &p_class);
|
||||
static Object *instantiate(const StringName &p_class);
|
||||
static void instance_get_native_extension_data(ObjectNativeExtension **r_extension, void **r_extension_instance);
|
||||
static void instance_get_native_extension_data(ObjectNativeExtension **r_extension, GDExtensionClassInstancePtr *r_extension_instance);
|
||||
|
||||
static APIType get_api_type(const StringName &p_class);
|
||||
|
||||
static uint64_t get_api_hash(APIType p_api);
|
||||
|
|
|
@ -0,0 +1,152 @@
|
|||
proto = """
|
||||
#define GDVIRTUAL$VER($RET m_name $ARG) \\
|
||||
GDNativeExtensionClassCallVirtual _gdvirtual_##m_name = (_get_extension() && _get_extension()->get_virtual) ? _get_extension()->get_virtual(_get_extension()->class_userdata, #m_name) : (GDNativeExtensionClassCallVirtual) nullptr;\\
|
||||
StringName _gdvirtual_##m_name##_sn = #m_name;\\
|
||||
bool _gdvirtual_##m_name##_call($CALLARGS) $CONST { \\
|
||||
ScriptInstance *script_instance = ((Object*)(this))->get_script_instance();\\
|
||||
if (script_instance) {\\
|
||||
Callable::CallError ce; \\
|
||||
$CALLSIARGS\\
|
||||
$CALLSIBEGINscript_instance->call(_gdvirtual_##m_name##_sn, $CALLSIARGPASS, ce);\\
|
||||
if (ce.error == Callable::CallError::CALL_OK) {\\
|
||||
$CALLSIRET\\
|
||||
return true;\\
|
||||
} \\
|
||||
}\\
|
||||
if (_gdvirtual_##m_name) {\\
|
||||
$CALLPTRARGS\\
|
||||
$CALLPTRRETDEF\\
|
||||
_gdvirtual_##m_name(_get_extension_instance(),$CALLPTRARGPASS,$CALLPTRRETPASS);\\
|
||||
$CALLPTRRET\\
|
||||
return true;\\
|
||||
}\\
|
||||
\\
|
||||
return false;\\
|
||||
}\\
|
||||
\\
|
||||
_FORCE_INLINE_ static MethodInfo _gdvirtual_##m_name##_get_method_info() { \\
|
||||
MethodInfo method_info;\\
|
||||
method_info.name = #m_name;\\
|
||||
method_info.flags = METHOD_FLAG_VIRTUAL;\\
|
||||
$FILL_METHOD_INFO\\
|
||||
return method_info;\\
|
||||
}
|
||||
|
||||
|
||||
"""
|
||||
|
||||
|
||||
def generate_version(argcount, const=False, returns=False):
|
||||
s = proto
|
||||
sproto = str(argcount)
|
||||
method_info = ""
|
||||
if returns:
|
||||
sproto += "R"
|
||||
s = s.replace("$RET", "m_ret, ")
|
||||
s = s.replace("$CALLPTRRETDEF", "PtrToArg<m_ret>::EncodeT ret;")
|
||||
method_info += "\tmethod_info.return_val = GetTypeInfo<m_ret>::get_class_info();\\\n"
|
||||
else:
|
||||
s = s.replace("$RET", "")
|
||||
s = s.replace("$CALLPTRRETDEF", "")
|
||||
|
||||
if const:
|
||||
sproto += "C"
|
||||
s = s.replace("$CONST", "const")
|
||||
method_info += "\tmethod_info.flags|=METHOD_FLAG_CONST;\\\n"
|
||||
else:
|
||||
s = s.replace("$CONST", "")
|
||||
|
||||
s = s.replace("$VER", sproto)
|
||||
argtext = ""
|
||||
callargtext = ""
|
||||
callsiargs = ""
|
||||
callsiargptrs = ""
|
||||
callptrargsptr = ""
|
||||
if argcount > 0:
|
||||
argtext += ", "
|
||||
callsiargs = "Variant vargs[" + str(argcount) + "]={"
|
||||
callsiargptrs = "\t\tconst Variant *vargptrs[" + str(argcount) + "]={"
|
||||
callptrargsptr = "\t\tconst GDNativeTypePtr argptrs[" + str(argcount) + "]={"
|
||||
callptrargs = ""
|
||||
for i in range(argcount):
|
||||
if i > 0:
|
||||
argtext += ", "
|
||||
callargtext += ", "
|
||||
callsiargs += ", "
|
||||
callsiargptrs += ", "
|
||||
callptrargs += "\t\t"
|
||||
callptrargsptr += ", "
|
||||
argtext += "m_type" + str(i + 1)
|
||||
callargtext += "const m_type" + str(i + 1) + "& arg" + str(i + 1)
|
||||
callsiargs += "Variant(arg" + str(i + 1) + ")"
|
||||
callsiargptrs += "&vargs[" + str(i) + "]"
|
||||
callptrargs += (
|
||||
"PtrToArg<m_type" + str(i + 1) + ">::EncodeT argval" + str(i + 1) + " = arg" + str(i + 1) + ";\\\n"
|
||||
)
|
||||
callptrargsptr += "&argval" + str(i + 1)
|
||||
method_info += "\tmethod_info.arguments.push_back(GetTypeInfo<m_type" + str(i + 1) + ">::get_class_info());\\\n"
|
||||
|
||||
if argcount:
|
||||
callsiargs += "};\\\n"
|
||||
callsiargptrs += "};\\\n"
|
||||
s = s.replace("$CALLSIARGS", callsiargs + callsiargptrs)
|
||||
s = s.replace("$CALLSIARGPASS", "(const Variant **)vargptrs," + str(argcount))
|
||||
callptrargsptr += "};\\\n"
|
||||
s = s.replace("$CALLPTRARGS", callptrargs + callptrargsptr)
|
||||
s = s.replace("$CALLPTRARGPASS", "(const GDNativeTypePtr*)argptrs")
|
||||
else:
|
||||
s = s.replace("$CALLSIARGS", "")
|
||||
s = s.replace("$CALLSIARGPASS", "nullptr, 0")
|
||||
s = s.replace("$CALLPTRARGS", "")
|
||||
s = s.replace("$CALLPTRARGPASS", "nullptr")
|
||||
|
||||
if returns:
|
||||
if argcount > 0:
|
||||
callargtext += ","
|
||||
callargtext += " m_ret& r_ret"
|
||||
s = s.replace("$CALLSIBEGIN", "Variant ret = ")
|
||||
s = s.replace("$CALLSIRET", "r_ret = ret;")
|
||||
s = s.replace("$CALLPTRRETPASS", "&ret")
|
||||
s = s.replace("$CALLPTRRET", "r_ret = ret;")
|
||||
else:
|
||||
s = s.replace("$CALLSIBEGIN", "")
|
||||
s = s.replace("$CALLSIRET", "")
|
||||
s = s.replace("$CALLPTRRETPASS", "nullptr")
|
||||
s = s.replace("$CALLPTRRET", "")
|
||||
|
||||
s = s.replace("$ARG", argtext)
|
||||
s = s.replace("$CALLARGS", callargtext)
|
||||
s = s.replace("$FILL_METHOD_INFO", method_info)
|
||||
|
||||
return s
|
||||
|
||||
|
||||
def run(target, source, env):
|
||||
|
||||
max_versions = 12
|
||||
|
||||
txt = """
|
||||
#ifndef GDVIRTUAL_GEN_H
|
||||
#define GDVIRTUAL_GEN_H
|
||||
|
||||
|
||||
"""
|
||||
|
||||
for i in range(max_versions + 1):
|
||||
|
||||
txt += "/* " + str(i) + " Arguments */\n\n"
|
||||
txt += generate_version(i, False, False)
|
||||
txt += generate_version(i, False, True)
|
||||
txt += generate_version(i, True, False)
|
||||
txt += generate_version(i, True, True)
|
||||
|
||||
txt += "#endif"
|
||||
|
||||
with open(target[0], "w") as f:
|
||||
f.write(txt)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
from platform_methods import subprocess_main
|
||||
|
||||
subprocess_main(globals())
|
|
@ -34,6 +34,35 @@
|
|||
|
||||
#include "method_bind.h"
|
||||
|
||||
uint32_t MethodBind::get_hash() const {
|
||||
uint32_t hash = hash_djb2_one_32(has_return() ? 1 : 0);
|
||||
hash = hash_djb2_one_32(get_argument_count(), hash);
|
||||
|
||||
#ifndef _MSC_VER
|
||||
#warning This needs proper class name and argument type for hashing
|
||||
#endif
|
||||
#if 0
|
||||
|
||||
for (int i = (has_return() ? -1 : 0); i < get_argument_count(); i++) {
|
||||
PropertyInfo pi = i == -1 ? get_return_info() : get_argument_info(i);
|
||||
hash = hash_djb2_one_32(get_argument_type(i), hash);
|
||||
if (pi.class_name != StringName()) {
|
||||
hash = hash_djb2_one_32(pi.class_name.operator String().hash(), hash);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
hash = hash_djb2_one_32(get_default_argument_count(), hash);
|
||||
for (int i = 0; i < get_default_argument_count(); i++) {
|
||||
Variant v = get_default_argument(i);
|
||||
hash = hash_djb2_one_32(v.hash(), hash);
|
||||
}
|
||||
|
||||
hash = hash_djb2_one_32(is_const(), hash);
|
||||
hash = hash_djb2_one_32(is_vararg(), hash);
|
||||
|
||||
return hash;
|
||||
}
|
||||
|
||||
#ifdef DEBUG_METHODS_ENABLED
|
||||
PropertyInfo MethodBind::get_argument_info(int p_argument) const {
|
||||
ERR_FAIL_INDEX_V(p_argument, get_argument_count(), PropertyInfo());
|
||||
|
|
|
@ -135,6 +135,8 @@ public:
|
|||
|
||||
void set_default_arguments(const Vector<Variant> &p_defargs);
|
||||
|
||||
uint32_t get_hash() const;
|
||||
|
||||
MethodBind();
|
||||
virtual ~MethodBind();
|
||||
};
|
||||
|
|
|
@ -386,12 +386,20 @@ void Object::set(const StringName &p_name, const Variant &p_value, bool *r_valid
|
|||
}
|
||||
|
||||
if (_extension && _extension->set) {
|
||||
if (_extension->set(_extension_instance, &p_name, &p_value)) {
|
||||
// C style pointer casts should never trigger a compiler warning because the risk is assumed by the user, so GCC should keep quiet about it.
|
||||
#if defined(__GNUC__) && !defined(__clang__)
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wignored-qualifiers"
|
||||
#endif
|
||||
if (_extension->set(_extension_instance, (const GDNativeStringNamePtr)&p_name, (const GDNativeVariantPtr)&p_value)) {
|
||||
if (r_valid) {
|
||||
*r_valid = true;
|
||||
}
|
||||
return;
|
||||
}
|
||||
#if defined(__GNUC__) && !defined(__clang__)
|
||||
#pragma GCC diagnostic pop
|
||||
#endif
|
||||
}
|
||||
|
||||
//try built-in setgetter
|
||||
|
@ -459,14 +467,22 @@ Variant Object::get(const StringName &p_name, bool *r_valid) const {
|
|||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
if (_extension && _extension->get) {
|
||||
if (_extension->get(_extension_instance, &p_name, &ret)) {
|
||||
// C style pointer casts should never trigger a compiler warning because the risk is assumed by the user, so GCC should keep quiet about it.
|
||||
#if defined(__GNUC__) && !defined(__clang__)
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wignored-qualifiers"
|
||||
#endif
|
||||
|
||||
if (_extension->get(_extension_instance, (const GDNativeStringNamePtr)&p_name, (GDNativeVariantPtr)&ret)) {
|
||||
if (r_valid) {
|
||||
*r_valid = true;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
#if defined(__GNUC__) && !defined(__clang__)
|
||||
#pragma GCC diagnostic pop
|
||||
#endif
|
||||
}
|
||||
|
||||
//try built-in setgetter
|
||||
|
@ -616,7 +632,7 @@ void Object::get_property_list(List<PropertyInfo> *p_list, bool p_reversed) cons
|
|||
|
||||
if (_extension && _extension->get_property_list) {
|
||||
uint32_t pcount;
|
||||
const ObjectNativeExtension::PInfo *pinfo = _extension->get_property_list(_extension_instance, &pcount);
|
||||
const GDNativePropertyInfo *pinfo = _extension->get_property_list(_extension_instance, &pcount);
|
||||
for (uint32_t i = 0; i < pcount; i++) {
|
||||
p_list->push_back(PropertyInfo(Variant::Type(pinfo[i].type), pinfo[i].class_name, PropertyHint(pinfo[i].hint), pinfo[i].hint_string, pinfo[i].usage, pinfo[i].class_name));
|
||||
}
|
||||
|
@ -1812,7 +1828,7 @@ Object::~Object() {
|
|||
script_instance = nullptr;
|
||||
|
||||
if (_extension && _extension->free_instance) {
|
||||
_extension->free_instance(_extension->create_instance_userdata, _extension_instance);
|
||||
_extension->free_instance(_extension->class_userdata, _extension_instance);
|
||||
_extension = nullptr;
|
||||
_extension_instance = nullptr;
|
||||
}
|
||||
|
|
|
@ -31,6 +31,7 @@
|
|||
#ifndef OBJECT_H
|
||||
#define OBJECT_H
|
||||
|
||||
#include "core/extension/gdnative_interface.h"
|
||||
#include "core/object/object_id.h"
|
||||
#include "core/os/rw_lock.h"
|
||||
#include "core/os/spin_lock.h"
|
||||
|
@ -244,29 +245,18 @@ class MethodBind;
|
|||
|
||||
struct ObjectNativeExtension {
|
||||
ObjectNativeExtension *parent = nullptr;
|
||||
List<ObjectNativeExtension *> children;
|
||||
StringName parent_class_name;
|
||||
StringName class_name;
|
||||
bool editor_class = false;
|
||||
bool (*set)(void *instance, const void *name, const void *value) = nullptr;
|
||||
bool (*get)(void *instance, const void *name, void *ret_variant) = nullptr;
|
||||
struct PInfo {
|
||||
uint32_t type;
|
||||
const char *name;
|
||||
const char *class_name;
|
||||
uint32_t hint;
|
||||
const char *hint_string;
|
||||
uint32_t usage;
|
||||
};
|
||||
const PInfo *(*get_property_list)(void *instance, uint32_t *count) = nullptr;
|
||||
void (*free_property_list)(void *instance, const PInfo *) = nullptr;
|
||||
|
||||
//call is not used, as all methods registered in ClassDB
|
||||
|
||||
void (*notification)(void *instance, int32_t what) = nullptr;
|
||||
const char *(*to_string)(void *instance) = nullptr;
|
||||
|
||||
void (*reference)(void *instance) = nullptr;
|
||||
void (*unreference)(void *instance) = nullptr;
|
||||
GDNativeExtensionClassSet set;
|
||||
GDNativeExtensionClassGet get;
|
||||
GDNativeExtensionClassGetPropertyList get_property_list;
|
||||
GDNativeExtensionClassFreePropertyList free_property_list;
|
||||
GDNativeExtensionClassNotification notification;
|
||||
GDNativeExtensionClassToString to_string;
|
||||
GDNativeExtensionClassReference reference;
|
||||
GDNativeExtensionClassReference unreference;
|
||||
|
||||
_FORCE_INLINE_ bool is_class(const String &p_class) const {
|
||||
const ObjectNativeExtension *e = this;
|
||||
|
@ -278,11 +268,16 @@ struct ObjectNativeExtension {
|
|||
}
|
||||
return false;
|
||||
}
|
||||
void *create_instance_userdata = nullptr;
|
||||
void *(*create_instance)(void *create_instance_userdata) = nullptr;
|
||||
void (*free_instance)(void *create_instance_userdata, void *instance) = nullptr;
|
||||
void *class_userdata = nullptr;
|
||||
|
||||
GDNativeExtensionClassCreateInstance create_instance;
|
||||
GDNativeExtensionClassFreeInstance free_instance;
|
||||
GDNativeExtensionClassGetVirtual get_virtual;
|
||||
};
|
||||
|
||||
#define GDVIRTUAL_CALL(m_name, ...) _gdvirtual_##m_name##_call(__VA_ARGS__)
|
||||
#define GDVIRTUAL_BIND(m_name) ClassDB::add_virtual_method(get_class_static(), _gdvirtual_##m_name##_get_method_info());
|
||||
|
||||
/*
|
||||
the following is an incomprehensible blob of hacks and workarounds to compensate for many of the fallencies in C++. As a plus, this macro pretty much alone defines the object model.
|
||||
*/
|
||||
|
@ -497,7 +492,7 @@ private:
|
|||
friend void postinitialize_handler(Object *);
|
||||
|
||||
ObjectNativeExtension *_extension = nullptr;
|
||||
void *_extension_instance = nullptr;
|
||||
GDExtensionClassInstancePtr _extension_instance = nullptr;
|
||||
|
||||
struct SignalData {
|
||||
struct Slot {
|
||||
|
@ -554,8 +549,9 @@ private:
|
|||
Object(bool p_reference);
|
||||
|
||||
protected:
|
||||
friend class NativeExtensionMethodBind;
|
||||
_ALWAYS_INLINE_ const ObjectNativeExtension *_get_extension() const { return _extension; }
|
||||
_ALWAYS_INLINE_ void *_get_extension_instance() const { return _extension_instance; }
|
||||
_ALWAYS_INLINE_ GDExtensionClassInstancePtr _get_extension_instance() const { return _extension_instance; }
|
||||
virtual void _initialize_classv() { initialize_class(); }
|
||||
virtual bool _setv(const StringName &p_name, const Variant &p_property) { return false; };
|
||||
virtual bool _getv(const StringName &p_name, Variant &r_property) const { return false; };
|
||||
|
|
|
@ -258,6 +258,8 @@ struct PtrToArg<Ref<T>> {
|
|||
return Ref<T>(const_cast<T *>(reinterpret_cast<const T *>(p_ptr)));
|
||||
}
|
||||
|
||||
typedef Ref<T> EncodeT;
|
||||
|
||||
_FORCE_INLINE_ static void encode(Ref<T> p_val, const void *p_ptr) {
|
||||
*(Ref<RefCounted> *)p_ptr = p_val;
|
||||
}
|
||||
|
@ -265,6 +267,8 @@ struct PtrToArg<Ref<T>> {
|
|||
|
||||
template <class T>
|
||||
struct PtrToArg<const Ref<T> &> {
|
||||
typedef Ref<T> EncodeT;
|
||||
|
||||
_FORCE_INLINE_ static Ref<T> convert(const void *p_ptr) {
|
||||
return Ref<T>((T *)p_ptr);
|
||||
}
|
||||
|
|
|
@ -37,6 +37,8 @@
|
|||
#include "core/crypto/aes_context.h"
|
||||
#include "core/crypto/crypto.h"
|
||||
#include "core/crypto/hashing_context.h"
|
||||
#include "core/extension/native_extension.h"
|
||||
#include "core/extension/native_extension_manager.h"
|
||||
#include "core/input/input.h"
|
||||
#include "core/input/input_map.h"
|
||||
#include "core/io/config_file.h"
|
||||
|
@ -95,6 +97,8 @@ static _Geometry3D *_geometry_3d = nullptr;
|
|||
|
||||
extern Mutex _global_mutex;
|
||||
|
||||
static NativeExtensionManager *native_extension_manager = nullptr;
|
||||
|
||||
extern void register_global_constants();
|
||||
extern void unregister_global_constants();
|
||||
|
||||
|
@ -217,6 +221,12 @@ void register_core_types() {
|
|||
|
||||
ClassDB::register_virtual_class<ResourceImporter>();
|
||||
|
||||
ClassDB::register_class<NativeExtension>();
|
||||
|
||||
ClassDB::register_virtual_class<NativeExtensionManager>();
|
||||
|
||||
native_extension_manager = memnew(NativeExtensionManager);
|
||||
|
||||
ip = IP::create();
|
||||
|
||||
_geometry_2d = memnew(_Geometry2D);
|
||||
|
@ -261,7 +271,7 @@ void register_core_singletons() {
|
|||
ClassDB::register_class<Time>();
|
||||
|
||||
Engine::get_singleton()->add_singleton(Engine::Singleton("ProjectSettings", ProjectSettings::get_singleton()));
|
||||
Engine::get_singleton()->add_singleton(Engine::Singleton("IP", IP::get_singleton()));
|
||||
Engine::get_singleton()->add_singleton(Engine::Singleton("IP", IP::get_singleton(), "IP"));
|
||||
Engine::get_singleton()->add_singleton(Engine::Singleton("Geometry2D", _Geometry2D::get_singleton()));
|
||||
Engine::get_singleton()->add_singleton(Engine::Singleton("Geometry3D", _Geometry3D::get_singleton()));
|
||||
Engine::get_singleton()->add_singleton(Engine::Singleton("ResourceLoader", _ResourceLoader::get_singleton()));
|
||||
|
@ -275,9 +285,25 @@ void register_core_singletons() {
|
|||
Engine::get_singleton()->add_singleton(Engine::Singleton("InputMap", InputMap::get_singleton()));
|
||||
Engine::get_singleton()->add_singleton(Engine::Singleton("EngineDebugger", _EngineDebugger::get_singleton()));
|
||||
Engine::get_singleton()->add_singleton(Engine::Singleton("Time", Time::get_singleton()));
|
||||
Engine::get_singleton()->add_singleton(Engine::Singleton("NativeExtensionManager", NativeExtensionManager::get_singleton()));
|
||||
}
|
||||
|
||||
void register_core_extensions() {
|
||||
//harcoded for now
|
||||
if (ProjectSettings::get_singleton()->has_setting("native_extensions/paths")) {
|
||||
Vector<String> paths = ProjectSettings::get_singleton()->get("native_extensions/paths");
|
||||
for (int i = 0; i < paths.size(); i++) {
|
||||
NativeExtensionManager::LoadStatus status = native_extension_manager->load_extension(paths[i]);
|
||||
ERR_CONTINUE_MSG(status != NativeExtensionManager::LOAD_STATUS_OK, "Error loading extension: " + paths[i]);
|
||||
}
|
||||
}
|
||||
native_extension_manager->initialize_extensions(NativeExtension::INITIALIZATION_LEVEL_CORE);
|
||||
}
|
||||
|
||||
void unregister_core_types() {
|
||||
native_extension_manager->deinitialize_extensions(NativeExtension::INITIALIZATION_LEVEL_CORE);
|
||||
|
||||
memdelete(native_extension_manager);
|
||||
memdelete(_resource_loader);
|
||||
memdelete(_resource_saver);
|
||||
memdelete(_os);
|
||||
|
|
|
@ -33,6 +33,7 @@
|
|||
|
||||
void register_core_types();
|
||||
void register_core_settings();
|
||||
void register_core_extensions();
|
||||
void register_core_singletons();
|
||||
void unregister_core_types();
|
||||
|
||||
|
|
|
@ -77,6 +77,7 @@ struct VariantCaster<const T &> {
|
|||
_FORCE_INLINE_ static m_enum convert(const void *p_ptr) { \
|
||||
return m_enum(*reinterpret_cast<const int *>(p_ptr)); \
|
||||
} \
|
||||
typedef int64_t EncodeT; \
|
||||
_FORCE_INLINE_ static void encode(m_enum p_val, const void *p_ptr) { \
|
||||
*(int *)p_ptr = p_val; \
|
||||
} \
|
||||
|
@ -117,6 +118,7 @@ struct PtrToArg<char32_t> {
|
|||
_FORCE_INLINE_ static char32_t convert(const void *p_ptr) {
|
||||
return char32_t(*reinterpret_cast<const int *>(p_ptr));
|
||||
}
|
||||
typedef int64_t EncodeT;
|
||||
_FORCE_INLINE_ static void encode(char32_t p_val, const void *p_ptr) {
|
||||
*(int *)p_ptr = p_val;
|
||||
}
|
||||
|
|
|
@ -45,6 +45,7 @@ struct PtrToArg {};
|
|||
_FORCE_INLINE_ static m_type convert(const void *p_ptr) { \
|
||||
return *reinterpret_cast<const m_type *>(p_ptr); \
|
||||
} \
|
||||
typedef m_type EncodeT; \
|
||||
_FORCE_INLINE_ static void encode(m_type p_val, void *p_ptr) { \
|
||||
*((m_type *)p_ptr) = p_val; \
|
||||
} \
|
||||
|
@ -54,6 +55,7 @@ struct PtrToArg {};
|
|||
_FORCE_INLINE_ static m_type convert(const void *p_ptr) { \
|
||||
return *reinterpret_cast<const m_type *>(p_ptr); \
|
||||
} \
|
||||
typedef m_type EncodeT; \
|
||||
_FORCE_INLINE_ static void encode(m_type p_val, void *p_ptr) { \
|
||||
*((m_type *)p_ptr) = p_val; \
|
||||
} \
|
||||
|
@ -65,6 +67,7 @@ struct PtrToArg {};
|
|||
_FORCE_INLINE_ static m_type convert(const void *p_ptr) { \
|
||||
return static_cast<m_type>(*reinterpret_cast<const m_conv *>(p_ptr)); \
|
||||
} \
|
||||
typedef m_conv EncodeT; \
|
||||
_FORCE_INLINE_ static void encode(m_type p_val, void *p_ptr) { \
|
||||
*((m_conv *)p_ptr) = static_cast<m_conv>(p_val); \
|
||||
} \
|
||||
|
@ -74,6 +77,7 @@ struct PtrToArg {};
|
|||
_FORCE_INLINE_ static m_type convert(const void *p_ptr) { \
|
||||
return static_cast<m_type>(*reinterpret_cast<const m_conv *>(p_ptr)); \
|
||||
} \
|
||||
typedef m_conv EncodeT; \
|
||||
_FORCE_INLINE_ static void encode(m_type p_val, void *p_ptr) { \
|
||||
*((m_conv *)p_ptr) = static_cast<m_conv>(p_val); \
|
||||
} \
|
||||
|
@ -85,6 +89,7 @@ struct PtrToArg {};
|
|||
_FORCE_INLINE_ static m_type convert(const void *p_ptr) { \
|
||||
return *reinterpret_cast<const m_type *>(p_ptr); \
|
||||
} \
|
||||
typedef m_type EncodeT; \
|
||||
_FORCE_INLINE_ static void encode(const m_type &p_val, void *p_ptr) { \
|
||||
*((m_type *)p_ptr) = p_val; \
|
||||
} \
|
||||
|
@ -94,12 +99,13 @@ struct PtrToArg {};
|
|||
_FORCE_INLINE_ static m_type convert(const void *p_ptr) { \
|
||||
return *reinterpret_cast<const m_type *>(p_ptr); \
|
||||
} \
|
||||
typedef m_type EncodeT; \
|
||||
_FORCE_INLINE_ static void encode(const m_type &p_val, void *p_ptr) { \
|
||||
*((m_type *)p_ptr) = p_val; \
|
||||
} \
|
||||
}
|
||||
|
||||
MAKE_PTRARG(bool);
|
||||
MAKE_PTRARGCONV(bool, uint32_t);
|
||||
// Integer types.
|
||||
MAKE_PTRARGCONV(uint8_t, int64_t);
|
||||
MAKE_PTRARGCONV(int8_t, int64_t);
|
||||
|
@ -153,7 +159,7 @@ struct PtrToArg<T *> {
|
|||
_FORCE_INLINE_ static T *convert(const void *p_ptr) {
|
||||
return const_cast<T *>(reinterpret_cast<const T *>(p_ptr));
|
||||
}
|
||||
|
||||
typedef Object *EncodeT;
|
||||
_FORCE_INLINE_ static void encode(T *p_var, void *p_ptr) {
|
||||
*((T **)p_ptr) = p_var;
|
||||
}
|
||||
|
@ -164,7 +170,7 @@ struct PtrToArg<const T *> {
|
|||
_FORCE_INLINE_ static const T *convert(const void *p_ptr) {
|
||||
return reinterpret_cast<const T *>(p_ptr);
|
||||
}
|
||||
|
||||
typedef const Object *EncodeT;
|
||||
_FORCE_INLINE_ static void encode(T *p_var, void *p_ptr) {
|
||||
*((T **)p_ptr) = p_var;
|
||||
}
|
||||
|
@ -177,7 +183,7 @@ struct PtrToArg<ObjectID> {
|
|||
_FORCE_INLINE_ static const ObjectID convert(const void *p_ptr) {
|
||||
return ObjectID(*reinterpret_cast<const uint64_t *>(p_ptr));
|
||||
}
|
||||
|
||||
typedef uint64_t EncodeT;
|
||||
_FORCE_INLINE_ static void encode(const ObjectID &p_val, void *p_ptr) {
|
||||
*((uint64_t *)p_ptr) = p_val;
|
||||
}
|
||||
|
|
|
@ -499,6 +499,7 @@ public:
|
|||
static bool is_builtin_method_vararg(Variant::Type p_type, const StringName &p_method);
|
||||
static void get_builtin_method_list(Variant::Type p_type, List<StringName> *p_list);
|
||||
static int get_builtin_method_count(Variant::Type p_type);
|
||||
static uint32_t get_builtin_method_hash(Variant::Type p_type, const StringName &p_method);
|
||||
|
||||
void call(const StringName &p_method, const Variant **p_args, int p_argcount, Variant &r_ret, Callable::CallError &r_error);
|
||||
Variant call(const StringName &p_method, const Variant &p_arg1 = Variant(), const Variant &p_arg2 = Variant(), const Variant &p_arg3 = Variant(), const Variant &p_arg4 = Variant(), const Variant &p_arg5 = Variant());
|
||||
|
@ -586,7 +587,7 @@ public:
|
|||
|
||||
typedef void (*PTRKeyedSetter)(void *base, const void *key, const void *value);
|
||||
typedef void (*PTRKeyedGetter)(const void *base, const void *key, void *value);
|
||||
typedef bool (*PTRKeyedChecker)(const void *base, const void *key);
|
||||
typedef uint32_t (*PTRKeyedChecker)(const void *base, const void *key);
|
||||
|
||||
static PTRKeyedSetter get_member_ptr_keyed_setter(Variant::Type p_type);
|
||||
static PTRKeyedGetter get_member_ptr_keyed_getter(Variant::Type p_type);
|
||||
|
@ -631,6 +632,7 @@ public:
|
|||
static bool has_utility_function_return_value(const StringName &p_name);
|
||||
static Variant::Type get_utility_function_return_type(const StringName &p_name);
|
||||
static bool is_utility_function_vararg(const StringName &p_name);
|
||||
static uint32_t get_utility_function_hash(const StringName &p_name);
|
||||
|
||||
static void get_utility_function_list(List<StringName> *r_functions);
|
||||
static int get_utility_function_count();
|
||||
|
|
|
@ -1126,6 +1126,25 @@ bool Variant::is_builtin_method_vararg(Variant::Type p_type, const StringName &p
|
|||
return method->is_vararg;
|
||||
}
|
||||
|
||||
uint32_t Variant::get_builtin_method_hash(Variant::Type p_type, const StringName &p_method) {
|
||||
ERR_FAIL_INDEX_V(p_type, Variant::VARIANT_MAX, 0);
|
||||
const VariantBuiltInMethodInfo *method = builtin_method_info[p_type].lookup_ptr(p_method);
|
||||
ERR_FAIL_COND_V(!method, 0);
|
||||
uint32_t hash = hash_djb2_one_32(method->is_const);
|
||||
hash = hash_djb2_one_32(method->is_static, hash);
|
||||
hash = hash_djb2_one_32(method->is_vararg, hash);
|
||||
hash = hash_djb2_one_32(method->has_return_type, hash);
|
||||
if (method->has_return_type) {
|
||||
hash = hash_djb2_one_32(method->return_type, hash);
|
||||
}
|
||||
hash = hash_djb2_one_32(method->argument_count, hash);
|
||||
for (int i = 0; i < method->argument_count; i++) {
|
||||
hash = method->get_argument_type(i);
|
||||
}
|
||||
|
||||
return hash;
|
||||
}
|
||||
|
||||
void Variant::get_method_list(List<MethodInfo> *p_list) const {
|
||||
if (type == OBJECT) {
|
||||
Object *obj = get_validated_object();
|
||||
|
|
|
@ -661,8 +661,8 @@ static const char *_op_names[Variant::OP_MAX] = {
|
|||
"-",
|
||||
"*",
|
||||
"/",
|
||||
"-",
|
||||
"+",
|
||||
"unary-",
|
||||
"unary+",
|
||||
"%",
|
||||
"<<",
|
||||
">>",
|
||||
|
|
|
@ -871,7 +871,7 @@ struct VariantKeyedSetGetDictionary {
|
|||
*r_valid = true;
|
||||
return VariantGetInternalPtr<Dictionary>::get_ptr(base)->has(*key);
|
||||
}
|
||||
static bool ptr_has(const void *base, const void *key) {
|
||||
static uint32_t ptr_has(const void *base, const void *key) {
|
||||
/* avoid ptrconvert for performance*/
|
||||
const Dictionary &v = *reinterpret_cast<const Dictionary *>(base);
|
||||
return v.has(PtrToArg<Variant>::convert(key));
|
||||
|
@ -921,7 +921,7 @@ struct VariantKeyedSetGetObject {
|
|||
obj->getvar(*key, &exists);
|
||||
return exists;
|
||||
}
|
||||
static bool ptr_has(const void *base, const void *key) {
|
||||
static uint32_t ptr_has(const void *base, const void *key) {
|
||||
const Object *obj = PtrToArg<Object *>::convert(base);
|
||||
ERR_FAIL_COND_V(!obj, false);
|
||||
bool valid;
|
||||
|
|
|
@ -1348,8 +1348,8 @@ String Variant::get_utility_function_argument_name(const StringName &p_name, int
|
|||
if (!bfi) {
|
||||
return String();
|
||||
}
|
||||
ERR_FAIL_COND_V(bfi->is_vararg, String());
|
||||
ERR_FAIL_INDEX_V(p_arg, bfi->argnames.size(), String());
|
||||
ERR_FAIL_COND_V(bfi->is_vararg, String());
|
||||
return bfi->argnames[p_arg];
|
||||
}
|
||||
|
||||
|
@ -1379,6 +1379,23 @@ bool Variant::is_utility_function_vararg(const StringName &p_name) {
|
|||
return bfi->is_vararg;
|
||||
}
|
||||
|
||||
uint32_t Variant::get_utility_function_hash(const StringName &p_name) {
|
||||
const VariantUtilityFunctionInfo *bfi = utility_function_table.lookup_ptr(p_name);
|
||||
ERR_FAIL_COND_V(!bfi, 0);
|
||||
|
||||
uint32_t hash = hash_djb2_one_32(bfi->is_vararg);
|
||||
hash = hash_djb2_one_32(bfi->returns_value, hash);
|
||||
if (bfi->returns_value) {
|
||||
hash = hash_djb2_one_32(bfi->return_type, hash);
|
||||
}
|
||||
hash = hash_djb2_one_32(bfi->argcount, hash);
|
||||
for (int i = 0; i < bfi->argcount; i++) {
|
||||
hash = hash_djb2_one_32(bfi->get_arg_type(i), hash);
|
||||
}
|
||||
|
||||
return hash;
|
||||
}
|
||||
|
||||
void Variant::get_utility_function_list(List<StringName> *r_functions) {
|
||||
for (List<StringName>::Element *E = utility_function_name_table.front(); E; E = E->next()) {
|
||||
r_functions->push_back(E->get());
|
||||
|
|
|
@ -1224,6 +1224,8 @@
|
|||
<member name="Marshalls" type="Marshalls" setter="" getter="">
|
||||
The [Marshalls] singleton.
|
||||
</member>
|
||||
<member name="NativeExtensionManager" type="NativeExtensionManager" setter="" getter="">
|
||||
</member>
|
||||
<member name="NavigationMeshGenerator" type="NavigationMeshGenerator" setter="" getter="">
|
||||
The [NavigationMeshGenerator] singleton.
|
||||
</member>
|
||||
|
|
|
@ -80,14 +80,16 @@
|
|||
</argument>
|
||||
<argument index="2" name="b" type="float">
|
||||
</argument>
|
||||
<argument index="3" name="a" type="float">
|
||||
</argument>
|
||||
<description>
|
||||
Constructs a [Color] from RGB values, typically between 0 and 1. Alpha will be 1.
|
||||
Constructs a [Color] from RGBA values, typically between 0 and 1.
|
||||
[codeblocks]
|
||||
[gdscript]
|
||||
var color = Color(0.2, 1.0, 0.7) # Similar to `Color8(51, 255, 178, 255)`
|
||||
var color = Color(0.2, 1.0, 0.7, 0.8) # Similar to `Color8(51, 255, 178, 204)`
|
||||
[/gdscript]
|
||||
[csharp]
|
||||
var color = new Color(0.2f, 1.0f, 0.7f); // Similar to `Color.Color8(51, 255, 178, 255)`
|
||||
var color = new Color(0.2f, 1.0f, 0.7f, 0.8f); // Similar to `Color.Color8(51, 255, 178, 255, 204)`
|
||||
[/csharp]
|
||||
[/codeblocks]
|
||||
</description>
|
||||
|
@ -101,16 +103,14 @@
|
|||
</argument>
|
||||
<argument index="2" name="b" type="float">
|
||||
</argument>
|
||||
<argument index="3" name="a" type="float">
|
||||
</argument>
|
||||
<description>
|
||||
Constructs a [Color] from RGBA values, typically between 0 and 1.
|
||||
Constructs a [Color] from RGB values, typically between 0 and 1. Alpha will be 1.
|
||||
[codeblocks]
|
||||
[gdscript]
|
||||
var color = Color(0.2, 1.0, 0.7, 0.8) # Similar to `Color8(51, 255, 178, 204)`
|
||||
var color = Color(0.2, 1.0, 0.7) # Similar to `Color8(51, 255, 178, 255)`
|
||||
[/gdscript]
|
||||
[csharp]
|
||||
var color = new Color(0.2f, 1.0f, 0.7f, 0.8f); // Similar to `Color.Color8(51, 255, 178, 255, 204)`
|
||||
var color = new Color(0.2f, 1.0f, 0.7f); // Similar to `Color.Color8(51, 255, 178, 255)`
|
||||
[/csharp]
|
||||
[/codeblocks]
|
||||
</description>
|
||||
|
@ -346,12 +346,6 @@
|
|||
<description>
|
||||
</description>
|
||||
</method>
|
||||
<method name="operator +" qualifiers="operator">
|
||||
<return type="Color">
|
||||
</return>
|
||||
<description>
|
||||
</description>
|
||||
</method>
|
||||
<method name="operator +" qualifiers="operator">
|
||||
<return type="Color">
|
||||
</return>
|
||||
|
@ -360,12 +354,6 @@
|
|||
<description>
|
||||
</description>
|
||||
</method>
|
||||
<method name="operator -" qualifiers="operator">
|
||||
<return type="Color">
|
||||
</return>
|
||||
<description>
|
||||
</description>
|
||||
</method>
|
||||
<method name="operator -" qualifiers="operator">
|
||||
<return type="Color">
|
||||
</return>
|
||||
|
@ -414,6 +402,18 @@
|
|||
<description>
|
||||
</description>
|
||||
</method>
|
||||
<method name="operator unary+" qualifiers="operator">
|
||||
<return type="Color">
|
||||
</return>
|
||||
<description>
|
||||
</description>
|
||||
</method>
|
||||
<method name="operator unary-" qualifiers="operator">
|
||||
<return type="Color">
|
||||
</return>
|
||||
<description>
|
||||
</description>
|
||||
</method>
|
||||
<method name="to_abgr32" qualifiers="const">
|
||||
<return type="int">
|
||||
</return>
|
||||
|
|
|
@ -150,10 +150,10 @@
|
|||
* it happens outside parent's rectangle and the parent has either [member rect_clip_content] enabled.
|
||||
</description>
|
||||
</method>
|
||||
<method name="_has_point" qualifiers="virtual">
|
||||
<method name="_has_point" qualifiers="virtual const">
|
||||
<return type="bool">
|
||||
</return>
|
||||
<argument index="0" name="point" type="Vector2">
|
||||
<argument index="0" name="" type="Vector2">
|
||||
</argument>
|
||||
<description>
|
||||
Virtual method to be implemented by the user. Returns whether the given [code]point[/code] is inside this control.
|
||||
|
|
|
@ -0,0 +1,57 @@
|
|||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
<class name="NativeExtension" inherits="RefCounted" version="4.0">
|
||||
<brief_description>
|
||||
</brief_description>
|
||||
<description>
|
||||
</description>
|
||||
<tutorials>
|
||||
</tutorials>
|
||||
<methods>
|
||||
<method name="close_library">
|
||||
<return type="void">
|
||||
</return>
|
||||
<description>
|
||||
</description>
|
||||
</method>
|
||||
<method name="get_minimum_library_initialization_level" qualifiers="const">
|
||||
<return type="int" enum="NativeExtension.InitializationLevel">
|
||||
</return>
|
||||
<description>
|
||||
</description>
|
||||
</method>
|
||||
<method name="initialize_library">
|
||||
<return type="void">
|
||||
</return>
|
||||
<argument index="0" name="level" type="int" enum="NativeExtension.InitializationLevel">
|
||||
</argument>
|
||||
<description>
|
||||
</description>
|
||||
</method>
|
||||
<method name="is_library_open" qualifiers="const">
|
||||
<return type="bool">
|
||||
</return>
|
||||
<description>
|
||||
</description>
|
||||
</method>
|
||||
<method name="open_library">
|
||||
<return type="int" enum="Error">
|
||||
</return>
|
||||
<argument index="0" name="path" type="String">
|
||||
</argument>
|
||||
<argument index="1" name="entry_symbol" type="String">
|
||||
</argument>
|
||||
<description>
|
||||
</description>
|
||||
</method>
|
||||
</methods>
|
||||
<constants>
|
||||
<constant name="INITIALIZATION_LEVEL_CORE" value="0" enum="InitializationLevel">
|
||||
</constant>
|
||||
<constant name="INITIALIZATION_LEVEL_SERVERS" value="1" enum="InitializationLevel">
|
||||
</constant>
|
||||
<constant name="INITIALIZATION_LEVEL_SCENE" value="2" enum="InitializationLevel">
|
||||
</constant>
|
||||
<constant name="INITIALIZATION_LEVEL_EDITOR" value="3" enum="InitializationLevel">
|
||||
</constant>
|
||||
</constants>
|
||||
</class>
|
|
@ -0,0 +1,61 @@
|
|||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
<class name="NativeExtensionManager" inherits="Object" version="4.0">
|
||||
<brief_description>
|
||||
</brief_description>
|
||||
<description>
|
||||
</description>
|
||||
<tutorials>
|
||||
</tutorials>
|
||||
<methods>
|
||||
<method name="get_extension">
|
||||
<return type="NativeExtension">
|
||||
</return>
|
||||
<argument index="0" name="path" type="String">
|
||||
</argument>
|
||||
<description>
|
||||
</description>
|
||||
</method>
|
||||
<method name="get_loaded_extensions" qualifiers="const">
|
||||
<return type="PackedStringArray">
|
||||
</return>
|
||||
<description>
|
||||
</description>
|
||||
</method>
|
||||
<method name="load_extension">
|
||||
<return type="int" enum="NativeExtensionManager.LoadStatus">
|
||||
</return>
|
||||
<argument index="0" name="path" type="String">
|
||||
</argument>
|
||||
<description>
|
||||
</description>
|
||||
</method>
|
||||
<method name="reload_extension">
|
||||
<return type="int" enum="NativeExtensionManager.LoadStatus">
|
||||
</return>
|
||||
<argument index="0" name="path" type="String">
|
||||
</argument>
|
||||
<description>
|
||||
</description>
|
||||
</method>
|
||||
<method name="unload_extension">
|
||||
<return type="int" enum="NativeExtensionManager.LoadStatus">
|
||||
</return>
|
||||
<argument index="0" name="path" type="String">
|
||||
</argument>
|
||||
<description>
|
||||
</description>
|
||||
</method>
|
||||
</methods>
|
||||
<constants>
|
||||
<constant name="LOAD_STATUS_OK" value="0" enum="LoadStatus">
|
||||
</constant>
|
||||
<constant name="LOAD_STATUS_FAILED" value="1" enum="LoadStatus">
|
||||
</constant>
|
||||
<constant name="LOAD_STATUS_ALREADY_LOADED" value="2" enum="LoadStatus">
|
||||
</constant>
|
||||
<constant name="LOAD_STATUS_NOT_LOADED" value="3" enum="LoadStatus">
|
||||
</constant>
|
||||
<constant name="LOAD_STATUS_NEEDS_RESTART" value="4" enum="LoadStatus">
|
||||
</constant>
|
||||
</constants>
|
||||
</class>
|
|
@ -169,18 +169,6 @@
|
|||
<description>
|
||||
</description>
|
||||
</method>
|
||||
<method name="operator +" qualifiers="operator">
|
||||
<return type="Plane">
|
||||
</return>
|
||||
<description>
|
||||
</description>
|
||||
</method>
|
||||
<method name="operator -" qualifiers="operator">
|
||||
<return type="Plane">
|
||||
</return>
|
||||
<description>
|
||||
</description>
|
||||
</method>
|
||||
<method name="operator ==" qualifiers="operator">
|
||||
<return type="bool">
|
||||
</return>
|
||||
|
@ -189,6 +177,18 @@
|
|||
<description>
|
||||
</description>
|
||||
</method>
|
||||
<method name="operator unary+" qualifiers="operator">
|
||||
<return type="Plane">
|
||||
</return>
|
||||
<description>
|
||||
</description>
|
||||
</method>
|
||||
<method name="operator unary-" qualifiers="operator">
|
||||
<return type="Plane">
|
||||
</return>
|
||||
<description>
|
||||
</description>
|
||||
</method>
|
||||
<method name="project" qualifiers="const">
|
||||
<return type="Vector3">
|
||||
</return>
|
||||
|
|
|
@ -177,17 +177,17 @@
|
|||
</description>
|
||||
</method>
|
||||
<method name="operator *" qualifiers="operator">
|
||||
<return type="Quaternion">
|
||||
<return type="Vector3">
|
||||
</return>
|
||||
<argument index="0" name="right" type="Quaternion">
|
||||
<argument index="0" name="right" type="Vector3">
|
||||
</argument>
|
||||
<description>
|
||||
</description>
|
||||
</method>
|
||||
<method name="operator *" qualifiers="operator">
|
||||
<return type="Vector3">
|
||||
<return type="Quaternion">
|
||||
</return>
|
||||
<argument index="0" name="right" type="Vector3">
|
||||
<argument index="0" name="right" type="Quaternion">
|
||||
</argument>
|
||||
<description>
|
||||
</description>
|
||||
|
@ -208,12 +208,6 @@
|
|||
<description>
|
||||
</description>
|
||||
</method>
|
||||
<method name="operator +" qualifiers="operator">
|
||||
<return type="Quaternion">
|
||||
</return>
|
||||
<description>
|
||||
</description>
|
||||
</method>
|
||||
<method name="operator +" qualifiers="operator">
|
||||
<return type="Quaternion">
|
||||
</return>
|
||||
|
@ -222,12 +216,6 @@
|
|||
<description>
|
||||
</description>
|
||||
</method>
|
||||
<method name="operator -" qualifiers="operator">
|
||||
<return type="Quaternion">
|
||||
</return>
|
||||
<description>
|
||||
</description>
|
||||
</method>
|
||||
<method name="operator -" qualifiers="operator">
|
||||
<return type="Quaternion">
|
||||
</return>
|
||||
|
@ -268,6 +256,18 @@
|
|||
<description>
|
||||
</description>
|
||||
</method>
|
||||
<method name="operator unary+" qualifiers="operator">
|
||||
<return type="Quaternion">
|
||||
</return>
|
||||
<description>
|
||||
</description>
|
||||
</method>
|
||||
<method name="operator unary-" qualifiers="operator">
|
||||
<return type="Quaternion">
|
||||
</return>
|
||||
<description>
|
||||
</description>
|
||||
</method>
|
||||
<method name="slerp" qualifiers="const">
|
||||
<return type="Quaternion">
|
||||
</return>
|
||||
|
|
|
@ -301,12 +301,6 @@
|
|||
<description>
|
||||
</description>
|
||||
</method>
|
||||
<method name="operator +" qualifiers="operator">
|
||||
<return type="Vector2">
|
||||
</return>
|
||||
<description>
|
||||
</description>
|
||||
</method>
|
||||
<method name="operator +" qualifiers="operator">
|
||||
<return type="Vector2">
|
||||
</return>
|
||||
|
@ -315,12 +309,6 @@
|
|||
<description>
|
||||
</description>
|
||||
</method>
|
||||
<method name="operator -" qualifiers="operator">
|
||||
<return type="Vector2">
|
||||
</return>
|
||||
<description>
|
||||
</description>
|
||||
</method>
|
||||
<method name="operator -" qualifiers="operator">
|
||||
<return type="Vector2">
|
||||
</return>
|
||||
|
@ -401,6 +389,18 @@
|
|||
<description>
|
||||
</description>
|
||||
</method>
|
||||
<method name="operator unary+" qualifiers="operator">
|
||||
<return type="Vector2">
|
||||
</return>
|
||||
<description>
|
||||
</description>
|
||||
</method>
|
||||
<method name="operator unary-" qualifiers="operator">
|
||||
<return type="Vector2">
|
||||
</return>
|
||||
<description>
|
||||
</description>
|
||||
</method>
|
||||
<method name="orthogonal" qualifiers="const">
|
||||
<return type="Vector2">
|
||||
</return>
|
||||
|
|
|
@ -123,12 +123,6 @@
|
|||
<description>
|
||||
</description>
|
||||
</method>
|
||||
<method name="operator +" qualifiers="operator">
|
||||
<return type="Vector2i">
|
||||
</return>
|
||||
<description>
|
||||
</description>
|
||||
</method>
|
||||
<method name="operator +" qualifiers="operator">
|
||||
<return type="Vector2i">
|
||||
</return>
|
||||
|
@ -137,12 +131,6 @@
|
|||
<description>
|
||||
</description>
|
||||
</method>
|
||||
<method name="operator -" qualifiers="operator">
|
||||
<return type="Vector2i">
|
||||
</return>
|
||||
<description>
|
||||
</description>
|
||||
</method>
|
||||
<method name="operator -" qualifiers="operator">
|
||||
<return type="Vector2i">
|
||||
</return>
|
||||
|
@ -223,6 +211,18 @@
|
|||
<description>
|
||||
</description>
|
||||
</method>
|
||||
<method name="operator unary+" qualifiers="operator">
|
||||
<return type="Vector2i">
|
||||
</return>
|
||||
<description>
|
||||
</description>
|
||||
</method>
|
||||
<method name="operator unary-" qualifiers="operator">
|
||||
<return type="Vector2i">
|
||||
</return>
|
||||
<description>
|
||||
</description>
|
||||
</method>
|
||||
<method name="sign" qualifiers="const">
|
||||
<return type="Vector2i">
|
||||
</return>
|
||||
|
|
|
@ -315,12 +315,6 @@
|
|||
<description>
|
||||
</description>
|
||||
</method>
|
||||
<method name="operator +" qualifiers="operator">
|
||||
<return type="Vector3">
|
||||
</return>
|
||||
<description>
|
||||
</description>
|
||||
</method>
|
||||
<method name="operator +" qualifiers="operator">
|
||||
<return type="Vector3">
|
||||
</return>
|
||||
|
@ -329,12 +323,6 @@
|
|||
<description>
|
||||
</description>
|
||||
</method>
|
||||
<method name="operator -" qualifiers="operator">
|
||||
<return type="Vector3">
|
||||
</return>
|
||||
<description>
|
||||
</description>
|
||||
</method>
|
||||
<method name="operator -" qualifiers="operator">
|
||||
<return type="Vector3">
|
||||
</return>
|
||||
|
@ -415,6 +403,18 @@
|
|||
<description>
|
||||
</description>
|
||||
</method>
|
||||
<method name="operator unary+" qualifiers="operator">
|
||||
<return type="Vector3">
|
||||
</return>
|
||||
<description>
|
||||
</description>
|
||||
</method>
|
||||
<method name="operator unary-" qualifiers="operator">
|
||||
<return type="Vector3">
|
||||
</return>
|
||||
<description>
|
||||
</description>
|
||||
</method>
|
||||
<method name="outer" qualifiers="const">
|
||||
<return type="Basis">
|
||||
</return>
|
||||
|
|
|
@ -131,12 +131,6 @@
|
|||
<description>
|
||||
</description>
|
||||
</method>
|
||||
<method name="operator +" qualifiers="operator">
|
||||
<return type="Vector3i">
|
||||
</return>
|
||||
<description>
|
||||
</description>
|
||||
</method>
|
||||
<method name="operator +" qualifiers="operator">
|
||||
<return type="Vector3i">
|
||||
</return>
|
||||
|
@ -145,12 +139,6 @@
|
|||
<description>
|
||||
</description>
|
||||
</method>
|
||||
<method name="operator -" qualifiers="operator">
|
||||
<return type="Vector3i">
|
||||
</return>
|
||||
<description>
|
||||
</description>
|
||||
</method>
|
||||
<method name="operator -" qualifiers="operator">
|
||||
<return type="Vector3i">
|
||||
</return>
|
||||
|
@ -231,6 +219,18 @@
|
|||
<description>
|
||||
</description>
|
||||
</method>
|
||||
<method name="operator unary+" qualifiers="operator">
|
||||
<return type="Vector3i">
|
||||
</return>
|
||||
<description>
|
||||
</description>
|
||||
</method>
|
||||
<method name="operator unary-" qualifiers="operator">
|
||||
<return type="Vector3i">
|
||||
</return>
|
||||
<description>
|
||||
</description>
|
||||
</method>
|
||||
<method name="sign" qualifiers="const">
|
||||
<return type="Vector3i">
|
||||
</return>
|
||||
|
|
|
@ -142,16 +142,6 @@
|
|||
Multiplies a [float] and an [int]. The result is a [float].
|
||||
</description>
|
||||
</method>
|
||||
<method name="operator +" qualifiers="operator">
|
||||
<return type="float">
|
||||
</return>
|
||||
<description>
|
||||
Unary plus operator. Doesn't have any effect.
|
||||
[codeblock]
|
||||
var a = +2.5 # a is 2.5.
|
||||
[/codeblock]
|
||||
</description>
|
||||
</method>
|
||||
<method name="operator +" qualifiers="operator">
|
||||
<return type="float">
|
||||
</return>
|
||||
|
@ -170,17 +160,6 @@
|
|||
Adds a [float] and an [int]. The result is a [float].
|
||||
</description>
|
||||
</method>
|
||||
<method name="operator -" qualifiers="operator">
|
||||
<return type="float">
|
||||
</return>
|
||||
<description>
|
||||
Unary minus operator. Negates the number.
|
||||
[codeblock]
|
||||
var a = -2.5 # a is -2.5.
|
||||
print(-a) # 2.5
|
||||
[/codeblock]
|
||||
</description>
|
||||
</method>
|
||||
<method name="operator -" qualifiers="operator">
|
||||
<return type="float">
|
||||
</return>
|
||||
|
@ -308,6 +287,18 @@
|
|||
Returns [code]true[/code] if this [float] is greater than or equal to the given [int].
|
||||
</description>
|
||||
</method>
|
||||
<method name="operator unary+" qualifiers="operator">
|
||||
<return type="float">
|
||||
</return>
|
||||
<description>
|
||||
</description>
|
||||
</method>
|
||||
<method name="operator unary-" qualifiers="operator">
|
||||
<return type="float">
|
||||
</return>
|
||||
<description>
|
||||
</description>
|
||||
</method>
|
||||
</methods>
|
||||
<constants>
|
||||
</constants>
|
||||
|
|
|
@ -125,15 +125,6 @@
|
|||
[/codeblock]
|
||||
</description>
|
||||
</method>
|
||||
<method name="operator *" qualifiers="operator">
|
||||
<return type="float">
|
||||
</return>
|
||||
<argument index="0" name="right" type="float">
|
||||
</argument>
|
||||
<description>
|
||||
Multiplies an [int] and a [float]. The result is a [float].
|
||||
</description>
|
||||
</method>
|
||||
<method name="operator *" qualifiers="operator">
|
||||
<return type="int">
|
||||
</return>
|
||||
|
@ -143,6 +134,15 @@
|
|||
Multiplies two [int]s.
|
||||
</description>
|
||||
</method>
|
||||
<method name="operator *" qualifiers="operator">
|
||||
<return type="float">
|
||||
</return>
|
||||
<argument index="0" name="right" type="float">
|
||||
</argument>
|
||||
<description>
|
||||
Multiplies an [int] and a [float]. The result is a [float].
|
||||
</description>
|
||||
</method>
|
||||
<method name="operator *" qualifiers="operator">
|
||||
<return type="Vector2">
|
||||
</return>
|
||||
|
@ -203,16 +203,6 @@
|
|||
[/codeblock]
|
||||
</description>
|
||||
</method>
|
||||
<method name="operator +" qualifiers="operator">
|
||||
<return type="int">
|
||||
</return>
|
||||
<description>
|
||||
Unary plus operator. Doesn't have any effect.
|
||||
[codeblock]
|
||||
var a = +1 # a is 1.
|
||||
[/codeblock]
|
||||
</description>
|
||||
</method>
|
||||
<method name="operator +" qualifiers="operator">
|
||||
<return type="float">
|
||||
</return>
|
||||
|
@ -231,17 +221,6 @@
|
|||
Adds two integers.
|
||||
</description>
|
||||
</method>
|
||||
<method name="operator -" qualifiers="operator">
|
||||
<return type="int">
|
||||
</return>
|
||||
<description>
|
||||
Unary minus operator. Negates the number.
|
||||
[codeblock]
|
||||
var a = -1 # a is -1.
|
||||
print(-a) # 1
|
||||
[/codeblock]
|
||||
</description>
|
||||
</method>
|
||||
<method name="operator -" qualifiers="operator">
|
||||
<return type="float">
|
||||
</return>
|
||||
|
@ -414,6 +393,18 @@
|
|||
[/codeblock]
|
||||
</description>
|
||||
</method>
|
||||
<method name="operator unary+" qualifiers="operator">
|
||||
<return type="int">
|
||||
</return>
|
||||
<description>
|
||||
</description>
|
||||
</method>
|
||||
<method name="operator unary-" qualifiers="operator">
|
||||
<return type="int">
|
||||
</return>
|
||||
<description>
|
||||
</description>
|
||||
</method>
|
||||
<method name="operator |" qualifiers="operator">
|
||||
<return type="int">
|
||||
</return>
|
||||
|
|
|
@ -32,6 +32,7 @@
|
|||
|
||||
#include "core/config/project_settings.h"
|
||||
#include "core/core_bind.h"
|
||||
#include "core/extension/native_extension_manager.h"
|
||||
#include "core/input/input.h"
|
||||
#include "core/io/config_file.h"
|
||||
#include "core/io/file_access.h"
|
||||
|
@ -3771,9 +3772,12 @@ void EditorNode::register_editor_types() {
|
|||
ClassDB::register_class<EditorScenePostImport>();
|
||||
//ClassDB::register_type<EditorImportExport>();
|
||||
ClassDB::register_class<EditorDebuggerPlugin>();
|
||||
|
||||
NativeExtensionManager::get_singleton()->initialize_extensions(NativeExtension::INITIALIZATION_LEVEL_EDITOR);
|
||||
}
|
||||
|
||||
void EditorNode::unregister_editor_types() {
|
||||
NativeExtensionManager::get_singleton()->deinitialize_extensions(NativeExtension::INITIALIZATION_LEVEL_EDITOR);
|
||||
_init_callbacks.clear();
|
||||
if (EditorPaths::get_singleton()) {
|
||||
EditorPaths::free();
|
||||
|
|
|
@ -34,6 +34,7 @@
|
|||
#include "core/core_string_names.h"
|
||||
#include "core/crypto/crypto.h"
|
||||
#include "core/debugger/engine_debugger.h"
|
||||
#include "core/extension/extension_api_dump.h"
|
||||
#include "core/input/input.h"
|
||||
#include "core/input/input_map.h"
|
||||
#include "core/io/dir_access.h"
|
||||
|
@ -174,7 +175,9 @@ static int frame_delay = 0;
|
|||
static bool disable_render_loop = false;
|
||||
static int fixed_fps = -1;
|
||||
static bool print_fps = false;
|
||||
|
||||
#ifdef TOOLS_ENABLED
|
||||
static bool dump_extension_api = false;
|
||||
#endif
|
||||
bool profile_gpu = false;
|
||||
|
||||
/* Helper methods */
|
||||
|
@ -406,6 +409,8 @@ Error Main::test_setup() {
|
|||
|
||||
translation_server = memnew(TranslationServer);
|
||||
|
||||
register_core_extensions();
|
||||
|
||||
// From `Main::setup2()`.
|
||||
preregister_module_types();
|
||||
preregister_server_types();
|
||||
|
@ -887,7 +892,7 @@ Error Main::setup(const char *execpath, int argc, char *argv[], bool p_second_ph
|
|||
auto_build_solutions = true;
|
||||
editor = true;
|
||||
cmdline_tool = true;
|
||||
#ifdef DEBUG_METHODS_ENABLED
|
||||
|
||||
} else if (I->get() == "--gdnative-generate-json-api" || I->get() == "--gdnative-generate-json-builtin-api") {
|
||||
// Register as an editor instance to use low-end fallback if relevant.
|
||||
editor = true;
|
||||
|
@ -895,7 +900,13 @@ Error Main::setup(const char *execpath, int argc, char *argv[], bool p_second_ph
|
|||
|
||||
// We still pass it to the main arguments since the argument handling itself is not done in this function
|
||||
main_args.push_back(I->get());
|
||||
#endif
|
||||
} else if (I->get() == "--dump-extension-api") {
|
||||
// Register as an editor instance to use low-end fallback if relevant.
|
||||
editor = true;
|
||||
cmdline_tool = true;
|
||||
dump_extension_api = true;
|
||||
print_line("dump extension?");
|
||||
main_args.push_back(I->get());
|
||||
} else if (I->get() == "--export" || I->get() == "--export-debug" ||
|
||||
I->get() == "--export-pack") { // Export project
|
||||
// Actually handling is done in start().
|
||||
|
@ -1198,6 +1209,8 @@ Error Main::setup(const char *execpath, int argc, char *argv[], bool p_second_ph
|
|||
|
||||
OS::get_singleton()->set_cmdline(execpath, main_args);
|
||||
|
||||
register_core_extensions(); //before display
|
||||
|
||||
GLOBAL_DEF("rendering/driver/driver_name", "Vulkan");
|
||||
ProjectSettings::get_singleton()->set_custom_property_info("rendering/driver/driver_name",
|
||||
PropertyInfo(Variant::STRING,
|
||||
|
@ -2004,6 +2017,11 @@ bool Main::start() {
|
|||
|
||||
return false;
|
||||
}
|
||||
|
||||
if (dump_extension_api) {
|
||||
NativeExtensionAPIDump::generate_extension_json_file("extension_api.json");
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (script == "" && game_path == "" && String(GLOBAL_GET("application/run/main_scene")) != "") {
|
||||
|
|
|
@ -164,7 +164,7 @@ typedef void (*godot_validated_keyed_getter)(const godot_variant *p_base, const
|
|||
typedef bool (*godot_validated_keyed_checker)(const godot_variant *p_base, const godot_variant *p_key, bool *r_valid);
|
||||
typedef void (*godot_ptr_keyed_setter)(void *p_base, const void *p_key, const void *p_value);
|
||||
typedef void (*godot_ptr_keyed_getter)(const void *p_base, const void *p_key, void *r_value);
|
||||
typedef bool (*godot_ptr_keyed_checker)(const godot_variant *p_base, const godot_variant *p_key);
|
||||
typedef uint32_t (*godot_ptr_keyed_checker)(const godot_variant *p_base, const godot_variant *p_key);
|
||||
typedef void (*godot_validated_utility_function)(godot_variant *r_return, const godot_variant **p_arguments, int p_argument_count);
|
||||
typedef void (*godot_ptr_utility_function)(void *r_return, const void **p_arguments, int p_argument_count);
|
||||
|
||||
|
|
|
@ -651,19 +651,10 @@ void Control::_notification(int p_notification) {
|
|||
}
|
||||
|
||||
bool Control::has_point(const Point2 &p_point) const {
|
||||
if (get_script_instance()) {
|
||||
Variant v = p_point;
|
||||
const Variant *p = &v;
|
||||
Callable::CallError ce;
|
||||
Variant ret = get_script_instance()->call(SceneStringNames::get_singleton()->_has_point, &p, 1, ce);
|
||||
if (ce.error == Callable::CallError::CALL_OK) {
|
||||
return ret;
|
||||
}
|
||||
bool ret;
|
||||
if (GDVIRTUAL_CALL(_has_point, p_point, ret)) {
|
||||
return ret;
|
||||
}
|
||||
/*if (has_stylebox("mask")) {
|
||||
Ref<StyleBox> mask = get_stylebox("mask");
|
||||
return mask->test_mask(p_point,Rect2(Point2(),get_size()));
|
||||
}*/
|
||||
return Rect2(Point2(), get_size()).has_point(p_point);
|
||||
}
|
||||
|
||||
|
@ -2932,5 +2923,5 @@ void Control::_bind_methods() {
|
|||
ADD_SIGNAL(MethodInfo("minimum_size_changed"));
|
||||
ADD_SIGNAL(MethodInfo("theme_changed"));
|
||||
|
||||
BIND_VMETHOD(MethodInfo(Variant::BOOL, "_has_point", PropertyInfo(Variant::VECTOR2, "point")));
|
||||
GDVIRTUAL_BIND(_has_point);
|
||||
}
|
||||
|
|
|
@ -32,6 +32,7 @@
|
|||
#define CONTROL_H
|
||||
|
||||
#include "core/math/transform_2d.h"
|
||||
#include "core/object/gdvirtual.gen.inc"
|
||||
#include "core/templates/rid.h"
|
||||
#include "scene/gui/shortcut.h"
|
||||
#include "scene/main/canvas_item.h"
|
||||
|
@ -264,6 +265,7 @@ private:
|
|||
static bool has_theme_item_in_types(Control *p_theme_owner, Window *p_theme_owner_window, Theme::DataType p_data_type, const StringName &p_name, List<StringName> p_theme_types);
|
||||
_FORCE_INLINE_ void _get_theme_type_dependencies(const StringName &p_theme_type, List<StringName> *p_list) const;
|
||||
|
||||
GDVIRTUAL1RC(bool, _has_point, Vector2)
|
||||
protected:
|
||||
virtual void add_child_notify(Node *p_child) override;
|
||||
virtual void remove_child_notify(Node *p_child) override;
|
||||
|
|
|
@ -31,6 +31,7 @@
|
|||
#include "register_scene_types.h"
|
||||
|
||||
#include "core/config/project_settings.h"
|
||||
#include "core/extension/native_extension_manager.h"
|
||||
#include "core/object/class_db.h"
|
||||
#include "core/os/os.h"
|
||||
#include "scene/2d/animated_sprite_2d.h"
|
||||
|
@ -1040,9 +1041,13 @@ void register_scene_types() {
|
|||
}
|
||||
}
|
||||
SceneDebugger::initialize();
|
||||
|
||||
NativeExtensionManager::get_singleton()->initialize_extensions(NativeExtension::INITIALIZATION_LEVEL_SCENE);
|
||||
}
|
||||
|
||||
void unregister_scene_types() {
|
||||
NativeExtensionManager::get_singleton()->deinitialize_extensions(NativeExtension::INITIALIZATION_LEVEL_SCENE);
|
||||
|
||||
SceneDebugger::deinitialize();
|
||||
clear_default_theme();
|
||||
|
||||
|
|
|
@ -55,6 +55,7 @@
|
|||
#include "audio_server.h"
|
||||
#include "camera/camera_feed.h"
|
||||
#include "camera_server.h"
|
||||
#include "core/extension/native_extension_manager.h"
|
||||
#include "display_server.h"
|
||||
#include "navigation_server_2d.h"
|
||||
#include "navigation_server_3d.h"
|
||||
|
@ -233,22 +234,26 @@ void register_server_types() {
|
|||
|
||||
PhysicsServer3DManager::register_server("GodotPhysics3D", &_createGodotPhysics3DCallback);
|
||||
PhysicsServer3DManager::set_default_server("GodotPhysics3D");
|
||||
|
||||
NativeExtensionManager::get_singleton()->initialize_extensions(NativeExtension::INITIALIZATION_LEVEL_SERVERS);
|
||||
}
|
||||
|
||||
void unregister_server_types() {
|
||||
NativeExtensionManager::get_singleton()->deinitialize_extensions(NativeExtension::INITIALIZATION_LEVEL_SERVERS);
|
||||
|
||||
memdelete(shader_types);
|
||||
TextServer::finish_hex_code_box_fonts();
|
||||
}
|
||||
|
||||
void register_server_singletons() {
|
||||
Engine::get_singleton()->add_singleton(Engine::Singleton("DisplayServer", DisplayServer::get_singleton()));
|
||||
Engine::get_singleton()->add_singleton(Engine::Singleton("RenderingServer", RenderingServer::get_singleton()));
|
||||
Engine::get_singleton()->add_singleton(Engine::Singleton("AudioServer", AudioServer::get_singleton()));
|
||||
Engine::get_singleton()->add_singleton(Engine::Singleton("PhysicsServer2D", PhysicsServer2D::get_singleton()));
|
||||
Engine::get_singleton()->add_singleton(Engine::Singleton("PhysicsServer3D", PhysicsServer3D::get_singleton()));
|
||||
Engine::get_singleton()->add_singleton(Engine::Singleton("NavigationServer2D", NavigationServer2D::get_singleton_mut()));
|
||||
Engine::get_singleton()->add_singleton(Engine::Singleton("NavigationServer3D", NavigationServer3D::get_singleton_mut()));
|
||||
Engine::get_singleton()->add_singleton(Engine::Singleton("TextServerManager", TextServerManager::get_singleton()));
|
||||
Engine::get_singleton()->add_singleton(Engine::Singleton("XRServer", XRServer::get_singleton()));
|
||||
Engine::get_singleton()->add_singleton(Engine::Singleton("CameraServer", CameraServer::get_singleton()));
|
||||
Engine::get_singleton()->add_singleton(Engine::Singleton("DisplayServer", DisplayServer::get_singleton(), "DisplayServer"));
|
||||
Engine::get_singleton()->add_singleton(Engine::Singleton("RenderingServer", RenderingServer::get_singleton(), "RenderingServer"));
|
||||
Engine::get_singleton()->add_singleton(Engine::Singleton("AudioServer", AudioServer::get_singleton(), "AudioServer"));
|
||||
Engine::get_singleton()->add_singleton(Engine::Singleton("PhysicsServer2D", PhysicsServer2D::get_singleton(), "PhysicsServer2D"));
|
||||
Engine::get_singleton()->add_singleton(Engine::Singleton("PhysicsServer3D", PhysicsServer3D::get_singleton(), "PhysicsServer3D"));
|
||||
Engine::get_singleton()->add_singleton(Engine::Singleton("NavigationServer2D", NavigationServer2D::get_singleton_mut(), "NavigationServer2D"));
|
||||
Engine::get_singleton()->add_singleton(Engine::Singleton("NavigationServer3D", NavigationServer3D::get_singleton_mut(), "NavigationServer3D"));
|
||||
Engine::get_singleton()->add_singleton(Engine::Singleton("TextServerManager", TextServerManager::get_singleton(), "TextServerManager"));
|
||||
Engine::get_singleton()->add_singleton(Engine::Singleton("XRServer", XRServer::get_singleton(), "XRServer"));
|
||||
Engine::get_singleton()->add_singleton(Engine::Singleton("CameraServer", CameraServer::get_singleton(), "CameraServer"));
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue