Compare commits
83 Commits
60247076e0
...
f0a1128ee4
Author | SHA1 | Date |
---|---|---|
|
f0a1128ee4 | |
|
2e0fb69144 | |
|
3f44e9b404 | |
|
1c19d627aa | |
|
646c71c277 | |
|
e17c7bf530 | |
|
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 | |
|
c4b7b08c91 | |
|
9d528c30ee | |
|
3d22ab88a3 | |
|
5deb29b283 | |
|
c51c5425ba | |
|
306774b5a4 | |
|
39c139c814 | |
|
73757e3a9f | |
|
adb0cfc59c | |
|
29b34d92bb | |
|
cc89bd2132 | |
|
4af46132c2 | |
|
bcac96c8c2 | |
|
d239312e7b | |
|
59392bc1fa | |
|
92dd34ae96 | |
|
648b8c4489 | |
|
d33bd47219 | |
|
2dfe7929de | |
|
93260e1700 | |
|
e4eee8b12d | |
|
86dbd5fa0d | |
|
6eb5d450bd | |
|
db884e9b1d | |
|
c1196a1ab0 | |
|
4b76485a4e | |
|
f79bd795d5 | |
|
1ab94699c5 | |
|
c82f2a3714 | |
|
edb52293d9 | |
|
379ce2b5e5 | |
|
a61cdc8860 | |
|
bf1c03ab5f | |
|
421c61e730 | |
|
d733663e8b | |
|
0a6a19e33b | |
|
5182624141 | |
|
7a260f5e93 | |
|
2d5024ac8e | |
|
7a3cfe8089 | |
|
5c4a7dc7b2 | |
|
a926b96103 | |
|
7a5cbcac21 | |
|
64eac01d04 | |
|
b507b3e591 | |
|
60dfa3445a |
|
@ -65,7 +65,7 @@ jobs:
|
|||
platform: android
|
||||
artifact-name: godot-cpp-android-arm64-release
|
||||
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
|
||||
cache-name: android-arm64
|
||||
|
||||
|
@ -88,7 +88,7 @@ jobs:
|
|||
|
||||
env:
|
||||
SCONS_CACHE: ${{ github.workspace }}/.scons-cache/
|
||||
EM_VERSION: 3.1.45
|
||||
EM_VERSION: 3.1.39
|
||||
EM_CACHE_FOLDER: "emsdk-cache"
|
||||
|
||||
steps:
|
||||
|
@ -104,33 +104,34 @@ jobs:
|
|||
continue-on-error: true
|
||||
|
||||
- name: Set up Python (for SCons)
|
||||
uses: actions/setup-python@v4
|
||||
uses: actions/setup-python@v5
|
||||
with:
|
||||
python-version: '3.x'
|
||||
|
||||
- name: Linux dependencies
|
||||
if: ${{ matrix.platform == 'linux' }}
|
||||
run: |
|
||||
sudo apt-get update -qq
|
||||
sudo apt-get install -qqq build-essential pkg-config
|
||||
- name: Android dependencies
|
||||
if: ${{ matrix.platform == 'android' }}
|
||||
uses: nttld/setup-ndk@v1
|
||||
with:
|
||||
ndk-version: r23c
|
||||
link-to-sdk: true
|
||||
|
||||
- name: Web dependencies
|
||||
if: ${{ matrix.platform == 'web' }}
|
||||
uses: mymindstorm/setup-emsdk@v12
|
||||
uses: mymindstorm/setup-emsdk@v13
|
||||
with:
|
||||
version: ${{env.EM_VERSION}}
|
||||
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
|
||||
if: ${{ matrix.platform == 'windows' && matrix.flags == 'use_mingw=yes' }}
|
||||
uses: egor-tensin/setup-mingw@v2
|
||||
with:
|
||||
version: 12.2.0
|
||||
|
||||
- name: Install scons
|
||||
run: |
|
||||
python -m pip install scons==4.0.0
|
||||
|
||||
- name: Generate godot-cpp sources only
|
||||
run: |
|
||||
scons platform=${{ matrix.platform }} build_library=no ${{ matrix.flags }}
|
||||
|
@ -172,7 +173,7 @@ jobs:
|
|||
./godot-artifacts/godot.linuxbsd.editor.x86_64.mono --headless --version
|
||||
cd test
|
||||
# Need to run the editor so .godot is generated... but it crashes! Ignore that :-)
|
||||
(cd project && (../../godot-artifacts/godot.linuxbsd.editor.x86_64.mono --editor --headless --quit >/dev/null 2>&1 || true))
|
||||
(cd project && (timeout 10 ../../godot-artifacts/godot.linuxbsd.editor.x86_64.mono --editor --headless --quit >/dev/null 2>&1 || true))
|
||||
GODOT=../godot-artifacts/godot.linuxbsd.editor.x86_64.mono ./run-tests.sh
|
||||
|
||||
- name: Upload artifact
|
||||
|
|
|
@ -191,3 +191,7 @@ godot.creator.*
|
|||
|
||||
# compile commands (https://clang.llvm.org/docs/JSONCompilationDatabase.html)
|
||||
compile_commands.json
|
||||
|
||||
# Python development
|
||||
.venv
|
||||
venv
|
||||
|
|
|
@ -47,11 +47,6 @@ option(GODOT_CPP_WARNING_AS_ERROR "Treat warnings as errors" OFF)
|
|||
# Add path to modules
|
||||
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( compiler_is_clang "$<OR:$<CXX_COMPILER_ID:AppleClang>,$<CXX_COMPILER_ID:Clang>>" )
|
||||
set( compiler_is_gnu "$<CXX_COMPILER_ID:GNU>" )
|
||||
|
@ -72,21 +67,22 @@ endif()
|
|||
# Input from user for GDExtension interface header and the API JSON file
|
||||
set(GODOT_GDEXTENSION_DIR "gdextension" CACHE STRING "")
|
||||
set(GODOT_CUSTOM_API_FILE "" CACHE STRING "")
|
||||
set(FLOAT_PRECISION "single" CACHE STRING "")
|
||||
if ("${FLOAT_PRECISION}" STREQUAL "double")
|
||||
add_definitions(-DREAL_T_IS_DOUBLE)
|
||||
endif()
|
||||
|
||||
set(GODOT_GDEXTENSION_API_FILE "${GODOT_GDEXTENSION_DIR}/extension_api.json")
|
||||
if (NOT "${GODOT_CUSTOM_API_FILE}" STREQUAL "") # User-defined override.
|
||||
set(GODOT_GDEXTENSION_API_FILE "${GODOT_CUSTOM_API_FILE}")
|
||||
endif()
|
||||
|
||||
set(FLOAT_PRECISION "single" CACHE STRING "")
|
||||
if ("${FLOAT_PRECISION}" STREQUAL "double")
|
||||
add_definitions(-DREAL_T_IS_DOUBLE)
|
||||
endif()
|
||||
|
||||
set(GODOT_COMPILE_FLAGS )
|
||||
|
||||
if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC")
|
||||
# using Visual Studio C++
|
||||
set(GODOT_COMPILE_FLAGS "/EHsc /utf-8") # /GF /MP
|
||||
set(GODOT_COMPILE_FLAGS "/utf-8") # /GF /MP
|
||||
|
||||
if(CMAKE_BUILD_TYPE MATCHES Debug)
|
||||
set(GODOT_COMPILE_FLAGS "${GODOT_COMPILE_FLAGS} /MDd") # /Od /RTC1 /Zi
|
||||
|
@ -98,15 +94,28 @@ if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC")
|
|||
|
||||
add_definitions(-DNOMINMAX)
|
||||
else() # GCC/Clang
|
||||
set(GODOT_COMPILE_FLAGS "${GODOT_COMPILE_FLAGS} -g")
|
||||
|
||||
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()
|
||||
set(GODOT_COMPILE_FLAGS "${GODOT_COMPILE_FLAGS} -O3")
|
||||
endif(CMAKE_BUILD_TYPE MATCHES Debug)
|
||||
endif()
|
||||
|
||||
# Disable exception handling. Godot doesn't use exceptions anywhere, and this
|
||||
# saves around 20% of binary size and very significant build time (GH-80513).
|
||||
option(GODOT_DISABLE_EXCEPTIONS ON "Force disabling exception handling code")
|
||||
if (GODOT_DISABLE_EXCEPTIONS)
|
||||
if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC")
|
||||
set(GODOT_COMPILE_FLAGS "${GODOT_COMPILE_FLAGS} -D_HAS_EXCEPTIONS=0")
|
||||
else()
|
||||
set(GODOT_COMPILE_FLAGS "${GODOT_COMPILE_FLAGS} -fno-exceptions")
|
||||
endif()
|
||||
else()
|
||||
if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC")
|
||||
set(GODOT_COMPILE_FLAGS "${GODOT_COMPILE_FLAGS} /EHsc")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# Generate source from the bindings file
|
||||
find_package(Python3 3.4 REQUIRED) # pathlib should be present
|
||||
if(GENERATE_TEMPLATE_GET_NODE)
|
||||
|
@ -118,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)"
|
||||
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
|
||||
OUTPUT_VARIABLE GENERATED_FILES_LIST
|
||||
OUTPUT_STRIP_TRAILING_WHITESPACE
|
||||
)
|
||||
|
||||
add_custom_command(OUTPUT ${GENERATED_FILES_LIST}
|
||||
|
@ -143,12 +153,6 @@ add_library(godot::cpp ALIAS ${PROJECT_NAME})
|
|||
|
||||
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}
|
||||
PRIVATE
|
||||
cxx_std_17
|
||||
|
|
|
@ -7,8 +7,9 @@
|
|||
> from Godot's `master` branch.
|
||||
>
|
||||
> 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.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`).
|
||||
>
|
||||
|
|
|
@ -110,6 +110,8 @@ def get_file_list(api_filepath, output_dir, headers=False, sources=False):
|
|||
|
||||
for native_struct in api["native_structures"]:
|
||||
struct_name = native_struct["name"]
|
||||
if struct_name == "ObjectID":
|
||||
continue
|
||||
snake_struct_name = camel_to_snake(struct_name)
|
||||
|
||||
header_filename = include_gen_folder / "classes" / (snake_struct_name + ".hpp")
|
||||
|
@ -131,16 +133,12 @@ def get_file_list(api_filepath, output_dir, headers=False, sources=False):
|
|||
if sources:
|
||||
utility_functions_source_path = source_gen_folder / "variant" / "utility_functions.cpp"
|
||||
files.append(str(utility_functions_source_path.as_posix()))
|
||||
register_engine_classes_source_path = source_gen_folder / "register_engine_classes.cpp"
|
||||
files.append(str(register_engine_classes_source_path.as_posix()))
|
||||
|
||||
return files
|
||||
|
||||
|
||||
def print_file_list(api_filepath, output_dir, headers=False, sources=False):
|
||||
end = ";"
|
||||
for f in get_file_list(api_filepath, output_dir, headers, sources):
|
||||
print(f, end=end)
|
||||
print(*get_file_list(api_filepath, output_dir, headers, sources), sep=";", end=None)
|
||||
|
||||
|
||||
def scons_emit_files(target, source, env):
|
||||
|
@ -418,6 +416,9 @@ def generate_builtin_class_header(builtin_api, size, used_classes, fully_used_cl
|
|||
if class_name == "Array":
|
||||
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:
|
||||
if include == "TypedArray":
|
||||
result.append("#include <godot_cpp/variant/typed_array.hpp>")
|
||||
|
@ -527,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 char16_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:
|
||||
axis_constants_count = 0
|
||||
|
@ -1085,6 +1089,8 @@ def generate_engine_classes_bindings(api, output_dir, use_template_get_node):
|
|||
class_api["alias_for"] = "ClassDB"
|
||||
engine_classes[class_api["name"]] = class_api["is_refcounted"]
|
||||
for native_struct in api["native_structures"]:
|
||||
if native_struct["name"] == "ObjectID":
|
||||
continue
|
||||
engine_classes[native_struct["name"]] = False
|
||||
native_structures.append(native_struct["name"])
|
||||
|
||||
|
@ -1210,12 +1216,10 @@ def generate_engine_classes_bindings(api, output_dir, use_template_get_node):
|
|||
generate_engine_class_source(class_api, used_classes, fully_used_classes, use_template_get_node)
|
||||
)
|
||||
|
||||
register_engine_classes_filename = Path(output_dir) / "src" / "register_engine_classes.cpp"
|
||||
with register_engine_classes_filename.open("w+", encoding="utf-8") as source_file:
|
||||
source_file.write(generate_register_engine_classes_source(api))
|
||||
|
||||
for native_struct in api["native_structures"]:
|
||||
struct_name = native_struct["name"]
|
||||
if struct_name == "ObjectID":
|
||||
continue
|
||||
snake_struct_name = camel_to_snake(struct_name)
|
||||
|
||||
header_filename = include_gen_folder / (snake_struct_name + ".hpp")
|
||||
|
@ -1288,7 +1292,7 @@ def generate_engine_class_header(class_api, used_classes, fully_used_classes, us
|
|||
result.append(f"#include <godot_cpp/{get_include_path(included)}>")
|
||||
|
||||
if class_name == "EditorPlugin":
|
||||
result.append("#include <godot_cpp/templates/vector.hpp>")
|
||||
result.append("#include <godot_cpp/classes/editor_plugin_registration.hpp>")
|
||||
|
||||
if len(fully_used_classes) > 0:
|
||||
result.append("")
|
||||
|
@ -1325,7 +1329,11 @@ def generate_engine_class_header(class_api, used_classes, fully_used_classes, us
|
|||
|
||||
if "enums" in class_api:
|
||||
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"]:
|
||||
result.append(f'\t\t{value["name"]} = {value["value"]},')
|
||||
result.append("\t};")
|
||||
|
@ -1440,30 +1448,6 @@ def generate_engine_class_header(class_api, used_classes, fully_used_classes, us
|
|||
result.append("};")
|
||||
result.append("")
|
||||
|
||||
if class_name == "EditorPlugin":
|
||||
result.append("class EditorPlugins {")
|
||||
result.append("private:")
|
||||
result.append("\tstatic Vector<StringName> plugin_classes;")
|
||||
result.append("")
|
||||
result.append("public:")
|
||||
result.append("\tstatic void add_plugin_class(const StringName &p_class_name);")
|
||||
result.append("\tstatic void remove_plugin_class(const StringName &p_class_name);")
|
||||
result.append("\tstatic void deinitialize(GDExtensionInitializationLevel p_level);")
|
||||
result.append("")
|
||||
|
||||
result.append("\ttemplate <class T>")
|
||||
result.append("\tstatic void add_by_type() {")
|
||||
result.append("\t\tadd_plugin_class(T::get_class_static());")
|
||||
result.append("\t}")
|
||||
|
||||
result.append("\ttemplate <class T>")
|
||||
result.append("\tstatic void remove_by_type() {")
|
||||
result.append("\t\tremove_plugin_class(T::get_class_static());")
|
||||
result.append("\t}")
|
||||
|
||||
result.append("};")
|
||||
result.append("")
|
||||
|
||||
result.append("} // namespace godot")
|
||||
result.append("")
|
||||
|
||||
|
@ -1688,38 +1672,6 @@ def generate_engine_class_source(class_api, used_classes, fully_used_classes, us
|
|||
return "\n".join(result)
|
||||
|
||||
|
||||
def generate_register_engine_classes_source(api):
|
||||
includes = []
|
||||
registrations = []
|
||||
|
||||
for class_api in api["classes"]:
|
||||
if class_api["name"] == "ClassDB":
|
||||
continue
|
||||
|
||||
class_name = class_api["name"]
|
||||
snake_class_name = camel_to_snake(class_name)
|
||||
|
||||
includes.append(f"#include <godot_cpp/classes/{snake_class_name}.hpp>")
|
||||
registrations.append(f"\tClassDB::register_engine_class<{class_name}>();")
|
||||
|
||||
result = []
|
||||
add_header(f"register_engine_classes.cpp", result)
|
||||
|
||||
result.append("#include <godot_cpp/godot.hpp>")
|
||||
result.append("")
|
||||
result = result + includes
|
||||
result.append("")
|
||||
result.append("namespace godot {")
|
||||
result.append("")
|
||||
result.append("void GDExtensionBinding::register_engine_classes() {")
|
||||
result = result + registrations
|
||||
result.append("}")
|
||||
result.append("")
|
||||
result.append("} // namespace godot ")
|
||||
|
||||
return "\n".join(result)
|
||||
|
||||
|
||||
def generate_global_constants(api, output_dir):
|
||||
include_gen_folder = Path(output_dir) / "include" / "godot_cpp" / "classes"
|
||||
source_gen_folder = Path(output_dir) / "src" / "classes"
|
||||
|
@ -1738,6 +1690,8 @@ def generate_global_constants(api, output_dir):
|
|||
header.append(f"#ifndef {header_guard}")
|
||||
header.append(f"#define {header_guard}")
|
||||
header.append("")
|
||||
header.append("#include <cstdint>")
|
||||
header.append("")
|
||||
header.append("namespace godot {")
|
||||
header.append("")
|
||||
|
||||
|
@ -1750,7 +1704,11 @@ def generate_global_constants(api, output_dir):
|
|||
if enum_def["name"].startswith("Variant."):
|
||||
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"]:
|
||||
header.append(f'\t\t{value["name"]} = {value["value"]},')
|
||||
header.append("\t};")
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -290,7 +290,7 @@ typedef struct {
|
|||
GDExtensionClassGetVirtual get_virtual_func; // Queries a virtual function by name and returns a callback to invoke the requested virtual function.
|
||||
GDExtensionClassGetRID get_rid_func;
|
||||
void *class_userdata; // Per-class user data, later accessible in instance bindings.
|
||||
} GDExtensionClassCreationInfo; // Deprecated. Use GDExtensionClassCreationInfo2 instead.
|
||||
} GDExtensionClassCreationInfo; // Deprecated. Use GDExtensionClassCreationInfo3 instead.
|
||||
|
||||
typedef struct {
|
||||
GDExtensionBool is_virtual;
|
||||
|
@ -323,7 +323,41 @@ typedef struct {
|
|||
GDExtensionClassCallVirtualWithData call_virtual_with_data_func;
|
||||
GDExtensionClassGetRID get_rid_func;
|
||||
void *class_userdata; // Per-class user data, later accessible in instance bindings.
|
||||
} GDExtensionClassCreationInfo2;
|
||||
} GDExtensionClassCreationInfo2; // Deprecated. Use GDExtensionClassCreationInfo3 instead.
|
||||
|
||||
typedef struct {
|
||||
GDExtensionBool is_virtual;
|
||||
GDExtensionBool is_abstract;
|
||||
GDExtensionBool is_exposed;
|
||||
GDExtensionBool is_gameplay;
|
||||
GDExtensionClassSet set_func;
|
||||
GDExtensionClassGet get_func;
|
||||
GDExtensionClassGetPropertyList get_property_list_func;
|
||||
GDExtensionClassFreePropertyList free_property_list_func;
|
||||
GDExtensionClassPropertyCanRevert property_can_revert_func;
|
||||
GDExtensionClassPropertyGetRevert property_get_revert_func;
|
||||
GDExtensionClassValidateProperty validate_property_func;
|
||||
GDExtensionClassNotification2 notification_func;
|
||||
GDExtensionClassToString to_string_func;
|
||||
GDExtensionClassReference reference_func;
|
||||
GDExtensionClassUnreference unreference_func;
|
||||
GDExtensionClassCreateInstance create_instance_func; // (Default) constructor; mandatory. If the class is not instantiable, consider making it virtual or abstract.
|
||||
GDExtensionClassFreeInstance free_instance_func; // Destructor; mandatory.
|
||||
GDExtensionClassRecreateInstance recreate_instance_func;
|
||||
// Queries a virtual function by name and returns a callback to invoke the requested virtual function.
|
||||
GDExtensionClassGetVirtual get_virtual_func;
|
||||
// Paired with `call_virtual_with_data_func`, this is an alternative to `get_virtual_func` for extensions that
|
||||
// need or benefit from extra data when calling virtual functions.
|
||||
// Returns user data that will be passed to `call_virtual_with_data_func`.
|
||||
// Returning `NULL` from this function signals to Godot that the virtual function is not overridden.
|
||||
// Data returned from this function should be managed by the extension and must be valid until the extension is deinitialized.
|
||||
// You should supply either `get_virtual_func`, or `get_virtual_call_data_func` with `call_virtual_with_data_func`.
|
||||
GDExtensionClassGetVirtualCallData get_virtual_call_data_func;
|
||||
// Used to call virtual functions when `get_virtual_call_data_func` is not null.
|
||||
GDExtensionClassCallVirtualWithData call_virtual_with_data_func;
|
||||
GDExtensionClassGetRID get_rid_func;
|
||||
void *class_userdata; // Per-class user data, later accessible in instance bindings.
|
||||
} GDExtensionClassCreationInfo3;
|
||||
|
||||
typedef void *GDExtensionClassLibraryPtr;
|
||||
|
||||
|
@ -392,7 +426,7 @@ typedef GDExtensionBool (*GDExtensionCallableCustomLessThan)(void *callable_user
|
|||
typedef void (*GDExtensionCallableCustomToString)(void *callable_userdata, GDExtensionBool *r_is_valid, GDExtensionStringPtr r_out);
|
||||
|
||||
typedef struct {
|
||||
/* Only `call_func` and `token` are strictly required, however, `object` should be passed if its not a static method.
|
||||
/* Only `call_func` and `token` are strictly required, however, `object_id` should be passed if its not a static method.
|
||||
*
|
||||
* `token` should point to an address that uniquely identifies the GDExtension (for example, the
|
||||
* `GDExtensionClassLibraryPtr` passed to the entry symbol function.
|
||||
|
@ -409,7 +443,7 @@ typedef struct {
|
|||
void *callable_userdata;
|
||||
void *token;
|
||||
|
||||
GDExtensionObjectPtr object;
|
||||
GDObjectInstanceID object_id;
|
||||
|
||||
GDExtensionCallableCustomCall call_func;
|
||||
GDExtensionCallableCustomIsValid is_valid_func;
|
||||
|
@ -590,7 +624,10 @@ typedef GDExtensionInterfaceFunctionPtr (*GDExtensionInterfaceGetProcAddress)(co
|
|||
*
|
||||
* For example:
|
||||
*
|
||||
* GDExtensionInterfaceGetGodotVersion *get_godot_version = (GDExtensionInterfaceGetGodotVersion)p_get_proc_address("get_godot_version");
|
||||
* GDExtensionInterfaceGetGodotVersion get_godot_version = (GDExtensionInterfaceGetGodotVersion)p_get_proc_address("get_godot_version");
|
||||
*
|
||||
* (Note that snippet may cause "cast between incompatible function types" on some compilers, you can
|
||||
* silence this by adding an intermediary `void*` cast.)
|
||||
*
|
||||
* You can then call it like a normal function:
|
||||
*
|
||||
|
@ -2466,6 +2503,21 @@ typedef void (*GDExtensionInterfaceClassdbRegisterExtensionClass)(GDExtensionCla
|
|||
*/
|
||||
typedef void (*GDExtensionInterfaceClassdbRegisterExtensionClass2)(GDExtensionClassLibraryPtr p_library, GDExtensionConstStringNamePtr p_class_name, GDExtensionConstStringNamePtr p_parent_class_name, const GDExtensionClassCreationInfo2 *p_extension_funcs);
|
||||
|
||||
/**
|
||||
* @name classdb_register_extension_class3
|
||||
* @since 4.3
|
||||
*
|
||||
* Registers an extension class in the ClassDB.
|
||||
*
|
||||
* Provided struct can be safely freed once the function returns.
|
||||
*
|
||||
* @param p_library A pointer the library received by the GDExtension's entry point function.
|
||||
* @param p_class_name A pointer to a StringName with the class name.
|
||||
* @param p_parent_class_name A pointer to a StringName with the parent class name.
|
||||
* @param p_extension_funcs A pointer to a GDExtensionClassCreationInfo2 struct.
|
||||
*/
|
||||
typedef void (*GDExtensionInterfaceClassdbRegisterExtensionClass3)(GDExtensionClassLibraryPtr p_library, GDExtensionConstStringNamePtr p_class_name, GDExtensionConstStringNamePtr p_parent_class_name, const GDExtensionClassCreationInfo3 *p_extension_funcs);
|
||||
|
||||
/**
|
||||
* @name classdb_register_extension_class_method
|
||||
* @since 4.1
|
||||
|
|
|
@ -0,0 +1,62 @@
|
|||
/**************************************************************************/
|
||||
/* editor_plugin_registration.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_EDITOR_PLUGIN_REGISTRATION_HPP
|
||||
#define GODOT_EDITOR_PLUGIN_REGISTRATION_HPP
|
||||
|
||||
#include <godot_cpp/templates/vector.hpp>
|
||||
|
||||
namespace godot {
|
||||
|
||||
class EditorPlugin;
|
||||
class StringName;
|
||||
|
||||
class EditorPlugins {
|
||||
private:
|
||||
static Vector<StringName> plugin_classes;
|
||||
|
||||
public:
|
||||
static void add_plugin_class(const StringName &p_class_name);
|
||||
static void remove_plugin_class(const StringName &p_class_name);
|
||||
static void deinitialize(GDExtensionInitializationLevel p_level);
|
||||
|
||||
template <class T>
|
||||
static void add_by_type() {
|
||||
add_plugin_class(T::get_class_static());
|
||||
}
|
||||
template <class T>
|
||||
static void remove_by_type() {
|
||||
remove_plugin_class(T::get_class_static());
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace godot
|
||||
|
||||
#endif // GODOT_EDITOR_PLUGIN_REGISTRATION_HPP
|
|
@ -111,6 +111,22 @@ namespace internal {
|
|||
GDExtensionPropertyInfo *create_c_property_list(const ::godot::List<::godot::PropertyInfo> &plist_cpp, uint32_t *r_size);
|
||||
void free_c_property_list(GDExtensionPropertyInfo *plist);
|
||||
|
||||
typedef void (*EngineClassRegistrationCallback)();
|
||||
void add_engine_class_registration_callback(EngineClassRegistrationCallback p_callback);
|
||||
void register_engine_class(const StringName &p_name, const GDExtensionInstanceBindingCallbacks *p_callbacks);
|
||||
void register_engine_classes();
|
||||
|
||||
template <class T>
|
||||
struct EngineClassRegistration {
|
||||
EngineClassRegistration() {
|
||||
add_engine_class_registration_callback(&EngineClassRegistration<T>::callback);
|
||||
}
|
||||
|
||||
static void callback() {
|
||||
register_engine_class(T::get_class_static(), &T::_gde_binding_callbacks);
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace internal
|
||||
|
||||
} // namespace godot
|
||||
|
@ -186,6 +202,8 @@ protected:
|
|||
} \
|
||||
\
|
||||
public: \
|
||||
typedef m_class self_type; \
|
||||
\
|
||||
static void initialize_class() { \
|
||||
static bool initialized = false; \
|
||||
if (initialized) { \
|
||||
|
@ -347,87 +365,109 @@ public:
|
|||
_gde_binding_create_callback, \
|
||||
_gde_binding_free_callback, \
|
||||
_gde_binding_reference_callback, \
|
||||
};
|
||||
}; \
|
||||
\
|
||||
private:
|
||||
|
||||
// Don't use this for your classes, use GDCLASS() instead.
|
||||
#define GDEXTENSION_CLASS_ALIAS(m_class, m_alias_for, m_inherits) \
|
||||
private: \
|
||||
void operator=(const m_class &p_rval) {} \
|
||||
\
|
||||
protected: \
|
||||
virtual const GDExtensionInstanceBindingCallbacks *_get_bindings_callbacks() const override { \
|
||||
return &_gde_binding_callbacks; \
|
||||
} \
|
||||
\
|
||||
m_class(const char *p_godot_class) : m_inherits(p_godot_class) {} \
|
||||
m_class(GodotObject *p_godot_object) : m_inherits(p_godot_object) {} \
|
||||
\
|
||||
static void (*_get_bind_methods())() { \
|
||||
return nullptr; \
|
||||
} \
|
||||
\
|
||||
static void (Wrapped::*_get_notification())(int) { \
|
||||
return nullptr; \
|
||||
} \
|
||||
\
|
||||
static bool (Wrapped::*_get_set())(const ::godot::StringName &p_name, const Variant &p_property) { \
|
||||
return nullptr; \
|
||||
} \
|
||||
\
|
||||
static bool (Wrapped::*_get_get())(const ::godot::StringName &p_name, Variant &r_ret) const { \
|
||||
return nullptr; \
|
||||
} \
|
||||
\
|
||||
static void (Wrapped::*_get_get_property_list())(List<PropertyInfo> * p_list) const { \
|
||||
return nullptr; \
|
||||
} \
|
||||
\
|
||||
static bool (Wrapped::*_get_property_can_revert())(const ::godot::StringName &p_name) const { \
|
||||
return nullptr; \
|
||||
} \
|
||||
\
|
||||
static bool (Wrapped::*_get_property_get_revert())(const ::godot::StringName &p_name, Variant &) const { \
|
||||
return nullptr; \
|
||||
} \
|
||||
\
|
||||
static void (Wrapped::*_get_validate_property())(::godot::PropertyInfo & p_property) const { \
|
||||
return nullptr; \
|
||||
} \
|
||||
\
|
||||
static String (Wrapped::*_get_to_string())() const { \
|
||||
return nullptr; \
|
||||
} \
|
||||
\
|
||||
public: \
|
||||
static void initialize_class() {} \
|
||||
\
|
||||
static ::godot::StringName &get_class_static() { \
|
||||
static ::godot::StringName string_name = ::godot::StringName(#m_alias_for); \
|
||||
return string_name; \
|
||||
} \
|
||||
\
|
||||
static ::godot::StringName &get_parent_class_static() { \
|
||||
return m_inherits::get_class_static(); \
|
||||
} \
|
||||
\
|
||||
static void *_gde_binding_create_callback(void *p_token, void *p_instance) { \
|
||||
/* Do not call memnew here, we don't want the post-initializer to be called */ \
|
||||
return new ("") m_class((GodotObject *)p_instance); \
|
||||
} \
|
||||
static void _gde_binding_free_callback(void *p_token, void *p_instance, void *p_binding) { \
|
||||
/* Explicitly call the deconstructor to ensure proper lifecycle for non-trivial members */ \
|
||||
reinterpret_cast<m_class *>(p_binding)->~m_class(); \
|
||||
Memory::free_static(reinterpret_cast<m_class *>(p_binding)); \
|
||||
} \
|
||||
static GDExtensionBool _gde_binding_reference_callback(void *p_token, void *p_instance, GDExtensionBool p_reference) { \
|
||||
return true; \
|
||||
} \
|
||||
static constexpr GDExtensionInstanceBindingCallbacks _gde_binding_callbacks = { \
|
||||
_gde_binding_create_callback, \
|
||||
_gde_binding_free_callback, \
|
||||
_gde_binding_reference_callback, \
|
||||
}; \
|
||||
m_class() : m_class(#m_alias_for) {}
|
||||
#define GDEXTENSION_CLASS_ALIAS(m_class, m_alias_for, m_inherits) /******************************************************************************************************************/ \
|
||||
private: \
|
||||
inline static ::godot::internal::EngineClassRegistration<m_class> _gde_engine_class_registration_helper; \
|
||||
void operator=(const m_class &p_rval) {} \
|
||||
\
|
||||
protected: \
|
||||
virtual const GDExtensionInstanceBindingCallbacks *_get_bindings_callbacks() const override { \
|
||||
return &_gde_binding_callbacks; \
|
||||
} \
|
||||
\
|
||||
m_class(const char *p_godot_class) : m_inherits(p_godot_class) {} \
|
||||
m_class(GodotObject *p_godot_object) : m_inherits(p_godot_object) {} \
|
||||
\
|
||||
static void (*_get_bind_methods())() { \
|
||||
return nullptr; \
|
||||
} \
|
||||
\
|
||||
static void (Wrapped::*_get_notification())(int) { \
|
||||
return nullptr; \
|
||||
} \
|
||||
\
|
||||
static bool (Wrapped::*_get_set())(const ::godot::StringName &p_name, const Variant &p_property) { \
|
||||
return nullptr; \
|
||||
} \
|
||||
\
|
||||
static bool (Wrapped::*_get_get())(const ::godot::StringName &p_name, Variant &r_ret) const { \
|
||||
return nullptr; \
|
||||
} \
|
||||
\
|
||||
static inline bool has_get_property_list() { \
|
||||
return false; \
|
||||
} \
|
||||
\
|
||||
static void (Wrapped::*_get_get_property_list())(List<PropertyInfo> * p_list) const { \
|
||||
return nullptr; \
|
||||
} \
|
||||
\
|
||||
static bool (Wrapped::*_get_property_can_revert())(const ::godot::StringName &p_name) const { \
|
||||
return nullptr; \
|
||||
} \
|
||||
\
|
||||
static bool (Wrapped::*_get_property_get_revert())(const ::godot::StringName &p_name, Variant &) const { \
|
||||
return nullptr; \
|
||||
} \
|
||||
\
|
||||
static void (Wrapped::*_get_validate_property())(::godot::PropertyInfo & p_property) const { \
|
||||
return nullptr; \
|
||||
} \
|
||||
\
|
||||
static String (Wrapped::*_get_to_string())() const { \
|
||||
return nullptr; \
|
||||
} \
|
||||
\
|
||||
public: \
|
||||
typedef m_class self_type; \
|
||||
\
|
||||
static void initialize_class() {} \
|
||||
\
|
||||
static ::godot::StringName &get_class_static() { \
|
||||
static ::godot::StringName string_name = ::godot::StringName(#m_alias_for); \
|
||||
return string_name; \
|
||||
} \
|
||||
\
|
||||
static ::godot::StringName &get_parent_class_static() { \
|
||||
return m_inherits::get_class_static(); \
|
||||
} \
|
||||
\
|
||||
static GDExtensionObjectPtr create(void *data) { \
|
||||
return nullptr; \
|
||||
} \
|
||||
\
|
||||
static GDExtensionClassInstancePtr recreate(void *data, GDExtensionObjectPtr obj) { \
|
||||
return nullptr; \
|
||||
} \
|
||||
\
|
||||
static void free(void *data, GDExtensionClassInstancePtr ptr) { \
|
||||
} \
|
||||
\
|
||||
static void *_gde_binding_create_callback(void *p_token, void *p_instance) { \
|
||||
/* Do not call memnew here, we don't want the post-initializer to be called */ \
|
||||
return new ("", "") m_class((GodotObject *)p_instance); \
|
||||
} \
|
||||
static void _gde_binding_free_callback(void *p_token, void *p_instance, void *p_binding) { \
|
||||
/* Explicitly call the deconstructor to ensure proper lifecycle for non-trivial members */ \
|
||||
reinterpret_cast<m_class *>(p_binding)->~m_class(); \
|
||||
Memory::free_static(reinterpret_cast<m_class *>(p_binding)); \
|
||||
} \
|
||||
static GDExtensionBool _gde_binding_reference_callback(void *p_token, void *p_instance, GDExtensionBool p_reference) { \
|
||||
return true; \
|
||||
} \
|
||||
static constexpr GDExtensionInstanceBindingCallbacks _gde_binding_callbacks = { \
|
||||
_gde_binding_create_callback, \
|
||||
_gde_binding_free_callback, \
|
||||
_gde_binding_reference_callback, \
|
||||
}; \
|
||||
m_class() : m_class(#m_alias_for) {} \
|
||||
\
|
||||
private:
|
||||
|
||||
// Don't use this for your classes, use GDCLASS() instead.
|
||||
#define GDEXTENSION_CLASS(m_class, m_inherits) GDEXTENSION_CLASS_ALIAS(m_class, m_class, m_inherits)
|
||||
|
|
|
@ -110,7 +110,7 @@ private:
|
|||
static void bind_method_godot(const StringName &p_class_name, MethodBind *p_method);
|
||||
|
||||
template <class T, bool is_abstract>
|
||||
static void _register_class(bool p_virtual = false, bool p_exposed = true);
|
||||
static void _register_class(bool p_virtual = false, bool p_exposed = true, bool p_gameplay = false);
|
||||
|
||||
public:
|
||||
template <class T>
|
||||
|
@ -120,7 +120,11 @@ public:
|
|||
template <class T>
|
||||
static void register_internal_class();
|
||||
template <class T>
|
||||
static void register_engine_class();
|
||||
static void register_gameplay_class();
|
||||
|
||||
_FORCE_INLINE_ static void _register_engine_class(const StringName &p_name, const GDExtensionInstanceBindingCallbacks *p_callbacks) {
|
||||
instance_binding_callbacks[p_name] = p_callbacks;
|
||||
}
|
||||
|
||||
template <class N, class M, typename... VarArgs>
|
||||
static MethodBind *bind_method(N p_method_name, M p_method, VarArgs... p_args);
|
||||
|
@ -167,7 +171,8 @@ public:
|
|||
}
|
||||
|
||||
template <class T, bool is_abstract>
|
||||
void ClassDB::_register_class(bool p_virtual, bool p_exposed) {
|
||||
void ClassDB::_register_class(bool p_virtual, bool p_exposed, bool p_gameplay) {
|
||||
static_assert(TypesAreSame<typename T::self_type, T>::value, "Class not declared properly, please use GDCLASS.");
|
||||
instance_binding_callbacks[T::get_class_static()] = &T::_gde_binding_callbacks;
|
||||
|
||||
// Register this class within our plugin
|
||||
|
@ -184,10 +189,11 @@ void ClassDB::_register_class(bool p_virtual, bool p_exposed) {
|
|||
class_register_order.push_back(cl.name);
|
||||
|
||||
// Register this class with Godot
|
||||
GDExtensionClassCreationInfo2 class_info = {
|
||||
GDExtensionClassCreationInfo3 class_info = {
|
||||
p_virtual, // GDExtensionBool is_virtual;
|
||||
is_abstract, // GDExtensionBool is_abstract;
|
||||
p_exposed, // GDExtensionBool is_exposed;
|
||||
p_gameplay, // GDExtensionBool is_gameplay;
|
||||
T::set_bind, // GDExtensionClassSet set_func;
|
||||
T::get_bind, // GDExtensionClassGet get_func;
|
||||
T::has_get_property_list() ? T::get_property_list_bind : nullptr, // GDExtensionClassGetPropertyList get_property_list_func;
|
||||
|
@ -209,7 +215,7 @@ void ClassDB::_register_class(bool p_virtual, bool p_exposed) {
|
|||
(void *)&T::get_class_static(), // void *class_userdata;
|
||||
};
|
||||
|
||||
internal::gdextension_interface_classdb_register_extension_class2(internal::library, cl.name._native_ptr(), cl.parent_name._native_ptr(), &class_info);
|
||||
internal::gdextension_interface_classdb_register_extension_class3(internal::library, cl.name._native_ptr(), cl.parent_name._native_ptr(), &class_info);
|
||||
|
||||
// call bind_methods etc. to register all members of the class
|
||||
T::initialize_class();
|
||||
|
@ -234,8 +240,8 @@ void ClassDB::register_internal_class() {
|
|||
}
|
||||
|
||||
template <class T>
|
||||
void ClassDB::register_engine_class() {
|
||||
instance_binding_callbacks[T::get_class_static()] = &T::_gde_binding_callbacks;
|
||||
void ClassDB::register_gameplay_class() {
|
||||
ClassDB::_register_class<T, false>(false, true, true);
|
||||
}
|
||||
|
||||
template <class N, class M, typename... VarArgs>
|
||||
|
@ -297,6 +303,7 @@ MethodBind *ClassDB::bind_vararg_method(uint32_t p_flags, StringName p_name, M p
|
|||
#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_INTERNAL_CLASS(m_class) ClassDB::register_internal_class<m_class>();
|
||||
#define GDREGISTER_GAMEPLAY_CLASS(m_class) ClassDB::register_gameplay_class<m_class>();
|
||||
|
||||
} // namespace godot
|
||||
|
||||
|
|
|
@ -44,20 +44,21 @@
|
|||
#define PAD_ALIGN 16 //must always be greater than this at much
|
||||
#endif
|
||||
|
||||
void *operator new(size_t p_size, const char *p_description); ///< operator new that takes a description and uses MemoryStaticPool
|
||||
void *operator new(size_t p_size, void *(*p_allocfunc)(size_t p_size)); ///< operator new that takes a description and uses MemoryStaticPool
|
||||
void *operator new(size_t p_size, void *p_pointer, size_t check, const char *p_description); ///< operator new that takes a description and uses a pointer to the preallocated memory
|
||||
// p_dummy argument is added to avoid conflicts with the engine functions when both engine and GDExtension are built as a static library on iOS.
|
||||
void *operator new(size_t p_size, const char *p_dummy, const char *p_description); ///< operator new that takes a description and uses MemoryStaticPool
|
||||
void *operator new(size_t p_size, const char *p_dummy, void *(*p_allocfunc)(size_t p_size)); ///< operator new that takes a description and uses MemoryStaticPool
|
||||
void *operator new(size_t p_size, const char *p_dummy, void *p_pointer, size_t check, const char *p_description); ///< operator new that takes a description and uses a pointer to the preallocated memory
|
||||
|
||||
_ALWAYS_INLINE_ void *operator new(size_t p_size, void *p_pointer, size_t check, const char *p_description) {
|
||||
_ALWAYS_INLINE_ void *operator new(size_t p_size, const char *p_dummy, void *p_pointer, size_t check, const char *p_description) {
|
||||
return p_pointer;
|
||||
}
|
||||
|
||||
#ifdef _MSC_VER
|
||||
// When compiling with VC++ 2017, the above declarations of placement new generate many irrelevant warnings (C4291).
|
||||
// The purpose of the following definitions is to muffle these warnings, not to provide a usable implementation of placement delete.
|
||||
void operator delete(void *p_mem, const char *p_description);
|
||||
void operator delete(void *p_mem, void *(*p_allocfunc)(size_t p_size));
|
||||
void operator delete(void *p_mem, void *p_pointer, size_t check, const char *p_description);
|
||||
void operator delete(void *p_mem, const char *p_dummy, const char *p_description);
|
||||
void operator delete(void *p_mem, const char *p_dummy, void *(*p_allocfunc)(size_t p_size));
|
||||
void operator delete(void *p_mem, const char *p_dummy, void *p_pointer, size_t check, const char *p_description);
|
||||
#endif
|
||||
|
||||
namespace godot {
|
||||
|
@ -85,10 +86,10 @@ _ALWAYS_INLINE_ T *_post_initialize(T *p_obj) {
|
|||
#define memrealloc(m_mem, m_size) ::godot::Memory::realloc_static(m_mem, m_size)
|
||||
#define memfree(m_mem) ::godot::Memory::free_static(m_mem)
|
||||
|
||||
#define memnew(m_class) ::godot::_post_initialize(new ("") m_class)
|
||||
#define memnew(m_class) ::godot::_post_initialize(new ("", "") m_class)
|
||||
|
||||
#define memnew_allocator(m_class, m_allocator) ::godot::_post_initialize(new (m_allocator::alloc) m_class)
|
||||
#define memnew_placement(m_placement, m_class) ::godot::_post_initialize(new (m_placement, sizeof(m_class), "") m_class)
|
||||
#define memnew_allocator(m_class, m_allocator) ::godot::_post_initialize(new ("", m_allocator::alloc) m_class)
|
||||
#define memnew_placement(m_placement, m_class) ::godot::_post_initialize(new ("", m_placement, sizeof(m_class), "") m_class)
|
||||
|
||||
// Generic comparator used in Map, List, etc.
|
||||
template <class T>
|
||||
|
@ -154,7 +155,7 @@ T *memnew_arr_template(size_t p_elements, const char *p_descr = "") {
|
|||
|
||||
/* call operator new */
|
||||
for (size_t i = 0; i < p_elements; i++) {
|
||||
new (&elems[i], sizeof(T), p_descr) T;
|
||||
new ("", &elems[i], sizeof(T), p_descr) T;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -33,6 +33,8 @@
|
|||
|
||||
#include <godot_cpp/core/defs.hpp>
|
||||
|
||||
#include <godot_cpp/core/object_id.hpp>
|
||||
|
||||
#include <godot_cpp/core/property_info.hpp>
|
||||
|
||||
#include <godot_cpp/variant/variant.hpp>
|
||||
|
@ -106,28 +108,6 @@ MethodInfo::MethodInfo(const PropertyInfo &p_ret, StringName p_name, const 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 {
|
||||
public:
|
||||
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" GDExtensionInterfaceObjectGetInstanceId gdextension_interface_object_get_instance_id;
|
||||
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" GDExtensionInterfaceRefSetObject gdextension_interface_ref_set_object;
|
||||
extern "C" GDExtensionInterfaceScriptInstanceCreate2 gdextension_interface_script_instance_create2;
|
||||
|
@ -174,7 +175,7 @@ extern "C" GDExtensionInterfacePlaceHolderScriptInstanceUpdate gdextension_inter
|
|||
extern "C" GDExtensionInterfaceClassdbConstructObject gdextension_interface_classdb_construct_object;
|
||||
extern "C" GDExtensionInterfaceClassdbGetMethodBind gdextension_interface_classdb_get_method_bind;
|
||||
extern "C" GDExtensionInterfaceClassdbGetClassTag gdextension_interface_classdb_get_class_tag;
|
||||
extern "C" GDExtensionInterfaceClassdbRegisterExtensionClass2 gdextension_interface_classdb_register_extension_class2;
|
||||
extern "C" GDExtensionInterfaceClassdbRegisterExtensionClass3 gdextension_interface_classdb_register_extension_class3;
|
||||
extern "C" GDExtensionInterfaceClassdbRegisterExtensionClassMethod gdextension_interface_classdb_register_extension_class_method;
|
||||
extern "C" GDExtensionInterfaceClassdbRegisterExtensionClassIntegerConstant gdextension_interface_classdb_register_extension_class_integer_constant;
|
||||
extern "C" GDExtensionInterfaceClassdbRegisterExtensionClassProperty gdextension_interface_classdb_register_extension_class_property;
|
||||
|
@ -193,29 +194,44 @@ enum ModuleInitializationLevel {
|
|||
MODULE_INITIALIZATION_LEVEL_CORE = GDEXTENSION_INITIALIZATION_CORE,
|
||||
MODULE_INITIALIZATION_LEVEL_SERVERS = GDEXTENSION_INITIALIZATION_SERVERS,
|
||||
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 {
|
||||
private:
|
||||
static void register_engine_classes();
|
||||
|
||||
public:
|
||||
using Callback = void (*)(ModuleInitializationLevel p_level);
|
||||
|
||||
static Callback init_callback;
|
||||
static Callback terminate_callback;
|
||||
static GDExtensionInitializationLevel minimum_initialization_level;
|
||||
static GDExtensionBool init(GDExtensionInterfaceGetProcAddress p_get_proc_address, GDExtensionClassLibraryPtr p_library, GDExtensionInitialization *r_initialization);
|
||||
struct InitData {
|
||||
GDExtensionInitializationLevel minimum_initialization_level = GDEXTENSION_INITIALIZATION_CORE;
|
||||
Callback init_callback = nullptr;
|
||||
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:
|
||||
static void initialize_level(void *userdata, GDExtensionInitializationLevel p_level);
|
||||
static void deinitialize_level(void *userdata, GDExtensionInitializationLevel p_level);
|
||||
static void initialize_level(void *p_userdata, GDExtensionInitializationLevel p_level);
|
||||
static void deinitialize_level(void *p_userdata, GDExtensionInitializationLevel p_level);
|
||||
|
||||
class InitObject {
|
||||
GDExtensionInterfaceGetProcAddress get_proc_address;
|
||||
GDExtensionClassLibraryPtr library;
|
||||
GDExtensionInitialization *initialization;
|
||||
mutable InitData *init_data = nullptr;
|
||||
|
||||
public:
|
||||
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,15 +36,23 @@
|
|||
|
||||
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:
|
||||
virtual Object *get_object() const = 0;
|
||||
virtual void call(const Variant **p_arguments, int p_argcount, Variant &r_return_value, GDExtensionCallError &r_call_error) const = 0;
|
||||
_FORCE_INLINE_ const uint32_t *get_comp_ptr() const { return comp_ptr; }
|
||||
_FORCE_INLINE_ uint32_t get_comp_size() const { return comp_size; }
|
||||
_FORCE_INLINE_ uint32_t get_hash() const { return h; }
|
||||
};
|
||||
|
||||
namespace internal {
|
||||
|
||||
Callable create_custom_callable(CallableCustomMethodPointerBase *p_callable_method_pointer);
|
||||
Callable create_callable_from_ccmp(CallableCustomMethodPointerBase *p_callable_method_pointer);
|
||||
|
||||
} // namespace internal
|
||||
|
||||
|
@ -54,21 +62,26 @@ Callable create_custom_callable(CallableCustomMethodPointerBase *p_callable_meth
|
|||
|
||||
template <class T, class... P>
|
||||
class CallableCustomMethodPointer : public CallableCustomMethodPointerBase {
|
||||
T *instance;
|
||||
void (T::*method)(P...);
|
||||
struct Data {
|
||||
T *instance;
|
||||
void (T::*method)(P...);
|
||||
} data;
|
||||
static_assert(sizeof(Data) % 4 == 0);
|
||||
|
||||
public:
|
||||
virtual Object *get_object() const override {
|
||||
return instance;
|
||||
virtual ObjectID get_object() const override {
|
||||
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 {
|
||||
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...)) {
|
||||
instance = p_instance;
|
||||
method = p_method;
|
||||
memset(&data, 0, sizeof(Data));
|
||||
data.instance = p_instance;
|
||||
data.method = p_method;
|
||||
_setup((uint32_t *)&data, sizeof(Data));
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -76,7 +89,7 @@ template <class T, class... P>
|
|||
Callable create_custom_callable_function_pointer(T *p_instance, void (T::*p_method)(P...)) {
|
||||
typedef CallableCustomMethodPointer<T, P...> CCMP;
|
||||
CCMP *ccmp = memnew(CCMP(p_instance, p_method));
|
||||
return ::godot::internal::create_custom_callable(ccmp);
|
||||
return ::godot::internal::create_callable_from_ccmp(ccmp);
|
||||
}
|
||||
|
||||
//
|
||||
|
@ -85,22 +98,27 @@ Callable create_custom_callable_function_pointer(T *p_instance, void (T::*p_meth
|
|||
|
||||
template <class T, class R, class... P>
|
||||
class CallableCustomMethodPointerRet : public CallableCustomMethodPointerBase {
|
||||
T *instance;
|
||||
R(T::*method)
|
||||
(P...);
|
||||
struct Data {
|
||||
T *instance;
|
||||
R(T::*method)
|
||||
(P...);
|
||||
} data;
|
||||
static_assert(sizeof(Data) % 4 == 0);
|
||||
|
||||
public:
|
||||
virtual Object *get_object() const override {
|
||||
return instance;
|
||||
virtual ObjectID get_object() const override {
|
||||
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 {
|
||||
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...)) {
|
||||
instance = p_instance;
|
||||
method = p_method;
|
||||
memset(&data, 0, sizeof(Data));
|
||||
data.instance = p_instance;
|
||||
data.method = p_method;
|
||||
_setup((uint32_t *)&data, sizeof(Data));
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -108,7 +126,7 @@ template <class T, class R, class... 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.
|
||||
CCMP *ccmp = memnew(CCMP(p_instance, p_method));
|
||||
return ::godot::internal::create_custom_callable(ccmp);
|
||||
return ::godot::internal::create_callable_from_ccmp(ccmp);
|
||||
}
|
||||
|
||||
//
|
||||
|
@ -117,22 +135,27 @@ Callable create_custom_callable_function_pointer(T *p_instance, R (T::*p_method)
|
|||
|
||||
template <class T, class R, class... P>
|
||||
class CallableCustomMethodPointerRetC : public CallableCustomMethodPointerBase {
|
||||
T *instance;
|
||||
R(T::*method)
|
||||
(P...) const;
|
||||
struct Data {
|
||||
T *instance;
|
||||
R(T::*method)
|
||||
(P...) const;
|
||||
} data;
|
||||
static_assert(sizeof(Data) % 4 == 0);
|
||||
|
||||
public:
|
||||
virtual Object *get_object() const override {
|
||||
return instance;
|
||||
virtual ObjectID get_object() const override {
|
||||
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 {
|
||||
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) {
|
||||
instance = const_cast<T *>(p_instance);
|
||||
method = p_method;
|
||||
memset(&data, 0, sizeof(Data));
|
||||
data.instance = const_cast<T *>(p_instance);
|
||||
data.method = p_method;
|
||||
_setup((uint32_t *)&data, sizeof(Data));
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -140,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) {
|
||||
typedef CallableCustomMethodPointerRetC<T, R, P...> CCMP; // Messes with memnew otherwise.
|
||||
CCMP *ccmp = memnew(CCMP(p_instance, p_method));
|
||||
return ::godot::internal::create_custom_callable(ccmp);
|
||||
return ::godot::internal::create_callable_from_ccmp(ccmp);
|
||||
}
|
||||
|
||||
//
|
||||
|
@ -149,20 +172,25 @@ Callable create_custom_callable_function_pointer(const T *p_instance, R (T::*p_m
|
|||
|
||||
template <class... P>
|
||||
class CallableCustomStaticMethodPointer : public CallableCustomMethodPointerBase {
|
||||
void (*method)(P...);
|
||||
struct Data {
|
||||
void (*method)(P...);
|
||||
} data;
|
||||
static_assert(sizeof(Data) % 4 == 0);
|
||||
|
||||
public:
|
||||
virtual Object *get_object() const override {
|
||||
return nullptr;
|
||||
virtual ObjectID get_object() const override {
|
||||
return ObjectID();
|
||||
}
|
||||
|
||||
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();
|
||||
}
|
||||
|
||||
CallableCustomStaticMethodPointer(void (*p_method)(P...)) {
|
||||
method = p_method;
|
||||
memset(&data, 0, sizeof(Data));
|
||||
data.method = p_method;
|
||||
_setup((uint32_t *)&data, sizeof(Data));
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -170,7 +198,7 @@ template <class... P>
|
|||
Callable create_custom_callable_static_function_pointer(void (*p_method)(P...)) {
|
||||
typedef CallableCustomStaticMethodPointer<P...> CCMP;
|
||||
CCMP *ccmp = memnew(CCMP(p_method));
|
||||
return ::godot::internal::create_custom_callable(ccmp);
|
||||
return ::godot::internal::create_callable_from_ccmp(ccmp);
|
||||
}
|
||||
|
||||
//
|
||||
|
@ -179,20 +207,25 @@ Callable create_custom_callable_static_function_pointer(void (*p_method)(P...))
|
|||
|
||||
template <class R, class... P>
|
||||
class CallableCustomStaticMethodPointerRet : public CallableCustomMethodPointerBase {
|
||||
R(*method)
|
||||
(P...);
|
||||
struct Data {
|
||||
R(*method)
|
||||
(P...);
|
||||
} data;
|
||||
static_assert(sizeof(Data) % 4 == 0);
|
||||
|
||||
public:
|
||||
virtual Object *get_object() const override {
|
||||
return nullptr;
|
||||
virtual ObjectID get_object() const override {
|
||||
return ObjectID();
|
||||
}
|
||||
|
||||
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...)) {
|
||||
method = p_method;
|
||||
memset(&data, 0, sizeof(Data));
|
||||
data.method = p_method;
|
||||
_setup((uint32_t *)&data, sizeof(Data));
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -200,7 +233,7 @@ template <class R, class... P>
|
|||
Callable create_custom_callable_static_function_pointer(R (*p_method)(P...)) {
|
||||
typedef CallableCustomStaticMethodPointerRet<R, P...> CCMP;
|
||||
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(int32_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(uint64_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(float v) :
|
||||
Variant((double)v) {}
|
||||
|
@ -209,8 +217,12 @@ public:
|
|||
operator bool() const;
|
||||
operator int64_t() const;
|
||||
operator int32_t() const;
|
||||
operator int16_t() const;
|
||||
operator int8_t() const;
|
||||
operator uint64_t() const;
|
||||
operator uint32_t() const;
|
||||
operator uint16_t() const;
|
||||
operator uint8_t() const;
|
||||
operator double() const;
|
||||
operator float() 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>
|
||||
|
||||
#ifdef REAL_T_IS_DOUBLE
|
||||
using PackedRealArray = PackedFloat64Array;
|
||||
#else
|
||||
using PackedRealArray = PackedFloat32Array;
|
||||
#endif // REAL_T_IS_DOUBLE
|
||||
|
||||
} // namespace godot
|
||||
|
||||
#endif // GODOT_VARIANT_HPP
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/**************************************************************************/
|
||||
/* editor_plugin.cpp */
|
||||
/* editor_plugin_registration.cpp */
|
||||
/**************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
|
@ -28,9 +28,9 @@
|
|||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
/**************************************************************************/
|
||||
|
||||
#include <godot_cpp/classes/editor_plugin.hpp>
|
||||
#include <godot_cpp/classes/editor_plugin_registration.hpp>
|
||||
|
||||
#include <godot_cpp/variant/string_name.hpp>
|
||||
#include <godot_cpp/variant/variant.hpp>
|
||||
|
||||
namespace godot {
|
||||
|
|
@ -28,12 +28,16 @@
|
|||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
/**************************************************************************/
|
||||
|
||||
#include <vector>
|
||||
|
||||
#include <godot_cpp/classes/wrapped.hpp>
|
||||
|
||||
#include <godot_cpp/variant/builtin_types.hpp>
|
||||
|
||||
#include <godot_cpp/classes/object.hpp>
|
||||
|
||||
#include <godot_cpp/core/class_db.hpp>
|
||||
|
||||
namespace godot {
|
||||
|
||||
const StringName *Wrapped::_get_extension_class_name() const {
|
||||
|
@ -46,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_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) {
|
||||
|
@ -81,6 +91,11 @@ void postinitialize_handler(Wrapped *p_wrapped) {
|
|||
|
||||
namespace internal {
|
||||
|
||||
std::vector<EngineClassRegistrationCallback> &get_engine_class_registration_callbacks() {
|
||||
static std::vector<EngineClassRegistrationCallback> engine_class_registration_callbacks;
|
||||
return engine_class_registration_callbacks;
|
||||
}
|
||||
|
||||
GDExtensionPropertyInfo *create_c_property_list(const ::godot::List<::godot::PropertyInfo> &plist_cpp, uint32_t *r_size) {
|
||||
GDExtensionPropertyInfo *plist = nullptr;
|
||||
// Linked list size can be expensive to get so we cache it
|
||||
|
@ -106,6 +121,22 @@ void free_c_property_list(GDExtensionPropertyInfo *plist) {
|
|||
memfree(plist);
|
||||
}
|
||||
|
||||
void add_engine_class_registration_callback(EngineClassRegistrationCallback p_callback) {
|
||||
get_engine_class_registration_callbacks().push_back(p_callback);
|
||||
}
|
||||
|
||||
void register_engine_class(const StringName &p_name, const GDExtensionInstanceBindingCallbacks *p_callbacks) {
|
||||
ClassDB::_register_engine_class(p_name, p_callbacks);
|
||||
}
|
||||
|
||||
void register_engine_classes() {
|
||||
std::vector<EngineClassRegistrationCallback> &engine_class_registration_callbacks = get_engine_class_registration_callbacks();
|
||||
for (EngineClassRegistrationCallback cb : engine_class_registration_callbacks) {
|
||||
cb();
|
||||
}
|
||||
engine_class_registration_callbacks.clear();
|
||||
}
|
||||
|
||||
} // namespace internal
|
||||
|
||||
} // namespace godot
|
||||
|
|
|
@ -103,28 +103,29 @@ _GlobalNil _GlobalNilClass::_nil;
|
|||
|
||||
} // namespace godot
|
||||
|
||||
void *operator new(size_t p_size, const char *p_description) {
|
||||
// p_dummy argument is added to avoid conflicts with the engine functions when both engine and GDExtension are built as a static library on iOS.
|
||||
void *operator new(size_t p_size, const char *p_dummy, const char *p_description) {
|
||||
return godot::Memory::alloc_static(p_size);
|
||||
}
|
||||
|
||||
void *operator new(size_t p_size, void *(*p_allocfunc)(size_t p_size)) {
|
||||
void *operator new(size_t p_size, const char *p_dummy, void *(*p_allocfunc)(size_t p_size)) {
|
||||
return p_allocfunc(p_size);
|
||||
}
|
||||
|
||||
using namespace godot;
|
||||
|
||||
#ifdef _MSC_VER
|
||||
void operator delete(void *p_mem, const char *p_description) {
|
||||
void operator delete(void *p_mem, const char *p_dummy, const char *p_description) {
|
||||
ERR_PRINT("Call to placement delete should not happen.");
|
||||
CRASH_NOW();
|
||||
}
|
||||
|
||||
void operator delete(void *p_mem, void *(*p_allocfunc)(size_t p_size)) {
|
||||
void operator delete(void *p_mem, const char *p_dummy, void *(*p_allocfunc)(size_t p_size)) {
|
||||
ERR_PRINT("Call to placement delete should not happen.");
|
||||
CRASH_NOW();
|
||||
}
|
||||
|
||||
void operator delete(void *p_mem, void *p_pointer, size_t check, const char *p_description) {
|
||||
void operator delete(void *p_mem, const char *p_dummy, void *p_pointer, size_t check, const char *p_description) {
|
||||
ERR_PRINT("Call to placement delete should not happen.");
|
||||
CRASH_NOW();
|
||||
}
|
||||
|
|
105
src/godot.cpp
105
src/godot.cpp
|
@ -30,7 +30,7 @@
|
|||
|
||||
#include <godot_cpp/godot.hpp>
|
||||
|
||||
#include <godot_cpp/classes/editor_plugin.hpp>
|
||||
#include <godot_cpp/classes/editor_plugin_registration.hpp>
|
||||
#include <godot_cpp/classes/wrapped.hpp>
|
||||
#include <godot_cpp/core/class_db.hpp>
|
||||
#include <godot_cpp/core/memory.hpp>
|
||||
|
@ -172,6 +172,7 @@ GDExtensionInterfaceObjectCastTo gdextension_interface_object_cast_to = nullptr;
|
|||
GDExtensionInterfaceObjectGetInstanceFromId gdextension_interface_object_get_instance_from_id = nullptr;
|
||||
GDExtensionInterfaceObjectGetInstanceId gdextension_interface_object_get_instance_id = nullptr;
|
||||
GDExtensionInterfaceCallableCustomCreate gdextension_interface_callable_custom_create = nullptr;
|
||||
GDExtensionInterfaceCallableCustomGetUserData gdextension_interface_callable_custom_get_userdata = nullptr;
|
||||
GDExtensionInterfaceRefGetObject gdextension_interface_ref_get_object = nullptr;
|
||||
GDExtensionInterfaceRefSetObject gdextension_interface_ref_set_object = nullptr;
|
||||
GDExtensionInterfaceScriptInstanceCreate2 gdextension_interface_script_instance_create2 = nullptr;
|
||||
|
@ -180,7 +181,7 @@ GDExtensionInterfacePlaceHolderScriptInstanceUpdate gdextension_interface_placeh
|
|||
GDExtensionInterfaceClassdbConstructObject gdextension_interface_classdb_construct_object = nullptr;
|
||||
GDExtensionInterfaceClassdbGetMethodBind gdextension_interface_classdb_get_method_bind = nullptr;
|
||||
GDExtensionInterfaceClassdbGetClassTag gdextension_interface_classdb_get_class_tag = nullptr;
|
||||
GDExtensionInterfaceClassdbRegisterExtensionClass2 gdextension_interface_classdb_register_extension_class2 = nullptr;
|
||||
GDExtensionInterfaceClassdbRegisterExtensionClass3 gdextension_interface_classdb_register_extension_class3 = nullptr;
|
||||
GDExtensionInterfaceClassdbRegisterExtensionClassMethod gdextension_interface_classdb_register_extension_class_method = nullptr;
|
||||
GDExtensionInterfaceClassdbRegisterExtensionClassIntegerConstant gdextension_interface_classdb_register_extension_class_integer_constant = nullptr;
|
||||
GDExtensionInterfaceClassdbRegisterExtensionClassProperty gdextension_interface_classdb_register_extension_class_property = nullptr;
|
||||
|
@ -195,9 +196,9 @@ GDExtensionInterfaceEditorRemovePlugin gdextension_interface_editor_remove_plugi
|
|||
|
||||
} // namespace internal
|
||||
|
||||
GDExtensionBinding::Callback GDExtensionBinding::init_callback = nullptr;
|
||||
GDExtensionBinding::Callback GDExtensionBinding::terminate_callback = nullptr;
|
||||
GDExtensionInitializationLevel GDExtensionBinding::minimum_initialization_level = GDEXTENSION_INITIALIZATION_CORE;
|
||||
bool GDExtensionBinding::api_initialized = false;
|
||||
int GDExtensionBinding::level_initialized[MODULE_INITIALIZATION_LEVEL_MAX] = { 0 };
|
||||
GDExtensionBinding::InitDataList GDExtensionBinding::initdata;
|
||||
|
||||
#define ERR_PRINT_EARLY(m_msg) \
|
||||
internal::gdextension_interface_print_error(m_msg, FUNCTION_STR, __FILE__, __LINE__, false)
|
||||
|
@ -224,7 +225,20 @@ typedef struct {
|
|||
GDExtensionInterfacePrintErrorWithMessage print_error_with_message;
|
||||
} 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.
|
||||
uint32_t *raw_interface = (uint32_t *)(void *)p_get_proc_address;
|
||||
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) {
|
||||
compatible = internal::godot_version.minor > GODOT_VERSION_MINOR;
|
||||
} else {
|
||||
#if GODOT_VERSION_PATCH > 0
|
||||
compatible = internal::godot_version.patch >= GODOT_VERSION_PATCH;
|
||||
#else
|
||||
// Prevent -Wtype-limits warning due to unsigned comparison.
|
||||
compatible = true;
|
||||
#endif
|
||||
}
|
||||
if (!compatible) {
|
||||
// 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_id, GDExtensionInterfaceObjectGetInstanceId);
|
||||
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_set_object, GDExtensionInterfaceRefSetObject);
|
||||
LOAD_PROC_ADDRESS(script_instance_create2, GDExtensionInterfaceScriptInstanceCreate2);
|
||||
|
@ -398,7 +418,7 @@ GDExtensionBool GDExtensionBinding::init(GDExtensionInterfaceGetProcAddress p_ge
|
|||
LOAD_PROC_ADDRESS(classdb_construct_object, GDExtensionInterfaceClassdbConstructObject);
|
||||
LOAD_PROC_ADDRESS(classdb_get_method_bind, GDExtensionInterfaceClassdbGetMethodBind);
|
||||
LOAD_PROC_ADDRESS(classdb_get_class_tag, GDExtensionInterfaceClassdbGetClassTag);
|
||||
LOAD_PROC_ADDRESS(classdb_register_extension_class2, GDExtensionInterfaceClassdbRegisterExtensionClass2);
|
||||
LOAD_PROC_ADDRESS(classdb_register_extension_class3, GDExtensionInterfaceClassdbRegisterExtensionClass3);
|
||||
LOAD_PROC_ADDRESS(classdb_register_extension_class_method, GDExtensionInterfaceClassdbRegisterExtensionClassMethod);
|
||||
LOAD_PROC_ADDRESS(classdb_register_extension_class_integer_constant, GDExtensionInterfaceClassdbRegisterExtensionClassIntegerConstant);
|
||||
LOAD_PROC_ADDRESS(classdb_register_extension_class_property, GDExtensionInterfaceClassdbRegisterExtensionClassProperty);
|
||||
|
@ -413,59 +433,96 @@ GDExtensionBool GDExtensionBinding::init(GDExtensionInterfaceGetProcAddress p_ge
|
|||
|
||||
r_initialization->initialize = initialize_level;
|
||||
r_initialization->deinitialize = deinitialize_level;
|
||||
r_initialization->minimum_initialization_level = minimum_initialization_level;
|
||||
|
||||
ERR_FAIL_NULL_V_MSG(init_callback, false, "Initialization callback must be defined.");
|
||||
r_initialization->userdata = p_init_data;
|
||||
r_initialization->minimum_initialization_level = p_init_data->minimum_initialization_level;
|
||||
|
||||
Variant::init_bindings();
|
||||
register_engine_classes();
|
||||
godot::internal::register_engine_classes();
|
||||
|
||||
api_initialized = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
#undef LOAD_PROC_ADDRESS
|
||||
#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;
|
||||
|
||||
if (init_callback) {
|
||||
init_callback(static_cast<ModuleInitializationLevel>(p_level));
|
||||
InitData *init_data = static_cast<InitData *>(p_userdata);
|
||||
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;
|
||||
|
||||
if (terminate_callback) {
|
||||
terminate_callback(static_cast<ModuleInitializationLevel>(p_level));
|
||||
InitData *init_data = static_cast<InitData *>(p_userdata);
|
||||
if (init_data && init_data->terminate_callback) {
|
||||
init_data->terminate_callback(static_cast<ModuleInitializationLevel>(p_level));
|
||||
}
|
||||
|
||||
EditorPlugins::deinitialize(p_level);
|
||||
ClassDB::deinitialize(p_level);
|
||||
level_initialized[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) {
|
||||
get_proc_address = p_get_proc_address;
|
||||
library = p_library;
|
||||
initialization = r_initialization;
|
||||
init_data = new InitData();
|
||||
GDExtensionBinding::initdata.add(init_data);
|
||||
}
|
||||
|
||||
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 {
|
||||
GDExtensionBinding::terminate_callback = p_terminate;
|
||||
init_data->terminate_callback = p_terminate;
|
||||
}
|
||||
|
||||
void GDExtensionBinding::InitObject::set_minimum_library_initialization_level(ModuleInitializationLevel p_level) const {
|
||||
GDExtensionBinding::minimum_initialization_level = static_cast<GDExtensionInitializationLevel>(p_level);
|
||||
init_data->minimum_initialization_level = static_cast<GDExtensionInitializationLevel>(p_level);
|
||||
}
|
||||
|
||||
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
|
||||
|
|
|
@ -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/godot.hpp>
|
||||
#include <godot_cpp/templates/hashfuncs.hpp>
|
||||
|
||||
namespace godot {
|
||||
|
||||
static void call_custom_callable(void *userdata, const GDExtensionConstVariantPtr *p_args, GDExtensionInt p_argument_count, GDExtensionVariantPtr r_return, GDExtensionCallError *r_error) {
|
||||
CallableCustomMethodPointerBase *callable_method_pointer = (CallableCustomMethodPointerBase *)userdata;
|
||||
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 *)p_userdata;
|
||||
callable_method_pointer->call((const Variant **)p_args, p_argument_count, *(Variant *)r_return, *r_error);
|
||||
}
|
||||
|
||||
static void free_custom_callable(void *userdata) {
|
||||
CallableCustomMethodPointerBase *callable_method_pointer = (CallableCustomMethodPointerBase *)userdata;
|
||||
static GDExtensionBool custom_callable_mp_is_valid(void *p_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);
|
||||
}
|
||||
|
||||
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 {
|
||||
|
||||
Callable create_custom_callable(CallableCustomMethodPointerBase *p_callable_method_pointer) {
|
||||
Object *object = p_callable_method_pointer->get_object();
|
||||
|
||||
Callable create_callable_from_ccmp(CallableCustomMethodPointerBase *p_callable_method_pointer) {
|
||||
GDExtensionCallableCustomInfo info = {};
|
||||
info.callable_userdata = p_callable_method_pointer;
|
||||
info.token = internal::token;
|
||||
info.object = object != nullptr ? object->_owner : nullptr;
|
||||
info.call_func = &call_custom_callable;
|
||||
info.free_func = &free_custom_callable;
|
||||
info.object_id = p_callable_method_pointer->get_object();
|
||||
info.call_func = &custom_callable_mp_call;
|
||||
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;
|
||||
::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());
|
||||
}
|
||||
|
||||
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 {
|
||||
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());
|
||||
}
|
||||
|
||||
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 {
|
||||
double result;
|
||||
to_type_constructor[FLOAT](&result, _native_ptr());
|
||||
|
@ -638,14 +654,16 @@ bool Variant::in(const Variant &index, bool *r_valid) const {
|
|||
|
||||
bool Variant::iter_init(Variant &r_iter, bool &r_valid) const {
|
||||
GDExtensionBool valid;
|
||||
internal::gdextension_interface_variant_iter_init(_native_ptr(), r_iter._native_ptr(), &valid);
|
||||
return PtrToArg<bool>::convert(&valid);
|
||||
GDExtensionBool result = internal::gdextension_interface_variant_iter_init(_native_ptr(), r_iter._native_ptr(), &valid);
|
||||
r_valid = PtrToArg<bool>::convert(&valid);
|
||||
return PtrToArg<bool>::convert(&result);
|
||||
}
|
||||
|
||||
bool Variant::iter_next(Variant &r_iter, bool &r_valid) const {
|
||||
GDExtensionBool valid;
|
||||
internal::gdextension_interface_variant_iter_next(_native_ptr(), r_iter._native_ptr(), &valid);
|
||||
return PtrToArg<bool>::convert(&valid);
|
||||
GDExtensionBool result = internal::gdextension_interface_variant_iter_next(_native_ptr(), r_iter._native_ptr(), &valid);
|
||||
r_valid = PtrToArg<bool>::convert(&valid);
|
||||
return PtrToArg<bool>::convert(&result);
|
||||
}
|
||||
|
||||
Variant Variant::iter_get(const Variant &r_iter, bool &r_valid) const {
|
||||
|
|
|
@ -36,7 +36,7 @@ set(GODOT_LINKER_FLAGS )
|
|||
|
||||
if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC")
|
||||
# using Visual Studio C++
|
||||
set(GODOT_COMPILE_FLAGS "${GODOT_COMPILE_FLAGS} /EHsc /WX") # /GF /MP
|
||||
set(GODOT_COMPILE_FLAGS "${GODOT_COMPILE_FLAGS} /WX") # /GF /MP
|
||||
set(GODOT_COMPILE_FLAGS "${GODOT_COMPILE_FLAGS} /DTYPED_METHOD_BIND")
|
||||
|
||||
if(CMAKE_BUILD_TYPE MATCHES Debug)
|
||||
|
@ -59,31 +59,9 @@ if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC")
|
|||
|
||||
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'")
|
||||
|
||||
# Hmm.. maybe to strikt?
|
||||
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)
|
||||
set(GODOT_COMPILE_FLAGS "${GODOT_COMPILE_FLAGS} -fno-omit-frame-pointer -O0")
|
||||
|
@ -92,6 +70,21 @@ else()
|
|||
endif(CMAKE_BUILD_TYPE MATCHES Debug)
|
||||
endif()
|
||||
|
||||
# Disable exception handling. Godot doesn't use exceptions anywhere, and this
|
||||
# saves around 20% of binary size and very significant build time (GH-80513).
|
||||
option(GODOT_DISABLE_EXCEPTIONS ON "Force disabling exception handling code")
|
||||
if (GODOT_DISABLE_EXCEPTIONS)
|
||||
if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC")
|
||||
set(GODOT_COMPILE_FLAGS "${GODOT_COMPILE_FLAGS} -D_HAS_EXCEPTIONS=0")
|
||||
else()
|
||||
set(GODOT_COMPILE_FLAGS "${GODOT_COMPILE_FLAGS} -fno-exceptions")
|
||||
endif()
|
||||
else()
|
||||
if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC")
|
||||
set(GODOT_COMPILE_FLAGS "${GODOT_COMPILE_FLAGS} /EHsc")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# Get Sources
|
||||
file(GLOB_RECURSE SOURCES src/*.c**)
|
||||
file(GLOB_RECURSE HEADERS include/*.h**)
|
||||
|
|
|
@ -23,6 +23,17 @@ if env["platform"] == "macos":
|
|||
),
|
||||
source=sources,
|
||||
)
|
||||
elif env["platform"] == "ios":
|
||||
if env["ios_simulator"]:
|
||||
library = env.StaticLibrary(
|
||||
"project/bin/libgdexample.{}.{}.simulator.a".format(env["platform"], env["target"]),
|
||||
source=sources,
|
||||
)
|
||||
else:
|
||||
library = env.StaticLibrary(
|
||||
"project/bin/libgdexample.{}.{}.a".format(env["platform"], env["target"]),
|
||||
source=sources,
|
||||
)
|
||||
else:
|
||||
library = env.SharedLibrary(
|
||||
"project/bin/libgdexample{}{}".format(env["suffix"], env["SHLIBSUFFIX"]),
|
||||
|
|
|
@ -0,0 +1,7 @@
|
|||
#!/bin/sh
|
||||
|
||||
scons arch=universal ios_simulator=yes platform=ios target=$1 $2
|
||||
scons arch=arm64 ios_simulator=no platform=ios target=$1 $2
|
||||
|
||||
xcodebuild -create-xcframework -library ./project/bin/libgdexample.ios.$1.a -library ./project/bin/libgdexample.ios.$1.simulator.a -output ./project/bin/libgdexample.ios.$1.xcframework
|
||||
xcodebuild -create-xcframework -library ../bin/libgodot-cpp.ios.$1.arm64.a -library ../bin/libgodot-cpp.ios.$1.universal.simulator.a -output ./project/bin/libgodot-cpp.ios.$1.xcframework
|
|
@ -11,8 +11,14 @@ windows.debug.x86_32 = "res://bin/libgdexample.windows.template_debug.x86_32.dll
|
|||
windows.release.x86_32 = "res://bin/libgdexample.windows.template_release.x86_32.dll"
|
||||
windows.debug.x86_64 = "res://bin/libgdexample.windows.template_debug.x86_64.dll"
|
||||
windows.release.x86_64 = "res://bin/libgdexample.windows.template_release.x86_64.dll"
|
||||
windows.debug.arm64 = "res://bin/libgdexample.windows.template_debug.arm64.dll"
|
||||
windows.release.arm64 = "res://bin/libgdexample.windows.template_release.arm64.dll"
|
||||
linux.debug.x86_32 = "res://bin/libgdexample.linux.template_debug.x86_32.so"
|
||||
linux.release.x86_32 = "res://bin/libgdexample.linux.template_release.x86_32.so"
|
||||
linux.debug.x86_64 = "res://bin/libgdexample.linux.template_debug.x86_64.so"
|
||||
linux.release.x86_64 = "res://bin/libgdexample.linux.template_release.x86_64.so"
|
||||
linux.debug.arm32 = "res://bin/libgdexample.linux.template_debug.arm32.so"
|
||||
linux.release.arm32 = "res://bin/libgdexample.linux.template_release.arm32.so"
|
||||
linux.debug.arm64 = "res://bin/libgdexample.linux.template_debug.arm64.so"
|
||||
linux.release.arm64 = "res://bin/libgdexample.linux.template_release.arm64.so"
|
||||
linux.debug.rv64 = "res://bin/libgdexample.linux.template_debug.rv64.so"
|
||||
|
@ -21,5 +27,15 @@ android.debug.x86_64 = "res://bin/libgdexample.android.template_debug.x86_64.so"
|
|||
android.release.x86_64 = "res://bin/libgdexample.android.template_release.x86_64.so"
|
||||
android.debug.arm64 = "res://bin/libgdexample.android.template_debug.arm64.so"
|
||||
android.release.arm64 = "res://bin/libgdexample.android.template_release.arm64.so"
|
||||
ios.debug = "res://bin/libgdexample.ios.template_debug.xcframework"
|
||||
ios.release = "res://bin/libgdexample.ios.template_release.xcframework"
|
||||
web.debug.wasm32 = "res://bin/libgdexample.web.template_debug.wasm32.wasm"
|
||||
web.release.wasm32 = "res://bin/libgdexample.web.template_release.wasm32.wasm"
|
||||
|
||||
[dependencies]
|
||||
ios.debug = {
|
||||
"res://bin/libgodot-cpp.ios.template_debug.xcframework": ""
|
||||
}
|
||||
ios.release = {
|
||||
"res://bin/libgodot-cpp.ios.template_release.xcframework": ""
|
||||
}
|
||||
|
|
|
@ -83,6 +83,9 @@ func _ready():
|
|||
var array: Array[int] = [1, 2, 3]
|
||||
assert_equal(example.test_tarray_arg(array), 6)
|
||||
|
||||
example.callable_bind()
|
||||
assert_equal(custom_signal_emitted, ["bound", 11])
|
||||
|
||||
# String += operator
|
||||
assert_equal(example.test_string_ops(), "ABCĎE")
|
||||
|
||||
|
@ -98,9 +101,20 @@ func _ready():
|
|||
|
||||
# mp_callable() with void method.
|
||||
var mp_callable: Callable = example.test_callable_mp()
|
||||
assert_equal(mp_callable.is_valid(), true)
|
||||
mp_callable.call(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.
|
||||
var mp_callable_ret: Callable = example.test_callable_mp_ret()
|
||||
assert_equal(mp_callable_ret.call(example, "test", 77), "unbound_method2: Example - test - 77")
|
||||
|
@ -114,10 +128,30 @@ func _ready():
|
|||
mp_callable_static.call(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.
|
||||
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")
|
||||
|
||||
# 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
|
||||
assert_equal(example.test_vector_ops(), 105)
|
||||
|
||||
|
@ -184,6 +218,10 @@ func _ready():
|
|||
assert_equal(example.test_bitfield(0), 0)
|
||||
assert_equal(example.test_bitfield(Example.FLAG_ONE | Example.FLAG_TWO), 3)
|
||||
|
||||
# Test variant iterator.
|
||||
assert_equal(example.test_variant_iterator([10, 20, 30]), [15, 25, 35])
|
||||
assert_equal(example.test_variant_iterator(null), "iter_init: not valid")
|
||||
|
||||
# RPCs.
|
||||
assert_equal(example.return_last_rpc_arg(), 0)
|
||||
example.test_rpc(42)
|
||||
|
@ -198,6 +236,11 @@ func _ready():
|
|||
get_viewport().push_input(event)
|
||||
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()
|
||||
|
||||
func _on_Example_custom_signal(signal_name, value):
|
||||
|
|
|
@ -21,4 +21,5 @@ paths=["res://example.gdextension"]
|
|||
|
||||
[rendering]
|
||||
|
||||
textures/vram_compression/import_etc2_astc=true
|
||||
environment/defaults/default_environment="res://default_env.tres"
|
||||
|
|
|
@ -15,6 +15,46 @@
|
|||
|
||||
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) {
|
||||
id = p_id;
|
||||
}
|
||||
|
@ -23,10 +63,18 @@ int ExampleRef::get_id() const {
|
|||
return id;
|
||||
}
|
||||
|
||||
void ExampleRef::_notification(int p_what) {
|
||||
if (p_what == NOTIFICATION_POSTINITIALIZE) {
|
||||
post_initialized = true;
|
||||
}
|
||||
}
|
||||
|
||||
void ExampleRef::_bind_methods() {
|
||||
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("was_post_initialized"), &ExampleRef::was_post_initialized);
|
||||
|
||||
ADD_PROPERTY(PropertyInfo(Variant::INT, "id"), "set_id", "get_id");
|
||||
}
|
||||
|
||||
|
@ -168,14 +216,19 @@ 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_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_custom_callable"), &Example::test_custom_callable);
|
||||
|
||||
ClassDB::bind_method(D_METHOD("test_bitfield", "flags"), &Example::test_bitfield);
|
||||
|
||||
ClassDB::bind_method(D_METHOD("test_variant_iterator", "input"), &Example::test_variant_iterator);
|
||||
|
||||
ClassDB::bind_method(D_METHOD("test_rpc", "value"), &Example::test_rpc);
|
||||
ClassDB::bind_method(D_METHOD("test_send_rpc", "value"), &Example::test_send_rpc);
|
||||
ClassDB::bind_method(D_METHOD("return_last_rpc_arg"), &Example::return_last_rpc_arg);
|
||||
|
||||
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("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_static2"), &Example::test_static2);
|
||||
|
@ -375,6 +428,10 @@ Callable Example::test_callable_mp_static_ret() const {
|
|||
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) {
|
||||
String test = "unbound_method1: ";
|
||||
test += p_object->get_class();
|
||||
|
@ -484,6 +541,41 @@ BitField<Example::Flags> Example::test_bitfield(BitField<Flags> flags) {
|
|||
return flags;
|
||||
}
|
||||
|
||||
Variant Example::test_variant_iterator(const Variant &p_input) {
|
||||
Array output;
|
||||
|
||||
Variant iter;
|
||||
|
||||
bool is_init_valid = true;
|
||||
if (!p_input.iter_init(iter, is_init_valid)) {
|
||||
if (!is_init_valid) {
|
||||
return "iter_init: not valid";
|
||||
}
|
||||
return output;
|
||||
}
|
||||
|
||||
bool is_iter_next_valid = true;
|
||||
bool is_iter_get_valid = true;
|
||||
do {
|
||||
if (!is_iter_next_valid) {
|
||||
return "iter_next: not valid";
|
||||
}
|
||||
|
||||
Variant value = p_input.iter_get(iter, is_iter_get_valid);
|
||||
if (!is_iter_get_valid) {
|
||||
return "iter_get: not valid";
|
||||
}
|
||||
output.push_back(((int)value) + 5);
|
||||
|
||||
} while (p_input.iter_next(iter, is_iter_next_valid));
|
||||
|
||||
if (!is_iter_next_valid) {
|
||||
return "iter_next: not valid";
|
||||
}
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
void Example::test_rpc(int p_value) {
|
||||
last_rpc_arg = p_value;
|
||||
}
|
||||
|
@ -496,6 +588,11 @@ int Example::return_last_rpc_arg() {
|
|||
return last_rpc_arg;
|
||||
}
|
||||
|
||||
void Example::callable_bind() {
|
||||
Callable c = Callable(this, "emit_custom_signal").bind("bound", 11);
|
||||
c.call();
|
||||
}
|
||||
|
||||
// Properties.
|
||||
void Example::set_custom_position(const Vector2 &pos) {
|
||||
custom_position = pos;
|
||||
|
@ -509,6 +606,12 @@ Vector4 Example::get_v4() const {
|
|||
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.
|
||||
bool Example::_has_point(const Vector2 &point) const {
|
||||
Label *label = get_node<Label>("Label");
|
||||
|
@ -523,3 +626,23 @@ void Example::_input(const Ref<InputEvent> &event) {
|
|||
emit_custom_signal(String("_input: ") + key_event->get_key_label(), key_event->get_unicode());
|
||||
}
|
||||
}
|
||||
|
||||
void ExampleGameplay::_bind_methods() {
|
||||
ClassDB::bind_method(D_METHOD("set_prop_value", "value"), &ExampleGameplay::set_prop_value);
|
||||
ClassDB::bind_method(D_METHOD("get_prop_value"), &ExampleGameplay::get_prop_value);
|
||||
ADD_PROPERTY(PropertyInfo(Variant::INT, "prop_value"), "set_prop_value", "get_prop_value");
|
||||
}
|
||||
|
||||
void ExampleGameplay::set_prop_value(int p_prop_value) {
|
||||
prop_value = p_prop_value;
|
||||
}
|
||||
|
||||
int ExampleGameplay::get_prop_value() const {
|
||||
return prop_value;
|
||||
}
|
||||
|
||||
ExampleGameplay::ExampleGameplay() {
|
||||
}
|
||||
|
||||
ExampleGameplay::~ExampleGameplay() {
|
||||
}
|
||||
|
|
|
@ -35,16 +35,21 @@ private:
|
|||
static int last_id;
|
||||
|
||||
int id;
|
||||
bool post_initialized = false;
|
||||
|
||||
protected:
|
||||
static void _bind_methods();
|
||||
|
||||
void _notification(int p_what);
|
||||
|
||||
public:
|
||||
ExampleRef();
|
||||
~ExampleRef();
|
||||
|
||||
void set_id(int p_id);
|
||||
int get_id() const;
|
||||
|
||||
bool was_post_initialized() const { return post_initialized; }
|
||||
};
|
||||
|
||||
class ExampleMin : public Control {
|
||||
|
@ -143,6 +148,7 @@ public:
|
|||
Callable test_callable_mp_retc() const;
|
||||
Callable test_callable_mp_static() 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);
|
||||
String unbound_method2(Object *p_object, String p_string, int p_int);
|
||||
|
@ -152,16 +158,22 @@ public:
|
|||
|
||||
BitField<Flags> test_bitfield(BitField<Flags> flags);
|
||||
|
||||
Variant test_variant_iterator(const Variant &p_input);
|
||||
|
||||
// RPC
|
||||
void test_rpc(int p_value);
|
||||
void test_send_rpc(int p_value);
|
||||
int return_last_rpc_arg();
|
||||
|
||||
void callable_bind();
|
||||
|
||||
// Property.
|
||||
void set_custom_position(const Vector2 &pos);
|
||||
Vector2 get_custom_position() const;
|
||||
Vector4 get_v4() const;
|
||||
|
||||
bool test_post_initialize() const;
|
||||
|
||||
// Static method.
|
||||
static int test_static(int p_a, int p_b);
|
||||
static void test_static2();
|
||||
|
@ -193,4 +205,20 @@ protected:
|
|||
static void _bind_methods() {}
|
||||
};
|
||||
|
||||
class ExampleGameplay : public Node {
|
||||
GDCLASS(ExampleGameplay, Node);
|
||||
|
||||
int prop_value = 12;
|
||||
|
||||
protected:
|
||||
static void _bind_methods();
|
||||
|
||||
public:
|
||||
void set_prop_value(int p_prop_value);
|
||||
int get_prop_value() const;
|
||||
|
||||
ExampleGameplay();
|
||||
~ExampleGameplay();
|
||||
};
|
||||
|
||||
#endif // EXAMPLE_CLASS_H
|
||||
|
|
|
@ -26,6 +26,7 @@ void initialize_example_module(ModuleInitializationLevel p_level) {
|
|||
ClassDB::register_class<Example>();
|
||||
ClassDB::register_class<ExampleVirtual>(true);
|
||||
ClassDB::register_abstract_class<ExampleAbstract>();
|
||||
ClassDB::register_gameplay_class<ExampleGameplay>();
|
||||
}
|
||||
|
||||
void uninitialize_example_module(ModuleInitializationLevel p_level) {
|
||||
|
|
|
@ -8,23 +8,35 @@ def options(opts):
|
|||
opts.Add(
|
||||
"android_api_level",
|
||||
"Target Android API level",
|
||||
"18" if "32" in ARGUMENTS.get("arch", "arm64") else "21",
|
||||
"21",
|
||||
)
|
||||
opts.Add(
|
||||
"ANDROID_NDK_ROOT",
|
||||
"Path to your Android NDK installation. By default, uses ANDROID_NDK_ROOT from your defined environment variables.",
|
||||
os.environ.get("ANDROID_NDK_ROOT", None),
|
||||
"ANDROID_HOME",
|
||||
"Path to your Android SDK installation. By default, uses ANDROID_HOME from your defined environment variables.",
|
||||
os.environ.get("ANDROID_HOME", os.environ.get("ANDROID_SDK_ROOT")),
|
||||
)
|
||||
|
||||
|
||||
def exists(env):
|
||||
return "ANDROID_NDK_ROOT" in os.environ or "ANDROID_NDK_ROOT" in ARGUMENTS
|
||||
return get_android_ndk_root(env) is not None
|
||||
|
||||
|
||||
# This must be kept in sync with the value in https://github.com/godotengine/godot/blob/master/platform/android/detect.py#L58.
|
||||
def get_ndk_version():
|
||||
return "23.2.8568313"
|
||||
|
||||
|
||||
def get_android_ndk_root(env):
|
||||
if env["ANDROID_HOME"]:
|
||||
return env["ANDROID_HOME"] + "/ndk/" + get_ndk_version()
|
||||
else:
|
||||
return os.environ.get("ANDROID_NDK_ROOT")
|
||||
|
||||
|
||||
def generate(env):
|
||||
if "ANDROID_NDK_ROOT" not in env:
|
||||
if get_android_ndk_root(env) is None:
|
||||
raise ValueError(
|
||||
"To build for Android, ANDROID_NDK_ROOT must be defined. Please set ANDROID_NDK_ROOT to the root folder of your Android NDK installation."
|
||||
"To build for Android, the path to the NDK must be defined. Please set ANDROID_HOME to the root folder of your Android SDK installation."
|
||||
)
|
||||
|
||||
if env["arch"] not in ("arm64", "x86_64", "arm32", "x86_32"):
|
||||
|
@ -35,14 +47,12 @@ def generate(env):
|
|||
my_spawn.configure(env)
|
||||
|
||||
# Validate API level
|
||||
api_level = int(env["android_api_level"])
|
||||
if "64" in env["arch"] and api_level < 21:
|
||||
print("WARN: 64-bit Android architectures require an API level of at least 21; setting android_api_level=21")
|
||||
if int(env["android_api_level"]) < 21:
|
||||
print("WARNING: minimum supported Android target api is 21. Forcing target api 21.")
|
||||
env["android_api_level"] = "21"
|
||||
api_level = 21
|
||||
|
||||
# Setup toolchain
|
||||
toolchain = env["ANDROID_NDK_ROOT"] + "/toolchains/llvm/prebuilt/"
|
||||
toolchain = get_android_ndk_root(env) + "/toolchains/llvm/prebuilt/"
|
||||
if sys.platform == "win32" or sys.platform == "msys":
|
||||
toolchain += "windows"
|
||||
import platform as pltfm
|
||||
|
|
|
@ -179,7 +179,22 @@ def options(opts, env):
|
|||
BoolVariable(
|
||||
key="use_hot_reload",
|
||||
help="Enable the extra accounting required to support hot reload.",
|
||||
default=(env.get("target", "template_debug") != "template_release"),
|
||||
default=env.get("use_hot_reload", None),
|
||||
)
|
||||
)
|
||||
|
||||
opts.Add(
|
||||
BoolVariable(
|
||||
"disable_exceptions", "Force disabling exception handling code", default=env.get("disable_exceptions", True)
|
||||
)
|
||||
)
|
||||
|
||||
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"],
|
||||
)
|
||||
)
|
||||
|
||||
|
@ -239,6 +254,8 @@ def generate(env):
|
|||
|
||||
print("Building for architecture " + env["arch"] + " on platform " + env["platform"])
|
||||
|
||||
if env.get("use_hot_reload") is None:
|
||||
env["use_hot_reload"] = env["target"] != "template_release"
|
||||
if env["use_hot_reload"]:
|
||||
env.Append(CPPDEFINES=["HOT_RELOAD_ENABLED"])
|
||||
|
||||
|
@ -251,6 +268,24 @@ def generate(env):
|
|||
target_tool = Tool("targets", toolpath=["tools"])
|
||||
target_tool.generate(env)
|
||||
|
||||
# Disable exception handling. Godot doesn't use exceptions anywhere, and this
|
||||
# saves around 20% of binary size and very significant build time.
|
||||
if env["disable_exceptions"]:
|
||||
if env.get("is_msvc", False):
|
||||
env.Append(CPPDEFINES=[("_HAS_EXCEPTIONS", 0)])
|
||||
else:
|
||||
env.Append(CXXFLAGS=["-fno-exceptions"])
|
||||
elif env.get("is_msvc", False):
|
||||
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
|
||||
if env.get("is_msvc", False):
|
||||
env.Append(CXXFLAGS=["/std:c++17"])
|
||||
|
@ -260,6 +295,9 @@ def generate(env):
|
|||
if env["precision"] == "double":
|
||||
env.Append(CPPDEFINES=["REAL_T_IS_DOUBLE"])
|
||||
|
||||
# Allow detecting when building as a GDExtension.
|
||||
env.Append(CPPDEFINES=["GDEXTENSION"])
|
||||
|
||||
# Suffix
|
||||
suffix = ".{}.{}".format(env["platform"], env["target"])
|
||||
if env.dev_build:
|
||||
|
@ -274,9 +312,8 @@ def generate(env):
|
|||
env["OBJSUFFIX"] = suffix + env["OBJSUFFIX"]
|
||||
|
||||
# compile_commands.json
|
||||
if env.get("compiledb", False):
|
||||
env.Tool("compilation_db")
|
||||
env.Alias("compiledb", env.CompilationDatabase(normalize_path(env["compiledb_file"], env)))
|
||||
env.Tool("compilation_db")
|
||||
env.Alias("compiledb", env.CompilationDatabase(normalize_path(env["compiledb_file"], env)))
|
||||
|
||||
# Builders
|
||||
env.Append(BUILDERS={"GodotCPPBindings": Builder(action=scons_generate_bindings, emitter=scons_emit_files)})
|
||||
|
@ -284,8 +321,8 @@ def generate(env):
|
|||
|
||||
|
||||
def _godot_cpp(env):
|
||||
api_file = normalize_path(env.get("custom_api_file", env.File("gdextension/extension_api.json").abspath), env)
|
||||
extension_dir = normalize_path(env.get("gdextension_dir", env.Dir("gdextension").abspath), env)
|
||||
api_file = normalize_path(env.get("custom_api_file", env.File(extension_dir + "/extension_api.json").abspath), env)
|
||||
bindings = env.GodotCPPBindings(
|
||||
env.Dir("."),
|
||||
[
|
||||
|
@ -315,7 +352,13 @@ def _godot_cpp(env):
|
|||
|
||||
if env["build_library"]:
|
||||
library = env.StaticLibrary(target=env.File("bin/%s" % library_name), source=sources)
|
||||
env.Default(library)
|
||||
default_args = [library]
|
||||
|
||||
# Add compiledb if the option is set
|
||||
if env.get("compiledb", False):
|
||||
default_args += ["compiledb"]
|
||||
|
||||
env.Default(*default_args)
|
||||
|
||||
env.AppendUnique(LIBS=[env.File("bin/%s" % library_name)])
|
||||
return library
|
||||
|
|
|
@ -21,7 +21,7 @@ def has_ios_osxcross():
|
|||
|
||||
def options(opts):
|
||||
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(
|
||||
"IOS_TOOLCHAIN_PATH",
|
||||
"Path to iOS toolchain",
|
||||
|
|
|
@ -31,7 +31,7 @@ def generate(env):
|
|||
env.Tool("mslink")
|
||||
|
||||
env.Append(CPPDEFINES=["TYPED_METHOD_BIND", "NOMINMAX"])
|
||||
env.Append(CCFLAGS=["/EHsc", "/utf-8"])
|
||||
env.Append(CCFLAGS=["/utf-8"])
|
||||
env.Append(LINKFLAGS=["/WX"])
|
||||
|
||||
if env["use_clang_cl"]:
|
||||
|
|
Loading…
Reference in New Issue