Merge remote-tracking branch 'godot/master' into cmake-exporting-config
commit
6b02a58e5a
|
@ -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 }}
|
||||||
|
|
|
@ -50,11 +50,6 @@ option(GODOT_CPP_INSTALL "Enables target install for exporting godot-cpp cmake c
|
||||||
# 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>" )
|
||||||
|
@ -102,10 +97,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)
|
||||||
|
@ -137,6 +130,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}
|
||||||
|
@ -162,12 +156,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": [
|
||||||
{
|
{
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
|
|
|
@ -154,10 +154,18 @@ public:
|
||||||
Variant(int64_t v);
|
Variant(int64_t v);
|
||||||
Variant(int32_t v) :
|
Variant(int32_t v) :
|
||||||
Variant(static_cast<int64_t>(v)) {}
|
Variant(static_cast<int64_t>(v)) {}
|
||||||
Variant(uint32_t v) :
|
Variant(int16_t v) :
|
||||||
|
Variant(static_cast<int64_t>(v)) {}
|
||||||
|
Variant(int8_t v) :
|
||||||
Variant(static_cast<int64_t>(v)) {}
|
Variant(static_cast<int64_t>(v)) {}
|
||||||
Variant(uint64_t v) :
|
Variant(uint64_t v) :
|
||||||
Variant(static_cast<int64_t>(v)) {}
|
Variant(static_cast<int64_t>(v)) {}
|
||||||
|
Variant(uint32_t v) :
|
||||||
|
Variant(static_cast<int64_t>(v)) {}
|
||||||
|
Variant(uint16_t v) :
|
||||||
|
Variant(static_cast<int64_t>(v)) {}
|
||||||
|
Variant(uint8_t v) :
|
||||||
|
Variant(static_cast<int64_t>(v)) {}
|
||||||
Variant(double v);
|
Variant(double v);
|
||||||
Variant(float v) :
|
Variant(float v) :
|
||||||
Variant((double)v) {}
|
Variant((double)v) {}
|
||||||
|
@ -209,8 +217,12 @@ public:
|
||||||
operator bool() const;
|
operator bool() const;
|
||||||
operator int64_t() const;
|
operator int64_t() const;
|
||||||
operator int32_t() const;
|
operator int32_t() const;
|
||||||
|
operator int16_t() const;
|
||||||
|
operator int8_t() const;
|
||||||
operator uint64_t() const;
|
operator uint64_t() const;
|
||||||
operator uint32_t() const;
|
operator uint32_t() const;
|
||||||
|
operator uint16_t() const;
|
||||||
|
operator uint8_t() const;
|
||||||
operator double() const;
|
operator double() const;
|
||||||
operator float() const;
|
operator float() const;
|
||||||
operator String() const;
|
operator String() const;
|
||||||
|
@ -344,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) {
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -268,6 +268,14 @@ Variant::operator int32_t() const {
|
||||||
return static_cast<int32_t>(operator int64_t());
|
return static_cast<int32_t>(operator int64_t());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Variant::operator int16_t() const {
|
||||||
|
return static_cast<int16_t>(operator int64_t());
|
||||||
|
}
|
||||||
|
|
||||||
|
Variant::operator int8_t() const {
|
||||||
|
return static_cast<int8_t>(operator int64_t());
|
||||||
|
}
|
||||||
|
|
||||||
Variant::operator uint64_t() const {
|
Variant::operator uint64_t() const {
|
||||||
return static_cast<uint64_t>(operator int64_t());
|
return static_cast<uint64_t>(operator int64_t());
|
||||||
}
|
}
|
||||||
|
@ -276,6 +284,14 @@ Variant::operator uint32_t() const {
|
||||||
return static_cast<uint32_t>(operator int64_t());
|
return static_cast<uint32_t>(operator int64_t());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Variant::operator uint16_t() const {
|
||||||
|
return static_cast<uint16_t>(operator int64_t());
|
||||||
|
}
|
||||||
|
|
||||||
|
Variant::operator uint8_t() const {
|
||||||
|
return static_cast<uint8_t>(operator int64_t());
|
||||||
|
}
|
||||||
|
|
||||||
Variant::operator double() const {
|
Variant::operator double() const {
|
||||||
double result;
|
double result;
|
||||||
to_type_constructor[FLOAT](&result, _native_ptr());
|
to_type_constructor[FLOAT](&result, _native_ptr());
|
||||||
|
|
|
@ -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