Skip to content

Commit

Permalink
feat: Remove requirement for 'bindingToken' .
Browse files Browse the repository at this point in the history
This is a giant refactor that completely removes the need for 'bindingTokens'. This should, eventually, allow me to get ride of `.cast` except to be used as an actual dynamic cast instead of a necessity over Dart `is` / `as`.

This still needs to be tested with a more complex project to see if it actually works.
  • Loading branch information
fuzzybinary committed Dec 22, 2024
1 parent 85c7f5f commit d4d8d61
Show file tree
Hide file tree
Showing 39 changed files with 272 additions and 319 deletions.
1 change: 1 addition & 0 deletions example/2d_tutorial/.gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,4 @@
*.dylib
*.pdb
*.exp
*.so
2 changes: 2 additions & 0 deletions example/2d_tutorial/fonts/Xolonium-Regular.ttf.import
Original file line number Diff line number Diff line change
Expand Up @@ -15,13 +15,15 @@ dest_files=["res://.godot/imported/Xolonium-Regular.ttf-bc2981e3069cff4c34dd7c8e
Rendering=null
antialiasing=1
generate_mipmaps=false
disable_embedded_bitmaps=true
multichannel_signed_distance_field=false
msdf_pixel_range=8
msdf_size=48
allow_system_fallback=true
force_autohinter=false
hinting=1
subpixel_positioning=1
keep_rounding_remainders=true
oversampling=0.0
Fallbacks=null
fallbacks=[]
Expand Down
1 change: 1 addition & 0 deletions example/2d_tutorial/godot_dart.gdextension.uid
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
uid://b6chiggk1agbi
2 changes: 1 addition & 1 deletion example/2d_tutorial/main.tscn
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[gd_scene load_steps=9 format=4 uid="uid://tnm416ggiork"]

[ext_resource type="Script" path="res://src/lib/game_logic.dart" id="1_724d8"]
[ext_resource type="Script" uid="uid://wy5n7q67gfpi" path="res://src/lib/game_logic.dart" id="1_724d8"]
[ext_resource type="PackedScene" uid="uid://j6e8fjrrm1xp" path="res://mob.tscn" id="2_7ma3k"]
[ext_resource type="PackedScene" uid="uid://ylcs4f06tfbg" path="res://player.tscn" id="2_eccq4"]
[ext_resource type="PackedScene" uid="uid://6a3aidlclhn4" path="res://hud.tscn" id="4_abxjl"]
Expand Down
8 changes: 4 additions & 4 deletions example/2d_tutorial/project.godot
Original file line number Diff line number Diff line change
Expand Up @@ -25,21 +25,21 @@ window/stretch/mode="canvas_items"

move_right={
"deadzone": 0.5,
"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-3,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":4194321,"key_label":0,"unicode":0,"location":0,"echo":false,"script":null)
"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":4194321,"key_label":0,"unicode":0,"location":0,"echo":false,"script":null)
]
}
move_left={
"deadzone": 0.5,
"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-3,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":4194319,"key_label":0,"unicode":0,"location":0,"echo":false,"script":null)
"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":4194319,"key_label":0,"unicode":0,"location":0,"echo":false,"script":null)
]
}
move_up={
"deadzone": 0.5,
"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-3,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":4194320,"key_label":0,"unicode":0,"location":0,"echo":false,"script":null)
"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":4194320,"key_label":0,"unicode":0,"location":0,"echo":false,"script":null)
]
}
move_down={
"deadzone": 0.5,
"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-3,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":4194322,"key_label":0,"unicode":0,"location":0,"echo":false,"script":null)
"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":4194322,"key_label":0,"unicode":0,"location":0,"echo":false,"script":null)
]
}
1 change: 1 addition & 0 deletions example/2d_tutorial/src/godot_dart_scripts.g.dart.uid
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
uid://ccw2wbfog3u58
1 change: 1 addition & 0 deletions example/2d_tutorial/src/lib/game_logic.dart.uid
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
uid://wy5n7q67gfpi
1 change: 1 addition & 0 deletions example/2d_tutorial/src/lib/game_logic.g.dart.uid
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
uid://bxs73svhcgluv
1 change: 1 addition & 0 deletions example/2d_tutorial/src/lib/hud.dart.uid
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
uid://cj0mstcs30fnk
1 change: 1 addition & 0 deletions example/2d_tutorial/src/lib/hud.g.dart.uid
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
uid://8n72sq862ktq
1 change: 1 addition & 0 deletions example/2d_tutorial/src/lib/mob.dart.uid
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
uid://cjjhbkgdf1t1e
1 change: 1 addition & 0 deletions example/2d_tutorial/src/lib/mob.g.dart.uid
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
uid://dh20pv8eus6ui
2 changes: 1 addition & 1 deletion example/2d_tutorial/src/lib/player.dart
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ class Player extends Area2D {
animatedSprite?.setFlipV(velocity.y > 0);
}
} else {
getNodeT<AnimatedSprite2D>()?.stop();
animatedSprite?.stop();
}

