Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Cherry-picks for the godot-cpp 4.1 branch - 4th batch #1261

Merged
merged 6 commits into from
Oct 12, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 17 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -78,8 +78,18 @@ jobs:
run-tests: false
cache-name: ios-arm64

- name: 🌐 Web (wasm32)
os: ubuntu-20.04
platform: javascript
artifact-name: godot-cpp-javascript-wasm32-release
artifact-path: bin/libgodot-cpp.javascript.template_release.wasm32.a
run-tests: false
cache-name: javascript-wasm32

env:
SCONS_CACHE: ${{ github.workspace }}/.scons-cache/
EM_VERSION: 3.1.45
EM_CACHE_FOLDER: "emsdk-cache"

steps:
- name: Checkout
Expand All @@ -104,6 +114,13 @@ jobs:
sudo apt-get update -qq
sudo apt-get install -qqq build-essential pkg-config

- name: Web dependencies
if: ${{ matrix.platform == 'javascript' }}
uses: mymindstorm/setup-emsdk@v12
with:
version: ${{env.EM_VERSION}}
actions-cache-folder: ${{env.EM_CACHE_FOLDER}}

- name: Install scons
run: |
python -m pip install scons==4.0.0
Expand Down
4 changes: 4 additions & 0 deletions SConstruct
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,10 @@ env.PrependENVPath("PATH", os.getenv("PATH"))

# Custom options and profile flags.
customs = ["custom.py"]
try:
customs += Import("customs")
except:
pass
profile = ARGUMENTS.get("profile", "")
if profile:
if os.path.isfile(profile):
Expand Down
4 changes: 2 additions & 2 deletions binding_generator.py
Original file line number Diff line number Diff line change
Expand Up @@ -1519,13 +1519,13 @@ def generate_engine_class_source(class_api, used_classes, fully_used_classes, us
f"\t\tGDExtensionObjectPtr singleton_obj = internal::gdextension_interface_global_get_singleton({class_name}::get_class_static()._native_ptr());"
)
result.append("#ifdef DEBUG_ENABLED")
result.append("\t\tERR_FAIL_COND_V(singleton_obj == nullptr, nullptr);")
result.append("\t\tERR_FAIL_NULL_V(singleton_obj, nullptr);")
result.append("#endif // DEBUG_ENABLED")
result.append(
f"\t\tsingleton = reinterpret_cast<{class_name} *>(internal::gdextension_interface_object_get_instance_binding(singleton_obj, internal::token, &{class_name}::_gde_binding_callbacks));"
)
result.append("#ifdef DEBUG_ENABLED")
result.append("\t\tERR_FAIL_COND_V(singleton == nullptr, nullptr);")
result.append("\t\tERR_FAIL_NULL_V(singleton, nullptr);")
result.append("#endif // DEBUG_ENABLED")
result.append("\t}")
result.append("\treturn singleton;")
Expand Down
2 changes: 1 addition & 1 deletion include/godot_cpp/classes/ref.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ class Ref {
}

