diff --git a/spine-flutter/example/lib/main.dart b/spine-flutter/example/lib/main.dart index 00205f80d..99f2bb7f9 100644 --- a/spine-flutter/example/lib/main.dart +++ b/spine-flutter/example/lib/main.dart @@ -71,7 +71,7 @@ class AnimationStateEvents extends StatelessWidget { } controller.skeleton?.setScaleX(0.5); controller.skeleton?.setScaleY(0.5); - controller.skeleton?.setColor(Color(1, 1, 0, 1)); + controller.skeleton?.findSlot("gun")?.setColor(Color(1, 0, 0, 1)); controller.animationState?.setAnimation(0, "walk", true)?.setListener((event) { print("Walk animation event ${event.type}"); }); diff --git a/spine-flutter/lib/spine_flutter.dart b/spine-flutter/lib/spine_flutter.dart index 6043f6b0c..0f38146bd 100644 --- a/spine-flutter/lib/spine_flutter.dart +++ b/spine-flutter/lib/spine_flutter.dart @@ -16,6 +16,24 @@ int majorVersion() => _bindings.spine_major_version(); int minorVersion() => _bindings.spine_minor_version(); void reportLeaks() => _bindings.spine_report_leaks(); +class Color { + double r; + double g; + double b; + double a; + + Color(this.r, this.g, this.b, this.a); +} + +class Bounds { + double x; + double y; + double width; + double height; + + Bounds(this.x, this.y, this.width, this.height); +} + class Atlas { final Pointer _atlas; final List atlasPages; @@ -88,6 +106,7 @@ class SkeletonData { static SkeletonData fromJson(Atlas atlas, String json) { final jsonNative = json.toNativeUtf8(); final result = _bindings.spine_skeleton_data_load_json(atlas._atlas, jsonNative.cast()); + calloc.free(jsonNative); if (result.error.address != nullptr.address) { final Pointer error = result.error.cast(); final message = error.toDartString(); @@ -118,16 +137,122 @@ class SkeletonData { } } +enum BlendMode { + Normal(0), + Additive(1), + Multiply(2), + Screen(3); + + final int value; + const BlendMode(this.value); +} + +class BoneData { + final spine_bone_data _data; + + BoneData(this._data); +} + class Bone { final spine_bone _bone; Bone(this._bone); } +class SlotData { + final spine_slot_data _data; + + SlotData(this._data); + + int getIndex() { + return _bindings.spine_slot_data_get_index(_data); + } + + String getName() { + final Pointer value = _bindings.spine_slot_data_get_name(_data).cast(); + return value.toDartString(); + } + + BoneData getBoneData() { + return BoneData(_bindings.spine_slot_data_get_bone_data(_data)); + } + + Color getColor() { + final color = _bindings.spine_slot_data_get_color(_data); + return Color(color.r, color.g, color.b, color.a); + } + + Color getDarkColor() { + final color = _bindings.spine_slot_data_get_dark_color(_data); + return Color(color.r, color.g, color.b, color.a); + } + + bool hasDarkColor() { + return _bindings.spine_slot_data_has_dark_color(_data) == -1; + } + + String getAttachmentName() { + final Pointer value = _bindings.spine_slot_data_get_attachment_name(_data).cast(); + return value.toDartString(); + } + + BlendMode getBlendMode() { + return BlendMode.values[_bindings.spine_slot_data_get_blend_mode(_data)]; + } +} + class Slot { final spine_slot _slot; Slot(this._slot); + + void setToSetupPose() { + _bindings.spine_slot_set_to_setup_pose(_slot); + } + + SlotData getData() { + return SlotData(_bindings.spine_slot_get_data(_slot)); + } + + Bone getBone() { + return Bone(_bindings.spine_slot_get_bone(_slot)); + } + + Skeleton getSkeleton() { + return Skeleton(_bindings.spine_slot_get_skeleton(_slot)); + } + + Color getColor() { + final color = _bindings.spine_slot_get_color(_slot); + return Color(color.r, color.g, color.b, color.a); + } + + void setColor(Color color) { + _bindings.spine_slot_set_color(_slot, color.r, color.g, color.b, color.a); + } + + Color getDarkColor() { + final color = _bindings.spine_slot_get_dark_color(_slot); + return Color(color.r, color.g, color.b, color.a); + } + + void setDarkColor(Color color) { + _bindings.spine_slot_set_dark_color(_slot, color.r, color.g, color.b, color.a); + } + + bool hasDarkColor() { + return _bindings.spine_slot_has_dark_color(_slot) == -1; + } + + Attachment? getAttachment() { + final attachment = _bindings.spine_slot_get_attachment(_slot); + if (attachment.address == nullptr.address) return null; + return Attachment(attachment); + } + + void setAttachment(Attachment? attachment) { + _bindings.spine_slot_set_attachment(_slot, attachment != null ? attachment._attachment : nullptr); + } } class Attachment { @@ -142,15 +267,6 @@ class Skin { Skin(this._skin); } -class Color { - double r; - double g; - double b; - double a; - - Color(this.r, this.g, this.b, this.a); -} - class IkConstraint { final spine_ik_constraint _constraint; @@ -169,15 +285,6 @@ class PathConstraint { PathConstraint(this._constraint); } -class Bounds { - double x; - double y; - double width; - double height; - - Bounds(this.x, this.y, this.width, this.height); -} - class Skeleton { final spine_skeleton _skeleton; @@ -234,7 +341,7 @@ class Skeleton { /// 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. + /// @param skinName May be NULL. void setSkin(String skinName) { final nameNative = skinName.toNativeUtf8(); _bindings.spine_skeleton_set_skin(_skeleton, nameNative.cast()); diff --git a/spine-flutter/lib/spine_flutter_bindings_generated.dart b/spine-flutter/lib/spine_flutter_bindings_generated.dart index d8fd9dd99..64c8bc329 100644 --- a/spine-flutter/lib/spine_flutter_bindings_generated.dart +++ b/spine-flutter/lib/spine_flutter_bindings_generated.dart @@ -2162,6 +2162,296 @@ class SpineFlutterBindings { 'spine_event_get_balance'); late final _spine_event_get_balance = _spine_event_get_balancePtr.asFunction(); + + int spine_slot_data_get_index( + spine_slot_data slot, + ) { + return _spine_slot_data_get_index( + slot, + ); + } + + late final _spine_slot_data_get_indexPtr = + _lookup>( + 'spine_slot_data_get_index'); + late final _spine_slot_data_get_index = + _spine_slot_data_get_indexPtr.asFunction(); + + ffi.Pointer spine_slot_data_get_name( + spine_slot_data slot, + ) { + return _spine_slot_data_get_name( + slot, + ); + } + + late final _spine_slot_data_get_namePtr = _lookup< + ffi.NativeFunction Function(spine_slot_data)>>( + 'spine_slot_data_get_name'); + late final _spine_slot_data_get_name = _spine_slot_data_get_namePtr + .asFunction Function(spine_slot_data)>(); + + spine_bone_data spine_slot_data_get_bone_data( + spine_slot_data slot, + ) { + return _spine_slot_data_get_bone_data( + slot, + ); + } + + late final _spine_slot_data_get_bone_dataPtr = + _lookup>( + 'spine_slot_data_get_bone_data'); + late final _spine_slot_data_get_bone_data = _spine_slot_data_get_bone_dataPtr + .asFunction(); + + spine_color spine_slot_data_get_color( + spine_slot_data slot, + ) { + return _spine_slot_data_get_color( + slot, + ); + } + + late final _spine_slot_data_get_colorPtr = + _lookup>( + 'spine_slot_data_get_color'); + late final _spine_slot_data_get_color = _spine_slot_data_get_colorPtr + .asFunction(); + + spine_color spine_slot_data_get_dark_color( + spine_slot_data slot, + ) { + return _spine_slot_data_get_dark_color( + slot, + ); + } + + late final _spine_slot_data_get_dark_colorPtr = + _lookup>( + 'spine_slot_data_get_dark_color'); + late final _spine_slot_data_get_dark_color = + _spine_slot_data_get_dark_colorPtr + .asFunction(); + + int spine_slot_data_has_dark_color( + spine_slot_data slot, + ) { + return _spine_slot_data_has_dark_color( + slot, + ); + } + + late final _spine_slot_data_has_dark_colorPtr = + _lookup>( + 'spine_slot_data_has_dark_color'); + late final _spine_slot_data_has_dark_color = + _spine_slot_data_has_dark_colorPtr + .asFunction(); + + ffi.Pointer spine_slot_data_get_attachment_name( + spine_slot_data slot, + ) { + return _spine_slot_data_get_attachment_name( + slot, + ); + } + + late final _spine_slot_data_get_attachment_namePtr = _lookup< + ffi.NativeFunction Function(spine_slot_data)>>( + 'spine_slot_data_get_attachment_name'); + late final _spine_slot_data_get_attachment_name = + _spine_slot_data_get_attachment_namePtr + .asFunction Function(spine_slot_data)>(); + + int spine_slot_data_get_blend_mode( + spine_slot_data slot, + ) { + return _spine_slot_data_get_blend_mode( + slot, + ); + } + + late final _spine_slot_data_get_blend_modePtr = + _lookup>( + 'spine_slot_data_get_blend_mode'); + late final _spine_slot_data_get_blend_mode = + _spine_slot_data_get_blend_modePtr + .asFunction(); + + void spine_slot_set_to_setup_pose( + spine_slot slot, + ) { + return _spine_slot_set_to_setup_pose( + slot, + ); + } + + late final _spine_slot_set_to_setup_posePtr = + _lookup>( + 'spine_slot_set_to_setup_pose'); + late final _spine_slot_set_to_setup_pose = + _spine_slot_set_to_setup_posePtr.asFunction(); + + spine_slot_data spine_slot_get_data( + spine_slot slot, + ) { + return _spine_slot_get_data( + slot, + ); + } + + late final _spine_slot_get_dataPtr = + _lookup>( + 'spine_slot_get_data'); + late final _spine_slot_get_data = _spine_slot_get_dataPtr + .asFunction(); + + spine_bone spine_slot_get_bone( + spine_slot slot, + ) { + return _spine_slot_get_bone( + slot, + ); + } + + late final _spine_slot_get_bonePtr = + _lookup>( + 'spine_slot_get_bone'); + late final _spine_slot_get_bone = + _spine_slot_get_bonePtr.asFunction(); + + spine_skeleton spine_slot_get_skeleton( + spine_slot slot, + ) { + return _spine_slot_get_skeleton( + slot, + ); + } + + late final _spine_slot_get_skeletonPtr = + _lookup>( + 'spine_slot_get_skeleton'); + late final _spine_slot_get_skeleton = _spine_slot_get_skeletonPtr + .asFunction(); + + spine_color spine_slot_get_color( + spine_slot slot, + ) { + return _spine_slot_get_color( + slot, + ); + } + + late final _spine_slot_get_colorPtr = + _lookup>( + 'spine_slot_get_color'); + late final _spine_slot_get_color = + _spine_slot_get_colorPtr.asFunction(); + + void spine_slot_set_color( + spine_slot slot, + double r, + double g, + double b, + double a, + ) { + return _spine_slot_set_color( + slot, + r, + g, + b, + a, + ); + } + + late final _spine_slot_set_colorPtr = _lookup< + ffi.NativeFunction< + ffi.Void Function(spine_slot, ffi.Float, ffi.Float, ffi.Float, + ffi.Float)>>('spine_slot_set_color'); + late final _spine_slot_set_color = _spine_slot_set_colorPtr + .asFunction(); + + spine_color spine_slot_get_dark_color( + spine_slot slot, + ) { + return _spine_slot_get_dark_color( + slot, + ); + } + + late final _spine_slot_get_dark_colorPtr = + _lookup>( + 'spine_slot_get_dark_color'); + late final _spine_slot_get_dark_color = _spine_slot_get_dark_colorPtr + .asFunction(); + + void spine_slot_set_dark_color( + spine_slot slot, + double r, + double g, + double b, + double a, + ) { + return _spine_slot_set_dark_color( + slot, + r, + g, + b, + a, + ); + } + + late final _spine_slot_set_dark_colorPtr = _lookup< + ffi.NativeFunction< + ffi.Void Function(spine_slot, ffi.Float, ffi.Float, ffi.Float, + ffi.Float)>>('spine_slot_set_dark_color'); + late final _spine_slot_set_dark_color = _spine_slot_set_dark_colorPtr + .asFunction(); + + int spine_slot_has_dark_color( + spine_slot slot, + ) { + return _spine_slot_has_dark_color( + slot, + ); + } + + late final _spine_slot_has_dark_colorPtr = + _lookup>( + 'spine_slot_has_dark_color'); + late final _spine_slot_has_dark_color = + _spine_slot_has_dark_colorPtr.asFunction(); + + spine_attachment spine_slot_get_attachment( + spine_slot slot, + ) { + return _spine_slot_get_attachment( + slot, + ); + } + + late final _spine_slot_get_attachmentPtr = + _lookup>( + 'spine_slot_get_attachment'); + late final _spine_slot_get_attachment = _spine_slot_get_attachmentPtr + .asFunction(); + + void spine_slot_set_attachment( + spine_slot slot, + spine_attachment attachment, + ) { + return _spine_slot_set_attachment( + slot, + attachment, + ); + } + + late final _spine_slot_set_attachmentPtr = _lookup< + ffi.NativeFunction>( + 'spine_slot_set_attachment'); + late final _spine_slot_set_attachment = _spine_slot_set_attachmentPtr + .asFunction(); } class spine_atlas extends ffi.Struct { @@ -2284,3 +2574,5 @@ typedef spine_ik_constraint = ffi.Pointer; typedef spine_transform_constraint = ffi.Pointer; typedef spine_path_constraint = ffi.Pointer; typedef spine_event_data = ffi.Pointer; +typedef spine_slot_data = ffi.Pointer; +typedef spine_bone_data = ffi.Pointer; diff --git a/spine-flutter/src/spine_flutter.cpp b/spine-flutter/src/spine_flutter.cpp index 8af327d72..7f45f4dc1 100644 --- a/spine-flutter/src/spine_flutter.cpp +++ b/spine-flutter/src/spine_flutter.cpp @@ -1041,4 +1041,128 @@ FFI_PLUGIN_EXPORT float spine_event_get_balance(spine_event event) { if (event == nullptr) return 0; Event *_event = (Event*)event; return _event->getBalance(); +} + +// SlotData +FFI_PLUGIN_EXPORT int spine_slot_data_get_index(spine_slot_data slot) { + if (slot == nullptr) return 0; + SlotData *_slot = (SlotData*)slot; + return _slot->getIndex(); +} + +FFI_PLUGIN_EXPORT const char* spine_slot_data_get_name(spine_slot_data slot) { + if (slot == nullptr) return nullptr; + SlotData *_slot = (SlotData*)slot; + return _slot->getName().buffer(); +} + +FFI_PLUGIN_EXPORT spine_bone_data spine_slot_data_get_bone_data(spine_slot_data slot) { + if (slot == nullptr) return nullptr; + SlotData *_slot = (SlotData*)slot; + return &_slot->getBoneData(); +} + +FFI_PLUGIN_EXPORT spine_color spine_slot_data_get_color(spine_slot_data slot) { + spine_color color = { 0, 0, 0, 0 }; + if (slot == nullptr) return color; + SlotData *_slot = (SlotData*)slot; + color = { _slot->getColor().r, _slot->getColor().g, _slot->getColor().b, _slot->getColor().a }; + return color; +} + +FFI_PLUGIN_EXPORT spine_color spine_slot_data_get_dark_color(spine_slot_data slot) { + spine_color color = { 0, 0, 0, 0 }; + if (slot == nullptr) return color; + SlotData *_slot = (SlotData*)slot; + color = { _slot->getDarkColor().r, _slot->getDarkColor().g, _slot->getDarkColor().b, _slot->getDarkColor().a }; + return color; +} + +FFI_PLUGIN_EXPORT int spine_slot_data_has_dark_color(spine_slot_data slot) { + if (slot == nullptr) return 0; + SlotData *_slot = (SlotData*)slot; + return _slot->hasDarkColor() ? -1 : 0; +} + +FFI_PLUGIN_EXPORT const char* spine_slot_data_get_attachment_name(spine_slot_data slot) { + if (slot == nullptr) return nullptr; + SlotData *_slot = (SlotData*)slot; + return _slot->getAttachmentName().buffer(); +} + +FFI_PLUGIN_EXPORT spine_blend_mode spine_slot_data_get_blend_mode(spine_slot_data slot) { + if (slot == nullptr) return SPINE_BLEND_MODE_NORMAL; + SlotData *_slot = (SlotData*)slot; + return (spine_blend_mode)_slot->getBlendMode(); +} + +// Slot +FFI_PLUGIN_EXPORT void spine_slot_set_to_setup_pose(spine_slot slot) { + if (slot == nullptr) return; + Slot *_slot = (Slot*)slot; + _slot->setToSetupPose(); +} + +FFI_PLUGIN_EXPORT spine_slot_data spine_slot_get_data(spine_slot slot) { + if (slot == nullptr) return nullptr; + Slot *_slot = (Slot*)slot; + return &_slot->getData(); +} + +FFI_PLUGIN_EXPORT spine_bone spine_slot_get_bone(spine_slot slot) { + if (slot == nullptr) return nullptr; + Slot *_slot = (Slot*)slot; + return &_slot->getBone(); +} + +FFI_PLUGIN_EXPORT spine_skeleton spine_slot_get_skeleton(spine_slot slot) { + if (slot == nullptr) return nullptr; + Slot *_slot = (Slot*)slot; + return &_slot->getSkeleton(); +} + +FFI_PLUGIN_EXPORT spine_color spine_slot_get_color(spine_slot slot) { + spine_color color = { 0, 0, 0, 0 }; + if (slot == nullptr) return color; + Slot *_slot = (Slot*)slot; + color = { _slot->getColor().r, _slot->getColor().g, _slot->getColor().b, _slot->getColor().a }; + return color; +} + +FFI_PLUGIN_EXPORT void spine_slot_set_color(spine_slot slot, float r, float g, float b, float a) { + if (slot == nullptr) return; + Slot *_slot = (Slot*)slot; + _slot->getColor().set(r, g, b, a); +} + +FFI_PLUGIN_EXPORT spine_color spine_slot_get_dark_color(spine_slot slot) { + spine_color color = { 0, 0, 0, 0 }; + if (slot == nullptr) return color; + Slot *_slot = (Slot*)slot; + color = { _slot->getDarkColor().r, _slot->getDarkColor().g, _slot->getDarkColor().b, _slot->getDarkColor().a }; + return color; +} + +FFI_PLUGIN_EXPORT void spine_slot_set_dark_color(spine_slot slot, float r, float g, float b, float a) { + if (slot == nullptr) return; + Slot *_slot = (Slot*)slot; + _slot->getDarkColor().set(r, g, b, a); +} + +FFI_PLUGIN_EXPORT int spine_slot_has_dark_color(spine_slot slot) { + if (slot == nullptr) return 0; + Slot *_slot = (Slot*)slot; + return _slot->hasDarkColor() ? -1 : 0; +} + +FFI_PLUGIN_EXPORT spine_attachment spine_slot_get_attachment(spine_slot slot) { + if (slot == nullptr) return nullptr; + Slot *_slot = (Slot*)slot; + return _slot->getAttachment(); +} + +FFI_PLUGIN_EXPORT void spine_slot_set_attachment(spine_slot slot, spine_attachment attachment) { + if (slot == nullptr) return; + Slot *_slot = (Slot*)slot; + _slot->setAttachment((Attachment*)attachment); } \ No newline at end of file diff --git a/spine-flutter/src/spine_flutter.h b/spine-flutter/src/spine_flutter.h index 767d235e3..ef37cd176 100644 --- a/spine-flutter/src/spine_flutter.h +++ b/spine-flutter/src/spine_flutter.h @@ -250,4 +250,25 @@ FFI_PLUGIN_EXPORT int spine_event_get_int_value(spine_event event); FFI_PLUGIN_EXPORT float spine_event_get_float_value(spine_event event); FFI_PLUGIN_EXPORT const char* spine_event_get_string_value(spine_event event); FFI_PLUGIN_EXPORT float spine_event_get_volume(spine_event event); -FFI_PLUGIN_EXPORT float spine_event_get_balance(spine_event event); \ No newline at end of file +FFI_PLUGIN_EXPORT float spine_event_get_balance(spine_event event); + +FFI_PLUGIN_EXPORT int spine_slot_data_get_index(spine_slot_data slot); +FFI_PLUGIN_EXPORT const char* spine_slot_data_get_name(spine_slot_data slot); +FFI_PLUGIN_EXPORT spine_bone_data spine_slot_data_get_bone_data(spine_slot_data slot); +FFI_PLUGIN_EXPORT spine_color spine_slot_data_get_color(spine_slot_data slot); +FFI_PLUGIN_EXPORT spine_color spine_slot_data_get_dark_color(spine_slot_data slot); +FFI_PLUGIN_EXPORT int spine_slot_data_has_dark_color(spine_slot_data slot); +FFI_PLUGIN_EXPORT const char* spine_slot_data_get_attachment_name(spine_slot_data slot); +FFI_PLUGIN_EXPORT spine_blend_mode spine_slot_data_get_blend_mode(spine_slot_data slot); + +FFI_PLUGIN_EXPORT void spine_slot_set_to_setup_pose(spine_slot slot); +FFI_PLUGIN_EXPORT spine_slot_data spine_slot_get_data(spine_slot slot); +FFI_PLUGIN_EXPORT spine_bone spine_slot_get_bone(spine_slot slot); +FFI_PLUGIN_EXPORT spine_skeleton spine_slot_get_skeleton(spine_slot slot); +FFI_PLUGIN_EXPORT spine_color spine_slot_get_color(spine_slot slot); +FFI_PLUGIN_EXPORT void spine_slot_set_color(spine_slot slot, float r, float g, float b, float a); +FFI_PLUGIN_EXPORT spine_color spine_slot_get_dark_color(spine_slot slot); +FFI_PLUGIN_EXPORT void spine_slot_set_dark_color(spine_slot slot, float r, float g, float b, float a); +FFI_PLUGIN_EXPORT int spine_slot_has_dark_color(spine_slot slot); +FFI_PLUGIN_EXPORT spine_attachment spine_slot_get_attachment(spine_slot slot); +FFI_PLUGIN_EXPORT void spine_slot_set_attachment(spine_slot slot, spine_attachment attachment); \ No newline at end of file