var position = getPosition();
Expand Down
1 change: 1 addition & 0 deletions example/2d_tutorial/src/lib/player.dart.uid
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
uid://doy5q8n0id6u6
1 change: 1 addition & 0 deletions example/2d_tutorial/src/lib/player.g.dart.uid
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
uid://bm6hxkpovixtq
1 change: 1 addition & 0 deletions example/2d_tutorial/src/main.dart.uid
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
uid://d0jqb13n3xw3w
84 changes: 40 additions & 44 deletions src/cpp/dart_bindings.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -64,13 +64,19 @@ bool GodotDartBindings::initialize(const char *script_path, const char *package_
Dart_SetMessageNotifyCallback(dart_message_notify_callback);

Dart_Handle godot_dart_package_name = Dart_NewStringFromCString("package:godot_dart/godot_dart.dart");
Dart_Handle godot_dart_library = Dart_LookupLibrary(godot_dart_package_name);
if (Dart_IsError(godot_dart_library)) {
GD_PRINT_ERROR("GodotDart: Initialization Error (Could not find the `godot_dart` "
DART_CHECK_RET(godot_dart_library, Dart_LookupLibrary(godot_dart_package_name), false,
"GodotDart: Initialization Error (Could not find the `godot_dart` "
"package)");
_godot_dart_library = Dart_NewPersistentHandle(godot_dart_library);

// Find the Engine classes library. This is needed to lookup engine types
{
Dart_Handle engine_classes_package_name =
Dart_NewStringFromCString("package:godot_dart/src/gen/engine_classes.dart");
DART_CHECK_RET(engine_classes_library, Dart_LookupLibrary(engine_classes_package_name), false,
"GodotDart: Initialization Error (Could not find the `engine_classes.dart` "
"package)");
return false;
} else {
_godot_dart_library = Dart_NewPersistentHandle(godot_dart_library);
_engine_classes_library = Dart_NewPersistentHandle(engine_classes_library);
}

// Find the DartBindings "library" (just the file) and set us as the native callback handler
Expand All @@ -83,11 +89,10 @@ bool GodotDartBindings::initialize(const char *script_path, const char *package_
Dart_SetNativeResolver(library, native_resolver, nullptr);
}

// Find the DartBindings "library" (just the file) and set us as the native callback handler
// Find the CoreTypes "library" (just the file) and set us as the native callback handler
{
Dart_Handle native_bindings_library_name =
Dart_NewStringFromCString("package:godot_dart/src/core/core_types.dart");
DART_CHECK_RET(library, Dart_LookupLibrary(native_bindings_library_name), false, "Error finding core_types.dart");
Dart_Handle core_bindings_library_name = Dart_NewStringFromCString("package:godot_dart/src/core/core_types.dart");
DART_CHECK_RET(library, Dart_LookupLibrary(core_bindings_library_name), false, "Error finding core_types.dart");
Dart_SetNativeResolver(library, native_resolver, nullptr);
}

Expand Down Expand Up @@ -151,7 +156,7 @@ bool GodotDartBindings::initialize(const char *script_path, const char *package_
{
GDEWrapper *wrapper = GDEWrapper::instance();
Dart_Handle args[] = {
Dart_NewInteger((int64_t)wrapper->get_library_ptr()),
Dart_NewInteger((int64_t)this),
Dart_NewInteger(((int64_t)&DartGodotInstanceBinding::engine_binding_callbacks)),
};
DART_CHECK_RET(result, Dart_Invoke(godot_dart_library, Dart_NewStringFromCString("_registerGodot"), 2, args),
Expand Down Expand Up @@ -389,6 +394,25 @@ void GodotDartBindings::bind_method(const TypeInfo &bind_type, const char *metho
delete[] arg_meta_info;
}

Dart_Handle GodotDartBindings::find_dart_type(Dart_Handle type_name) {
DartBlockScope scope;

uint8_t* c_type_name = nullptr;
intptr_t length = 0;
Dart_StringToUTF8(type_name, &c_type_name, &length);
if (0 == strncmp(reinterpret_cast<const char*>(c_type_name), "Object", length)) {
type_name = Dart_NewStringFromCString("GodotObject");
}

DART_CHECK_RET(engine_classes_library, Dart_HandleFromPersistent(_engine_classes_library), Dart_Null(),
"Error getting class class library.")

DART_CHECK_RET(type, Dart_GetNonNullableType(engine_classes_library, type_name, 0, nullptr), Dart_Null(),
"Could not find type in the engine_classes_library.");

return type;
}

void GodotDartBindings::add_property(const TypeInfo &bind_type, Dart_Handle dart_prop_info) {

GDExtensionPropertyInfo prop_info = {};
Expand Down Expand Up @@ -791,25 +815,9 @@ void gd_object_to_dart_object(Dart_NativeArguments args) {
}

GDEWrapper *gde = GDEWrapper::instance();

// Default for non-engine classes
void *token = gde->get_library_ptr();

Dart_Handle bindings_token = Dart_GetNativeArgument(args, 2);
if (!Dart_IsNull(bindings_token)) {
address = Dart_GetField(bindings_token, Dart_NewStringFromCString("address"));
if (Dart_IsError(address)) {
GD_PRINT_ERROR(Dart_GetError(address));
Dart_ThrowException(Dart_NewStringFromCString(Dart_GetError(address)));
return;
}
uint64_t token_int = 0;
Dart_IntegerToUint64(address, &token_int);
token = (void *)token_int;
}

DartGodotInstanceBinding *binding = (DartGodotInstanceBinding *)gde_object_get_instance_binding(
reinterpret_cast<GDExtensionObjectPtr>(object_ptr), token, &DartGodotInstanceBinding::engine_binding_callbacks);
reinterpret_cast<GDExtensionObjectPtr>(object_ptr), bindings, &DartGodotInstanceBinding::engine_binding_callbacks);
if (binding == nullptr) {
Dart_SetReturnValue(args, Dart_Null());
} else {
Expand Down Expand Up @@ -897,27 +905,15 @@ void type_info_from_dart(TypeInfo *type_info, Dart_Handle dart_type_info) {

Dart_Handle class_name = Dart_GetField(dart_type_info, Dart_NewStringFromCString("className"));
Dart_Handle parent_type = Dart_GetField(dart_type_info, Dart_NewStringFromCString("parentType"));
Dart_Handle variant_type = Dart_GetField(dart_type_info, Dart_NewStringFromCString("variantType"));
Dart_Handle binding_token = Dart_GetField(dart_type_info, Dart_NewStringFromCString("bindingToken"));
Dart_Handle variant_type = Dart_GetField(dart_type_info, Dart_NewStringFromCString("variantType"));

type_info->type_name = get_object_address(class_name);
type_info->parent_type = parent_type;

int64_t temp;
Dart_IntegerToInt64(variant_type, &temp);
type_info->variant_type = static_cast<GDExtensionVariantType>(temp);
if (Dart_IsNull(binding_token)) {
type_info->binding_token = nullptr;
type_info->binding_callbacks = nullptr;
} else {
Dart_Handle dart_address = Dart_GetField(binding_token, Dart_NewStringFromCString("address"));

uint64_t address = 0;
Dart_IntegerToUint64(dart_address, &address);

type_info->binding_token = (void *)address;
type_info->binding_callbacks = &DartGodotInstanceBinding::engine_binding_callbacks;
}
type_info->binding_callbacks = &DartGodotInstanceBinding::engine_binding_callbacks;

Dart_ExitScope();
}
Expand All @@ -928,6 +924,7 @@ extern "C" {

GDE_EXPORT void tie_dart_to_native(Dart_Handle dart_object, GDExtensionObjectPtr godot_object, bool is_refcounted,
bool is_godot_defined) {
GodotDartBindings *bindings = GodotDartBindings::instance();
DartBlockScope scope;

Dart_Handle d_class_type_info = Dart_GetField(dart_object, Dart_NewStringFromCString("typeInfo"));
Expand All @@ -942,7 +939,7 @@ GDE_EXPORT void tie_dart_to_native(Dart_Handle dart_object, GDExtensionObjectPtr

const GDExtensionInstanceBindingCallbacks *callbacks = &DartGodotInstanceBinding::engine_binding_callbacks;
DartGodotInstanceBinding *binding = (DartGodotInstanceBinding *)gde_object_get_instance_binding(
godot_object, class_type_info.binding_token, callbacks);
godot_object, bindings, callbacks);
if (!binding->is_initialized()) {
binding->initialize(dart_object, is_refcounted);
}
Expand Down Expand Up @@ -1033,5 +1030,4 @@ GDE_EXPORT void *safe_new_persistent_handle(Dart_Handle handle) {

return (void *)result;
}

}
2 changes: 2 additions & 0 deletions src/cpp/dart_bindings.h
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ class GodotDartBindings {

void bind_method(const TypeInfo &bind_type, const char *method_name, const TypeInfo &ret_type_info,
Dart_Handle args_list, MethodFlags method_flags);
Dart_Handle find_dart_type(Dart_Handle type_name);
void add_property(const TypeInfo &bind_type, Dart_Handle dart_prop_info);
void execute_on_dart_thread(std::function<void()> work);
Dart_Handle new_dart_void_pointer(void *ptr);
Expand Down Expand Up @@ -82,6 +83,7 @@ class GodotDartBindings {
std::set<DartGodotInstanceBinding *> _pending_ref_changes;

Dart_PersistentHandle _godot_dart_library;
Dart_PersistentHandle _engine_classes_library;
Dart_PersistentHandle _native_library;

// Some things we need often
Expand Down
51 changes: 33 additions & 18 deletions src/cpp/dart_instance_binding.cpp
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
#include "dart_instance_binding.h"

#include <godot_cpp/classes/object.hpp>
#include <godot_cpp/godot.hpp>

#include "dart_helpers.h"
#include "dart_bindings.h"
#include "dart_helpers.h"
#include "gde_c_interface.h"
#include "ref_counted_wrapper.h"
#include "godot_string_wrappers.h"

void gde_weak_finalizer(void *isolate_callback_data, void *peer) {
if (peer == nullptr) {
Expand All @@ -22,7 +24,7 @@ void gde_weak_finalizer(void *isolate_callback_data, void *peer) {
}
}

std::map<intptr_t, DartGodotInstanceBinding*> DartGodotInstanceBinding::s_instanceMap;
std::map<intptr_t, DartGodotInstanceBinding *> DartGodotInstanceBinding::s_instanceMap;

DartGodotInstanceBinding::~DartGodotInstanceBinding() {
GodotDartBindings *bindings = GodotDartBindings::instance();
Expand All @@ -38,12 +40,10 @@ DartGodotInstanceBinding::~DartGodotInstanceBinding() {
// Don't attempt to execute on the Dart isolate if this is the case
// (it might be already doing things)
Dart_IsolateGroup current_isolate_group = Dart_CurrentIsolateGroup();
if(current_isolate_group) {
if (current_isolate_group) {
delete_dart_handle();
} else {
GodotDartBindings::instance()->execute_on_dart_thread([&]{
delete_dart_handle();
});
GodotDartBindings::instance()->execute_on_dart_thread([&] { delete_dart_handle(); });
}
bindings->remove_pending_ref_change(this);
}
Expand Down Expand Up @@ -136,7 +136,7 @@ void DartGodotInstanceBinding::create_dart_object() {
}

bindings->execute_on_dart_thread([&] {
Dart_PersistentHandle persistent_type = reinterpret_cast<Dart_PersistentHandle>(_token);
Dart_PersistentHandle persistent_type = reinterpret_cast<Dart_PersistentHandle>(_dart_type);
Dart_Handle dart_type = Dart_HandleFromPersistent(persistent_type);

Dart_Handle dart_pointer = bindings->new_dart_void_pointer(_godot_object);
Expand All @@ -152,7 +152,26 @@ void DartGodotInstanceBinding::create_dart_object() {
/* Binding callbacks used for Engine types implemented in Godot and wrapped in Dart */

static void *__engine_binding_create_callback(void *p_token, void *p_instance) {
DartGodotInstanceBinding *binding = new DartGodotInstanceBinding(p_token, p_instance);
GodotDartBindings *bindings = GodotDartBindings::instance();
godot::StringName class_name;

DartGodotInstanceBinding *binding = nullptr;
if (godot::internal::gdextension_interface_object_get_class_name(
p_instance, p_token, reinterpret_cast<GDExtensionStringNamePtr>(class_name._native_ptr()))) {
bindings->execute_on_dart_thread([&] {
Dart_EnterScope();

Dart_Handle type_name = to_dart_string(class_name);
DART_CHECK(type, bindings->find_dart_type(type_name), "Error finding Dart type");
if (!Dart_IsNull(type)) {
Dart_PersistentHandle persistent_type = Dart_NewPersistentHandle(type);
binding = new DartGodotInstanceBinding(persistent_type, p_instance);
}

Dart_ExitScope();
});
}

return binding;
}

Expand All @@ -164,10 +183,10 @@ static void __engine_binding_free_callback(void *p_token, void *p_instance, void
delete binding;
return;
}

if (binding->is_weak() || bindings->_is_stopping) {
// If the binding is weak or we're shutting down, there's a possibility Dart is asking us
// to kill this in a way that does not allow us to call back into any other Dart code other
// If the binding is weak or we're shutting down, there's a possibility Dart is asking us
// to kill this in a way that does not allow us to call back into any other Dart code other
// than deleting the reference. So just do that and be done with it.
delete binding;
return;
Expand Down Expand Up @@ -222,9 +241,7 @@ static GDExtensionBool __engine_binding_reference_callback(void *p_token, void *
// Refcount incremented, change our reference to strong to prevent Dart from finalizing
if (refcount > 1 && engine_binding->is_weak()) {
if (!is_finalizer) {
bindings->execute_on_dart_thread([&] {
engine_binding->convert_to_strong();
});
bindings->execute_on_dart_thread([&] { engine_binding->convert_to_strong(); });
} else {
bindings->add_pending_ref_change(engine_binding);
}
Expand All @@ -234,13 +251,11 @@ static GDExtensionBool __engine_binding_reference_callback(void *p_token, void *
} else {
if (refcount == 1 && !engine_binding->is_weak()) {
if (!is_finalizer) {
bindings->execute_on_dart_thread([&] {
engine_binding->convert_to_weak();
});
bindings->execute_on_dart_thread([&] { engine_binding->convert_to_weak(); });
} else {
bindings->add_pending_ref_change(engine_binding);
}

is_dieing = false;
}
}
Expand Down
6 changes: 3 additions & 3 deletions src/cpp/dart_instance_binding.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@
// persitent handles, encapsulate that into a custom GC handle
class DartGodotInstanceBinding {
public:
DartGodotInstanceBinding(void *token, GDExtensionObjectPtr godot_object)
: _is_refcounted(false), _is_weak(false), _persistent_handle(nullptr), _godot_object(godot_object), _token(token) {
DartGodotInstanceBinding(Dart_PersistentHandle dart_type, GDExtensionObjectPtr godot_object)
: _is_refcounted(false), _is_weak(false), _persistent_handle(nullptr), _godot_object(godot_object), _dart_type(dart_type) {
}

~DartGodotInstanceBinding();
Expand Down Expand Up @@ -46,7 +46,7 @@ class DartGodotInstanceBinding {
bool _is_weak;
void *_persistent_handle;
GDExtensionObjectPtr _godot_object;
void *_token;
Dart_PersistentHandle _dart_type;
};

void gde_weak_finalizer(void *isolate_callback_data, void *peer);
Loading

0 comments on commit d4d8d61

Please sign in to comment.