void ref_pointer(T *p_ref) {
ERR_FAIL_COND(!p_ref);
ERR_FAIL_NULL(p_ref);

if (p_ref->init_ref()) {
reference = p_ref;
Expand Down
2 changes: 1 addition & 1 deletion include/godot_cpp/core/class_db.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -257,7 +257,7 @@ MethodBind *ClassDB::bind_static_method(StringName p_class, N p_method_name, M p
template <class M>
MethodBind *ClassDB::bind_vararg_method(uint32_t p_flags, StringName p_name, M p_method, const MethodInfo &p_info, const std::vector<Variant> &p_default_args, bool p_return_nil_is_variant) {
MethodBind *bind = create_vararg_method_bind(p_method, p_info, p_return_nil_is_variant);
ERR_FAIL_COND_V(!bind, nullptr);
ERR_FAIL_NULL_V(bind, nullptr);

bind->set_name(p_name);
bind->set_default_arguments(p_default_args);
Expand Down
2 changes: 1 addition & 1 deletion include/godot_cpp/core/memory.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -146,7 +146,7 @@ T *memnew_arr_template(size_t p_elements, const char *p_descr = "") {
size_t len = sizeof(T) * p_elements;
uint64_t *mem = (uint64_t *)Memory::alloc_static(len, true);
T *failptr = nullptr; // Get rid of a warning.
ERR_FAIL_COND_V(!mem, failptr);
ERR_FAIL_NULL_V(mem, failptr);
*(mem - 1) = p_elements;

if (!std::is_trivially_destructible<T>::value) {
Expand Down
13 changes: 8 additions & 5 deletions include/godot_cpp/templates/cowdata.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,10 @@ class CowData {
}

_FORCE_INLINE_ bool _get_alloc_size_checked(size_t p_elements, size_t *out) const {
if (unlikely(p_elements == 0)) {
*out = 0;
return true;
}
#if defined(__GNUC__)
size_t o;
size_t p;
Expand All @@ -113,13 +117,12 @@ class CowData {
if (__builtin_add_overflow(o, static_cast<size_t>(32), &p)) {
return false; // No longer allocated here.
}
return true;
#else
// Speed is more important than correctness here, do the operations unchecked
// and hope for the best.
*out = _get_alloc_size(p_elements);
return true;
#endif
return *out;
}

void _unref(void *p_data);
Expand Down Expand Up @@ -294,15 +297,15 @@ Error CowData<T>::resize(int p_size) {
if (current_size == 0) {
// alloc from scratch
uint32_t *ptr = (uint32_t *)Memory::alloc_static(alloc_size, true);
ERR_FAIL_COND_V(!ptr, ERR_OUT_OF_MEMORY);
ERR_FAIL_NULL_V(ptr, ERR_OUT_OF_MEMORY);
*(ptr - 1) = 0; // size, currently none
new (ptr - 2) SafeNumeric<uint32_t>(1); // refcount

_ptr = (T *)ptr;

} else {
uint32_t *_ptrnew = (uint32_t *)Memory::realloc_static(_ptr, alloc_size, true);
ERR_FAIL_COND_V(!_ptrnew, ERR_OUT_OF_MEMORY);
ERR_FAIL_NULL_V(_ptrnew, ERR_OUT_OF_MEMORY);
new (_ptrnew - 2) SafeNumeric<uint32_t>(rc); // refcount

_ptr = (T *)(_ptrnew);
Expand Down Expand Up @@ -332,7 +335,7 @@ Error CowData<T>::resize(int p_size) {

if (alloc_size != current_alloc_size) {
uint32_t *_ptrnew = (uint32_t *)Memory::realloc_static(_ptr, alloc_size, true);
ERR_FAIL_COND_V(!_ptrnew, ERR_OUT_OF_MEMORY);
ERR_FAIL_NULL_V(_ptrnew, ERR_OUT_OF_MEMORY);
new (_ptrnew - 2) SafeNumeric<uint32_t>(rc); // refcount

_ptr = (T *)(_ptrnew);
Expand Down
2 changes: 1 addition & 1 deletion include/godot_cpp/templates/list.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -221,7 +221,7 @@ class List {
int size_cache = 0;

bool erase(const Element *p_I) {
ERR_FAIL_COND_V(!p_I, false);
ERR_FAIL_NULL_V(p_I, false);
ERR_FAIL_COND_V(p_I->data != this, false);

if (first == p_I) {
Expand Down
6 changes: 3 additions & 3 deletions include/godot_cpp/templates/rid_owner.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -186,12 +186,12 @@ class RID_Alloc {
}
void initialize_rid(RID p_rid) {
T *mem = get_or_null(p_rid, true);
ERR_FAIL_COND(!mem);
ERR_FAIL_NULL(mem);
memnew_placement(mem, T);
}
void initialize_rid(RID p_rid, const T &p_value) {
T *mem = get_or_null(p_rid, true);
ERR_FAIL_COND(!mem);
ERR_FAIL_NULL(mem);
memnew_placement(mem, T(p_value));
}

Expand Down Expand Up @@ -374,7 +374,7 @@ class RID_PtrOwner {

_FORCE_INLINE_ void replace(const RID &p_rid, T *p_new_ptr) {
T **ptr = alloc.get_or_null(p_rid);
ERR_FAIL_COND(!ptr);
ERR_FAIL_NULL(ptr);
*ptr = p_new_ptr;
}

Expand Down
8 changes: 4 additions & 4 deletions include/godot_cpp/templates/thread_work_pool.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,7 @@ class ThreadWorkPool {
public:
template <class C, class M, class U>
void begin_work(uint32_t p_elements, C *p_instance, M p_method, U p_userdata) {
ERR_FAIL_COND(!threads); // never initialized
ERR_FAIL_NULL(threads); // Never initialized.
ERR_FAIL_COND(current_work != nullptr);

index.store(0, std::memory_order_release);
Expand All @@ -123,18 +123,18 @@ class ThreadWorkPool {
}

bool is_done_dispatching() const {
ERR_FAIL_COND_V(current_work == nullptr, true);
ERR_FAIL_NULL_V(current_work, true);
return index.load(std::memory_order_acquire) >= current_work->max_elements;
}

uint32_t get_work_index() const {
ERR_FAIL_COND_V(current_work == nullptr, 0);
ERR_FAIL_NULL_V(current_work, 0);
uint32_t idx = index.load(std::memory_order_acquire);
return Math::min(idx, current_work->max_elements);
}

void end_work() {
ERR_FAIL_COND(current_work == nullptr);
ERR_FAIL_NULL(current_work);
for (uint32_t i = 0; i < threads_working; i++) {
threads[i].completed.wait();
threads[i].work = nullptr;
Expand Down
20 changes: 14 additions & 6 deletions include/godot_cpp/variant/variant.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -255,25 +255,33 @@ class Variant {
bool operator!=(const Variant &other) const;
bool operator<(const Variant &other) const;

void call(const StringName &method, const Variant **args, int argcount, Variant &r_ret, GDExtensionCallError &r_error);
void callp(const StringName &method, const Variant **args, int argcount, Variant &r_ret, GDExtensionCallError &r_error);

template <class... Args>
Variant call(const StringName &method, Args... args) {
std::array<Variant, sizeof...(args)> vargs = { args... };
std::array<const Variant *, sizeof...(args)> argptrs;
for (size_t i = 0; i < vargs.size(); i++) {
argptrs[i] = &vargs[i];
}
Variant result;
GDExtensionCallError error;
std::array<GDExtensionConstVariantPtr, sizeof...(Args)> call_args = { Variant(args)... };
call(method, call_args.data(), call_args.size(), result, error);
callp(method, argptrs.data(), argptrs.size(), result, error);
return result;
}

static void call_static(Variant::Type type, const StringName &method, const Variant **args, int argcount, Variant &r_ret, GDExtensionCallError &r_error);
static void callp_static(Variant::Type type, const StringName &method, const Variant **args, int argcount, Variant &r_ret, GDExtensionCallError &r_error);

template <class... Args>
static Variant call_static(Variant::Type type, const StringName &method, Args... args) {
std::array<Variant, sizeof...(args)> vargs = { args... };
std::array<const Variant *, sizeof...(args)> argptrs;
for (size_t i = 0; i < vargs.size(); i++) {
argptrs[i] = &vargs[i];
}
Variant result;
GDExtensionCallError error;
std::array<GDExtensionConstVariantPtr, sizeof...(Args)> call_args = { Variant(args)... };
call_static(type, method, call_args.data(), call_args.size(), result, error);
callp_static(type, method, argptrs.data(), argptrs.size(), sizeof...(args), result, error);
return result;
}

Expand Down
17 changes: 14 additions & 3 deletions src/core/class_db.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ void ClassDB::add_property(const StringName &p_class, const PropertyInfo &p_pinf
if (p_setter != String("")) {
setter = get_method(p_class, p_setter);

ERR_FAIL_COND_MSG(!setter, String("Setter method '{0}::{1}()' not found for property '{2}::{3}'.").format(Array::make(p_class, p_setter, p_class, p_pinfo.name)));
ERR_FAIL_NULL_MSG(setter, String("Setter method '{0}::{1}()' not found for property '{2}::{3}'.").format(Array::make(p_class, p_setter, p_class, p_pinfo.name)));

size_t exp_args = 1 + (p_index >= 0 ? 1 : 0);
ERR_FAIL_COND_MSG((int)exp_args != setter->get_argument_count(), String("Setter method '{0}::{1}()' must take a single argument.").format(Array::make(p_class, p_setter)));
Expand All @@ -86,7 +86,7 @@ void ClassDB::add_property(const StringName &p_class, const PropertyInfo &p_pinf
ERR_FAIL_COND_MSG(p_getter == String(""), String("Getter method must be specified for '{0}::{1}'.").format(Array::make(p_class, p_pinfo.name)));

MethodBind *getter = get_method(p_class, p_getter);
ERR_FAIL_COND_MSG(!getter, String("Getter method '{0}::{1}()' not found for property '{2}::{3}'.").format(Array::make(p_class, p_getter, p_class, p_pinfo.name)));
ERR_FAIL_NULL_MSG(getter, String("Getter method '{0}::{1}()' not found for property '{2}::{3}'.").format(Array::make(p_class, p_getter, p_class, p_pinfo.name)));
{
size_t exp_args = 0 + (p_index >= 0 ? 1 : 0);
ERR_FAIL_COND_MSG((int)exp_args != getter->get_argument_count(), String("Getter method '{0}::{1}()' must not take any argument.").format(Array::make(p_class, p_getter)));
Expand Down Expand Up @@ -318,7 +318,18 @@ GDExtensionClassCallVirtual ClassDB::get_virtual_func(void *p_userdata, GDExtens

const GDExtensionInstanceBindingCallbacks *ClassDB::get_instance_binding_callbacks(const StringName &p_class) {
std::unordered_map<StringName, const GDExtensionInstanceBindingCallbacks *>::iterator callbacks_it = instance_binding_callbacks.find(p_class);
ERR_FAIL_COND_V_MSG(callbacks_it == instance_binding_callbacks.end(), nullptr, String("Cannot find instance binding callbacks for class '{0}'.").format(Array::make(p_class)));
if (likely(callbacks_it != instance_binding_callbacks.end())) {
return callbacks_it->second;
}

// If we don't have an instance binding callback for the given class, find the closest parent where we do.
StringName class_name = p_class;
do {
class_name = get_parent_class(class_name);
ERR_FAIL_COND_V_MSG(class_name == StringName(), nullptr, String("Cannot find instance binding callbacks for class '{0}'.").format(Array::make(p_class)));
callbacks_it = instance_binding_callbacks.find(class_name);
} while (callbacks_it == instance_binding_callbacks.end());

return callbacks_it->second;
}

Expand Down
4 changes: 2 additions & 2 deletions src/core/memory.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ void *Memory::alloc_static(size_t p_bytes, bool p_pad_align) {
#endif

void *mem = internal::gdextension_interface_mem_alloc(p_bytes + (prepad ? PAD_ALIGN : 0));
ERR_FAIL_COND_V(!mem, nullptr);
ERR_FAIL_NULL_V(mem, nullptr);

if (prepad) {
uint8_t *s8 = (uint8_t *)mem;
Expand Down Expand Up @@ -71,7 +71,7 @@ void *Memory::realloc_static(void *p_memory, size_t p_bytes, bool p_pad_align) {
if (prepad) {
mem -= PAD_ALIGN;
mem = (uint8_t *)internal::gdextension_interface_mem_realloc(mem, p_bytes + PAD_ALIGN);
ERR_FAIL_COND_V(!mem, nullptr);
ERR_FAIL_NULL_V(mem, nullptr);
return mem + PAD_ALIGN;
} else {
return (uint8_t *)internal::gdextension_interface_mem_realloc(mem, p_bytes);
Expand Down
2 changes: 1 addition & 1 deletion src/godot.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -403,7 +403,7 @@ GDExtensionBool GDExtensionBinding::init(GDExtensionInterfaceGetProcAddress p_ge
r_initialization->deinitialize = deinitialize_level;
r_initialization->minimum_initialization_level = minimum_initialization_level;

ERR_FAIL_COND_V_MSG(init_callback == nullptr, false, "Initialization callback must be defined.");
ERR_FAIL_NULL_V_MSG(init_callback, false, "Initialization callback must be defined.");

Variant::init_bindings();
register_engine_classes();
Expand Down
4 changes: 2 additions & 2 deletions src/variant/variant.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -549,11 +549,11 @@ bool Variant::operator<(const Variant &other) const {
return result.operator bool();
}

void Variant::call(const StringName &method, const Variant **args, int argcount, Variant &r_ret, GDExtensionCallError &r_error) {
void Variant::callp(const StringName &method, const Variant **args, int argcount, Variant &r_ret, GDExtensionCallError &r_error) {
internal::gdextension_interface_variant_call(_native_ptr(), method._native_ptr(), reinterpret_cast<GDExtensionConstVariantPtr *>(args), argcount, r_ret._native_ptr(), &r_error);
}

void Variant::call_static(Variant::Type type, const StringName &method, const Variant **args, int argcount, Variant &r_ret, GDExtensionCallError &r_error) {
void Variant::callp_static(Variant::Type type, const StringName &method, const Variant **args, int argcount, Variant &r_ret, GDExtensionCallError &r_error) {
internal::gdextension_interface_variant_call_static(static_cast<GDExtensionVariantType>(type), method._native_ptr(), reinterpret_cast<GDExtensionConstVariantPtr *>(args), argcount, r_ret._native_ptr(), &r_error);
}

Expand Down
2 changes: 2 additions & 0 deletions test/project/example.gdextension
Original file line number Diff line number Diff line change
Expand Up @@ -21,3 +21,5 @@ 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"
web.debug.wasm32 = "res://bin/libgdexample.javascript.template_debug.wasm32.wasm"
web.release.wasm32 = "res://bin/libgdexample.javascript.template_release.wasm32.wasm"
7 changes: 7 additions & 0 deletions test/project/main.gd
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@ extends "res://test_base.gd"

var custom_signal_emitted = null

class TestClass:
func test(p_msg: String) -> String:
return p_msg + " world"

func _ready():
var example: Example = $Example
Expand Down Expand Up @@ -137,6 +140,10 @@ func _ready():
assert_equal(new_tilemap.tile_set, new_tileset)
new_tilemap.queue_free()

# Test variant call.
var test_obj = TestClass.new()
assert_equal(example.test_variant_call(test_obj), "hello world")

# Constants.
assert_equal(Example.FIRST, 0)
assert_equal(Example.ANSWER_TO_EVERYTHING, 42)
Expand Down
6 changes: 6 additions & 0 deletions test/src/example.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,8 @@ void Example::_bind_methods() {
ClassDB::bind_method(D_METHOD("test_add_child", "node"), &Example::test_add_child);
ClassDB::bind_method(D_METHOD("test_set_tileset", "tilemap", "tileset"), &Example::test_set_tileset);

ClassDB::bind_method(D_METHOD("test_variant_call", "variant"), &Example::test_variant_call);

ClassDB::bind_method(D_METHOD("test_bitfield", "flags"), &Example::test_bitfield);

ClassDB::bind_method(D_METHOD("test_rpc", "value"), &Example::test_rpc);
Expand Down Expand Up @@ -391,6 +393,10 @@ void Example::test_set_tileset(TileMap *p_tilemap, const Ref<TileSet> &p_tileset
p_tilemap->set_tileset(p_tileset);
}

Variant Example::test_variant_call(Variant p_variant) {
return p_variant.call("test", "hello");
}

BitField<Example::Flags> Example::test_bitfield(BitField<Flags> flags) {
return flags;
}
Expand Down
3 changes: 3 additions & 0 deletions test/src/example.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
#include <godot_cpp/classes/tile_map.hpp>
#include <godot_cpp/classes/tile_set.hpp>
#include <godot_cpp/classes/viewport.hpp>
#include <godot_cpp/variant/variant.hpp>

#include <godot_cpp/core/binder_common.hpp>

Expand Down Expand Up @@ -133,6 +134,8 @@ class Example : public Control {
void test_add_child(Node *p_node);
void test_set_tileset(TileMap *p_tilemap, const Ref<TileSet> &p_tileset) const;

Variant test_variant_call(Variant p_variant);

BitField<Flags> test_bitfield(BitField<Flags> flags);

// RPC
Expand Down
Loading