diff --git a/README.md b/README.md index e7c4b05..860593a 100644 --- a/README.md +++ b/README.md @@ -100,7 +100,7 @@ class SimpleScript extends Sprite2D { // Any method that needs to be seen by a signal needs to be exported @GodotExport() void onSignal() { - // To call and RPC as an RPC you use the $rpc variable + // To call an RPC as an RPC you use the $rpc variable $rpc.rpcMessage('message'); } } @@ -133,8 +133,7 @@ class Simple extends Sprite2D { StringName.fromString('Simple'), parentClass: StringName.fromString('Sprite2D'), // a vTable getter is required for classes that will be used from extensions. - // If you are not adding any virtual functions, just return the base class's vTable. - // If the class is only used from scripts, this is likely not necessary. + // If you are not adding any virtual functions, just return the base class's vTable. vTable: Sprite2D.sTypeInfo.vTable; ); // An override of [typeInfo] is required. This is how @@ -184,9 +183,9 @@ void main() { ### Casting -When you are working with a Godot object, do not use `is` or `as` to perform downcasting. This will -always fail because of how Godot extension works. Instead, use `.cast`, which will return `null` -if the cast fails. +Early versions of Godot Dart required using `.cast` to perform downcasting. This is no longer +necessary. Dart's built in `is` and `as` operators should now work to perform downcasting. `cast` +has also been removed and replaced with `.as`, which is an implementation of `as?` or `dynamic_cast`. ### Virtual functions diff --git a/example/2d_tutorial/src/lib/game_logic.dart b/example/2d_tutorial/src/lib/game_logic.dart index ba1cdd3..e23bc15 100644 --- a/example/2d_tutorial/src/lib/game_logic.dart +++ b/example/2d_tutorial/src/lib/game_logic.dart @@ -75,7 +75,7 @@ class GameLogic extends Node { @GodotExport() void onMobTimerTimeout() { - final mob = mobScene?.instantiate()?.cast(); + final mob = mobScene?.instantiate()?.as(); if (mob != null) { var mobSpawnLocation = getNodeT('MobPath/MobSpawnLocation')!; diff --git a/src/cpp/dart_bindings.cpp b/src/cpp/dart_bindings.cpp index b1138fe..027e995 100644 --- a/src/cpp/dart_bindings.cpp +++ b/src/cpp/dart_bindings.cpp @@ -397,18 +397,18 @@ void GodotDartBindings::bind_method(const TypeInfo &bind_type, const char *metho Dart_Handle GodotDartBindings::find_dart_type(Dart_Handle type_name) { DartBlockScope scope; - uint8_t* c_type_name = nullptr; + uint8_t *c_type_name = nullptr; intptr_t length = 0; Dart_StringToUTF8(type_name, &c_type_name, &length); - if (0 == strncmp(reinterpret_cast(c_type_name), "Object", length)) { + if (0 == strncmp(reinterpret_cast(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.") + "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."); + "Could not find type in the engine_classes_library."); return type; } @@ -815,9 +815,17 @@ void gd_object_to_dart_object(Dart_NativeArguments args) { } GDEWrapper *gde = GDEWrapper::instance(); + GDExtensionScriptInstanceDataPtr script_instance = gde_object_get_script_instance( + reinterpret_cast(object_ptr), DartScriptLanguage::instance()->_owner); + if (script_instance) { + Dart_Handle obj = reinterpret_cast(script_instance)->get_dart_object(); + Dart_SetReturnValue(args, obj); + return; + } DartGodotInstanceBinding *binding = (DartGodotInstanceBinding *)gde_object_get_instance_binding( - reinterpret_cast(object_ptr), bindings, &DartGodotInstanceBinding::engine_binding_callbacks); + reinterpret_cast(object_ptr), bindings, + &DartGodotInstanceBinding::engine_binding_callbacks); if (binding == nullptr) { Dart_SetReturnValue(args, Dart_Null()); } else { @@ -905,7 +913,7 @@ 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 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; @@ -938,8 +946,8 @@ GDE_EXPORT void tie_dart_to_native(Dart_Handle dart_object, GDExtensionObjectPtr type_info_from_dart(&class_type_info, d_class_type_info); const GDExtensionInstanceBindingCallbacks *callbacks = &DartGodotInstanceBinding::engine_binding_callbacks; - DartGodotInstanceBinding *binding = (DartGodotInstanceBinding *)gde_object_get_instance_binding( - godot_object, bindings, callbacks); + DartGodotInstanceBinding *binding = + (DartGodotInstanceBinding *)gde_object_get_instance_binding(godot_object, bindings, callbacks); if (!binding->is_initialized()) { binding->initialize(dart_object, is_refcounted); } diff --git a/src/dart/godot_dart/lib/src/core/gdextension.dart b/src/dart/godot_dart/lib/src/core/gdextension.dart index da99c40..ea88b4e 100644 --- a/src/dart/godot_dart/lib/src/core/gdextension.dart +++ b/src/dart/godot_dart/lib/src/core/gdextension.dart @@ -212,37 +212,8 @@ class GodotDart { } extension GodotObjectCast on GodotObject { - // TODO: We might not need this if gdObjectToDartObject checks - // if something has a script instance, than casts it directly. - T? cast() { - var typeInfo = gde.dartBindings.getGodotTypeInfo(T); - final classTag = gde.getClassTag(typeInfo.className); - Pointer casted; - if (classTag != nullptr) { - casted = gde.ffiBindings.gde_object_cast_to(nativePtr, classTag); - if (casted == nullptr) { - return null; - } - - final persistent = gde.ffiBindings.gde_object_get_instance_binding( - casted, - gde.extensionToken, - gde.engineBindingCallbacks, - ); - final dartObject = gde.dartBindings.objectFromInstanceBinding(persistent); - - return dartObject as T; - } else { - // Try getting the script instance, and casting from that - final scriptInstance = gde.dartBindings.getScriptInstance(nativePtr); - if (scriptInstance != nullptr) { - final o = gde.dartBindings.objectFromScriptInstance(scriptInstance); - if (o is T) { - return o; - } - } - } - - return null; + // Implementation of as? or dynamic_cast + T? as() { + return this is T ? this as T : null; } } diff --git a/src/dart/godot_dart/lib/src/core/type_info.dart b/src/dart/godot_dart/lib/src/core/type_info.dart index d34140e..9b8aad6 100644 --- a/src/dart/godot_dart/lib/src/core/type_info.dart +++ b/src/dart/godot_dart/lib/src/core/type_info.dart @@ -120,7 +120,7 @@ class TypeInfo { this.size = 0, this.vTable = const {}, this.scriptInfo, - }) {} + }); static late Map _typeMapping; static void initTypeMappings() { diff --git a/src/dart/godot_dart/lib/src/extensions/core_extensions.dart b/src/dart/godot_dart/lib/src/extensions/core_extensions.dart index 05699ab..1572ee3 100644 --- a/src/dart/godot_dart/lib/src/extensions/core_extensions.dart +++ b/src/dart/godot_dart/lib/src/extensions/core_extensions.dart @@ -15,7 +15,7 @@ extension TNode on Node { name = GDString.fromStringName(typeInfo.className); } var node = getNode(NodePath.fromGDString(name)); - return node?.cast(); + return node?.as(); } } diff --git a/src/dart/godot_dart_build/lib/src/godot_script_generator.dart b/src/dart/godot_dart_build/lib/src/godot_script_generator.dart index 165fb5c..ea0df57 100644 --- a/src/dart/godot_dart_build/lib/src/godot_script_generator.dart +++ b/src/dart/godot_dart_build/lib/src/godot_script_generator.dart @@ -149,7 +149,6 @@ class GodotScriptAnnotationGenerator buffer.writeln(' name: \'$exportName\','); buffer.writeln(' dartMethodName: \'${element.name}\','); } else if (element.hasOverride) { - // TODO - I might change the naming scheme here final godotMethodName = _convertVirtualMethodName(element.name); buffer.writeln(' name: \'$godotMethodName\','); buffer.writeln(' dartMethodName: \'${element.name}\','); @@ -311,7 +310,7 @@ class GodotScriptAnnotationGenerator StringBuffer buffer = StringBuffer(); final className = element.name; - final rpcMethodsClass = '_\$${className}RpcMethods'; + final rpcMethodsClass = '\$${className}RpcMethods'; buffer.writeln('class $rpcMethodsClass {'); buffer.writeln(' $className self;'); buffer.writeln(' $rpcMethodsClass(this.self);');