Skip to content

Commit

Permalink
Merge pull request #1244 from dsnopek/4.1-cherrypicks-3
Browse files Browse the repository at this point in the history
Cherry-picks for the godot-cpp 4.1 branch - 3rd batch
  • Loading branch information
akien-mga authored Sep 20, 2023
2 parents bc980b5 + bc82ae8 commit 4eed2d7
Show file tree
Hide file tree
Showing 13 changed files with 143 additions and 47 deletions.
8 changes: 4 additions & 4 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ jobs:

steps:
- name: Checkout
uses: actions/checkout@v3
uses: actions/checkout@v4
with:
submodules: recursive

Expand Down Expand Up @@ -168,7 +168,7 @@ jobs:
runs-on: ubuntu-20.04
steps:
- name: Checkout
uses: actions/checkout@v3
uses: actions/checkout@v4
with:
submodules: recursive

Expand All @@ -192,7 +192,7 @@ jobs:
runs-on: ubuntu-20.04
steps:
- name: Checkout
uses: actions/checkout@v3
uses: actions/checkout@v4
with:
submodules: recursive

Expand All @@ -216,7 +216,7 @@ jobs:
runs-on: windows-2019
steps:
- name: Checkout
uses: actions/checkout@v3
uses: actions/checkout@v4
with:
submodules: recursive

Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/static_checks.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ jobs:
runs-on: ubuntu-20.04
steps:
- name: Checkout
uses: actions/checkout@v3
uses: actions/checkout@v4

# Azure repositories are not reliable, we need to prevent Azure giving us packages.
- name: Make apt sources.list use the default Ubuntu repositories
Expand Down
1 change: 0 additions & 1 deletion SConstruct
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ import platform
import sys
import subprocess
from binding_generator import scons_generate_bindings, scons_emit_files
from SCons.Errors import UserError


EnsureSConsVersion(4, 0)
Expand Down
76 changes: 67 additions & 9 deletions binding_generator.py
Original file line number Diff line number Diff line change
Expand Up @@ -97,9 +97,10 @@ def get_file_list(api_filepath, output_dir, headers=False, sources=False):
files.append(str(source_filename.as_posix()))

for engine_class in api["classes"]:
# TODO: Properly setup this singleton since it conflicts with ClassDB in the bindings.
# Generate code for the ClassDB singleton under a different name.
if engine_class["name"] == "ClassDB":
continue
engine_class["name"] = "ClassDBSingleton"
engine_class["alias_for"] = "ClassDB"
header_filename = include_gen_folder / "classes" / (camel_to_snake(engine_class["name"]) + ".hpp")
source_filename = source_gen_folder / "classes" / (camel_to_snake(engine_class["name"]) + ".cpp")
if headers:
Expand Down Expand Up @@ -1038,21 +1039,23 @@ def generate_engine_classes_bindings(api, output_dir, use_template_get_node):

# First create map of classes and singletons.
for class_api in api["classes"]:
# TODO: Properly setup this singleton since it conflicts with ClassDB in the bindings.
# Generate code for the ClassDB singleton under a different name.
if class_api["name"] == "ClassDB":
continue
class_api["name"] = "ClassDBSingleton"
class_api["alias_for"] = "ClassDB"
engine_classes[class_api["name"]] = class_api["is_refcounted"]
for native_struct in api["native_structures"]:
engine_classes[native_struct["name"]] = False
native_structures.append(native_struct["name"])

for singleton in api["singletons"]:
# Generate code for the ClassDB singleton under a different name.
if singleton["name"] == "ClassDB":
singleton["name"] = "ClassDBSingleton"
singleton["alias_for"] = "ClassDB"
singletons.append(singleton["name"])

for class_api in api["classes"]:
# TODO: Properly setup this singleton since it conflicts with ClassDB in the bindings.
if class_api["name"] == "ClassDB":
continue
# Check used classes for header include.
used_classes = set()
fully_used_classes = set()
Expand Down Expand Up @@ -1142,6 +1145,12 @@ def generate_engine_classes_bindings(api, output_dir, use_template_get_node):
else:
fully_used_classes.add("Wrapped")

