Compare commits
38 Commits
156c50be99
...
8e68156620
Author | SHA1 | Date |
---|---|---|
|
8e68156620 | |
|
1c19d627aa | |
|
646c71c277 | |
|
48afa82f29 | |
|
39ca745d0d | |
|
a7becb43e6 | |
|
41517eacb1 | |
|
17137b2e2e | |
|
cad5be53b1 | |
|
54136ee835 | |
|
0f78fc45bd | |
|
11b2700b23 | |
|
20c4e843b0 | |
|
f3143c7a9c | |
|
943d1c8cdf | |
|
588d869a3b | |
|
5be275d73b | |
|
4fed88afcf | |
|
7fb8acaa53 | |
|
2f16eddf15 | |
|
adc9def046 | |
|
32409472b7 | |
|
79d2a9c456 | |
|
d0fdc3adf3 | |
|
78bf5a42ed | |
|
f5e4f95cde | |
|
6fd4e151b8 | |
|
e854e0b592 | |
|
fa10d1a303 | |
|
eea33b4133 | |
|
7cd79e4cc6 | |
|
8d17966e81 | |
|
f426b12b5b | |
|
4439a4a569 | |
|
39c139c814 | |
|
d33bd47219 | |
|
db884e9b1d | |
|
ff8fff1a28 |
|
@ -65,7 +65,7 @@ jobs:
|
||||||
platform: android
|
platform: android
|
||||||
artifact-name: godot-cpp-android-arm64-release
|
artifact-name: godot-cpp-android-arm64-release
|
||||||
artifact-path: bin/libgodot-cpp.android.template_release.arm64.a
|
artifact-path: bin/libgodot-cpp.android.template_release.arm64.a
|
||||||
flags: ANDROID_NDK_ROOT=$ANDROID_NDK_LATEST_HOME arch=arm64
|
flags: arch=arm64
|
||||||
run-tests: false
|
run-tests: false
|
||||||
cache-name: android-arm64
|
cache-name: android-arm64
|
||||||
|
|
||||||
|
@ -88,7 +88,7 @@ jobs:
|
||||||
|
|
||||||
env:
|
env:
|
||||||
SCONS_CACHE: ${{ github.workspace }}/.scons-cache/
|
SCONS_CACHE: ${{ github.workspace }}/.scons-cache/
|
||||||
EM_VERSION: 3.1.45
|
EM_VERSION: 3.1.39
|
||||||
EM_CACHE_FOLDER: "emsdk-cache"
|
EM_CACHE_FOLDER: "emsdk-cache"
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
|
@ -104,33 +104,34 @@ jobs:
|
||||||
continue-on-error: true
|
continue-on-error: true
|
||||||
|
|
||||||
- name: Set up Python (for SCons)
|
- name: Set up Python (for SCons)
|
||||||
uses: actions/setup-python@v4
|
uses: actions/setup-python@v5
|
||||||
with:
|
with:
|
||||||
python-version: '3.x'
|
python-version: '3.x'
|
||||||
|
|
||||||
- name: Linux dependencies
|
- name: Android dependencies
|
||||||
if: ${{ matrix.platform == 'linux' }}
|
if: ${{ matrix.platform == 'android' }}
|
||||||
run: |
|
uses: nttld/setup-ndk@v1
|
||||||
sudo apt-get update -qq
|
with:
|
||||||
sudo apt-get install -qqq build-essential pkg-config
|
ndk-version: r23c
|
||||||
|
link-to-sdk: true
|
||||||
|
|
||||||
- name: Web dependencies
|
- name: Web dependencies
|
||||||
if: ${{ matrix.platform == 'web' }}
|
if: ${{ matrix.platform == 'web' }}
|
||||||
uses: mymindstorm/setup-emsdk@v12
|
uses: mymindstorm/setup-emsdk@v13
|
||||||
with:
|
with:
|
||||||
version: ${{env.EM_VERSION}}
|
version: ${{env.EM_VERSION}}
|
||||||
actions-cache-folder: ${{env.EM_CACHE_FOLDER}}
|
actions-cache-folder: ${{env.EM_CACHE_FOLDER}}
|
||||||
|
|
||||||
- name: Install scons
|
|
||||||
run: |
|
|
||||||
python -m pip install scons==4.0.0
|
|
||||||
|
|
||||||
- name: Setup MinGW for Windows/MinGW build
|
- name: Setup MinGW for Windows/MinGW build
|
||||||
if: ${{ matrix.platform == 'windows' && matrix.flags == 'use_mingw=yes' }}
|
if: ${{ matrix.platform == 'windows' && matrix.flags == 'use_mingw=yes' }}
|
||||||
uses: egor-tensin/setup-mingw@v2
|
uses: egor-tensin/setup-mingw@v2
|
||||||
with:
|
with:
|
||||||
version: 12.2.0
|
version: 12.2.0
|
||||||
|
|
||||||
|
- name: Install scons
|
||||||
|
run: |
|
||||||
|
python -m pip install scons==4.0.0
|
||||||
|
|
||||||
- name: Generate godot-cpp sources only
|
- name: Generate godot-cpp sources only
|
||||||
run: |
|
run: |
|
||||||
scons platform=${{ matrix.platform }} build_library=no ${{ matrix.flags }}
|
scons platform=${{ matrix.platform }} build_library=no ${{ matrix.flags }}
|
||||||
|
|
|
@ -47,11 +47,6 @@ option(GODOT_CPP_WARNING_AS_ERROR "Treat warnings as errors" OFF)
|
||||||
# Add path to modules
|
# Add path to modules
|
||||||
list( APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake/" )
|
list( APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake/" )
|
||||||
|
|
||||||
# Check if we are building ourself or being included
|
|
||||||
if(${PROJECT_NAME} STREQUAL ${CMAKE_PROJECT_NAME})
|
|
||||||
set(GODOT_CPP_BUILDING_SELF ON)
|
|
||||||
endif()
|
|
||||||
|
|
||||||
# Set some helper variables for readability
|
# Set some helper variables for readability
|
||||||
set( compiler_is_clang "$<OR:$<CXX_COMPILER_ID:AppleClang>,$<CXX_COMPILER_ID:Clang>>" )
|
set( compiler_is_clang "$<OR:$<CXX_COMPILER_ID:AppleClang>,$<CXX_COMPILER_ID:Clang>>" )
|
||||||
set( compiler_is_gnu "$<CXX_COMPILER_ID:GNU>" )
|
set( compiler_is_gnu "$<CXX_COMPILER_ID:GNU>" )
|
||||||
|
@ -99,10 +94,8 @@ if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC")
|
||||||
|
|
||||||
add_definitions(-DNOMINMAX)
|
add_definitions(-DNOMINMAX)
|
||||||
else() # GCC/Clang
|
else() # GCC/Clang
|
||||||
set(GODOT_COMPILE_FLAGS "${GODOT_COMPILE_FLAGS} -g")
|
|
||||||
|
|
||||||
if(CMAKE_BUILD_TYPE MATCHES Debug)
|
if(CMAKE_BUILD_TYPE MATCHES Debug)
|
||||||
set(GODOT_COMPILE_FLAGS "${GODOT_COMPILE_FLAGS} -fno-omit-frame-pointer -O0")
|
set(GODOT_COMPILE_FLAGS "${GODOT_COMPILE_FLAGS} -fno-omit-frame-pointer -O0 -g")
|
||||||
else()
|
else()
|
||||||
set(GODOT_COMPILE_FLAGS "${GODOT_COMPILE_FLAGS} -O3")
|
set(GODOT_COMPILE_FLAGS "${GODOT_COMPILE_FLAGS} -O3")
|
||||||
endif(CMAKE_BUILD_TYPE MATCHES Debug)
|
endif(CMAKE_BUILD_TYPE MATCHES Debug)
|
||||||
|
@ -134,6 +127,7 @@ endif()
|
||||||
execute_process(COMMAND "${Python3_EXECUTABLE}" "-c" "import binding_generator; binding_generator.print_file_list(\"${GODOT_GDEXTENSION_API_FILE}\", \"${CMAKE_CURRENT_BINARY_DIR}\", headers=True, sources=True)"
|
execute_process(COMMAND "${Python3_EXECUTABLE}" "-c" "import binding_generator; binding_generator.print_file_list(\"${GODOT_GDEXTENSION_API_FILE}\", \"${CMAKE_CURRENT_BINARY_DIR}\", headers=True, sources=True)"
|
||||||
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
|
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
|
||||||
OUTPUT_VARIABLE GENERATED_FILES_LIST
|
OUTPUT_VARIABLE GENERATED_FILES_LIST
|
||||||
|
OUTPUT_STRIP_TRAILING_WHITESPACE
|
||||||
)
|
)
|
||||||
|
|
||||||
add_custom_command(OUTPUT ${GENERATED_FILES_LIST}
|
add_custom_command(OUTPUT ${GENERATED_FILES_LIST}
|
||||||
|
@ -159,12 +153,6 @@ add_library(godot::cpp ALIAS ${PROJECT_NAME})
|
||||||
|
|
||||||
include(GodotCompilerWarnings)
|
include(GodotCompilerWarnings)
|
||||||
|
|
||||||
# Treat warnings as errors if we are building ourself
|
|
||||||
if(GODOT_CPP_BUILDING_SELF)
|
|
||||||
unset( GODOT_CPP_WARNING_AS_ERROR CACHE )
|
|
||||||
set_warning_as_error()
|
|
||||||
endif()
|
|
||||||
|
|
||||||
target_compile_features(${PROJECT_NAME}
|
target_compile_features(${PROJECT_NAME}
|
||||||
PRIVATE
|
PRIVATE
|
||||||
cxx_std_17
|
cxx_std_17
|
||||||
|
|
|
@ -7,8 +7,9 @@
|
||||||
> from Godot's `master` branch.
|
> from Godot's `master` branch.
|
||||||
>
|
>
|
||||||
> For users of stable branches, switch to the branch matching your target Godot version:
|
> For users of stable branches, switch to the branch matching your target Godot version:
|
||||||
> - [`4.0`](https://github.com/godotengine/godot-cpp/tree/4.0)
|
> - [`4.2`](https://github.com/godotengine/godot-cpp/tree/4.2)
|
||||||
> - [`4.1`](https://github.com/godotengine/godot-cpp/tree/4.1)
|
> - [`4.1`](https://github.com/godotengine/godot-cpp/tree/4.1)
|
||||||
|
> - [`4.0`](https://github.com/godotengine/godot-cpp/tree/4.0)
|
||||||
>
|
>
|
||||||
> Or check out the Git tag matching your Godot version (e.g. `godot-4.1.1-stable`).
|
> Or check out the Git tag matching your Godot version (e.g. `godot-4.1.1-stable`).
|
||||||
>
|
>
|
||||||
|
|
|
@ -110,6 +110,8 @@ def get_file_list(api_filepath, output_dir, headers=False, sources=False):
|
||||||
|
|
||||||
for native_struct in api["native_structures"]:
|
for native_struct in api["native_structures"]:
|
||||||
struct_name = native_struct["name"]
|
struct_name = native_struct["name"]
|
||||||
|
if struct_name == "ObjectID":
|
||||||
|
continue
|
||||||
snake_struct_name = camel_to_snake(struct_name)
|
snake_struct_name = camel_to_snake(struct_name)
|
||||||
|
|
||||||
header_filename = include_gen_folder / "classes" / (snake_struct_name + ".hpp")
|
header_filename = include_gen_folder / "classes" / (snake_struct_name + ".hpp")
|
||||||
|
@ -136,9 +138,7 @@ def get_file_list(api_filepath, output_dir, headers=False, sources=False):
|
||||||
|
|
||||||
|
|
||||||
def print_file_list(api_filepath, output_dir, headers=False, sources=False):
|
def print_file_list(api_filepath, output_dir, headers=False, sources=False):
|
||||||
end = ";"
|
print(*get_file_list(api_filepath, output_dir, headers, sources), sep=";", end=None)
|
||||||
for f in get_file_list(api_filepath, output_dir, headers, sources):
|
|
||||||
print(f, end=end)
|
|
||||||
|
|
||||||
|
|
||||||
def scons_emit_files(target, source, env):
|
def scons_emit_files(target, source, env):
|
||||||
|
@ -416,6 +416,9 @@ def generate_builtin_class_header(builtin_api, size, used_classes, fully_used_cl
|
||||||
if class_name == "Array":
|
if class_name == "Array":
|
||||||
result.append("#include <godot_cpp/variant/array_helpers.hpp>")
|
result.append("#include <godot_cpp/variant/array_helpers.hpp>")
|
||||||
|
|
||||||
|
if class_name == "Callable":
|
||||||
|
result.append("#include <godot_cpp/variant/callable_custom.hpp>")
|
||||||
|
|
||||||
for include in fully_used_classes:
|
for include in fully_used_classes:
|
||||||
if include == "TypedArray":
|
if include == "TypedArray":
|
||||||
result.append("#include <godot_cpp/variant/typed_array.hpp>")
|
result.append("#include <godot_cpp/variant/typed_array.hpp>")
|
||||||
|
@ -525,6 +528,9 @@ def generate_builtin_class_header(builtin_api, size, used_classes, fully_used_cl
|
||||||
result.append(f"\t{class_name}(const wchar_t *from);")
|
result.append(f"\t{class_name}(const wchar_t *from);")
|
||||||
result.append(f"\t{class_name}(const char16_t *from);")
|
result.append(f"\t{class_name}(const char16_t *from);")
|
||||||
result.append(f"\t{class_name}(const char32_t *from);")
|
result.append(f"\t{class_name}(const char32_t *from);")
|
||||||
|
if class_name == "Callable":
|
||||||
|
result.append("\tCallable(CallableCustom *p_custom);")
|
||||||
|
result.append("\tCallableCustom *get_custom() const;")
|
||||||
|
|
||||||
if "constants" in builtin_api:
|
if "constants" in builtin_api:
|
||||||
axis_constants_count = 0
|
axis_constants_count = 0
|
||||||
|
@ -1083,6 +1089,8 @@ def generate_engine_classes_bindings(api, output_dir, use_template_get_node):
|
||||||
class_api["alias_for"] = "ClassDB"
|
class_api["alias_for"] = "ClassDB"
|
||||||
engine_classes[class_api["name"]] = class_api["is_refcounted"]
|
engine_classes[class_api["name"]] = class_api["is_refcounted"]
|
||||||
for native_struct in api["native_structures"]:
|
for native_struct in api["native_structures"]:
|
||||||
|
if native_struct["name"] == "ObjectID":
|
||||||
|
continue
|
||||||
engine_classes[native_struct["name"]] = False
|
engine_classes[native_struct["name"]] = False
|
||||||
native_structures.append(native_struct["name"])
|
native_structures.append(native_struct["name"])
|
||||||
|
|
||||||
|
@ -1210,6 +1218,8 @@ def generate_engine_classes_bindings(api, output_dir, use_template_get_node):
|
||||||
|
|
||||||
for native_struct in api["native_structures"]:
|
for native_struct in api["native_structures"]:
|
||||||
struct_name = native_struct["name"]
|
struct_name = native_struct["name"]
|
||||||
|
if struct_name == "ObjectID":
|
||||||
|
continue
|
||||||
snake_struct_name = camel_to_snake(struct_name)
|
snake_struct_name = camel_to_snake(struct_name)
|
||||||
|
|
||||||
header_filename = include_gen_folder / (snake_struct_name + ".hpp")
|
header_filename = include_gen_folder / (snake_struct_name + ".hpp")
|
||||||
|
@ -1319,7 +1329,11 @@ def generate_engine_class_header(class_api, used_classes, fully_used_classes, us
|
||||||
|
|
||||||
if "enums" in class_api:
|
if "enums" in class_api:
|
||||||
for enum_api in class_api["enums"]:
|
for enum_api in class_api["enums"]:
|
||||||
result.append(f'\tenum {enum_api["name"]} {{')
|
if enum_api["is_bitfield"]:
|
||||||
|
result.append(f'\tenum {enum_api["name"]} : uint64_t {{')
|
||||||
|
else:
|
||||||
|
result.append(f'\tenum {enum_api["name"]} {{')
|
||||||
|
|
||||||
for value in enum_api["values"]:
|
for value in enum_api["values"]:
|
||||||
result.append(f'\t\t{value["name"]} = {value["value"]},')
|
result.append(f'\t\t{value["name"]} = {value["value"]},')
|
||||||
result.append("\t};")
|
result.append("\t};")
|
||||||
|
@ -1676,6 +1690,8 @@ def generate_global_constants(api, output_dir):
|
||||||
header.append(f"#ifndef {header_guard}")
|
header.append(f"#ifndef {header_guard}")
|
||||||
header.append(f"#define {header_guard}")
|
header.append(f"#define {header_guard}")
|
||||||
header.append("")
|
header.append("")
|
||||||
|
header.append("#include <cstdint>")
|
||||||
|
header.append("")
|
||||||
header.append("namespace godot {")
|
header.append("namespace godot {")
|
||||||
header.append("")
|
header.append("")
|
||||||
|
|
||||||
|
@ -1688,7 +1704,11 @@ def generate_global_constants(api, output_dir):
|
||||||
if enum_def["name"].startswith("Variant."):
|
if enum_def["name"].startswith("Variant."):
|
||||||
continue
|
continue
|
||||||
|
|
||||||
header.append(f'\tenum {enum_def["name"]} {{')
|
if enum_def["is_bitfield"]:
|
||||||
|
header.append(f'\tenum {enum_def["name"]} : uint64_t {{')
|
||||||
|
else:
|
||||||
|
header.append(f'\tenum {enum_def["name"]} {{')
|
||||||
|
|
||||||
for value in enum_def["values"]:
|
for value in enum_def["values"]:
|
||||||
header.append(f'\t\t{value["name"]} = {value["value"]},')
|
header.append(f'\t\t{value["name"]} = {value["value"]},')
|
||||||
header.append("\t};")
|
header.append("\t};")
|
||||||
|
|
|
@ -3,9 +3,9 @@
|
||||||
"version_major": 4,
|
"version_major": 4,
|
||||||
"version_minor": 2,
|
"version_minor": 2,
|
||||||
"version_patch": 0,
|
"version_patch": 0,
|
||||||
"version_status": "beta6",
|
"version_status": "stable",
|
||||||
"version_build": "official",
|
"version_build": "official",
|
||||||
"version_full_name": "Godot Engine v4.2.beta6.official"
|
"version_full_name": "Godot Engine v4.2.stable.official"
|
||||||
},
|
},
|
||||||
"builtin_class_sizes": [
|
"builtin_class_sizes": [
|
||||||
{
|
{
|
||||||
|
|
|
@ -133,6 +133,9 @@ public:
|
||||||
template <class M>
|
template <class M>
|
||||||
static MethodBind *bind_vararg_method(uint32_t p_flags, StringName p_name, M p_method, const MethodInfo &p_info = MethodInfo(), const std::vector<Variant> &p_default_args = std::vector<Variant>{}, bool p_return_nil_is_variant = true);
|
static MethodBind *bind_vararg_method(uint32_t p_flags, StringName p_name, M p_method, const MethodInfo &p_info = MethodInfo(), const std::vector<Variant> &p_default_args = std::vector<Variant>{}, bool p_return_nil_is_variant = true);
|
||||||
|
|
||||||
|
template <class M>
|
||||||
|
static MethodBind *bind_static_vararg_method(uint32_t p_flags, StringName p_class, StringName p_name, M p_method, const MethodInfo &p_info = MethodInfo(), const std::vector<Variant> &p_default_args = std::vector<Variant>{}, bool p_return_nil_is_variant = true);
|
||||||
|
|
||||||
static void add_property_group(const StringName &p_class, const String &p_name, const String &p_prefix);
|
static void add_property_group(const StringName &p_class, const String &p_name, const String &p_prefix);
|
||||||
static void add_property_subgroup(const StringName &p_class, const String &p_name, const String &p_prefix);
|
static void add_property_subgroup(const StringName &p_class, const String &p_name, const String &p_prefix);
|
||||||
static void add_property(const StringName &p_class, const PropertyInfo &p_pinfo, const StringName &p_setter, const StringName &p_getter, int p_index = -1);
|
static void add_property(const StringName &p_class, const PropertyInfo &p_pinfo, const StringName &p_setter, const StringName &p_getter, int p_index = -1);
|
||||||
|
@ -291,6 +294,37 @@ MethodBind *ClassDB::bind_vararg_method(uint32_t p_flags, StringName p_name, M p
|
||||||
return bind;
|
return bind;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <class M>
|
||||||
|
MethodBind *ClassDB::bind_static_vararg_method(uint32_t p_flags, StringName p_class, StringName p_name, M p_method, const MethodInfo &p_info, const std::vector<Variant> &p_default_args, bool p_return_nil_is_variant) {
|
||||||
|
MethodBind *bind = create_vararg_method_bind(p_method, p_info, p_return_nil_is_variant);
|
||||||
|
ERR_FAIL_COND_V(!bind, nullptr);
|
||||||
|
|
||||||
|
bind->set_name(p_name);
|
||||||
|
bind->set_default_arguments(p_default_args);
|
||||||
|
bind->set_instance_class(p_class);
|
||||||
|
|
||||||
|
std::unordered_map<StringName, ClassInfo>::iterator type_it = classes.find(p_class);
|
||||||
|
if (type_it == classes.end()) {
|
||||||
|
memdelete(bind);
|
||||||
|
ERR_FAIL_V_MSG(nullptr, String("Class '{0}' doesn't exist.").format(Array::make(p_class)));
|
||||||
|
}
|
||||||
|
|
||||||
|
ClassInfo &type = type_it->second;
|
||||||
|
|
||||||
|
if (type.method_map.find(p_name) != type.method_map.end()) {
|
||||||
|
memdelete(bind);
|
||||||
|
ERR_FAIL_V_MSG(nullptr, String("Binding duplicate method: {0}::{1}.").format(Array::make(p_class, p_method)));
|
||||||
|
}
|
||||||
|
|
||||||
|
// register our method bind within our plugin
|
||||||
|
type.method_map[p_name] = bind;
|
||||||
|
|
||||||
|
// and register with godot
|
||||||
|
bind_method_godot(type.name, bind);
|
||||||
|
|
||||||
|
return bind;
|
||||||
|
}
|
||||||
|
|
||||||
#define GDREGISTER_CLASS(m_class) ClassDB::register_class<m_class>();
|
#define GDREGISTER_CLASS(m_class) ClassDB::register_class<m_class>();
|
||||||
#define GDREGISTER_VIRTUAL_CLASS(m_class) ClassDB::register_class<m_class>(true);
|
#define GDREGISTER_VIRTUAL_CLASS(m_class) ClassDB::register_class<m_class>(true);
|
||||||
#define GDREGISTER_ABSTRACT_CLASS(m_class) ClassDB::register_abstract_class<m_class>();
|
#define GDREGISTER_ABSTRACT_CLASS(m_class) ClassDB::register_abstract_class<m_class>();
|
||||||
|
|
|
@ -267,6 +267,120 @@ MethodBind *create_vararg_method_bind(R (T::*p_method)(const Variant **, GDExten
|
||||||
return a;
|
return a;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <class Derived, class R, bool should_returns>
|
||||||
|
class MethodBindVarArgBaseS : public MethodBind {
|
||||||
|
protected:
|
||||||
|
R(*function)
|
||||||
|
(const Variant **, GDExtensionInt, GDExtensionCallError &);
|
||||||
|
std::vector<PropertyInfo> arguments;
|
||||||
|
|
||||||
|
public:
|
||||||
|
virtual PropertyInfo gen_argument_type_info(int p_arg) const {
|
||||||
|
if (p_arg < 0) {
|
||||||
|
return _gen_return_type_info();
|
||||||
|
} else if ((size_t)(p_arg) < arguments.size()) {
|
||||||
|
return arguments[p_arg];
|
||||||
|
} else {
|
||||||
|
return make_property_info(Variant::Type::NIL, "vararg", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_NIL_IS_VARIANT);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual GDExtensionVariantType gen_argument_type(int p_arg) const {
|
||||||
|
return static_cast<GDExtensionVariantType>(gen_argument_type_info(p_arg).type);
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual GDExtensionClassMethodArgumentMetadata get_argument_metadata(int) const {
|
||||||
|
return GDEXTENSION_METHOD_ARGUMENT_METADATA_NONE;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void ptrcall(GDExtensionClassInstancePtr p_instance, const GDExtensionConstTypePtr *p_args, GDExtensionTypePtr r_return) const {
|
||||||
|
ERR_FAIL(); // Can't call.
|
||||||
|
}
|
||||||
|
|
||||||
|
MethodBindVarArgBaseS(
|
||||||
|
R (*p_function)(const Variant **, GDExtensionInt, GDExtensionCallError &),
|
||||||
|
const MethodInfo &p_method_info,
|
||||||
|
bool p_return_nil_is_variant) :
|
||||||
|
function(p_function) {
|
||||||
|
set_vararg(true);
|
||||||
|
set_argument_count(p_method_info.arguments.size());
|
||||||
|
if (p_method_info.arguments.size()) {
|
||||||
|
arguments = p_method_info.arguments;
|
||||||
|
|
||||||
|
std::vector<StringName> names;
|
||||||
|
names.reserve(p_method_info.arguments.size());
|
||||||
|
for (size_t i = 0; i < p_method_info.arguments.size(); i++) {
|
||||||
|
names.push_back(p_method_info.arguments[i].name);
|
||||||
|
}
|
||||||
|
set_argument_names(names);
|
||||||
|
}
|
||||||
|
generate_argument_types((int)p_method_info.arguments.size());
|
||||||
|
set_return(should_returns);
|
||||||
|
set_static(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
~MethodBindVarArgBaseS() {}
|
||||||
|
|
||||||
|
private:
|
||||||
|
PropertyInfo _gen_return_type_info() const {
|
||||||
|
return reinterpret_cast<const Derived *>(this)->_gen_return_type_info_impl();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
class MethodBindVarArgTS : public MethodBindVarArgBaseS<MethodBindVarArgTS, void, false> {
|
||||||
|
friend class MethodBindVarArgBaseS<MethodBindVarArgTS, void, false>;
|
||||||
|
|
||||||
|
public:
|
||||||
|
virtual Variant call(GDExtensionClassInstancePtr p_instance, const GDExtensionConstVariantPtr *p_args, GDExtensionInt p_argument_count, GDExtensionCallError &r_error) const {
|
||||||
|
(void)p_instance; // unused
|
||||||
|
MethodBindVarArgBaseS<MethodBindVarArgTS, void, false>::function((const Variant **)p_args, p_argument_count, r_error);
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
MethodBindVarArgTS(
|
||||||
|
void (*p_function)(const Variant **, GDExtensionInt, GDExtensionCallError &),
|
||||||
|
const MethodInfo &p_method_info,
|
||||||
|
bool p_return_nil_is_variant) :
|
||||||
|
MethodBindVarArgBaseS<MethodBindVarArgTS, void, false>(p_function, p_method_info, p_return_nil_is_variant) {
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
PropertyInfo _gen_return_type_info_impl() const {
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
MethodBind *create_vararg_method_bind(void (*p_function)(const Variant **, GDExtensionInt, GDExtensionCallError &), const MethodInfo &p_info, bool p_return_nil_is_variant);
|
||||||
|
|
||||||
|
template <class R>
|
||||||
|
class MethodBindVarArgTRS : public MethodBindVarArgBaseS<MethodBindVarArgTRS<R>, R, true> {
|
||||||
|
friend class MethodBindVarArgBaseS<MethodBindVarArgTRS, R, true>;
|
||||||
|
|
||||||
|
public:
|
||||||
|
virtual Variant call(GDExtensionClassInstancePtr p_instance, const GDExtensionConstVariantPtr *p_args, GDExtensionInt p_argument_count, GDExtensionCallError &r_error) const {
|
||||||
|
call_with_variant_args_static_dv(MethodBindVarArgBaseS<MethodBindVarArgTRS<R>, R, true>::function, p_args, p_argument_count, r_error);
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
MethodBindVarArgTRS(
|
||||||
|
void (*p_function)(const Variant **, GDExtensionInt, GDExtensionCallError &),
|
||||||
|
const MethodInfo &p_method_info,
|
||||||
|
bool p_return_nil_is_variant) :
|
||||||
|
MethodBindVarArgBaseS<MethodBindVarArgTRS<R>, R, true>(p_function, p_method_info, p_return_nil_is_variant) {
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
PropertyInfo _gen_return_type_info_impl() const {
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template <class R>
|
||||||
|
MethodBind *create_vararg_method_bind(R (*p_function)(const Variant **, GDExtensionInt, GDExtensionCallError &), const MethodInfo &p_info, bool p_return_nil_is_variant) {
|
||||||
|
MethodBind *a = memnew((MethodBindVarArgTRS<R>)(p_function, p_info, p_return_nil_is_variant));
|
||||||
|
return a;
|
||||||
|
}
|
||||||
|
|
||||||
#ifndef TYPED_METHOD_BIND
|
#ifndef TYPED_METHOD_BIND
|
||||||
class _gde_UnexistingClass;
|
class _gde_UnexistingClass;
|
||||||
#define MB_T _gde_UnexistingClass
|
#define MB_T _gde_UnexistingClass
|
||||||
|
|
|
@ -33,6 +33,8 @@
|
||||||
|
|
||||||
#include <godot_cpp/core/defs.hpp>
|
#include <godot_cpp/core/defs.hpp>
|
||||||
|
|
||||||
|
#include <godot_cpp/core/object_id.hpp>
|
||||||
|
|
||||||
#include <godot_cpp/core/property_info.hpp>
|
#include <godot_cpp/core/property_info.hpp>
|
||||||
|
|
||||||
#include <godot_cpp/variant/variant.hpp>
|
#include <godot_cpp/variant/variant.hpp>
|
||||||
|
@ -106,28 +108,6 @@ MethodInfo::MethodInfo(const PropertyInfo &p_ret, StringName p_name, const Args
|
||||||
arguments = { args... };
|
arguments = { args... };
|
||||||
}
|
}
|
||||||
|
|
||||||
class ObjectID {
|
|
||||||
uint64_t id = 0;
|
|
||||||
|
|
||||||
public:
|
|
||||||
_FORCE_INLINE_ bool is_ref_counted() const { return (id & (uint64_t(1) << 63)) != 0; }
|
|
||||||
_FORCE_INLINE_ bool is_valid() const { return id != 0; }
|
|
||||||
_FORCE_INLINE_ bool is_null() const { return id == 0; }
|
|
||||||
_FORCE_INLINE_ operator uint64_t() const { return id; }
|
|
||||||
_FORCE_INLINE_ operator int64_t() const { return id; }
|
|
||||||
|
|
||||||
_FORCE_INLINE_ bool operator==(const ObjectID &p_id) const { return id == p_id.id; }
|
|
||||||
_FORCE_INLINE_ bool operator!=(const ObjectID &p_id) const { return id != p_id.id; }
|
|
||||||
_FORCE_INLINE_ bool operator<(const ObjectID &p_id) const { return id < p_id.id; }
|
|
||||||
|
|
||||||
_FORCE_INLINE_ void operator=(int64_t p_int64) { id = p_int64; }
|
|
||||||
_FORCE_INLINE_ void operator=(uint64_t p_uint64) { id = p_uint64; }
|
|
||||||
|
|
||||||
_FORCE_INLINE_ ObjectID() {}
|
|
||||||
_FORCE_INLINE_ explicit ObjectID(const uint64_t p_id) { id = p_id; }
|
|
||||||
_FORCE_INLINE_ explicit ObjectID(const int64_t p_id) { id = p_id; }
|
|
||||||
};
|
|
||||||
|
|
||||||
class ObjectDB {
|
class ObjectDB {
|
||||||
public:
|
public:
|
||||||
static Object *get_instance(uint64_t p_object_id) {
|
static Object *get_instance(uint64_t p_object_id) {
|
||||||
|
|
|
@ -0,0 +1,62 @@
|
||||||
|
/**************************************************************************/
|
||||||
|
/* object_id.hpp */
|
||||||
|
/**************************************************************************/
|
||||||
|
/* This file is part of: */
|
||||||
|
/* GODOT ENGINE */
|
||||||
|
/* https://godotengine.org */
|
||||||
|
/**************************************************************************/
|
||||||
|
/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
|
||||||
|
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
|
||||||
|
/* */
|
||||||
|
/* Permission is hereby granted, free of charge, to any person obtaining */
|
||||||
|
/* a copy of this software and associated documentation files (the */
|
||||||
|
/* "Software"), to deal in the Software without restriction, including */
|
||||||
|
/* without limitation the rights to use, copy, modify, merge, publish, */
|
||||||
|
/* distribute, sublicense, and/or sell copies of the Software, and to */
|
||||||
|
/* permit persons to whom the Software is furnished to do so, subject to */
|
||||||
|
/* the following conditions: */
|
||||||
|
/* */
|
||||||
|
/* The above copyright notice and this permission notice shall be */
|
||||||
|
/* included in all copies or substantial portions of the Software. */
|
||||||
|
/* */
|
||||||
|
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
|
||||||
|
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
|
||||||
|
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
|
||||||
|
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
|
||||||
|
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
|
||||||
|
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
||||||
|
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||||
|
/**************************************************************************/
|
||||||
|
|
||||||
|
#ifndef GODOT_OBJECT_ID_HPP
|
||||||
|
#define GODOT_OBJECT_ID_HPP
|
||||||
|
|
||||||
|
#include <godot_cpp/core/defs.hpp>
|
||||||
|
|
||||||
|
namespace godot {
|
||||||
|
|
||||||
|
class ObjectID {
|
||||||
|
uint64_t id = 0;
|
||||||
|
|
||||||
|
public:
|
||||||
|
_FORCE_INLINE_ bool is_ref_counted() const { return (id & (uint64_t(1) << 63)) != 0; }
|
||||||
|
_FORCE_INLINE_ bool is_valid() const { return id != 0; }
|
||||||
|
_FORCE_INLINE_ bool is_null() const { return id == 0; }
|
||||||
|
_FORCE_INLINE_ operator uint64_t() const { return id; }
|
||||||
|
_FORCE_INLINE_ operator int64_t() const { return id; }
|
||||||
|
|
||||||
|
_FORCE_INLINE_ bool operator==(const ObjectID &p_id) const { return id == p_id.id; }
|
||||||
|
_FORCE_INLINE_ bool operator!=(const ObjectID &p_id) const { return id != p_id.id; }
|
||||||
|
_FORCE_INLINE_ bool operator<(const ObjectID &p_id) const { return id < p_id.id; }
|
||||||
|
|
||||||
|
_FORCE_INLINE_ void operator=(int64_t p_int64) { id = p_int64; }
|
||||||
|
_FORCE_INLINE_ void operator=(uint64_t p_uint64) { id = p_uint64; }
|
||||||
|
|
||||||
|
_FORCE_INLINE_ ObjectID() {}
|
||||||
|
_FORCE_INLINE_ explicit ObjectID(const uint64_t p_id) { id = p_id; }
|
||||||
|
_FORCE_INLINE_ explicit ObjectID(const int64_t p_id) { id = p_id; }
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace godot
|
||||||
|
|
||||||
|
#endif // GODOT_OBJECT_ID_HPP
|
|
@ -166,6 +166,7 @@ extern "C" GDExtensionInterfaceObjectCastTo gdextension_interface_object_cast_to
|
||||||
extern "C" GDExtensionInterfaceObjectGetInstanceFromId gdextension_interface_object_get_instance_from_id;
|
extern "C" GDExtensionInterfaceObjectGetInstanceFromId gdextension_interface_object_get_instance_from_id;
|
||||||
extern "C" GDExtensionInterfaceObjectGetInstanceId gdextension_interface_object_get_instance_id;
|
extern "C" GDExtensionInterfaceObjectGetInstanceId gdextension_interface_object_get_instance_id;
|
||||||
extern "C" GDExtensionInterfaceCallableCustomCreate gdextension_interface_callable_custom_create;
|
extern "C" GDExtensionInterfaceCallableCustomCreate gdextension_interface_callable_custom_create;
|
||||||
|
extern "C" GDExtensionInterfaceCallableCustomGetUserData gdextension_interface_callable_custom_get_userdata;
|
||||||
extern "C" GDExtensionInterfaceRefGetObject gdextension_interface_ref_get_object;
|
extern "C" GDExtensionInterfaceRefGetObject gdextension_interface_ref_get_object;
|
||||||
extern "C" GDExtensionInterfaceRefSetObject gdextension_interface_ref_set_object;
|
extern "C" GDExtensionInterfaceRefSetObject gdextension_interface_ref_set_object;
|
||||||
extern "C" GDExtensionInterfaceScriptInstanceCreate2 gdextension_interface_script_instance_create2;
|
extern "C" GDExtensionInterfaceScriptInstanceCreate2 gdextension_interface_script_instance_create2;
|
||||||
|
@ -193,26 +194,44 @@ enum ModuleInitializationLevel {
|
||||||
MODULE_INITIALIZATION_LEVEL_CORE = GDEXTENSION_INITIALIZATION_CORE,
|
MODULE_INITIALIZATION_LEVEL_CORE = GDEXTENSION_INITIALIZATION_CORE,
|
||||||
MODULE_INITIALIZATION_LEVEL_SERVERS = GDEXTENSION_INITIALIZATION_SERVERS,
|
MODULE_INITIALIZATION_LEVEL_SERVERS = GDEXTENSION_INITIALIZATION_SERVERS,
|
||||||
MODULE_INITIALIZATION_LEVEL_SCENE = GDEXTENSION_INITIALIZATION_SCENE,
|
MODULE_INITIALIZATION_LEVEL_SCENE = GDEXTENSION_INITIALIZATION_SCENE,
|
||||||
MODULE_INITIALIZATION_LEVEL_EDITOR = GDEXTENSION_INITIALIZATION_EDITOR
|
MODULE_INITIALIZATION_LEVEL_EDITOR = GDEXTENSION_INITIALIZATION_EDITOR,
|
||||||
|
MODULE_INITIALIZATION_LEVEL_MAX
|
||||||
};
|
};
|
||||||
|
|
||||||
class GDExtensionBinding {
|
class GDExtensionBinding {
|
||||||
public:
|
public:
|
||||||
using Callback = void (*)(ModuleInitializationLevel p_level);
|
using Callback = void (*)(ModuleInitializationLevel p_level);
|
||||||
|
|
||||||
static Callback init_callback;
|
struct InitData {
|
||||||
static Callback terminate_callback;
|
GDExtensionInitializationLevel minimum_initialization_level = GDEXTENSION_INITIALIZATION_CORE;
|
||||||
static GDExtensionInitializationLevel minimum_initialization_level;
|
Callback init_callback = nullptr;
|
||||||
static GDExtensionBool init(GDExtensionInterfaceGetProcAddress p_get_proc_address, GDExtensionClassLibraryPtr p_library, GDExtensionInitialization *r_initialization);
|
Callback terminate_callback = nullptr;
|
||||||
|
};
|
||||||
|
|
||||||
|
class InitDataList {
|
||||||
|
int data_count = 0;
|
||||||
|
int data_capacity = 0;
|
||||||
|
InitData **data = nullptr;
|
||||||
|
|
||||||
|
public:
|
||||||
|
void add(InitData *p_cb);
|
||||||
|
~InitDataList();
|
||||||
|
};
|
||||||
|
|
||||||
|
static bool api_initialized;
|
||||||
|
static int level_initialized[MODULE_INITIALIZATION_LEVEL_MAX];
|
||||||
|
static InitDataList initdata;
|
||||||
|
static GDExtensionBool init(GDExtensionInterfaceGetProcAddress p_get_proc_address, GDExtensionClassLibraryPtr p_library, InitData *p_init_data, GDExtensionInitialization *r_initialization);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
static void initialize_level(void *userdata, GDExtensionInitializationLevel p_level);
|
static void initialize_level(void *p_userdata, GDExtensionInitializationLevel p_level);
|
||||||
static void deinitialize_level(void *userdata, GDExtensionInitializationLevel p_level);
|
static void deinitialize_level(void *p_userdata, GDExtensionInitializationLevel p_level);
|
||||||
|
|
||||||
class InitObject {
|
class InitObject {
|
||||||
GDExtensionInterfaceGetProcAddress get_proc_address;
|
GDExtensionInterfaceGetProcAddress get_proc_address;
|
||||||
GDExtensionClassLibraryPtr library;
|
GDExtensionClassLibraryPtr library;
|
||||||
GDExtensionInitialization *initialization;
|
GDExtensionInitialization *initialization;
|
||||||
|
mutable InitData *init_data = nullptr;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
InitObject(GDExtensionInterfaceGetProcAddress p_get_proc_address, GDExtensionClassLibraryPtr p_library, GDExtensionInitialization *r_initialization);
|
InitObject(GDExtensionInterfaceGetProcAddress p_get_proc_address, GDExtensionClassLibraryPtr p_library, GDExtensionInitialization *r_initialization);
|
||||||
|
|
|
@ -0,0 +1,64 @@
|
||||||
|
/**************************************************************************/
|
||||||
|
/* callable_custom.hpp */
|
||||||
|
/**************************************************************************/
|
||||||
|
/* This file is part of: */
|
||||||
|
/* GODOT ENGINE */
|
||||||
|
/* https://godotengine.org */
|
||||||
|
/**************************************************************************/
|
||||||
|
/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
|
||||||
|
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
|
||||||
|
/* */
|
||||||
|
/* Permission is hereby granted, free of charge, to any person obtaining */
|
||||||
|
/* a copy of this software and associated documentation files (the */
|
||||||
|
/* "Software"), to deal in the Software without restriction, including */
|
||||||
|
/* without limitation the rights to use, copy, modify, merge, publish, */
|
||||||
|
/* distribute, sublicense, and/or sell copies of the Software, and to */
|
||||||
|
/* permit persons to whom the Software is furnished to do so, subject to */
|
||||||
|
/* the following conditions: */
|
||||||
|
/* */
|
||||||
|
/* The above copyright notice and this permission notice shall be */
|
||||||
|
/* included in all copies or substantial portions of the Software. */
|
||||||
|
/* */
|
||||||
|
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
|
||||||
|
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
|
||||||
|
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
|
||||||
|
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
|
||||||
|
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
|
||||||
|
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
||||||
|
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||||
|
/**************************************************************************/
|
||||||
|
|
||||||
|
#ifndef GODOT_CALLABLE_CUSTOM_HPP
|
||||||
|
#define GODOT_CALLABLE_CUSTOM_HPP
|
||||||
|
|
||||||
|
#include <godot_cpp/core/object_id.hpp>
|
||||||
|
#include <godot_cpp/variant/string_name.hpp>
|
||||||
|
|
||||||
|
namespace godot {
|
||||||
|
|
||||||
|
class Object;
|
||||||
|
|
||||||
|
class CallableCustomBase {
|
||||||
|
public:
|
||||||
|
virtual ObjectID get_object() const = 0;
|
||||||
|
virtual void call(const Variant **p_arguments, int p_argcount, Variant &r_return_value, GDExtensionCallError &r_call_error) const = 0;
|
||||||
|
virtual ~CallableCustomBase() {}
|
||||||
|
};
|
||||||
|
|
||||||
|
class CallableCustom : public CallableCustomBase {
|
||||||
|
public:
|
||||||
|
typedef bool (*CompareEqualFunc)(const CallableCustom *p_a, const CallableCustom *p_b);
|
||||||
|
typedef bool (*CompareLessFunc)(const CallableCustom *p_a, const CallableCustom *p_b);
|
||||||
|
|
||||||
|
virtual uint32_t hash() const = 0;
|
||||||
|
virtual String get_as_text() const = 0;
|
||||||
|
virtual CompareEqualFunc get_compare_equal_func() const = 0;
|
||||||
|
virtual CompareLessFunc get_compare_less_func() const = 0;
|
||||||
|
virtual bool is_valid() const;
|
||||||
|
virtual ObjectID get_object() const = 0;
|
||||||
|
virtual void call(const Variant **p_arguments, int p_argcount, Variant &r_return_value, GDExtensionCallError &r_call_error) const = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace godot
|
||||||
|
|
||||||
|
#endif // GODOT_CALLABLE_CUSTOM_HPP
|
|
@ -36,16 +36,23 @@
|
||||||
|
|
||||||
namespace godot {
|
namespace godot {
|
||||||
|
|
||||||
class CallableCustomMethodPointerBase {
|
class CallableCustomMethodPointerBase : public CallableCustomBase {
|
||||||
|
uint32_t *comp_ptr = nullptr;
|
||||||
|
uint32_t comp_size;
|
||||||
|
uint32_t h;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void _setup(uint32_t *p_base_ptr, uint32_t p_ptr_size);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
virtual Object *get_object() const = 0;
|
_FORCE_INLINE_ const uint32_t *get_comp_ptr() const { return comp_ptr; }
|
||||||
virtual void call(const Variant **p_arguments, int p_argcount, Variant &r_return_value, GDExtensionCallError &r_call_error) const = 0;
|
_FORCE_INLINE_ uint32_t get_comp_size() const { return comp_size; }
|
||||||
virtual ~CallableCustomMethodPointerBase() {}
|
_FORCE_INLINE_ uint32_t get_hash() const { return h; }
|
||||||
};
|
};
|
||||||
|
|
||||||
namespace internal {
|
namespace internal {
|
||||||
|
|
||||||
Callable create_custom_callable(CallableCustomMethodPointerBase *p_callable_method_pointer);
|
Callable create_callable_from_ccmp(CallableCustomMethodPointerBase *p_callable_method_pointer);
|
||||||
|
|
||||||
} // namespace internal
|
} // namespace internal
|
||||||
|
|
||||||
|
@ -55,21 +62,26 @@ Callable create_custom_callable(CallableCustomMethodPointerBase *p_callable_meth
|
||||||
|
|
||||||
template <class T, class... P>
|
template <class T, class... P>
|
||||||
class CallableCustomMethodPointer : public CallableCustomMethodPointerBase {
|
class CallableCustomMethodPointer : public CallableCustomMethodPointerBase {
|
||||||
T *instance;
|
struct Data {
|
||||||
void (T::*method)(P...);
|
T *instance;
|
||||||
|
void (T::*method)(P...);
|
||||||
|
} data;
|
||||||
|
static_assert(sizeof(Data) % 4 == 0);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
virtual Object *get_object() const override {
|
virtual ObjectID get_object() const override {
|
||||||
return instance;
|
return ObjectID(data.instance->get_instance_id());
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void call(const Variant **p_arguments, int p_argcount, Variant &r_return_value, GDExtensionCallError &r_call_error) const override {
|
virtual void call(const Variant **p_arguments, int p_argcount, Variant &r_return_value, GDExtensionCallError &r_call_error) const override {
|
||||||
call_with_variant_args(instance, method, p_arguments, p_argcount, r_call_error);
|
call_with_variant_args(data.instance, data.method, p_arguments, p_argcount, r_call_error);
|
||||||
}
|
}
|
||||||
|
|
||||||
CallableCustomMethodPointer(T *p_instance, void (T::*p_method)(P...)) {
|
CallableCustomMethodPointer(T *p_instance, void (T::*p_method)(P...)) {
|
||||||
instance = p_instance;
|
memset(&data, 0, sizeof(Data));
|
||||||
method = p_method;
|
data.instance = p_instance;
|
||||||
|
data.method = p_method;
|
||||||
|
_setup((uint32_t *)&data, sizeof(Data));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -77,7 +89,7 @@ template <class T, class... P>
|
||||||
Callable create_custom_callable_function_pointer(T *p_instance, void (T::*p_method)(P...)) {
|
Callable create_custom_callable_function_pointer(T *p_instance, void (T::*p_method)(P...)) {
|
||||||
typedef CallableCustomMethodPointer<T, P...> CCMP;
|
typedef CallableCustomMethodPointer<T, P...> CCMP;
|
||||||
CCMP *ccmp = memnew(CCMP(p_instance, p_method));
|
CCMP *ccmp = memnew(CCMP(p_instance, p_method));
|
||||||
return ::godot::internal::create_custom_callable(ccmp);
|
return ::godot::internal::create_callable_from_ccmp(ccmp);
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
|
@ -86,22 +98,27 @@ Callable create_custom_callable_function_pointer(T *p_instance, void (T::*p_meth
|
||||||
|
|
||||||
template <class T, class R, class... P>
|
template <class T, class R, class... P>
|
||||||
class CallableCustomMethodPointerRet : public CallableCustomMethodPointerBase {
|
class CallableCustomMethodPointerRet : public CallableCustomMethodPointerBase {
|
||||||
T *instance;
|
struct Data {
|
||||||
R(T::*method)
|
T *instance;
|
||||||
(P...);
|
R(T::*method)
|
||||||
|
(P...);
|
||||||
|
} data;
|
||||||
|
static_assert(sizeof(Data) % 4 == 0);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
virtual Object *get_object() const override {
|
virtual ObjectID get_object() const override {
|
||||||
return instance;
|
return ObjectID(data.instance->get_instance_id());
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void call(const Variant **p_arguments, int p_argcount, Variant &r_return_value, GDExtensionCallError &r_call_error) const override {
|
virtual void call(const Variant **p_arguments, int p_argcount, Variant &r_return_value, GDExtensionCallError &r_call_error) const override {
|
||||||
call_with_variant_args_ret(instance, method, p_arguments, p_argcount, r_return_value, r_call_error);
|
call_with_variant_args_ret(data.instance, data.method, p_arguments, p_argcount, r_return_value, r_call_error);
|
||||||
}
|
}
|
||||||
|
|
||||||
CallableCustomMethodPointerRet(T *p_instance, R (T::*p_method)(P...)) {
|
CallableCustomMethodPointerRet(T *p_instance, R (T::*p_method)(P...)) {
|
||||||
instance = p_instance;
|
memset(&data, 0, sizeof(Data));
|
||||||
method = p_method;
|
data.instance = p_instance;
|
||||||
|
data.method = p_method;
|
||||||
|
_setup((uint32_t *)&data, sizeof(Data));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -109,7 +126,7 @@ template <class T, class R, class... P>
|
||||||
Callable create_custom_callable_function_pointer(T *p_instance, R (T::*p_method)(P...)) {
|
Callable create_custom_callable_function_pointer(T *p_instance, R (T::*p_method)(P...)) {
|
||||||
typedef CallableCustomMethodPointerRet<T, R, P...> CCMP; // Messes with memnew otherwise.
|
typedef CallableCustomMethodPointerRet<T, R, P...> CCMP; // Messes with memnew otherwise.
|
||||||
CCMP *ccmp = memnew(CCMP(p_instance, p_method));
|
CCMP *ccmp = memnew(CCMP(p_instance, p_method));
|
||||||
return ::godot::internal::create_custom_callable(ccmp);
|
return ::godot::internal::create_callable_from_ccmp(ccmp);
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
|
@ -118,22 +135,27 @@ Callable create_custom_callable_function_pointer(T *p_instance, R (T::*p_method)
|
||||||
|
|
||||||
template <class T, class R, class... P>
|
template <class T, class R, class... P>
|
||||||
class CallableCustomMethodPointerRetC : public CallableCustomMethodPointerBase {
|
class CallableCustomMethodPointerRetC : public CallableCustomMethodPointerBase {
|
||||||
T *instance;
|
struct Data {
|
||||||
R(T::*method)
|
T *instance;
|
||||||
(P...) const;
|
R(T::*method)
|
||||||
|
(P...) const;
|
||||||
|
} data;
|
||||||
|
static_assert(sizeof(Data) % 4 == 0);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
virtual Object *get_object() const override {
|
virtual ObjectID get_object() const override {
|
||||||
return instance;
|
return ObjectID(data.instance->get_instance_id());
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void call(const Variant **p_arguments, int p_argcount, Variant &r_return_value, GDExtensionCallError &r_call_error) const override {
|
virtual void call(const Variant **p_arguments, int p_argcount, Variant &r_return_value, GDExtensionCallError &r_call_error) const override {
|
||||||
call_with_variant_args_retc(instance, method, p_arguments, p_argcount, r_return_value, r_call_error);
|
call_with_variant_args_retc(data.instance, data.method, p_arguments, p_argcount, r_return_value, r_call_error);
|
||||||
}
|
}
|
||||||
|
|
||||||
CallableCustomMethodPointerRetC(const T *p_instance, R (T::*p_method)(P...) const) {
|
CallableCustomMethodPointerRetC(const T *p_instance, R (T::*p_method)(P...) const) {
|
||||||
instance = const_cast<T *>(p_instance);
|
memset(&data, 0, sizeof(Data));
|
||||||
method = p_method;
|
data.instance = const_cast<T *>(p_instance);
|
||||||
|
data.method = p_method;
|
||||||
|
_setup((uint32_t *)&data, sizeof(Data));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -141,7 +163,7 @@ template <class T, class R, class... P>
|
||||||
Callable create_custom_callable_function_pointer(const T *p_instance, R (T::*p_method)(P...) const) {
|
Callable create_custom_callable_function_pointer(const T *p_instance, R (T::*p_method)(P...) const) {
|
||||||
typedef CallableCustomMethodPointerRetC<T, R, P...> CCMP; // Messes with memnew otherwise.
|
typedef CallableCustomMethodPointerRetC<T, R, P...> CCMP; // Messes with memnew otherwise.
|
||||||
CCMP *ccmp = memnew(CCMP(p_instance, p_method));
|
CCMP *ccmp = memnew(CCMP(p_instance, p_method));
|
||||||
return ::godot::internal::create_custom_callable(ccmp);
|
return ::godot::internal::create_callable_from_ccmp(ccmp);
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
|
@ -150,20 +172,25 @@ Callable create_custom_callable_function_pointer(const T *p_instance, R (T::*p_m
|
||||||
|
|
||||||
template <class... P>
|
template <class... P>
|
||||||
class CallableCustomStaticMethodPointer : public CallableCustomMethodPointerBase {
|
class CallableCustomStaticMethodPointer : public CallableCustomMethodPointerBase {
|
||||||
void (*method)(P...);
|
struct Data {
|
||||||
|
void (*method)(P...);
|
||||||
|
} data;
|
||||||
|
static_assert(sizeof(Data) % 4 == 0);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
virtual Object *get_object() const override {
|
virtual ObjectID get_object() const override {
|
||||||
return nullptr;
|
return ObjectID();
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void call(const Variant **p_arguments, int p_argcount, Variant &r_return_value, GDExtensionCallError &r_call_error) const override {
|
virtual void call(const Variant **p_arguments, int p_argcount, Variant &r_return_value, GDExtensionCallError &r_call_error) const override {
|
||||||
call_with_variant_args_static_ret(method, p_arguments, p_argcount, r_return_value, r_call_error);
|
call_with_variant_args_static_ret(data.method, p_arguments, p_argcount, r_return_value, r_call_error);
|
||||||
r_return_value = Variant();
|
r_return_value = Variant();
|
||||||
}
|
}
|
||||||
|
|
||||||
CallableCustomStaticMethodPointer(void (*p_method)(P...)) {
|
CallableCustomStaticMethodPointer(void (*p_method)(P...)) {
|
||||||
method = p_method;
|
memset(&data, 0, sizeof(Data));
|
||||||
|
data.method = p_method;
|
||||||
|
_setup((uint32_t *)&data, sizeof(Data));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -171,7 +198,7 @@ template <class... P>
|
||||||
Callable create_custom_callable_static_function_pointer(void (*p_method)(P...)) {
|
Callable create_custom_callable_static_function_pointer(void (*p_method)(P...)) {
|
||||||
typedef CallableCustomStaticMethodPointer<P...> CCMP;
|
typedef CallableCustomStaticMethodPointer<P...> CCMP;
|
||||||
CCMP *ccmp = memnew(CCMP(p_method));
|
CCMP *ccmp = memnew(CCMP(p_method));
|
||||||
return ::godot::internal::create_custom_callable(ccmp);
|
return ::godot::internal::create_callable_from_ccmp(ccmp);
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
|
@ -180,20 +207,25 @@ Callable create_custom_callable_static_function_pointer(void (*p_method)(P...))
|
||||||
|
|
||||||
template <class R, class... P>
|
template <class R, class... P>
|
||||||
class CallableCustomStaticMethodPointerRet : public CallableCustomMethodPointerBase {
|
class CallableCustomStaticMethodPointerRet : public CallableCustomMethodPointerBase {
|
||||||
R(*method)
|
struct Data {
|
||||||
(P...);
|
R(*method)
|
||||||
|
(P...);
|
||||||
|
} data;
|
||||||
|
static_assert(sizeof(Data) % 4 == 0);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
virtual Object *get_object() const override {
|
virtual ObjectID get_object() const override {
|
||||||
return nullptr;
|
return ObjectID();
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void call(const Variant **p_arguments, int p_argcount, Variant &r_return_value, GDExtensionCallError &r_call_error) const override {
|
virtual void call(const Variant **p_arguments, int p_argcount, Variant &r_return_value, GDExtensionCallError &r_call_error) const override {
|
||||||
call_with_variant_args_static_ret(method, p_arguments, p_argcount, r_return_value, r_call_error);
|
call_with_variant_args_static_ret(data.method, p_arguments, p_argcount, r_return_value, r_call_error);
|
||||||
}
|
}
|
||||||
|
|
||||||
CallableCustomStaticMethodPointerRet(R (*p_method)(P...)) {
|
CallableCustomStaticMethodPointerRet(R (*p_method)(P...)) {
|
||||||
method = p_method;
|
memset(&data, 0, sizeof(Data));
|
||||||
|
data.method = p_method;
|
||||||
|
_setup((uint32_t *)&data, sizeof(Data));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -201,7 +233,7 @@ template <class R, class... P>
|
||||||
Callable create_custom_callable_static_function_pointer(R (*p_method)(P...)) {
|
Callable create_custom_callable_static_function_pointer(R (*p_method)(P...)) {
|
||||||
typedef CallableCustomStaticMethodPointerRet<R, P...> CCMP;
|
typedef CallableCustomStaticMethodPointerRet<R, P...> CCMP;
|
||||||
CCMP *ccmp = memnew(CCMP(p_method));
|
CCMP *ccmp = memnew(CCMP(p_method));
|
||||||
return ::godot::internal::create_custom_callable(ccmp);
|
return ::godot::internal::create_callable_from_ccmp(ccmp);
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
|
|
|
@ -356,6 +356,12 @@ String vformat(const String &p_text, const VarArgs... p_args) {
|
||||||
|
|
||||||
#include <godot_cpp/variant/builtin_vararg_methods.hpp>
|
#include <godot_cpp/variant/builtin_vararg_methods.hpp>
|
||||||
|
|
||||||
|
#ifdef REAL_T_IS_DOUBLE
|
||||||
|
using PackedRealArray = PackedFloat64Array;
|
||||||
|
#else
|
||||||
|
using PackedRealArray = PackedFloat32Array;
|
||||||
|
#endif // REAL_T_IS_DOUBLE
|
||||||
|
|
||||||
} // namespace godot
|
} // namespace godot
|
||||||
|
|
||||||
#endif // GODOT_VARIANT_HPP
|
#endif // GODOT_VARIANT_HPP
|
||||||
|
|
|
@ -50,6 +50,12 @@ void Wrapped::_postinitialize() {
|
||||||
godot::internal::gdextension_interface_object_set_instance(_owner, reinterpret_cast<GDExtensionConstStringNamePtr>(extension_class), this);
|
godot::internal::gdextension_interface_object_set_instance(_owner, reinterpret_cast<GDExtensionConstStringNamePtr>(extension_class), this);
|
||||||
}
|
}
|
||||||
godot::internal::gdextension_interface_object_set_instance_binding(_owner, godot::internal::token, this, _get_bindings_callbacks());
|
godot::internal::gdextension_interface_object_set_instance_binding(_owner, godot::internal::token, this, _get_bindings_callbacks());
|
||||||
|
if (extension_class) {
|
||||||
|
Object *obj = dynamic_cast<Object *>(this);
|
||||||
|
if (obj) {
|
||||||
|
obj->notification(Object::NOTIFICATION_POSTINITIALIZE);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Wrapped::Wrapped(const StringName p_godot_class) {
|
Wrapped::Wrapped(const StringName p_godot_class) {
|
||||||
|
|
|
@ -110,4 +110,9 @@ MethodBind::~MethodBind() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
MethodBind *create_vararg_method_bind(void (*p_function)(const Variant **, GDExtensionInt, GDExtensionCallError &), const MethodInfo &p_info, bool p_return_nil_is_variant) {
|
||||||
|
MethodBind *a = memnew((MethodBindVarArgTS)(p_function, p_info, p_return_nil_is_variant));
|
||||||
|
return a;
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace godot
|
} // namespace godot
|
||||||
|
|
|
@ -172,6 +172,7 @@ GDExtensionInterfaceObjectCastTo gdextension_interface_object_cast_to = nullptr;
|
||||||
GDExtensionInterfaceObjectGetInstanceFromId gdextension_interface_object_get_instance_from_id = nullptr;
|
GDExtensionInterfaceObjectGetInstanceFromId gdextension_interface_object_get_instance_from_id = nullptr;
|
||||||
GDExtensionInterfaceObjectGetInstanceId gdextension_interface_object_get_instance_id = nullptr;
|
GDExtensionInterfaceObjectGetInstanceId gdextension_interface_object_get_instance_id = nullptr;
|
||||||
GDExtensionInterfaceCallableCustomCreate gdextension_interface_callable_custom_create = nullptr;
|
GDExtensionInterfaceCallableCustomCreate gdextension_interface_callable_custom_create = nullptr;
|
||||||
|
GDExtensionInterfaceCallableCustomGetUserData gdextension_interface_callable_custom_get_userdata = nullptr;
|
||||||
GDExtensionInterfaceRefGetObject gdextension_interface_ref_get_object = nullptr;
|
GDExtensionInterfaceRefGetObject gdextension_interface_ref_get_object = nullptr;
|
||||||
GDExtensionInterfaceRefSetObject gdextension_interface_ref_set_object = nullptr;
|
GDExtensionInterfaceRefSetObject gdextension_interface_ref_set_object = nullptr;
|
||||||
GDExtensionInterfaceScriptInstanceCreate2 gdextension_interface_script_instance_create2 = nullptr;
|
GDExtensionInterfaceScriptInstanceCreate2 gdextension_interface_script_instance_create2 = nullptr;
|
||||||
|
@ -195,9 +196,9 @@ GDExtensionInterfaceEditorRemovePlugin gdextension_interface_editor_remove_plugi
|
||||||
|
|
||||||
} // namespace internal
|
} // namespace internal
|
||||||
|
|
||||||
GDExtensionBinding::Callback GDExtensionBinding::init_callback = nullptr;
|
bool GDExtensionBinding::api_initialized = false;
|
||||||
GDExtensionBinding::Callback GDExtensionBinding::terminate_callback = nullptr;
|
int GDExtensionBinding::level_initialized[MODULE_INITIALIZATION_LEVEL_MAX] = { 0 };
|
||||||
GDExtensionInitializationLevel GDExtensionBinding::minimum_initialization_level = GDEXTENSION_INITIALIZATION_CORE;
|
GDExtensionBinding::InitDataList GDExtensionBinding::initdata;
|
||||||
|
|
||||||
#define ERR_PRINT_EARLY(m_msg) \
|
#define ERR_PRINT_EARLY(m_msg) \
|
||||||
internal::gdextension_interface_print_error(m_msg, FUNCTION_STR, __FILE__, __LINE__, false)
|
internal::gdextension_interface_print_error(m_msg, FUNCTION_STR, __FILE__, __LINE__, false)
|
||||||
|
@ -224,7 +225,20 @@ typedef struct {
|
||||||
GDExtensionInterfacePrintErrorWithMessage print_error_with_message;
|
GDExtensionInterfacePrintErrorWithMessage print_error_with_message;
|
||||||
} LegacyGDExtensionInterface;
|
} LegacyGDExtensionInterface;
|
||||||
|
|
||||||
GDExtensionBool GDExtensionBinding::init(GDExtensionInterfaceGetProcAddress p_get_proc_address, GDExtensionClassLibraryPtr p_library, GDExtensionInitialization *r_initialization) {
|
GDExtensionBool GDExtensionBinding::init(GDExtensionInterfaceGetProcAddress p_get_proc_address, GDExtensionClassLibraryPtr p_library, InitData *p_init_data, GDExtensionInitialization *r_initialization) {
|
||||||
|
if (!p_init_data || !p_init_data->init_callback) {
|
||||||
|
ERR_FAIL_V_MSG(false, "Initialization callback must be defined.");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (api_initialized) {
|
||||||
|
r_initialization->initialize = initialize_level;
|
||||||
|
r_initialization->deinitialize = deinitialize_level;
|
||||||
|
r_initialization->userdata = p_init_data;
|
||||||
|
r_initialization->minimum_initialization_level = p_init_data->minimum_initialization_level;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
// Make sure we weren't passed the legacy struct.
|
// Make sure we weren't passed the legacy struct.
|
||||||
uint32_t *raw_interface = (uint32_t *)(void *)p_get_proc_address;
|
uint32_t *raw_interface = (uint32_t *)(void *)p_get_proc_address;
|
||||||
if (raw_interface[0] == 4 && raw_interface[1] == 0) {
|
if (raw_interface[0] == 4 && raw_interface[1] == 0) {
|
||||||
|
@ -257,7 +271,12 @@ GDExtensionBool GDExtensionBinding::init(GDExtensionInterfaceGetProcAddress p_ge
|
||||||
} else if (internal::godot_version.minor != GODOT_VERSION_MINOR) {
|
} else if (internal::godot_version.minor != GODOT_VERSION_MINOR) {
|
||||||
compatible = internal::godot_version.minor > GODOT_VERSION_MINOR;
|
compatible = internal::godot_version.minor > GODOT_VERSION_MINOR;
|
||||||
} else {
|
} else {
|
||||||
|
#if GODOT_VERSION_PATCH > 0
|
||||||
compatible = internal::godot_version.patch >= GODOT_VERSION_PATCH;
|
compatible = internal::godot_version.patch >= GODOT_VERSION_PATCH;
|
||||||
|
#else
|
||||||
|
// Prevent -Wtype-limits warning due to unsigned comparison.
|
||||||
|
compatible = true;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
if (!compatible) {
|
if (!compatible) {
|
||||||
// We need to use snprintf() here because vformat() uses Variant, and we haven't loaded
|
// We need to use snprintf() here because vformat() uses Variant, and we haven't loaded
|
||||||
|
@ -390,6 +409,7 @@ GDExtensionBool GDExtensionBinding::init(GDExtensionInterfaceGetProcAddress p_ge
|
||||||
LOAD_PROC_ADDRESS(object_get_instance_from_id, GDExtensionInterfaceObjectGetInstanceFromId);
|
LOAD_PROC_ADDRESS(object_get_instance_from_id, GDExtensionInterfaceObjectGetInstanceFromId);
|
||||||
LOAD_PROC_ADDRESS(object_get_instance_id, GDExtensionInterfaceObjectGetInstanceId);
|
LOAD_PROC_ADDRESS(object_get_instance_id, GDExtensionInterfaceObjectGetInstanceId);
|
||||||
LOAD_PROC_ADDRESS(callable_custom_create, GDExtensionInterfaceCallableCustomCreate);
|
LOAD_PROC_ADDRESS(callable_custom_create, GDExtensionInterfaceCallableCustomCreate);
|
||||||
|
LOAD_PROC_ADDRESS(callable_custom_get_userdata, GDExtensionInterfaceCallableCustomGetUserData);
|
||||||
LOAD_PROC_ADDRESS(ref_get_object, GDExtensionInterfaceRefGetObject);
|
LOAD_PROC_ADDRESS(ref_get_object, GDExtensionInterfaceRefGetObject);
|
||||||
LOAD_PROC_ADDRESS(ref_set_object, GDExtensionInterfaceRefSetObject);
|
LOAD_PROC_ADDRESS(ref_set_object, GDExtensionInterfaceRefSetObject);
|
||||||
LOAD_PROC_ADDRESS(script_instance_create2, GDExtensionInterfaceScriptInstanceCreate2);
|
LOAD_PROC_ADDRESS(script_instance_create2, GDExtensionInterfaceScriptInstanceCreate2);
|
||||||
|
@ -413,59 +433,96 @@ GDExtensionBool GDExtensionBinding::init(GDExtensionInterfaceGetProcAddress p_ge
|
||||||
|
|
||||||
r_initialization->initialize = initialize_level;
|
r_initialization->initialize = initialize_level;
|
||||||
r_initialization->deinitialize = deinitialize_level;
|
r_initialization->deinitialize = deinitialize_level;
|
||||||
r_initialization->minimum_initialization_level = minimum_initialization_level;
|
r_initialization->userdata = p_init_data;
|
||||||
|
r_initialization->minimum_initialization_level = p_init_data->minimum_initialization_level;
|
||||||
ERR_FAIL_NULL_V_MSG(init_callback, false, "Initialization callback must be defined.");
|
|
||||||
|
|
||||||
Variant::init_bindings();
|
Variant::init_bindings();
|
||||||
godot::internal::register_engine_classes();
|
godot::internal::register_engine_classes();
|
||||||
|
|
||||||
|
api_initialized = true;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
#undef LOAD_PROC_ADDRESS
|
#undef LOAD_PROC_ADDRESS
|
||||||
#undef ERR_PRINT_EARLY
|
#undef ERR_PRINT_EARLY
|
||||||
|
|
||||||
void GDExtensionBinding::initialize_level(void *userdata, GDExtensionInitializationLevel p_level) {
|
void GDExtensionBinding::initialize_level(void *p_userdata, GDExtensionInitializationLevel p_level) {
|
||||||
|
ERR_FAIL_COND(static_cast<ModuleInitializationLevel>(p_level) >= MODULE_INITIALIZATION_LEVEL_MAX);
|
||||||
ClassDB::current_level = p_level;
|
ClassDB::current_level = p_level;
|
||||||
|
|
||||||
if (init_callback) {
|
InitData *init_data = static_cast<InitData *>(p_userdata);
|
||||||
init_callback(static_cast<ModuleInitializationLevel>(p_level));
|
if (init_data && init_data->init_callback) {
|
||||||
|
init_data->init_callback(static_cast<ModuleInitializationLevel>(p_level));
|
||||||
}
|
}
|
||||||
|
|
||||||
ClassDB::initialize(p_level);
|
if (level_initialized[p_level] == 0) {
|
||||||
|
ClassDB::initialize(p_level);
|
||||||
|
}
|
||||||
|
level_initialized[p_level]++;
|
||||||
}
|
}
|
||||||
|
|
||||||
void GDExtensionBinding::deinitialize_level(void *userdata, GDExtensionInitializationLevel p_level) {
|
void GDExtensionBinding::deinitialize_level(void *p_userdata, GDExtensionInitializationLevel p_level) {
|
||||||
|
ERR_FAIL_COND(static_cast<ModuleInitializationLevel>(p_level) >= MODULE_INITIALIZATION_LEVEL_MAX);
|
||||||
ClassDB::current_level = p_level;
|
ClassDB::current_level = p_level;
|
||||||
|
|
||||||
if (terminate_callback) {
|
InitData *init_data = static_cast<InitData *>(p_userdata);
|
||||||
terminate_callback(static_cast<ModuleInitializationLevel>(p_level));
|
if (init_data && init_data->terminate_callback) {
|
||||||
|
init_data->terminate_callback(static_cast<ModuleInitializationLevel>(p_level));
|
||||||
}
|
}
|
||||||
|
|
||||||
EditorPlugins::deinitialize(p_level);
|
level_initialized[p_level]--;
|
||||||
ClassDB::deinitialize(p_level);
|
if (level_initialized[p_level] == 0) {
|
||||||
|
EditorPlugins::deinitialize(p_level);
|
||||||
|
ClassDB::deinitialize(p_level);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void GDExtensionBinding::InitDataList::add(InitData *p_data) {
|
||||||
|
if (data_count == data_capacity) {
|
||||||
|
void *new_ptr = realloc(data, sizeof(InitData *) * (data_capacity + 32));
|
||||||
|
if (new_ptr) {
|
||||||
|
data = (InitData **)(new_ptr);
|
||||||
|
data_capacity += 32;
|
||||||
|
} else {
|
||||||
|
ERR_FAIL_MSG("Unable to allocate memory for extension callbacks.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
data[data_count++] = p_data;
|
||||||
|
}
|
||||||
|
|
||||||
|
GDExtensionBinding::InitDataList::~InitDataList() {
|
||||||
|
for (int i = 0; i < data_count; i++) {
|
||||||
|
if (data[i]) {
|
||||||
|
delete data[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (data) {
|
||||||
|
free(data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
GDExtensionBinding::InitObject::InitObject(GDExtensionInterfaceGetProcAddress p_get_proc_address, GDExtensionClassLibraryPtr p_library, GDExtensionInitialization *r_initialization) {
|
GDExtensionBinding::InitObject::InitObject(GDExtensionInterfaceGetProcAddress p_get_proc_address, GDExtensionClassLibraryPtr p_library, GDExtensionInitialization *r_initialization) {
|
||||||
get_proc_address = p_get_proc_address;
|
get_proc_address = p_get_proc_address;
|
||||||
library = p_library;
|
library = p_library;
|
||||||
initialization = r_initialization;
|
initialization = r_initialization;
|
||||||
|
init_data = new InitData();
|
||||||
|
GDExtensionBinding::initdata.add(init_data);
|
||||||
}
|
}
|
||||||
|
|
||||||
void GDExtensionBinding::InitObject::register_initializer(Callback p_init) const {
|
void GDExtensionBinding::InitObject::register_initializer(Callback p_init) const {
|
||||||
GDExtensionBinding::init_callback = p_init;
|
init_data->init_callback = p_init;
|
||||||
}
|
}
|
||||||
|
|
||||||
void GDExtensionBinding::InitObject::register_terminator(Callback p_terminate) const {
|
void GDExtensionBinding::InitObject::register_terminator(Callback p_terminate) const {
|
||||||
GDExtensionBinding::terminate_callback = p_terminate;
|
init_data->terminate_callback = p_terminate;
|
||||||
}
|
}
|
||||||
|
|
||||||
void GDExtensionBinding::InitObject::set_minimum_library_initialization_level(ModuleInitializationLevel p_level) const {
|
void GDExtensionBinding::InitObject::set_minimum_library_initialization_level(ModuleInitializationLevel p_level) const {
|
||||||
GDExtensionBinding::minimum_initialization_level = static_cast<GDExtensionInitializationLevel>(p_level);
|
init_data->minimum_initialization_level = static_cast<GDExtensionInitializationLevel>(p_level);
|
||||||
}
|
}
|
||||||
|
|
||||||
GDExtensionBool GDExtensionBinding::InitObject::init() const {
|
GDExtensionBool GDExtensionBinding::InitObject::init() const {
|
||||||
return GDExtensionBinding::init(get_proc_address, library, initialization);
|
return GDExtensionBinding::init(get_proc_address, library, init_data, initialization);
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace godot
|
} // namespace godot
|
||||||
|
|
|
@ -0,0 +1,113 @@
|
||||||
|
/**************************************************************************/
|
||||||
|
/* callable_custom.cpp */
|
||||||
|
/**************************************************************************/
|
||||||
|
/* This file is part of: */
|
||||||
|
/* GODOT ENGINE */
|
||||||
|
/* https://godotengine.org */
|
||||||
|
/**************************************************************************/
|
||||||
|
/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
|
||||||
|
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
|
||||||
|
/* */
|
||||||
|
/* Permission is hereby granted, free of charge, to any person obtaining */
|
||||||
|
/* a copy of this software and associated documentation files (the */
|
||||||
|
/* "Software"), to deal in the Software without restriction, including */
|
||||||
|
/* without limitation the rights to use, copy, modify, merge, publish, */
|
||||||
|
/* distribute, sublicense, and/or sell copies of the Software, and to */
|
||||||
|
/* permit persons to whom the Software is furnished to do so, subject to */
|
||||||
|
/* the following conditions: */
|
||||||
|
/* */
|
||||||
|
/* The above copyright notice and this permission notice shall be */
|
||||||
|
/* included in all copies or substantial portions of the Software. */
|
||||||
|
/* */
|
||||||
|
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
|
||||||
|
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
|
||||||
|
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
|
||||||
|
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
|
||||||
|
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
|
||||||
|
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
||||||
|
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||||
|
/**************************************************************************/
|
||||||
|
|
||||||
|
#include <godot_cpp/variant/callable_custom.hpp>
|
||||||
|
|
||||||
|
#include <godot_cpp/core/object.hpp>
|
||||||
|
#include <godot_cpp/variant/callable.hpp>
|
||||||
|
|
||||||
|
namespace godot {
|
||||||
|
|
||||||
|
static void callable_custom_call(void *p_userdata, const GDExtensionConstVariantPtr *p_args, GDExtensionInt p_argument_count, GDExtensionVariantPtr r_return, GDExtensionCallError *r_error) {
|
||||||
|
CallableCustom *callable_custom = (CallableCustom *)p_userdata;
|
||||||
|
callable_custom->call((const Variant **)p_args, p_argument_count, *(Variant *)r_return, *r_error);
|
||||||
|
}
|
||||||
|
|
||||||
|
static GDExtensionBool callable_custom_is_valid(void *p_userdata) {
|
||||||
|
CallableCustom *callable_custom = (CallableCustom *)p_userdata;
|
||||||
|
return callable_custom->is_valid();
|
||||||
|
}
|
||||||
|
|
||||||
|
static void callable_custom_free(void *p_userdata) {
|
||||||
|
CallableCustom *callable_custom = (CallableCustom *)p_userdata;
|
||||||
|
memdelete(callable_custom);
|
||||||
|
}
|
||||||
|
|
||||||
|
static uint32_t callable_custom_hash(void *p_userdata) {
|
||||||
|
CallableCustom *callable_custom = (CallableCustom *)p_userdata;
|
||||||
|
return callable_custom->hash();
|
||||||
|
}
|
||||||
|
|
||||||
|
static void callable_custom_to_string(void *p_userdata, GDExtensionBool *r_is_valid, GDExtensionStringPtr r_out) {
|
||||||
|
CallableCustom *callable_custom = (CallableCustom *)p_userdata;
|
||||||
|
*((String *)r_out) = callable_custom->get_as_text();
|
||||||
|
*r_is_valid = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static GDExtensionBool callable_custom_equal_func(void *p_a, void *p_b) {
|
||||||
|
CallableCustom *a = (CallableCustom *)p_a;
|
||||||
|
CallableCustom *b = (CallableCustom *)p_b;
|
||||||
|
CallableCustom::CompareEqualFunc func_a = a->get_compare_equal_func();
|
||||||
|
CallableCustom::CompareEqualFunc func_b = b->get_compare_equal_func();
|
||||||
|
if (func_a != func_b) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return func_a(a, b);
|
||||||
|
}
|
||||||
|
|
||||||
|
static GDExtensionBool callable_custom_less_than_func(void *p_a, void *p_b) {
|
||||||
|
CallableCustom *a = (CallableCustom *)p_a;
|
||||||
|
CallableCustom *b = (CallableCustom *)p_b;
|
||||||
|
CallableCustom::CompareEqualFunc func_a = a->get_compare_less_func();
|
||||||
|
CallableCustom::CompareEqualFunc func_b = b->get_compare_less_func();
|
||||||
|
if (func_a != func_b) {
|
||||||
|
// Just compare the addresses.
|
||||||
|
return p_a < p_b;
|
||||||
|
}
|
||||||
|
return func_a(a, b);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CallableCustom::is_valid() const {
|
||||||
|
// The same default implementation as in Godot.
|
||||||
|
return ObjectDB::get_instance(get_object());
|
||||||
|
}
|
||||||
|
|
||||||
|
Callable::Callable(CallableCustom *p_callable_custom) {
|
||||||
|
GDExtensionCallableCustomInfo info = {};
|
||||||
|
info.callable_userdata = p_callable_custom;
|
||||||
|
info.token = internal::token;
|
||||||
|
info.object_id = p_callable_custom->get_object();
|
||||||
|
info.call_func = &callable_custom_call;
|
||||||
|
info.is_valid_func = &callable_custom_is_valid;
|
||||||
|
info.free_func = &callable_custom_free;
|
||||||
|
info.hash_func = &callable_custom_hash;
|
||||||
|
info.equal_func = &callable_custom_equal_func;
|
||||||
|
info.less_than_func = &callable_custom_less_than_func;
|
||||||
|
info.to_string_func = &callable_custom_to_string;
|
||||||
|
|
||||||
|
::godot::internal::gdextension_interface_callable_custom_create(_native_ptr(), &info);
|
||||||
|
}
|
||||||
|
|
||||||
|
CallableCustom *Callable::get_custom() const {
|
||||||
|
CallableCustomBase *callable_custom = (CallableCustomBase *)::godot::internal::gdextension_interface_callable_custom_get_userdata(_native_ptr(), internal::token);
|
||||||
|
return dynamic_cast<CallableCustom *>(callable_custom);
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace godot
|
|
@ -30,31 +30,79 @@
|
||||||
|
|
||||||
#include <godot_cpp/variant/callable_method_pointer.hpp>
|
#include <godot_cpp/variant/callable_method_pointer.hpp>
|
||||||
|
|
||||||
//#include <godot_cpp/godot.hpp>
|
#include <godot_cpp/templates/hashfuncs.hpp>
|
||||||
|
|
||||||
namespace godot {
|
namespace godot {
|
||||||
|
|
||||||
static void call_custom_callable(void *userdata, const GDExtensionConstVariantPtr *p_args, GDExtensionInt p_argument_count, GDExtensionVariantPtr r_return, GDExtensionCallError *r_error) {
|
static void custom_callable_mp_call(void *p_userdata, const GDExtensionConstVariantPtr *p_args, GDExtensionInt p_argument_count, GDExtensionVariantPtr r_return, GDExtensionCallError *r_error) {
|
||||||
CallableCustomMethodPointerBase *callable_method_pointer = (CallableCustomMethodPointerBase *)userdata;
|
CallableCustomMethodPointerBase *callable_method_pointer = (CallableCustomMethodPointerBase *)p_userdata;
|
||||||
callable_method_pointer->call((const Variant **)p_args, p_argument_count, *(Variant *)r_return, *r_error);
|
callable_method_pointer->call((const Variant **)p_args, p_argument_count, *(Variant *)r_return, *r_error);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void free_custom_callable(void *userdata) {
|
static GDExtensionBool custom_callable_mp_is_valid(void *p_userdata) {
|
||||||
CallableCustomMethodPointerBase *callable_method_pointer = (CallableCustomMethodPointerBase *)userdata;
|
CallableCustomMethodPointerBase *callable_method_pointer = (CallableCustomMethodPointerBase *)p_userdata;
|
||||||
|
ObjectID object = callable_method_pointer->get_object();
|
||||||
|
return object == ObjectID() || ObjectDB::get_instance(object);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void custom_callable_mp_free(void *p_userdata) {
|
||||||
|
CallableCustomMethodPointerBase *callable_method_pointer = (CallableCustomMethodPointerBase *)p_userdata;
|
||||||
memdelete(callable_method_pointer);
|
memdelete(callable_method_pointer);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static uint32_t custom_callable_mp_hash(void *p_userdata) {
|
||||||
|
CallableCustomMethodPointerBase *callable_method_pointer = (CallableCustomMethodPointerBase *)p_userdata;
|
||||||
|
return callable_method_pointer->get_hash();
|
||||||
|
}
|
||||||
|
|
||||||
|
static GDExtensionBool custom_callable_mp_equal_func(void *p_a, void *p_b) {
|
||||||
|
CallableCustomMethodPointerBase *a = (CallableCustomMethodPointerBase *)p_a;
|
||||||
|
CallableCustomMethodPointerBase *b = (CallableCustomMethodPointerBase *)p_b;
|
||||||
|
|
||||||
|
if (a->get_comp_size() != b->get_comp_size()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return memcmp(a->get_comp_ptr(), b->get_comp_ptr(), a->get_comp_size() * 4) == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static GDExtensionBool custom_callable_mp_less_than_func(void *p_a, void *p_b) {
|
||||||
|
CallableCustomMethodPointerBase *a = (CallableCustomMethodPointerBase *)p_a;
|
||||||
|
CallableCustomMethodPointerBase *b = (CallableCustomMethodPointerBase *)p_b;
|
||||||
|
|
||||||
|
if (a->get_comp_size() != b->get_comp_size()) {
|
||||||
|
return a->get_comp_size() < b->get_comp_size();
|
||||||
|
}
|
||||||
|
|
||||||
|
return memcmp(a->get_comp_ptr(), b->get_comp_ptr(), a->get_comp_size() * 4) < 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CallableCustomMethodPointerBase::_setup(uint32_t *p_base_ptr, uint32_t p_ptr_size) {
|
||||||
|
comp_ptr = p_base_ptr;
|
||||||
|
comp_size = p_ptr_size / 4;
|
||||||
|
|
||||||
|
for (uint32_t i = 0; i < comp_size; i++) {
|
||||||
|
if (i == 0) {
|
||||||
|
h = hash_murmur3_one_32(comp_ptr[i]);
|
||||||
|
} else {
|
||||||
|
h = hash_murmur3_one_32(comp_ptr[i], h);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
namespace internal {
|
namespace internal {
|
||||||
|
|
||||||
Callable create_custom_callable(CallableCustomMethodPointerBase *p_callable_method_pointer) {
|
Callable create_callable_from_ccmp(CallableCustomMethodPointerBase *p_callable_method_pointer) {
|
||||||
Object *object = p_callable_method_pointer->get_object();
|
|
||||||
|
|
||||||
GDExtensionCallableCustomInfo info = {};
|
GDExtensionCallableCustomInfo info = {};
|
||||||
info.callable_userdata = p_callable_method_pointer;
|
info.callable_userdata = p_callable_method_pointer;
|
||||||
info.token = internal::token;
|
info.token = internal::token;
|
||||||
info.object_id = object ? object->get_instance_id() : 0;
|
info.object_id = p_callable_method_pointer->get_object();
|
||||||
info.call_func = &call_custom_callable;
|
info.call_func = &custom_callable_mp_call;
|
||||||
info.free_func = &free_custom_callable;
|
info.is_valid_func = &custom_callable_mp_is_valid;
|
||||||
|
info.free_func = &custom_callable_mp_free;
|
||||||
|
info.hash_func = &custom_callable_mp_hash;
|
||||||
|
info.equal_func = &custom_callable_mp_equal_func;
|
||||||
|
info.less_than_func = &custom_callable_mp_less_than_func;
|
||||||
|
|
||||||
Callable callable;
|
Callable callable;
|
||||||
::godot::internal::gdextension_interface_callable_custom_create(callable._native_ptr(), &info);
|
::godot::internal::gdextension_interface_callable_custom_create(callable._native_ptr(), &info);
|
||||||
|
|
|
@ -59,31 +59,9 @@ if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC")
|
||||||
|
|
||||||
else()
|
else()
|
||||||
|
|
||||||
#elseif ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang")
|
|
||||||
# using Clang
|
|
||||||
#elseif ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU")
|
|
||||||
# using GCC and maybe MinGW?
|
|
||||||
|
|
||||||
set(GODOT_LINKER_FLAGS "-static-libgcc -static-libstdc++ -Wl,-R,'$$ORIGIN'")
|
set(GODOT_LINKER_FLAGS "-static-libgcc -static-libstdc++ -Wl,-R,'$$ORIGIN'")
|
||||||
|
|
||||||
# Hmm.. maybe to strikt?
|
|
||||||
set(GODOT_COMPILE_FLAGS "-fPIC -g -Wwrite-strings")
|
set(GODOT_COMPILE_FLAGS "-fPIC -g -Wwrite-strings")
|
||||||
set(GODOT_COMPILE_FLAGS "${GODOT_COMPILE_FLAGS} -Wchar-subscripts -Wcomment -Wdisabled-optimization")
|
|
||||||
set(GODOT_COMPILE_FLAGS "${GODOT_COMPILE_FLAGS} -Wformat -Wformat=2 -Wformat-security -Wformat-y2k")
|
|
||||||
set(GODOT_COMPILE_FLAGS "${GODOT_COMPILE_FLAGS} -Wimport -Winit-self -Winline -Winvalid-pch -Werror")
|
|
||||||
set(GODOT_COMPILE_FLAGS "${GODOT_COMPILE_FLAGS} -Wmissing-braces -Wmissing-format-attribute")
|
|
||||||
set(GODOT_COMPILE_FLAGS "${GODOT_COMPILE_FLAGS} -Wmissing-include-dirs -Wmissing-noreturn -Wpacked -Wpointer-arith")
|
|
||||||
set(GODOT_COMPILE_FLAGS "${GODOT_COMPILE_FLAGS} -Wredundant-decls -Wreturn-type -Wsequence-point")
|
|
||||||
set(GODOT_COMPILE_FLAGS "${GODOT_COMPILE_FLAGS} -Wswitch -Wswitch-enum -Wtrigraphs")
|
|
||||||
set(GODOT_COMPILE_FLAGS "${GODOT_COMPILE_FLAGS} -Wuninitialized -Wunknown-pragmas -Wunreachable-code -Wunused-label")
|
|
||||||
set(GODOT_COMPILE_FLAGS "${GODOT_COMPILE_FLAGS} -Wunused-value -Wvariadic-macros -Wvolatile-register-var -Wno-error=attributes")
|
|
||||||
|
|
||||||
# -Wshadow -Wextra -Wall -Weffc++ -Wfloat-equal -Wstack-protector -Wunused-parameter -Wsign-compare -Wunused-variable -Wcast-align
|
|
||||||
# -Wunused-function -Wstrict-aliasing -Wstrict-aliasing=2 -Wmissing-field-initializers
|
|
||||||
|
|
||||||
if(NOT CMAKE_SYSTEM_NAME STREQUAL "Android")
|
|
||||||
set(GODOT_COMPILE_FLAGS "${GODOT_COMPILE_FLAGS} -Wno-ignored-attributes")
|
|
||||||
endif()
|
|
||||||
|
|
||||||
if(CMAKE_BUILD_TYPE MATCHES Debug)
|
if(CMAKE_BUILD_TYPE MATCHES Debug)
|
||||||
set(GODOT_COMPILE_FLAGS "${GODOT_COMPILE_FLAGS} -fno-omit-frame-pointer -O0")
|
set(GODOT_COMPILE_FLAGS "${GODOT_COMPILE_FLAGS} -fno-omit-frame-pointer -O0")
|
||||||
|
|
|
@ -101,9 +101,20 @@ func _ready():
|
||||||
|
|
||||||
# mp_callable() with void method.
|
# mp_callable() with void method.
|
||||||
var mp_callable: Callable = example.test_callable_mp()
|
var mp_callable: Callable = example.test_callable_mp()
|
||||||
|
assert_equal(mp_callable.is_valid(), true)
|
||||||
mp_callable.call(example, "void", 36)
|
mp_callable.call(example, "void", 36)
|
||||||
assert_equal(custom_signal_emitted, ["unbound_method1: Example - void", 36])
|
assert_equal(custom_signal_emitted, ["unbound_method1: Example - void", 36])
|
||||||
|
|
||||||
|
# Check that it works with is_connected().
|
||||||
|
assert_equal(example.renamed.is_connected(mp_callable), false)
|
||||||
|
example.renamed.connect(mp_callable)
|
||||||
|
assert_equal(example.renamed.is_connected(mp_callable), true)
|
||||||
|
# Make sure a new object is still treated as equivalent.
|
||||||
|
assert_equal(example.renamed.is_connected(example.test_callable_mp()), true)
|
||||||
|
assert_equal(mp_callable.hash(), example.test_callable_mp().hash())
|
||||||
|
example.renamed.disconnect(mp_callable)
|
||||||
|
assert_equal(example.renamed.is_connected(mp_callable), false)
|
||||||
|
|
||||||
# mp_callable() with return value.
|
# mp_callable() with return value.
|
||||||
var mp_callable_ret: Callable = example.test_callable_mp_ret()
|
var mp_callable_ret: Callable = example.test_callable_mp_ret()
|
||||||
assert_equal(mp_callable_ret.call(example, "test", 77), "unbound_method2: Example - test - 77")
|
assert_equal(mp_callable_ret.call(example, "test", 77), "unbound_method2: Example - test - 77")
|
||||||
|
@ -117,10 +128,30 @@ func _ready():
|
||||||
mp_callable_static.call(example, "static", 83)
|
mp_callable_static.call(example, "static", 83)
|
||||||
assert_equal(custom_signal_emitted, ["unbound_static_method1: Example - static", 83])
|
assert_equal(custom_signal_emitted, ["unbound_static_method1: Example - static", 83])
|
||||||
|
|
||||||
|
# Check that it works with is_connected().
|
||||||
|
assert_equal(example.renamed.is_connected(mp_callable_static), false)
|
||||||
|
example.renamed.connect(mp_callable_static)
|
||||||
|
assert_equal(example.renamed.is_connected(mp_callable_static), true)
|
||||||
|
# Make sure a new object is still treated as equivalent.
|
||||||
|
assert_equal(example.renamed.is_connected(example.test_callable_mp_static()), true)
|
||||||
|
assert_equal(mp_callable_static.hash(), example.test_callable_mp_static().hash())
|
||||||
|
example.renamed.disconnect(mp_callable_static)
|
||||||
|
assert_equal(example.renamed.is_connected(mp_callable_static), false)
|
||||||
|
|
||||||
# mp_callable_static() with return value.
|
# mp_callable_static() with return value.
|
||||||
var mp_callable_static_ret: Callable = example.test_callable_mp_static_ret()
|
var mp_callable_static_ret: Callable = example.test_callable_mp_static_ret()
|
||||||
assert_equal(mp_callable_static_ret.call(example, "static-ret", 84), "unbound_static_method2: Example - static-ret - 84")
|
assert_equal(mp_callable_static_ret.call(example, "static-ret", 84), "unbound_static_method2: Example - static-ret - 84")
|
||||||
|
|
||||||
|
# CallableCustom.
|
||||||
|
var custom_callable: Callable = example.test_custom_callable();
|
||||||
|
assert_equal(custom_callable.is_custom(), true);
|
||||||
|
assert_equal(custom_callable.is_valid(), true);
|
||||||
|
assert_equal(custom_callable.call(), "Hi")
|
||||||
|
assert_equal(custom_callable.hash(), 27);
|
||||||
|
assert_equal(custom_callable.get_object(), null);
|
||||||
|
assert_equal(custom_callable.get_method(), "");
|
||||||
|
assert_equal(str(custom_callable), "<MyCallableCustom>");
|
||||||
|
|
||||||
# PackedArray iterators
|
# PackedArray iterators
|
||||||
assert_equal(example.test_vector_ops(), 105)
|
assert_equal(example.test_vector_ops(), 105)
|
||||||
|
|
||||||
|
@ -205,6 +236,11 @@ func _ready():
|
||||||
get_viewport().push_input(event)
|
get_viewport().push_input(event)
|
||||||
assert_equal(custom_signal_emitted, ["_input: H", 72])
|
assert_equal(custom_signal_emitted, ["_input: H", 72])
|
||||||
|
|
||||||
|
# Check NOTIFICATION_POST_INITIALIZED, both when created from GDScript and godot-cpp.
|
||||||
|
var new_example_ref = ExampleRef.new()
|
||||||
|
assert_equal(new_example_ref.was_post_initialized(), true)
|
||||||
|
assert_equal(example.test_post_initialize(), true)
|
||||||
|
|
||||||
exit_with_status()
|
exit_with_status()
|
||||||
|
|
||||||
func _on_Example_custom_signal(signal_name, value):
|
func _on_Example_custom_signal(signal_name, value):
|
||||||
|
|
|
@ -15,6 +15,46 @@
|
||||||
|
|
||||||
using namespace godot;
|
using namespace godot;
|
||||||
|
|
||||||
|
class MyCallableCustom : public CallableCustom {
|
||||||
|
public:
|
||||||
|
virtual uint32_t hash() const {
|
||||||
|
return 27;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual String get_as_text() const {
|
||||||
|
return "<MyCallableCustom>";
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool compare_equal_func(const CallableCustom *p_a, const CallableCustom *p_b) {
|
||||||
|
return p_a == p_b;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual CompareEqualFunc get_compare_equal_func() const {
|
||||||
|
return &MyCallableCustom::compare_equal_func;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool compare_less_func(const CallableCustom *p_a, const CallableCustom *p_b) {
|
||||||
|
return (void *)p_a < (void *)p_b;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual CompareLessFunc get_compare_less_func() const {
|
||||||
|
return &MyCallableCustom::compare_less_func;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool is_valid() const {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual ObjectID get_object() const {
|
||||||
|
return ObjectID();
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void call(const Variant **p_arguments, int p_argcount, Variant &r_return_value, GDExtensionCallError &r_call_error) const {
|
||||||
|
r_return_value = "Hi";
|
||||||
|
r_call_error.error = GDEXTENSION_CALL_OK;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
void ExampleRef::set_id(int p_id) {
|
void ExampleRef::set_id(int p_id) {
|
||||||
id = p_id;
|
id = p_id;
|
||||||
}
|
}
|
||||||
|
@ -23,10 +63,18 @@ int ExampleRef::get_id() const {
|
||||||
return id;
|
return id;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ExampleRef::_notification(int p_what) {
|
||||||
|
if (p_what == NOTIFICATION_POSTINITIALIZE) {
|
||||||
|
post_initialized = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void ExampleRef::_bind_methods() {
|
void ExampleRef::_bind_methods() {
|
||||||
ClassDB::bind_method(D_METHOD("set_id", "id"), &ExampleRef::set_id);
|
ClassDB::bind_method(D_METHOD("set_id", "id"), &ExampleRef::set_id);
|
||||||
ClassDB::bind_method(D_METHOD("get_id"), &ExampleRef::get_id);
|
ClassDB::bind_method(D_METHOD("get_id"), &ExampleRef::get_id);
|
||||||
|
|
||||||
|
ClassDB::bind_method(D_METHOD("was_post_initialized"), &ExampleRef::was_post_initialized);
|
||||||
|
|
||||||
ADD_PROPERTY(PropertyInfo(Variant::INT, "id"), "set_id", "get_id");
|
ADD_PROPERTY(PropertyInfo(Variant::INT, "id"), "set_id", "get_id");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -168,6 +216,7 @@ void Example::_bind_methods() {
|
||||||
ClassDB::bind_method(D_METHOD("test_callable_mp_retc"), &Example::test_callable_mp_retc);
|
ClassDB::bind_method(D_METHOD("test_callable_mp_retc"), &Example::test_callable_mp_retc);
|
||||||
ClassDB::bind_method(D_METHOD("test_callable_mp_static"), &Example::test_callable_mp_static);
|
ClassDB::bind_method(D_METHOD("test_callable_mp_static"), &Example::test_callable_mp_static);
|
||||||
ClassDB::bind_method(D_METHOD("test_callable_mp_static_ret"), &Example::test_callable_mp_static_ret);
|
ClassDB::bind_method(D_METHOD("test_callable_mp_static_ret"), &Example::test_callable_mp_static_ret);
|
||||||
|
ClassDB::bind_method(D_METHOD("test_custom_callable"), &Example::test_custom_callable);
|
||||||
|
|
||||||
ClassDB::bind_method(D_METHOD("test_bitfield", "flags"), &Example::test_bitfield);
|
ClassDB::bind_method(D_METHOD("test_bitfield", "flags"), &Example::test_bitfield);
|
||||||
|
|
||||||
|
@ -179,6 +228,7 @@ void Example::_bind_methods() {
|
||||||
|
|
||||||
ClassDB::bind_method(D_METHOD("def_args", "a", "b"), &Example::def_args, DEFVAL(100), DEFVAL(200));
|
ClassDB::bind_method(D_METHOD("def_args", "a", "b"), &Example::def_args, DEFVAL(100), DEFVAL(200));
|
||||||
ClassDB::bind_method(D_METHOD("callable_bind"), &Example::callable_bind);
|
ClassDB::bind_method(D_METHOD("callable_bind"), &Example::callable_bind);
|
||||||
|
ClassDB::bind_method(D_METHOD("test_post_initialize"), &Example::test_post_initialize);
|
||||||
|
|
||||||
ClassDB::bind_static_method("Example", D_METHOD("test_static", "a", "b"), &Example::test_static);
|
ClassDB::bind_static_method("Example", D_METHOD("test_static", "a", "b"), &Example::test_static);
|
||||||
ClassDB::bind_static_method("Example", D_METHOD("test_static2"), &Example::test_static2);
|
ClassDB::bind_static_method("Example", D_METHOD("test_static2"), &Example::test_static2);
|
||||||
|
@ -378,6 +428,10 @@ Callable Example::test_callable_mp_static_ret() const {
|
||||||
return callable_mp_static(&Example::unbound_static_method2);
|
return callable_mp_static(&Example::unbound_static_method2);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Callable Example::test_custom_callable() const {
|
||||||
|
return Callable(memnew(MyCallableCustom));
|
||||||
|
}
|
||||||
|
|
||||||
void Example::unbound_method1(Object *p_object, String p_string, int p_int) {
|
void Example::unbound_method1(Object *p_object, String p_string, int p_int) {
|
||||||
String test = "unbound_method1: ";
|
String test = "unbound_method1: ";
|
||||||
test += p_object->get_class();
|
test += p_object->get_class();
|
||||||
|
@ -552,6 +606,12 @@ Vector4 Example::get_v4() const {
|
||||||
return Vector4(1.2, 3.4, 5.6, 7.8);
|
return Vector4(1.2, 3.4, 5.6, 7.8);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool Example::test_post_initialize() const {
|
||||||
|
Ref<ExampleRef> new_example_ref;
|
||||||
|
new_example_ref.instantiate();
|
||||||
|
return new_example_ref->was_post_initialized();
|
||||||
|
}
|
||||||
|
|
||||||
// Virtual function override.
|
// Virtual function override.
|
||||||
bool Example::_has_point(const Vector2 &point) const {
|
bool Example::_has_point(const Vector2 &point) const {
|
||||||
Label *label = get_node<Label>("Label");
|
Label *label = get_node<Label>("Label");
|
||||||
|
|
|
@ -35,16 +35,21 @@ private:
|
||||||
static int last_id;
|
static int last_id;
|
||||||
|
|
||||||
int id;
|
int id;
|
||||||
|
bool post_initialized = false;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
static void _bind_methods();
|
static void _bind_methods();
|
||||||
|
|
||||||
|
void _notification(int p_what);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
ExampleRef();
|
ExampleRef();
|
||||||
~ExampleRef();
|
~ExampleRef();
|
||||||
|
|
||||||
void set_id(int p_id);
|
void set_id(int p_id);
|
||||||
int get_id() const;
|
int get_id() const;
|
||||||
|
|
||||||
|
bool was_post_initialized() const { return post_initialized; }
|
||||||
};
|
};
|
||||||
|
|
||||||
class ExampleMin : public Control {
|
class ExampleMin : public Control {
|
||||||
|
@ -143,6 +148,7 @@ public:
|
||||||
Callable test_callable_mp_retc() const;
|
Callable test_callable_mp_retc() const;
|
||||||
Callable test_callable_mp_static() const;
|
Callable test_callable_mp_static() const;
|
||||||
Callable test_callable_mp_static_ret() const;
|
Callable test_callable_mp_static_ret() const;
|
||||||
|
Callable test_custom_callable() const;
|
||||||
|
|
||||||
void unbound_method1(Object *p_object, String p_string, int p_int);
|
void unbound_method1(Object *p_object, String p_string, int p_int);
|
||||||
String unbound_method2(Object *p_object, String p_string, int p_int);
|
String unbound_method2(Object *p_object, String p_string, int p_int);
|
||||||
|
@ -166,6 +172,8 @@ public:
|
||||||
Vector2 get_custom_position() const;
|
Vector2 get_custom_position() const;
|
||||||
Vector4 get_v4() const;
|
Vector4 get_v4() const;
|
||||||
|
|
||||||
|
bool test_post_initialize() const;
|
||||||
|
|
||||||
// Static method.
|
// Static method.
|
||||||
static int test_static(int p_a, int p_b);
|
static int test_static(int p_a, int p_b);
|
||||||
static void test_static2();
|
static void test_static2();
|
||||||
|
|
|
@ -8,7 +8,7 @@ def options(opts):
|
||||||
opts.Add(
|
opts.Add(
|
||||||
"android_api_level",
|
"android_api_level",
|
||||||
"Target Android API level",
|
"Target Android API level",
|
||||||
"18" if "32" in ARGUMENTS.get("arch", "arm64") else "21",
|
"21",
|
||||||
)
|
)
|
||||||
opts.Add(
|
opts.Add(
|
||||||
"ANDROID_HOME",
|
"ANDROID_HOME",
|
||||||
|
@ -47,11 +47,9 @@ def generate(env):
|
||||||
my_spawn.configure(env)
|
my_spawn.configure(env)
|
||||||
|
|
||||||
# Validate API level
|
# Validate API level
|
||||||
api_level = int(env["android_api_level"])
|
if int(env["android_api_level"]) < 21:
|
||||||
if "64" in env["arch"] and api_level < 21:
|
print("WARNING: minimum supported Android target api is 21. Forcing target api 21.")
|
||||||
print("WARN: 64-bit Android architectures require an API level of at least 21; setting android_api_level=21")
|
|
||||||
env["android_api_level"] = "21"
|
env["android_api_level"] = "21"
|
||||||
api_level = 21
|
|
||||||
|
|
||||||
# Setup toolchain
|
# Setup toolchain
|
||||||
toolchain = get_android_ndk_root(env) + "/toolchains/llvm/prebuilt/"
|
toolchain = get_android_ndk_root(env) + "/toolchains/llvm/prebuilt/"
|
||||||
|
|
|
@ -189,6 +189,15 @@ def options(opts, env):
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
opts.Add(
|
||||||
|
EnumVariable(
|
||||||
|
key="symbols_visibility",
|
||||||
|
help="Symbols visibility on GNU platforms. Use 'auto' to apply the default value.",
|
||||||
|
default=env.get("symbols_visibility", "hidden"),
|
||||||
|
allowed_values=["auto", "visible", "hidden"],
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
# Add platform options
|
# Add platform options
|
||||||
for pl in platforms:
|
for pl in platforms:
|
||||||
tool = Tool(pl, toolpath=["tools"])
|
tool = Tool(pl, toolpath=["tools"])
|
||||||
|
@ -269,6 +278,14 @@ def generate(env):
|
||||||
elif env.get("is_msvc", False):
|
elif env.get("is_msvc", False):
|
||||||
env.Append(CXXFLAGS=["/EHsc"])
|
env.Append(CXXFLAGS=["/EHsc"])
|
||||||
|
|
||||||
|
if not env.get("is_msvc", False):
|
||||||
|
if env["symbols_visibility"] == "visible":
|
||||||
|
env.Append(CCFLAGS=["-fvisibility=default"])
|
||||||
|
env.Append(LINKFLAGS=["-fvisibility=default"])
|
||||||
|
elif env["symbols_visibility"] == "hidden":
|
||||||
|
env.Append(CCFLAGS=["-fvisibility=hidden"])
|
||||||
|
env.Append(LINKFLAGS=["-fvisibility=hidden"])
|
||||||
|
|
||||||
# Require C++17
|
# Require C++17
|
||||||
if env.get("is_msvc", False):
|
if env.get("is_msvc", False):
|
||||||
env.Append(CXXFLAGS=["/std:c++17"])
|
env.Append(CXXFLAGS=["/std:c++17"])
|
||||||
|
|
|
@ -21,7 +21,7 @@ def has_ios_osxcross():
|
||||||
|
|
||||||
def options(opts):
|
def options(opts):
|
||||||
opts.Add(BoolVariable("ios_simulator", "Target iOS Simulator", False))
|
opts.Add(BoolVariable("ios_simulator", "Target iOS Simulator", False))
|
||||||
opts.Add("ios_min_version", "Target minimum iphoneos/iphonesimulator version", "10.0")
|
opts.Add("ios_min_version", "Target minimum iphoneos/iphonesimulator version", "12.0")
|
||||||
opts.Add(
|
opts.Add(
|
||||||
"IOS_TOOLCHAIN_PATH",
|
"IOS_TOOLCHAIN_PATH",
|
||||||
"Path to iOS toolchain",
|
"Path to iOS toolchain",
|
||||||
|
|
Loading…
Reference in New Issue