Merge 2cc967787a
into 631cd5fe37
commit
6a73abc560
|
@ -65,7 +65,7 @@ jobs:
|
||||||
platform: android
|
platform: android
|
||||||
artifact-name: godot-cpp-android-arm64-release
|
artifact-name: godot-cpp-android-arm64-release
|
||||||
artifact-path: bin/libgodot-cpp.android.template_release.arm64.a
|
artifact-path: bin/libgodot-cpp.android.template_release.arm64.a
|
||||||
flags: ANDROID_NDK_ROOT=$ANDROID_NDK_LATEST_HOME arch=arm64
|
flags: arch=arm64
|
||||||
run-tests: false
|
run-tests: false
|
||||||
cache-name: android-arm64
|
cache-name: android-arm64
|
||||||
|
|
||||||
|
@ -88,7 +88,7 @@ jobs:
|
||||||
|
|
||||||
env:
|
env:
|
||||||
SCONS_CACHE: ${{ github.workspace }}/.scons-cache/
|
SCONS_CACHE: ${{ github.workspace }}/.scons-cache/
|
||||||
EM_VERSION: 3.1.45
|
EM_VERSION: 3.1.39
|
||||||
EM_CACHE_FOLDER: "emsdk-cache"
|
EM_CACHE_FOLDER: "emsdk-cache"
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
|
@ -104,33 +104,34 @@ jobs:
|
||||||
continue-on-error: true
|
continue-on-error: true
|
||||||
|
|
||||||
- name: Set up Python (for SCons)
|
- name: Set up Python (for SCons)
|
||||||
uses: actions/setup-python@v4
|
uses: actions/setup-python@v5
|
||||||
with:
|
with:
|
||||||
python-version: '3.x'
|
python-version: '3.x'
|
||||||
|
|
||||||
- name: Linux dependencies
|
- name: Android dependencies
|
||||||
if: ${{ matrix.platform == 'linux' }}
|
if: ${{ matrix.platform == 'android' }}
|
||||||
run: |
|
uses: nttld/setup-ndk@v1
|
||||||
sudo apt-get update -qq
|
with:
|
||||||
sudo apt-get install -qqq build-essential pkg-config
|
ndk-version: r23c
|
||||||
|
link-to-sdk: true
|
||||||
|
|
||||||
- name: Web dependencies
|
- name: Web dependencies
|
||||||
if: ${{ matrix.platform == 'web' }}
|
if: ${{ matrix.platform == 'web' }}
|
||||||
uses: mymindstorm/setup-emsdk@v12
|
uses: mymindstorm/setup-emsdk@v13
|
||||||
with:
|
with:
|
||||||
version: ${{env.EM_VERSION}}
|
version: ${{env.EM_VERSION}}
|
||||||
actions-cache-folder: ${{env.EM_CACHE_FOLDER}}
|
actions-cache-folder: ${{env.EM_CACHE_FOLDER}}
|
||||||
|
|
||||||
- name: Install scons
|
|
||||||
run: |
|
|
||||||
python -m pip install scons==4.0.0
|
|
||||||
|
|
||||||
- name: Setup MinGW for Windows/MinGW build
|
- name: Setup MinGW for Windows/MinGW build
|
||||||
if: ${{ matrix.platform == 'windows' && matrix.flags == 'use_mingw=yes' }}
|
if: ${{ matrix.platform == 'windows' && matrix.flags == 'use_mingw=yes' }}
|
||||||
uses: egor-tensin/setup-mingw@v2
|
uses: egor-tensin/setup-mingw@v2
|
||||||
with:
|
with:
|
||||||
version: 12.2.0
|
version: 12.2.0
|
||||||
|
|
||||||
|
- name: Install scons
|
||||||
|
run: |
|
||||||
|
python -m pip install scons==4.0.0
|
||||||
|
|
||||||
- name: Generate godot-cpp sources only
|
- name: Generate godot-cpp sources only
|
||||||
run: |
|
run: |
|
||||||
scons platform=${{ matrix.platform }} build_library=no ${{ matrix.flags }}
|
scons platform=${{ matrix.platform }} build_library=no ${{ matrix.flags }}
|
||||||
|
|
|
@ -47,11 +47,6 @@ option(GODOT_CPP_WARNING_AS_ERROR "Treat warnings as errors" OFF)
|
||||||
# Add path to modules
|
# Add path to modules
|
||||||
list( APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake/" )
|
list( APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake/" )
|
||||||
|
|
||||||
# Check if we are building ourself or being included
|
|
||||||
if(${PROJECT_NAME} STREQUAL ${CMAKE_PROJECT_NAME})
|
|
||||||
set(GODOT_CPP_BUILDING_SELF ON)
|
|
||||||
endif()
|
|
||||||
|
|
||||||
# Set some helper variables for readability
|
# Set some helper variables for readability
|
||||||
set( compiler_is_clang "$<OR:$<CXX_COMPILER_ID:AppleClang>,$<CXX_COMPILER_ID:Clang>>" )
|
set( compiler_is_clang "$<OR:$<CXX_COMPILER_ID:AppleClang>,$<CXX_COMPILER_ID:Clang>>" )
|
||||||
set( compiler_is_gnu "$<CXX_COMPILER_ID:GNU>" )
|
set( compiler_is_gnu "$<CXX_COMPILER_ID:GNU>" )
|
||||||
|
@ -99,10 +94,8 @@ if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC")
|
||||||
|
|
||||||
add_definitions(-DNOMINMAX)
|
add_definitions(-DNOMINMAX)
|
||||||
else() # GCC/Clang
|
else() # GCC/Clang
|
||||||
set(GODOT_COMPILE_FLAGS "${GODOT_COMPILE_FLAGS} -g")
|
|
||||||
|
|
||||||
if(CMAKE_BUILD_TYPE MATCHES Debug)
|
if(CMAKE_BUILD_TYPE MATCHES Debug)
|
||||||
set(GODOT_COMPILE_FLAGS "${GODOT_COMPILE_FLAGS} -fno-omit-frame-pointer -O0")
|
set(GODOT_COMPILE_FLAGS "${GODOT_COMPILE_FLAGS} -fno-omit-frame-pointer -O0 -g")
|
||||||
else()
|
else()
|
||||||
set(GODOT_COMPILE_FLAGS "${GODOT_COMPILE_FLAGS} -O3")
|
set(GODOT_COMPILE_FLAGS "${GODOT_COMPILE_FLAGS} -O3")
|
||||||
endif(CMAKE_BUILD_TYPE MATCHES Debug)
|
endif(CMAKE_BUILD_TYPE MATCHES Debug)
|
||||||
|
@ -134,6 +127,7 @@ endif()
|
||||||
execute_process(COMMAND "${Python3_EXECUTABLE}" "-c" "import binding_generator; binding_generator.print_file_list(\"${GODOT_GDEXTENSION_API_FILE}\", \"${CMAKE_CURRENT_BINARY_DIR}\", headers=True, sources=True)"
|
execute_process(COMMAND "${Python3_EXECUTABLE}" "-c" "import binding_generator; binding_generator.print_file_list(\"${GODOT_GDEXTENSION_API_FILE}\", \"${CMAKE_CURRENT_BINARY_DIR}\", headers=True, sources=True)"
|
||||||
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
|
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
|
||||||
OUTPUT_VARIABLE GENERATED_FILES_LIST
|
OUTPUT_VARIABLE GENERATED_FILES_LIST
|
||||||
|
OUTPUT_STRIP_TRAILING_WHITESPACE
|
||||||
)
|
)
|
||||||
|
|
||||||
add_custom_command(OUTPUT ${GENERATED_FILES_LIST}
|
add_custom_command(OUTPUT ${GENERATED_FILES_LIST}
|
||||||
|
@ -159,12 +153,6 @@ add_library(godot::cpp ALIAS ${PROJECT_NAME})
|
||||||
|
|
||||||
include(GodotCompilerWarnings)
|
include(GodotCompilerWarnings)
|
||||||
|
|
||||||
# Treat warnings as errors if we are building ourself
|
|
||||||
if(GODOT_CPP_BUILDING_SELF)
|
|
||||||
unset( GODOT_CPP_WARNING_AS_ERROR CACHE )
|
|
||||||
set_warning_as_error()
|
|
||||||
endif()
|
|
||||||
|
|
||||||
target_compile_features(${PROJECT_NAME}
|
target_compile_features(${PROJECT_NAME}
|
||||||
PRIVATE
|
PRIVATE
|
||||||
cxx_std_17
|
cxx_std_17
|
||||||
|
|
|
@ -57,7 +57,7 @@ first-party `godot-cpp` extension.
|
||||||
Some compatibility breakage is to be expected as GDExtension and `godot-cpp`
|
Some compatibility breakage is to be expected as GDExtension and `godot-cpp`
|
||||||
get more used, documented, and critical issues get resolved. See the
|
get more used, documented, and critical issues get resolved. See the
|
||||||
[Godot issue tracker](https://github.com/godotengine/godot/issues?q=is%3Aissue+is%3Aopen+label%3Atopic%3Agdextension)
|
[Godot issue tracker](https://github.com/godotengine/godot/issues?q=is%3Aissue+is%3Aopen+label%3Atopic%3Agdextension)
|
||||||
and the [godot-cpp issue tracker](https://github.com/godotengine/godot/issues)
|
and the [godot-cpp issue tracker](https://github.com/godotengine/godot-cpp/issues)
|
||||||
for a list of known issues, and be sure to provide feedback on issues and PRs
|
for a list of known issues, and be sure to provide feedback on issues and PRs
|
||||||
which affect your use of this extension.
|
which affect your use of this extension.
|
||||||
|
|
||||||
|
@ -73,7 +73,10 @@ so formatting is done before your changes are submitted.
|
||||||
|
|
||||||
## Getting started
|
## Getting started
|
||||||
|
|
||||||
It's a bit similar to what it was for 3.x but also a bit different.
|
You need the same C++ pre-requisites installed that are required for the `godot` repository. Follow the [official build instructions for your target platform](https://docs.godotengine.org/en/latest/contributing/development/compiling/index.html#building-for-target-platforms).
|
||||||
|
|
||||||
|
Getting started with GDExtensions is a bit similar to what it was for 3.x but also a bit different.
|
||||||
|
|
||||||
This new approach is much more akin to how core Godot modules are structured.
|
This new approach is much more akin to how core Godot modules are structured.
|
||||||
|
|
||||||
Compiling this repository generates a static library to be linked with your shared lib,
|
Compiling this repository generates a static library to be linked with your shared lib,
|
||||||
|
|
|
@ -135,9 +135,7 @@ def get_file_list(api_filepath, output_dir, headers=False, sources=False):
|
||||||
|
|
||||||
|
|
||||||
def print_file_list(api_filepath, output_dir, headers=False, sources=False):
|
def print_file_list(api_filepath, output_dir, headers=False, sources=False):
|
||||||
end = ";"
|
print(*get_file_list(api_filepath, output_dir, headers, sources), sep=";", end=None)
|
||||||
for f in get_file_list(api_filepath, output_dir, headers, sources):
|
|
||||||
print(f, end=end)
|
|
||||||
|
|
||||||
|
|
||||||
def scons_emit_files(target, source, env):
|
def scons_emit_files(target, source, env):
|
||||||
|
@ -1718,9 +1716,9 @@ def generate_global_constant_binds(api, output_dir):
|
||||||
continue
|
continue
|
||||||
|
|
||||||
if enum_def["is_bitfield"]:
|
if enum_def["is_bitfield"]:
|
||||||
header.append(f'VARIANT_BITFIELD_CAST(godot::{enum_def["name"]});')
|
header.append(f'VARIANT_BITFIELD_CAST({enum_def["name"]});')
|
||||||
else:
|
else:
|
||||||
header.append(f'VARIANT_ENUM_CAST(godot::{enum_def["name"]});')
|
header.append(f'VARIANT_ENUM_CAST({enum_def["name"]});')
|
||||||
|
|
||||||
# Variant::Type is not a global enum, but only one line, it is worth to place in this file instead of creating new file.
|
# Variant::Type is not a global enum, but only one line, it is worth to place in this file instead of creating new file.
|
||||||
header.append(f"VARIANT_ENUM_CAST(godot::Variant::Type);")
|
header.append(f"VARIANT_ENUM_CAST(godot::Variant::Type);")
|
||||||
|
@ -2336,6 +2334,7 @@ def get_operator_id_name(op):
|
||||||
"unary-": "negate",
|
"unary-": "negate",
|
||||||
"unary+": "positive",
|
"unary+": "positive",
|
||||||
"%": "module",
|
"%": "module",
|
||||||
|
"**": "power",
|
||||||
"<<": "shift_left",
|
"<<": "shift_left",
|
||||||
">>": "shift_right",
|
">>": "shift_right",
|
||||||
"&": "bit_and",
|
"&": "bit_and",
|
||||||
|
|
|
@ -187,26 +187,44 @@ enum ModuleInitializationLevel {
|
||||||
MODULE_INITIALIZATION_LEVEL_CORE = GDEXTENSION_INITIALIZATION_CORE,
|
MODULE_INITIALIZATION_LEVEL_CORE = GDEXTENSION_INITIALIZATION_CORE,
|
||||||
MODULE_INITIALIZATION_LEVEL_SERVERS = GDEXTENSION_INITIALIZATION_SERVERS,
|
MODULE_INITIALIZATION_LEVEL_SERVERS = GDEXTENSION_INITIALIZATION_SERVERS,
|
||||||
MODULE_INITIALIZATION_LEVEL_SCENE = GDEXTENSION_INITIALIZATION_SCENE,
|
MODULE_INITIALIZATION_LEVEL_SCENE = GDEXTENSION_INITIALIZATION_SCENE,
|
||||||
MODULE_INITIALIZATION_LEVEL_EDITOR = GDEXTENSION_INITIALIZATION_EDITOR
|
MODULE_INITIALIZATION_LEVEL_EDITOR = GDEXTENSION_INITIALIZATION_EDITOR,
|
||||||
|
MODULE_INITIALIZATION_LEVEL_MAX
|
||||||
};
|
};
|
||||||
|
|
||||||
class GDExtensionBinding {
|
class GDExtensionBinding {
|
||||||
public:
|
public:
|
||||||
using Callback = void (*)(ModuleInitializationLevel p_level);
|
using Callback = void (*)(ModuleInitializationLevel p_level);
|
||||||
|
|
||||||
static Callback init_callback;
|
struct InitData {
|
||||||
static Callback terminate_callback;
|
GDExtensionInitializationLevel minimum_initialization_level = GDEXTENSION_INITIALIZATION_CORE;
|
||||||
static GDExtensionInitializationLevel minimum_initialization_level;
|
Callback init_callback = nullptr;
|
||||||
static GDExtensionBool init(GDExtensionInterfaceGetProcAddress p_get_proc_address, GDExtensionClassLibraryPtr p_library, GDExtensionInitialization *r_initialization);
|
Callback terminate_callback = nullptr;
|
||||||
|
};
|
||||||
|
|
||||||
|
class InitDataList {
|
||||||
|
int data_count = 0;
|
||||||
|
int data_capacity = 0;
|
||||||
|
InitData **data = nullptr;
|
||||||
|
|
||||||
|
public:
|
||||||
|
void add(InitData *p_cb);
|
||||||
|
~InitDataList();
|
||||||
|
};
|
||||||
|
|
||||||
|
static bool api_initialized;
|
||||||
|
static int level_initialized[MODULE_INITIALIZATION_LEVEL_MAX];
|
||||||
|
static InitDataList initdata;
|
||||||
|
static GDExtensionBool init(GDExtensionInterfaceGetProcAddress p_get_proc_address, GDExtensionClassLibraryPtr p_library, InitData *p_init_data, GDExtensionInitialization *r_initialization);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
static void initialize_level(void *userdata, GDExtensionInitializationLevel p_level);
|
static void initialize_level(void *p_userdata, GDExtensionInitializationLevel p_level);
|
||||||
static void deinitialize_level(void *userdata, GDExtensionInitializationLevel p_level);
|
static void deinitialize_level(void *p_userdata, GDExtensionInitializationLevel p_level);
|
||||||
|
|
||||||
class InitObject {
|
class InitObject {
|
||||||
GDExtensionInterfaceGetProcAddress get_proc_address;
|
GDExtensionInterfaceGetProcAddress get_proc_address;
|
||||||
GDExtensionClassLibraryPtr library;
|
GDExtensionClassLibraryPtr library;
|
||||||
GDExtensionInitialization *initialization;
|
GDExtensionInitialization *initialization;
|
||||||
|
mutable InitData *init_data = nullptr;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
InitObject(GDExtensionInterfaceGetProcAddress p_get_proc_address, GDExtensionClassLibraryPtr p_library, GDExtensionInitialization *r_initialization);
|
InitObject(GDExtensionInterfaceGetProcAddress p_get_proc_address, GDExtensionClassLibraryPtr p_library, GDExtensionInitialization *r_initialization);
|
||||||
|
|
|
@ -122,6 +122,7 @@ public:
|
||||||
OP_NEGATE,
|
OP_NEGATE,
|
||||||
OP_POSITIVE,
|
OP_POSITIVE,
|
||||||
OP_MODULE,
|
OP_MODULE,
|
||||||
|
OP_POWER,
|
||||||
// bitwise
|
// bitwise
|
||||||
OP_SHIFT_LEFT,
|
OP_SHIFT_LEFT,
|
||||||
OP_SHIFT_RIGHT,
|
OP_SHIFT_RIGHT,
|
||||||
|
@ -154,10 +155,18 @@ public:
|
||||||
Variant(int64_t v);
|
Variant(int64_t v);
|
||||||
Variant(int32_t v) :
|
Variant(int32_t v) :
|
||||||
Variant(static_cast<int64_t>(v)) {}
|
Variant(static_cast<int64_t>(v)) {}
|
||||||
Variant(uint32_t v) :
|
Variant(int16_t v) :
|
||||||
|
Variant(static_cast<int64_t>(v)) {}
|
||||||
|
Variant(int8_t v) :
|
||||||
Variant(static_cast<int64_t>(v)) {}
|
Variant(static_cast<int64_t>(v)) {}
|
||||||
Variant(uint64_t v) :
|
Variant(uint64_t v) :
|
||||||
Variant(static_cast<int64_t>(v)) {}
|
Variant(static_cast<int64_t>(v)) {}
|
||||||
|
Variant(uint32_t v) :
|
||||||
|
Variant(static_cast<int64_t>(v)) {}
|
||||||
|
Variant(uint16_t v) :
|
||||||
|
Variant(static_cast<int64_t>(v)) {}
|
||||||
|
Variant(uint8_t v) :
|
||||||
|
Variant(static_cast<int64_t>(v)) {}
|
||||||
Variant(double v);
|
Variant(double v);
|
||||||
Variant(float v) :
|
Variant(float v) :
|
||||||
Variant((double)v) {}
|
Variant((double)v) {}
|
||||||
|
@ -209,8 +218,12 @@ public:
|
||||||
operator bool() const;
|
operator bool() const;
|
||||||
operator int64_t() const;
|
operator int64_t() const;
|
||||||
operator int32_t() const;
|
operator int32_t() const;
|
||||||
|
operator int16_t() const;
|
||||||
|
operator int8_t() const;
|
||||||
operator uint64_t() const;
|
operator uint64_t() const;
|
||||||
operator uint32_t() const;
|
operator uint32_t() const;
|
||||||
|
operator uint16_t() const;
|
||||||
|
operator uint8_t() const;
|
||||||
operator double() const;
|
operator double() const;
|
||||||
operator float() const;
|
operator float() const;
|
||||||
operator String() const;
|
operator String() const;
|
||||||
|
|
|
@ -50,6 +50,12 @@ void Wrapped::_postinitialize() {
|
||||||
godot::internal::gdextension_interface_object_set_instance(_owner, reinterpret_cast<GDExtensionConstStringNamePtr>(extension_class), this);
|
godot::internal::gdextension_interface_object_set_instance(_owner, reinterpret_cast<GDExtensionConstStringNamePtr>(extension_class), this);
|
||||||
}
|
}
|
||||||
godot::internal::gdextension_interface_object_set_instance_binding(_owner, godot::internal::token, this, _get_bindings_callbacks());
|
godot::internal::gdextension_interface_object_set_instance_binding(_owner, godot::internal::token, this, _get_bindings_callbacks());
|
||||||
|
if (extension_class) {
|
||||||
|
Object *obj = dynamic_cast<Object *>(this);
|
||||||
|
if (obj) {
|
||||||
|
obj->notification(Object::NOTIFICATION_POSTINITIALIZE);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Wrapped::Wrapped(const StringName p_godot_class) {
|
Wrapped::Wrapped(const StringName p_godot_class) {
|
||||||
|
|
|
@ -189,9 +189,9 @@ GDExtensionInterfaceEditorRemovePlugin gdextension_interface_editor_remove_plugi
|
||||||
|
|
||||||
} // namespace internal
|
} // namespace internal
|
||||||
|
|
||||||
GDExtensionBinding::Callback GDExtensionBinding::init_callback = nullptr;
|
bool GDExtensionBinding::api_initialized = false;
|
||||||
GDExtensionBinding::Callback GDExtensionBinding::terminate_callback = nullptr;
|
int GDExtensionBinding::level_initialized[MODULE_INITIALIZATION_LEVEL_MAX] = { 0 };
|
||||||
GDExtensionInitializationLevel GDExtensionBinding::minimum_initialization_level = GDEXTENSION_INITIALIZATION_CORE;
|
GDExtensionBinding::InitDataList GDExtensionBinding::initdata;
|
||||||
|
|
||||||
#define ERR_PRINT_EARLY(m_msg) \
|
#define ERR_PRINT_EARLY(m_msg) \
|
||||||
internal::gdextension_interface_print_error(m_msg, FUNCTION_STR, __FILE__, __LINE__, false)
|
internal::gdextension_interface_print_error(m_msg, FUNCTION_STR, __FILE__, __LINE__, false)
|
||||||
|
@ -218,7 +218,20 @@ typedef struct {
|
||||||
GDExtensionInterfacePrintErrorWithMessage print_error_with_message;
|
GDExtensionInterfacePrintErrorWithMessage print_error_with_message;
|
||||||
} LegacyGDExtensionInterface;
|
} LegacyGDExtensionInterface;
|
||||||
|
|
||||||
GDExtensionBool GDExtensionBinding::init(GDExtensionInterfaceGetProcAddress p_get_proc_address, GDExtensionClassLibraryPtr p_library, GDExtensionInitialization *r_initialization) {
|
GDExtensionBool GDExtensionBinding::init(GDExtensionInterfaceGetProcAddress p_get_proc_address, GDExtensionClassLibraryPtr p_library, InitData *p_init_data, GDExtensionInitialization *r_initialization) {
|
||||||
|
if (!p_init_data || !p_init_data->init_callback) {
|
||||||
|
ERR_FAIL_V_MSG(false, "Initialization callback must be defined.");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (api_initialized) {
|
||||||
|
r_initialization->initialize = initialize_level;
|
||||||
|
r_initialization->deinitialize = deinitialize_level;
|
||||||
|
r_initialization->userdata = p_init_data;
|
||||||
|
r_initialization->minimum_initialization_level = p_init_data->minimum_initialization_level;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
// Make sure we weren't passed the legacy struct.
|
// Make sure we weren't passed the legacy struct.
|
||||||
uint32_t *raw_interface = (uint32_t *)(void *)p_get_proc_address;
|
uint32_t *raw_interface = (uint32_t *)(void *)p_get_proc_address;
|
||||||
if (raw_interface[0] == 4 && raw_interface[1] == 0) {
|
if (raw_interface[0] == 4 && raw_interface[1] == 0) {
|
||||||
|
@ -251,7 +264,12 @@ GDExtensionBool GDExtensionBinding::init(GDExtensionInterfaceGetProcAddress p_ge
|
||||||
} else if (internal::godot_version.minor != GODOT_VERSION_MINOR) {
|
} else if (internal::godot_version.minor != GODOT_VERSION_MINOR) {
|
||||||
compatible = internal::godot_version.minor > GODOT_VERSION_MINOR;
|
compatible = internal::godot_version.minor > GODOT_VERSION_MINOR;
|
||||||
} else {
|
} else {
|
||||||
|
#if GODOT_VERSION_PATCH > 0
|
||||||
compatible = internal::godot_version.patch >= GODOT_VERSION_PATCH;
|
compatible = internal::godot_version.patch >= GODOT_VERSION_PATCH;
|
||||||
|
#else
|
||||||
|
// Prevent -Wtype-limits warning due to unsigned comparison.
|
||||||
|
compatible = true;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
if (!compatible) {
|
if (!compatible) {
|
||||||
// We need to use snprintf() here because vformat() uses Variant, and we haven't loaded
|
// We need to use snprintf() here because vformat() uses Variant, and we haven't loaded
|
||||||
|
@ -401,59 +419,96 @@ GDExtensionBool GDExtensionBinding::init(GDExtensionInterfaceGetProcAddress p_ge
|
||||||
|
|
||||||
r_initialization->initialize = initialize_level;
|
r_initialization->initialize = initialize_level;
|
||||||
r_initialization->deinitialize = deinitialize_level;
|
r_initialization->deinitialize = deinitialize_level;
|
||||||
r_initialization->minimum_initialization_level = minimum_initialization_level;
|
r_initialization->userdata = p_init_data;
|
||||||
|
r_initialization->minimum_initialization_level = p_init_data->minimum_initialization_level;
|
||||||
ERR_FAIL_NULL_V_MSG(init_callback, false, "Initialization callback must be defined.");
|
|
||||||
|
|
||||||
Variant::init_bindings();
|
Variant::init_bindings();
|
||||||
godot::internal::register_engine_classes();
|
godot::internal::register_engine_classes();
|
||||||
|
|
||||||
|
api_initialized = true;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
#undef LOAD_PROC_ADDRESS
|
#undef LOAD_PROC_ADDRESS
|
||||||
#undef ERR_PRINT_EARLY
|
#undef ERR_PRINT_EARLY
|
||||||
|
|
||||||
void GDExtensionBinding::initialize_level(void *userdata, GDExtensionInitializationLevel p_level) {
|
void GDExtensionBinding::initialize_level(void *p_userdata, GDExtensionInitializationLevel p_level) {
|
||||||
|
ERR_FAIL_COND(static_cast<ModuleInitializationLevel>(p_level) >= MODULE_INITIALIZATION_LEVEL_MAX);
|
||||||
ClassDB::current_level = p_level;
|
ClassDB::current_level = p_level;
|
||||||
|
|
||||||
if (init_callback) {
|
InitData *init_data = static_cast<InitData *>(p_userdata);
|
||||||
init_callback(static_cast<ModuleInitializationLevel>(p_level));
|
if (init_data && init_data->init_callback) {
|
||||||
|
init_data->init_callback(static_cast<ModuleInitializationLevel>(p_level));
|
||||||
}
|
}
|
||||||
|
|
||||||
ClassDB::initialize(p_level);
|
if (level_initialized[p_level] == 0) {
|
||||||
|
ClassDB::initialize(p_level);
|
||||||
|
}
|
||||||
|
level_initialized[p_level]++;
|
||||||
}
|
}
|
||||||
|
|
||||||
void GDExtensionBinding::deinitialize_level(void *userdata, GDExtensionInitializationLevel p_level) {
|
void GDExtensionBinding::deinitialize_level(void *p_userdata, GDExtensionInitializationLevel p_level) {
|
||||||
|
ERR_FAIL_COND(static_cast<ModuleInitializationLevel>(p_level) >= MODULE_INITIALIZATION_LEVEL_MAX);
|
||||||
ClassDB::current_level = p_level;
|
ClassDB::current_level = p_level;
|
||||||
|
|
||||||
if (terminate_callback) {
|
InitData *init_data = static_cast<InitData *>(p_userdata);
|
||||||
terminate_callback(static_cast<ModuleInitializationLevel>(p_level));
|
if (init_data && init_data->terminate_callback) {
|
||||||
|
init_data->terminate_callback(static_cast<ModuleInitializationLevel>(p_level));
|
||||||
}
|
}
|
||||||
|
|
||||||
EditorPlugins::deinitialize(p_level);
|
level_initialized[p_level]--;
|
||||||
ClassDB::deinitialize(p_level);
|
if (level_initialized[p_level] == 0) {
|
||||||
|
EditorPlugins::deinitialize(p_level);
|
||||||
|
ClassDB::deinitialize(p_level);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void GDExtensionBinding::InitDataList::add(InitData *p_data) {
|
||||||
|
if (data_count == data_capacity) {
|
||||||
|
void *new_ptr = realloc(data, sizeof(InitData *) * (data_capacity + 32));
|
||||||
|
if (new_ptr) {
|
||||||
|
data = (InitData **)(new_ptr);
|
||||||
|
data_capacity += 32;
|
||||||
|
} else {
|
||||||
|
ERR_FAIL_MSG("Unable to allocate memory for extension callbacks.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
data[data_count++] = p_data;
|
||||||
|
}
|
||||||
|
|
||||||
|
GDExtensionBinding::InitDataList::~InitDataList() {
|
||||||
|
for (int i = 0; i < data_count; i++) {
|
||||||
|
if (data[i]) {
|
||||||
|
delete data[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (data) {
|
||||||
|
free(data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
GDExtensionBinding::InitObject::InitObject(GDExtensionInterfaceGetProcAddress p_get_proc_address, GDExtensionClassLibraryPtr p_library, GDExtensionInitialization *r_initialization) {
|
GDExtensionBinding::InitObject::InitObject(GDExtensionInterfaceGetProcAddress p_get_proc_address, GDExtensionClassLibraryPtr p_library, GDExtensionInitialization *r_initialization) {
|
||||||
get_proc_address = p_get_proc_address;
|
get_proc_address = p_get_proc_address;
|
||||||
library = p_library;
|
library = p_library;
|
||||||
initialization = r_initialization;
|
initialization = r_initialization;
|
||||||
|
init_data = new InitData();
|
||||||
|
GDExtensionBinding::initdata.add(init_data);
|
||||||
}
|
}
|
||||||
|
|
||||||
void GDExtensionBinding::InitObject::register_initializer(Callback p_init) const {
|
void GDExtensionBinding::InitObject::register_initializer(Callback p_init) const {
|
||||||
GDExtensionBinding::init_callback = p_init;
|
init_data->init_callback = p_init;
|
||||||
}
|
}
|
||||||
|
|
||||||
void GDExtensionBinding::InitObject::register_terminator(Callback p_terminate) const {
|
void GDExtensionBinding::InitObject::register_terminator(Callback p_terminate) const {
|
||||||
GDExtensionBinding::terminate_callback = p_terminate;
|
init_data->terminate_callback = p_terminate;
|
||||||
}
|
}
|
||||||
|
|
||||||
void GDExtensionBinding::InitObject::set_minimum_library_initialization_level(ModuleInitializationLevel p_level) const {
|
void GDExtensionBinding::InitObject::set_minimum_library_initialization_level(ModuleInitializationLevel p_level) const {
|
||||||
GDExtensionBinding::minimum_initialization_level = static_cast<GDExtensionInitializationLevel>(p_level);
|
init_data->minimum_initialization_level = static_cast<GDExtensionInitializationLevel>(p_level);
|
||||||
}
|
}
|
||||||
|
|
||||||
GDExtensionBool GDExtensionBinding::InitObject::init() const {
|
GDExtensionBool GDExtensionBinding::InitObject::init() const {
|
||||||
return GDExtensionBinding::init(get_proc_address, library, initialization);
|
return GDExtensionBinding::init(get_proc_address, library, init_data, initialization);
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace godot
|
} // namespace godot
|
||||||
|
|
|
@ -268,6 +268,14 @@ Variant::operator int32_t() const {
|
||||||
return static_cast<int32_t>(operator int64_t());
|
return static_cast<int32_t>(operator int64_t());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Variant::operator int16_t() const {
|
||||||
|
return static_cast<int16_t>(operator int64_t());
|
||||||
|
}
|
||||||
|
|
||||||
|
Variant::operator int8_t() const {
|
||||||
|
return static_cast<int8_t>(operator int64_t());
|
||||||
|
}
|
||||||
|
|
||||||
Variant::operator uint64_t() const {
|
Variant::operator uint64_t() const {
|
||||||
return static_cast<uint64_t>(operator int64_t());
|
return static_cast<uint64_t>(operator int64_t());
|
||||||
}
|
}
|
||||||
|
@ -276,6 +284,14 @@ Variant::operator uint32_t() const {
|
||||||
return static_cast<uint32_t>(operator int64_t());
|
return static_cast<uint32_t>(operator int64_t());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Variant::operator uint16_t() const {
|
||||||
|
return static_cast<uint16_t>(operator int64_t());
|
||||||
|
}
|
||||||
|
|
||||||
|
Variant::operator uint8_t() const {
|
||||||
|
return static_cast<uint8_t>(operator int64_t());
|
||||||
|
}
|
||||||
|
|
||||||
Variant::operator double() const {
|
Variant::operator double() const {
|
||||||
double result;
|
double result;
|
||||||
to_type_constructor[FLOAT](&result, _native_ptr());
|
to_type_constructor[FLOAT](&result, _native_ptr());
|
||||||
|
|
|
@ -59,31 +59,9 @@ if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC")
|
||||||
|
|
||||||
else()
|
else()
|
||||||
|
|
||||||
#elseif ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang")
|
|
||||||
# using Clang
|
|
||||||
#elseif ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU")
|
|
||||||
# using GCC and maybe MinGW?
|
|
||||||
|
|
||||||
set(GODOT_LINKER_FLAGS "-static-libgcc -static-libstdc++ -Wl,-R,'$$ORIGIN'")
|
set(GODOT_LINKER_FLAGS "-static-libgcc -static-libstdc++ -Wl,-R,'$$ORIGIN'")
|
||||||
|
|
||||||
# Hmm.. maybe to strikt?
|
|
||||||
set(GODOT_COMPILE_FLAGS "-fPIC -g -Wwrite-strings")
|
set(GODOT_COMPILE_FLAGS "-fPIC -g -Wwrite-strings")
|
||||||
set(GODOT_COMPILE_FLAGS "${GODOT_COMPILE_FLAGS} -Wchar-subscripts -Wcomment -Wdisabled-optimization")
|
|
||||||
set(GODOT_COMPILE_FLAGS "${GODOT_COMPILE_FLAGS} -Wformat -Wformat=2 -Wformat-security -Wformat-y2k")
|
|
||||||
set(GODOT_COMPILE_FLAGS "${GODOT_COMPILE_FLAGS} -Wimport -Winit-self -Winline -Winvalid-pch -Werror")
|
|
||||||
set(GODOT_COMPILE_FLAGS "${GODOT_COMPILE_FLAGS} -Wmissing-braces -Wmissing-format-attribute")
|
|
||||||
set(GODOT_COMPILE_FLAGS "${GODOT_COMPILE_FLAGS} -Wmissing-include-dirs -Wmissing-noreturn -Wpacked -Wpointer-arith")
|
|
||||||
set(GODOT_COMPILE_FLAGS "${GODOT_COMPILE_FLAGS} -Wredundant-decls -Wreturn-type -Wsequence-point")
|
|
||||||
set(GODOT_COMPILE_FLAGS "${GODOT_COMPILE_FLAGS} -Wswitch -Wswitch-enum -Wtrigraphs")
|
|
||||||
set(GODOT_COMPILE_FLAGS "${GODOT_COMPILE_FLAGS} -Wuninitialized -Wunknown-pragmas -Wunreachable-code -Wunused-label")
|
|
||||||
set(GODOT_COMPILE_FLAGS "${GODOT_COMPILE_FLAGS} -Wunused-value -Wvariadic-macros -Wvolatile-register-var -Wno-error=attributes")
|
|
||||||
|
|
||||||
# -Wshadow -Wextra -Wall -Weffc++ -Wfloat-equal -Wstack-protector -Wunused-parameter -Wsign-compare -Wunused-variable -Wcast-align
|
|
||||||
# -Wunused-function -Wstrict-aliasing -Wstrict-aliasing=2 -Wmissing-field-initializers
|
|
||||||
|
|
||||||
if(NOT CMAKE_SYSTEM_NAME STREQUAL "Android")
|
|
||||||
set(GODOT_COMPILE_FLAGS "${GODOT_COMPILE_FLAGS} -Wno-ignored-attributes")
|
|
||||||
endif()
|
|
||||||
|
|
||||||
if(CMAKE_BUILD_TYPE MATCHES Debug)
|
if(CMAKE_BUILD_TYPE MATCHES Debug)
|
||||||
set(GODOT_COMPILE_FLAGS "${GODOT_COMPILE_FLAGS} -fno-omit-frame-pointer -O0")
|
set(GODOT_COMPILE_FLAGS "${GODOT_COMPILE_FLAGS} -fno-omit-frame-pointer -O0")
|
||||||
|
|
|
@ -169,6 +169,11 @@ func _ready():
|
||||||
get_viewport().push_input(event)
|
get_viewport().push_input(event)
|
||||||
assert_equal(custom_signal_emitted, ["_input: H", 72])
|
assert_equal(custom_signal_emitted, ["_input: H", 72])
|
||||||
|
|
||||||
|
# Check NOTIFICATION_POST_INITIALIZED, both when created from GDScript and godot-cpp.
|
||||||
|
var new_example_ref = ExampleRef.new()
|
||||||
|
assert_equal(new_example_ref.was_post_initialized(), true)
|
||||||
|
assert_equal(example.test_post_initialize(), true)
|
||||||
|
|
||||||
exit_with_status()
|
exit_with_status()
|
||||||
|
|
||||||
func _on_Example_custom_signal(signal_name, value):
|
func _on_Example_custom_signal(signal_name, value):
|
||||||
|
|
|
@ -23,10 +23,18 @@ int ExampleRef::get_id() const {
|
||||||
return id;
|
return id;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ExampleRef::_notification(int p_what) {
|
||||||
|
if (p_what == NOTIFICATION_POSTINITIALIZE) {
|
||||||
|
post_initialized = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void ExampleRef::_bind_methods() {
|
void ExampleRef::_bind_methods() {
|
||||||
ClassDB::bind_method(D_METHOD("set_id", "id"), &ExampleRef::set_id);
|
ClassDB::bind_method(D_METHOD("set_id", "id"), &ExampleRef::set_id);
|
||||||
ClassDB::bind_method(D_METHOD("get_id"), &ExampleRef::get_id);
|
ClassDB::bind_method(D_METHOD("get_id"), &ExampleRef::get_id);
|
||||||
|
|
||||||
|
ClassDB::bind_method(D_METHOD("was_post_initialized"), &ExampleRef::was_post_initialized);
|
||||||
|
|
||||||
ADD_PROPERTY(PropertyInfo(Variant::INT, "id"), "set_id", "get_id");
|
ADD_PROPERTY(PropertyInfo(Variant::INT, "id"), "set_id", "get_id");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -161,6 +169,7 @@ void Example::_bind_methods() {
|
||||||
ClassDB::bind_method(D_METHOD("return_last_rpc_arg"), &Example::return_last_rpc_arg);
|
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("def_args", "a", "b"), &Example::def_args, DEFVAL(100), DEFVAL(200));
|
||||||
|
ClassDB::bind_method(D_METHOD("test_post_initialize"), &Example::test_post_initialize);
|
||||||
|
|
||||||
ClassDB::bind_static_method("Example", D_METHOD("test_static", "a", "b"), &Example::test_static);
|
ClassDB::bind_static_method("Example", D_METHOD("test_static", "a", "b"), &Example::test_static);
|
||||||
ClassDB::bind_static_method("Example", D_METHOD("test_static2"), &Example::test_static2);
|
ClassDB::bind_static_method("Example", D_METHOD("test_static2"), &Example::test_static2);
|
||||||
|
@ -426,6 +435,12 @@ Vector4 Example::get_v4() const {
|
||||||
return Vector4(1.2, 3.4, 5.6, 7.8);
|
return Vector4(1.2, 3.4, 5.6, 7.8);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool Example::test_post_initialize() const {
|
||||||
|
Ref<ExampleRef> new_example_ref;
|
||||||
|
new_example_ref.instantiate();
|
||||||
|
return new_example_ref->was_post_initialized();
|
||||||
|
}
|
||||||
|
|
||||||
// Virtual function override.
|
// Virtual function override.
|
||||||
bool Example::_has_point(const Vector2 &point) const {
|
bool Example::_has_point(const Vector2 &point) const {
|
||||||
Label *label = get_node<Label>("Label");
|
Label *label = get_node<Label>("Label");
|
||||||
|
|
|
@ -35,16 +35,21 @@ private:
|
||||||
static int last_id;
|
static int last_id;
|
||||||
|
|
||||||
int id;
|
int id;
|
||||||
|
bool post_initialized = false;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
static void _bind_methods();
|
static void _bind_methods();
|
||||||
|
|
||||||
|
void _notification(int p_what);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
ExampleRef();
|
ExampleRef();
|
||||||
~ExampleRef();
|
~ExampleRef();
|
||||||
|
|
||||||
void set_id(int p_id);
|
void set_id(int p_id);
|
||||||
int get_id() const;
|
int get_id() const;
|
||||||
|
|
||||||
|
bool was_post_initialized() const { return post_initialized; }
|
||||||
};
|
};
|
||||||
|
|
||||||
class ExampleMin : public Control {
|
class ExampleMin : public Control {
|
||||||
|
@ -148,6 +153,8 @@ public:
|
||||||
Vector2 get_custom_position() const;
|
Vector2 get_custom_position() const;
|
||||||
Vector4 get_v4() const;
|
Vector4 get_v4() const;
|
||||||
|
|
||||||
|
bool test_post_initialize() const;
|
||||||
|
|
||||||
// Static method.
|
// Static method.
|
||||||
static int test_static(int p_a, int p_b);
|
static int test_static(int p_a, int p_b);
|
||||||
static void test_static2();
|
static void test_static2();
|
||||||
|
|
|
@ -8,7 +8,7 @@ def options(opts):
|
||||||
opts.Add(
|
opts.Add(
|
||||||
"android_api_level",
|
"android_api_level",
|
||||||
"Target Android API level",
|
"Target Android API level",
|
||||||
"18" if "32" in ARGUMENTS.get("arch", "arm64") else "21",
|
"21",
|
||||||
)
|
)
|
||||||
opts.Add(
|
opts.Add(
|
||||||
"ANDROID_HOME",
|
"ANDROID_HOME",
|
||||||
|
@ -47,11 +47,9 @@ def generate(env):
|
||||||
my_spawn.configure(env)
|
my_spawn.configure(env)
|
||||||
|
|
||||||
# Validate API level
|
# Validate API level
|
||||||
api_level = int(env["android_api_level"])
|
if int(env["android_api_level"]) < 21:
|
||||||
if "64" in env["arch"] and api_level < 21:
|
print("WARNING: minimum supported Android target api is 21. Forcing target api 21.")
|
||||||
print("WARN: 64-bit Android architectures require an API level of at least 21; setting android_api_level=21")
|
|
||||||
env["android_api_level"] = "21"
|
env["android_api_level"] = "21"
|
||||||
api_level = 21
|
|
||||||
|
|
||||||
# Setup toolchain
|
# Setup toolchain
|
||||||
toolchain = get_android_ndk_root(env) + "/toolchains/llvm/prebuilt/"
|
toolchain = get_android_ndk_root(env) + "/toolchains/llvm/prebuilt/"
|
||||||
|
@ -66,6 +64,12 @@ def generate(env):
|
||||||
elif sys.platform == "darwin":
|
elif sys.platform == "darwin":
|
||||||
toolchain += "darwin-x86_64"
|
toolchain += "darwin-x86_64"
|
||||||
env.Append(LINKFLAGS=["-shared"])
|
env.Append(LINKFLAGS=["-shared"])
|
||||||
|
|
||||||
|
if not os.path.exists(toolchain):
|
||||||
|
print("ERROR: Could not find NDK toolchain at " + toolchain + ".")
|
||||||
|
print("Make sure NDK version " + get_ndk_version() + " is installed.")
|
||||||
|
env.Exit(1)
|
||||||
|
|
||||||
env.PrependENVPath("PATH", toolchain + "/bin") # This does nothing half of the time, but we'll put it here anyways
|
env.PrependENVPath("PATH", toolchain + "/bin") # This does nothing half of the time, but we'll put it here anyways
|
||||||
|
|
||||||
# Get architecture info
|
# Get architecture info
|
||||||
|
|
|
@ -267,6 +267,9 @@ def generate(env):
|
||||||
if env["precision"] == "double":
|
if env["precision"] == "double":
|
||||||
env.Append(CPPDEFINES=["REAL_T_IS_DOUBLE"])
|
env.Append(CPPDEFINES=["REAL_T_IS_DOUBLE"])
|
||||||
|
|
||||||
|
# Allow detecting when building as a GDExtension.
|
||||||
|
env.Append(CPPDEFINES=["GDEXTENSION"])
|
||||||
|
|
||||||
# Suffix
|
# Suffix
|
||||||
suffix = ".{}.{}".format(env["platform"], env["target"])
|
suffix = ".{}.{}".format(env["platform"], env["target"])
|
||||||
if env.dev_build:
|
if env.dev_build:
|
||||||
|
|
Loading…
Reference in New Issue