From 7adc7a29194d196e605585fae90b236d5b8d7d97 Mon Sep 17 00:00:00 2001 From: Mario Zechner Date: Sat, 27 Aug 2022 15:17:57 +0200 Subject: [PATCH] [flutter] Dart side wrapping of skeleton, incomplete. --- spine-flutter/example/lib/main.dart | 1 + spine-flutter/lib/spine_flutter.dart | 144 ++++++++++++++++++ .../lib/spine_flutter_bindings_generated.dart | 7 +- spine-flutter/lib/spine_widget.dart | 3 +- spine-flutter/src/spine_flutter.cpp | 2 +- spine-flutter/src/spine_flutter.h | 2 +- 6 files changed, 152 insertions(+), 7 deletions(-) diff --git a/spine-flutter/example/lib/main.dart b/spine-flutter/example/lib/main.dart index c00e71b44..b1cfa990f 100644 --- a/spine-flutter/example/lib/main.dart +++ b/spine-flutter/example/lib/main.dart @@ -53,6 +53,7 @@ class AnimationStateEvents extends StatelessWidget { Widget build(BuildContext context) { final controller = SpineWidgetController((controller) { final trackEntry = controller.animationState?.setAnimation(0, "walk", true); + controller.skeleton.setColor(1, 0, 0, 1); }); return Scaffold( diff --git a/spine-flutter/lib/spine_flutter.dart b/spine-flutter/lib/spine_flutter.dart index 78f9ae2ac..0895b63b1 100644 --- a/spine-flutter/lib/spine_flutter.dart +++ b/spine-flutter/lib/spine_flutter.dart @@ -118,10 +118,154 @@ class SkeletonData { } } +class Bone { + final spine_bone _bone; + + Bone(this._bone); +} + +class Slot { + final spine_slot _slot; + + Slot(this._slot); +} + +class Attachment { + final spine_attachment _attachment; + + Attachment(this._attachment); +} + +class IkConstraint { + final spine_ik_constraint _constraint; + + IkConstraint(this._constraint); +} + +class TransformConstraint { + final spine_transform_constraint _constraint; + + TransformConstraint(this._constraint); +} + +class PathConstraint { + final spine_path_constraint _constraint; + + PathConstraint(this._constraint); +} + class Skeleton { final spine_skeleton _skeleton; Skeleton(this._skeleton); + + /// Caches information about bones and constraints. Must be called if bones, constraints or weighted path attachments are added + /// or removed. + void updateCache() { + _bindings.spine_skeleton_update_cache(_skeleton); + } + + /// Updates the world transform for each bone and applies constraints. + void updateWorldTransform() { + _bindings.spine_skeleton_update_world_transform(_skeleton); + } + + void updateWorldTransformBone(Bone parent) { + _bindings.spine_skeleton_update_world_transform_bone(_skeleton, parent._bone); + } + + /// Sets the bones, constraints, and slots to their setup pose values. + void setToSetupPose() { + _bindings.spine_skeleton_set_to_setup_pose(_skeleton); + } + + /// Sets the bones and constraints to their setup pose values. + void setBonesToSetupPose() { + _bindings.spine_skeleton_set_bones_to_setup_pose(_skeleton); + } + + void setSlotsToSetupPose() { + _bindings.spine_skeleton_set_slots_to_setup_pose(_skeleton); + } + + Bone? findBone(String boneName) { + final nameNative = boneName.toNativeUtf8(); + final bone = _bindings.spine_skeleton_find_bone(_skeleton, nameNative.cast()); + calloc.free(nameNative); + if (bone.address == nullptr.address) return null; + return Bone(bone); + } + + Slot? findSlot(String slotName) { + final nameNative = slotName.toNativeUtf8(); + final slot = _bindings.spine_skeleton_find_slot(_skeleton, nameNative.cast()); + calloc.free(nameNative); + if (slot.address == nullptr.address) return null; + return Slot(slot); + } + + /// Attachments from the new skin are attached if the corresponding attachment from the old skin was attached. + /// If there was no old skin, each slot's setup mode attachment is attached from the new skin. + /// After changing the skin, the visible attachments can be reset to those attached in the setup pose by calling + /// See Skeleton::setSlotsToSetupPose() + /// Also, often AnimationState::apply(Skeleton&) is called before the next time the + /// skeleton is rendered to allow any attachment keys in the current animation(s) to hide or show attachments from the new skin. + /// @param newSkin May be NULL. + void setSkin(String skinName) { + final nameNative = skinName.toNativeUtf8(); + _bindings.spine_skeleton_set_skin(_skeleton, nameNative.cast()); + calloc.free(nameNative); + } + + Attachment? getAttachmentByName(String slotName, String attachmentName) { + final slotNameNative = slotName.toNativeUtf8(); + final attachmentNameNative = attachmentName.toNativeUtf8(); + final attachment = _bindings.spine_skeleton_get_attachment_by_name(_skeleton, slotNameNative.cast(), attachmentNameNative.cast()); + calloc.free(slotNameNative); + calloc.free(attachmentNameNative); + if (attachment.address == nullptr.address) return null; + return Attachment(attachment); + } + + Attachment? getAttachment(int slotIndex, String attachmentName) { + final attachmentNameNative = attachmentName.toNativeUtf8(); + final attachment = _bindings.spine_skeleton_get_attachment(_skeleton, slotIndex, attachmentNameNative.cast()); + calloc.free(attachmentNameNative); + if (attachment.address == nullptr.address) return null; + return Attachment(attachment); + } + + void setAttachment(String slotName, String attachmentName) { + final slotNameNative = slotName.toNativeUtf8(); + final attachmentNameNative = attachmentName.toNativeUtf8(); + _bindings.spine_skeleton_set_attachment(_skeleton, slotNameNative.cast(), attachmentNameNative.cast()); + calloc.free(slotNameNative); + calloc.free(attachmentNameNative); + } + + IkConstraint? findIkConstraint(String constraintName) { + final nameNative = constraintName.toNativeUtf8(); + final constraint = _bindings.spine_skeleton_find_ik_constraint(_skeleton, nameNative.cast()); + calloc.free(nameNative); + if (constraint.address == nullptr.address) return null; + return IkConstraint(constraint); + } + + TransformConstraint? findTransformConstraint(String constraintName) { + final nameNative = constraintName.toNativeUtf8(); + final constraint = _bindings.spine_skeleton_find_transform_constraint(_skeleton, nameNative.cast()); + calloc.free(nameNative); + if (constraint.address == nullptr.address) return null; + return TransformConstraint(constraint); + } + + PathConstraint? findPathConstraint(String constraintName) { + final nameNative = constraintName.toNativeUtf8(); + final constraint = _bindings.spine_skeleton_find_path_constraint(_skeleton, nameNative.cast()); + calloc.free(nameNative); + if (constraint.address == nullptr.address) return null; + return PathConstraint(constraint); + } } class Animation { diff --git a/spine-flutter/lib/spine_flutter_bindings_generated.dart b/spine-flutter/lib/spine_flutter_bindings_generated.dart index 4113d71dd..1b2f83659 100644 --- a/spine-flutter/lib/spine_flutter_bindings_generated.dart +++ b/spine-flutter/lib/spine_flutter_bindings_generated.dart @@ -1243,7 +1243,7 @@ class SpineFlutterBindings { void spine_skeleton_update_world_transform_bone( spine_skeleton skeleton, - ffi.Pointer parent, + spine_bone parent, ) { return _spine_skeleton_update_world_transform_bone( skeleton, @@ -1252,12 +1252,11 @@ class SpineFlutterBindings { } late final _spine_skeleton_update_world_transform_bonePtr = _lookup< - ffi.NativeFunction< - ffi.Void Function(spine_skeleton, ffi.Pointer)>>( + ffi.NativeFunction>( 'spine_skeleton_update_world_transform_bone'); late final _spine_skeleton_update_world_transform_bone = _spine_skeleton_update_world_transform_bonePtr - .asFunction)>(); + .asFunction(); void spine_skeleton_set_to_setup_pose( spine_skeleton skeleton, diff --git a/spine-flutter/lib/spine_widget.dart b/spine-flutter/lib/spine_widget.dart index 93ad69096..c95b1059b 100644 --- a/spine-flutter/lib/spine_widget.dart +++ b/spine-flutter/lib/spine_widget.dart @@ -204,9 +204,10 @@ class _SpineRenderObject extends RenderBox { ..save() ..clipRect(offset & size); - final commands = _skeletonDrawable.render(); canvas.save(); canvas.translate(offset.dx + size.width / 2, offset.dy + size.height); + + final commands = _skeletonDrawable.render(); for (final cmd in commands) { canvas.drawVertices(cmd.vertices, BlendMode.modulate, _skeletonDrawable.atlas.atlasPagePaints[cmd.atlasPageIndex]); diff --git a/spine-flutter/src/spine_flutter.cpp b/spine-flutter/src/spine_flutter.cpp index 5d3357ee6..7e0c8cbfe 100644 --- a/spine-flutter/src/spine_flutter.cpp +++ b/spine-flutter/src/spine_flutter.cpp @@ -660,7 +660,7 @@ FFI_PLUGIN_EXPORT void spine_skeleton_update_world_transform(spine_skeleton skel _skeleton->updateWorldTransform(); } -FFI_PLUGIN_EXPORT void spine_skeleton_update_world_transform_bone(spine_skeleton skeleton, spine_bone *parent) { +FFI_PLUGIN_EXPORT void spine_skeleton_update_world_transform_bone(spine_skeleton skeleton, spine_bone parent) { if (skeleton == nullptr) return; if (parent == nullptr) return; Skeleton *_skeleton = (Skeleton*)skeleton; diff --git a/spine-flutter/src/spine_flutter.h b/spine-flutter/src/spine_flutter.h index 866ef9a2b..6a06388ac 100644 --- a/spine-flutter/src/spine_flutter.h +++ b/spine-flutter/src/spine_flutter.h @@ -183,7 +183,7 @@ FFI_PLUGIN_EXPORT float spine_track_entry_get_track_complete(spine_track_entry e FFI_PLUGIN_EXPORT void spine_skeleton_update_cache(spine_skeleton skeleton); FFI_PLUGIN_EXPORT void spine_skeleton_update_world_transform(spine_skeleton skeleton); -FFI_PLUGIN_EXPORT void spine_skeleton_update_world_transform_bone(spine_skeleton skeleton, spine_bone *parent); +FFI_PLUGIN_EXPORT void spine_skeleton_update_world_transform_bone(spine_skeleton skeleton, spine_bone parent); FFI_PLUGIN_EXPORT void spine_skeleton_set_to_setup_pose(spine_skeleton skeleton); FFI_PLUGIN_EXPORT void spine_skeleton_set_bones_to_setup_pose(spine_skeleton skeleton); FFI_PLUGIN_EXPORT void spine_skeleton_set_slots_to_setup_pose(spine_skeleton skeleton);