# In order to ensure that PtrToArg specializations for native structs are
# always used, let's move any of them into 'fully_used_classes'.
for type_name in used_classes:
if is_struct_type(type_name) and not is_included_struct_type(type_name):
fully_used_classes.add(type_name)

for type_name in fully_used_classes:
if type_name in used_classes:
used_classes.remove(type_name)
Expand Down Expand Up @@ -1244,7 +1253,7 @@ def generate_engine_class_header(class_api, used_classes, fully_used_classes, us
if len(fully_used_classes) > 0:
result.append("")

if class_name != "Object":
if class_name != "Object" and class_name != "ClassDBSingleton":
result.append("#include <godot_cpp/core/class_db.hpp>")
result.append("")
result.append("#include <type_traits>")
Expand All @@ -1265,7 +1274,10 @@ def generate_engine_class_header(class_api, used_classes, fully_used_classes, us
inherits = class_api["inherits"] if "inherits" in class_api else "Wrapped"
result.append(f"class {class_name} : public {inherits} {{")

result.append(f"\tGDEXTENSION_CLASS({class_name}, {inherits})")
if "alias_for" in class_api:
result.append(f"\tGDEXTENSION_CLASS_ALIAS({class_name}, {class_api['alias_for']}, {inherits})")
else:
result.append(f"\tGDEXTENSION_CLASS({class_name}, {inherits})")
result.append("")

result.append("public:")
Expand Down Expand Up @@ -1423,6 +1435,51 @@ def generate_engine_class_header(class_api, used_classes, fully_used_classes, us
result.append(f'VARIANT_ENUM_CAST({class_name}::{enum_api["name"]});')
result.append("")

if class_name == "ClassDBSingleton":
result.append("#define CLASSDB_SINGLETON_FORWARD_METHODS \\")
for method in class_api["methods"]:
# ClassDBSingleton shouldn't have any static or vararg methods, but if some appear later, lets skip them.
if vararg:
continue
if "is_static" in method and method["is_static"]:
continue

method_signature = "\tstatic "
if "return_type" in method:
method_signature += f'{correct_type(method["return_type"])} '
elif "return_value" in method:
method_signature += (
correct_type(method["return_value"]["type"], method["return_value"].get("meta", None)) + " "
)
else:
method_signature += "void "

method_signature += f'{method["name"]}('

method_arguments = []
if "arguments" in method:
method_arguments = method["arguments"]

method_signature += make_function_parameters(
method_arguments, include_default=True, for_builtin=True, is_vararg=False
)

method_signature += ") { \\"

result.append(method_signature)

method_body = "\t\t"
if "return_type" in method or "return_value" in method:
method_body += "return "
method_body += f'ClassDBSingleton::get_singleton()->{method["name"]}('
method_body += ", ".join(map(lambda x: escape_identifier(x["name"]), method_arguments))
method_body += "); \\"

result.append(method_body)
result.append("\t} \\")
result.append("\t;")
result.append("")

result.append(f"#endif // ! {header_guard}")

return "\n".join(result)
Expand Down Expand Up @@ -2319,6 +2376,7 @@ def escape_identifier(id):
"operator": "_operator",
"typeof": "type_of",
"typename": "type_name",
"enum": "_enum",
}
if id in cpp_keywords_map:
return cpp_keywords_map[id]
Expand Down
27 changes: 15 additions & 12 deletions include/godot_cpp/classes/wrapped.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -132,16 +132,16 @@ protected:
return (void(::godot::Wrapped::*)(::godot::List<::godot::PropertyInfo> * p_list) const) & m_class::_get_property_list; \
} \
\
static bool (::godot::Wrapped::*_get_property_can_revert())(const ::godot::StringName &p_name) { \
return (bool(::godot::Wrapped::*)(const ::godot::StringName &p_name)) & m_class::_property_can_revert; \
static bool (::godot::Wrapped::*_get_property_can_revert())(const ::godot::StringName &p_name) const { \
return (bool(::godot::Wrapped::*)(const ::godot::StringName &p_name) const) & m_class::_property_can_revert; \
} \
\
static bool (::godot::Wrapped::*_get_property_get_revert())(const ::godot::StringName &p_name, ::godot::Variant &) { \
return (bool(::godot::Wrapped::*)(const ::godot::StringName &p_name, ::godot::Variant &)) & m_class::_property_get_revert; \
static bool (::godot::Wrapped::*_get_property_get_revert())(const ::godot::StringName &p_name, ::godot::Variant &) const { \
return (bool(::godot::Wrapped::*)(const ::godot::StringName &p_name, ::godot::Variant &) const) & m_class::_property_get_revert; \
} \
\
static ::godot::String (::godot::Wrapped::*_get_to_string())() { \
return (::godot::String(::godot::Wrapped::*)()) & m_class::_to_string; \
static ::godot::String (::godot::Wrapped::*_get_to_string())() const { \
return (::godot::String(::godot::Wrapped::*)() const) & m_class::_to_string; \
} \
\
template <class T, class B> \
Expand Down Expand Up @@ -306,7 +306,7 @@ public:
};

// Don't use this for your classes, use GDCLASS() instead.
#define GDEXTENSION_CLASS(m_class, m_inherits) \
#define GDEXTENSION_CLASS_ALIAS(m_class, m_alias_for, m_inherits) \
private: \
void operator=(const m_class &p_rval) {} \
\
Expand Down Expand Up @@ -338,23 +338,23 @@ protected:
return nullptr; \
} \
\
static bool (Wrapped::*_get_property_can_revert())(const ::godot::StringName &p_name) { \
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 &) { \
static bool (Wrapped::*_get_property_get_revert())(const ::godot::StringName &p_name, Variant &) const { \
return nullptr; \
} \
\
static String (Wrapped::*_get_to_string())() { \
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_class); \
static ::godot::StringName string_name = ::godot::StringName(#m_alias_for); \
return string_name; \
} \
\
Expand All @@ -379,6 +379,9 @@ public:
_gde_binding_free_callback, \
_gde_binding_reference_callback, \
}; \
m_class() : m_class(#m_class) {}
m_class() : m_class(#m_alias_for) {}

// 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)

#endif // GODOT_WRAPPED_HPP
4 changes: 4 additions & 0 deletions include/godot_cpp/core/class_db.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,8 @@
#include <godot_cpp/core/method_bind.hpp>
#include <godot_cpp/core/object.hpp>

#include <godot_cpp/classes/class_db_singleton.hpp>

#include <list>
#include <set>
#include <string>
Expand Down Expand Up @@ -146,6 +148,8 @@ class ClassDB {

static void initialize(GDExtensionInitializationLevel p_level);
static void deinitialize(GDExtensionInitializationLevel p_level);

CLASSDB_SINGLETON_FORWARD_METHODS;
};

#define BIND_CONSTANT(m_constant) \
Expand Down
2 changes: 2 additions & 0 deletions include/godot_cpp/core/method_ptrcall.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -168,6 +168,7 @@ MAKE_PTRARG_BY_REFERENCE(Variant);

template <class T>
struct PtrToArg<T *> {
static_assert(std::is_base_of<Object, T>::value, "Cannot encode non-Object value as an Object");
_FORCE_INLINE_ static T *convert(const void *p_ptr) {
return reinterpret_cast<T *>(godot::internal::get_object_instance_binding(*reinterpret_cast<GDExtensionObjectPtr *>(const_cast<void *>(p_ptr))));
}
Expand All @@ -179,6 +180,7 @@ struct PtrToArg<T *> {

template <class T>
struct PtrToArg<const T *> {
static_assert(std::is_base_of<Object, T>::value, "Cannot encode non-Object value as an Object");
_FORCE_INLINE_ static const T *convert(const void *p_ptr) {
return reinterpret_cast<const T *>(godot::internal::get_object_instance_binding(*reinterpret_cast<GDExtensionObjectPtr *>(const_cast<void *>(p_ptr))));
}
Expand Down
Loading

0 comments on commit 4eed2d7

Please sign in to comment.