diff --git a/spine-flutter/lib/spine_flutter.dart b/spine-flutter/lib/spine_flutter.dart index 15ec4347d..054b71de0 100644 --- a/spine-flutter/lib/spine_flutter.dart +++ b/spine-flutter/lib/spine_flutter.dart @@ -930,26 +930,130 @@ class Slot { } } -// FIXME +enum AttachmentType { + Region(0), + Mesh(1), + Clipping(2), + BoundingBox(3), + Path(4), + Point(5); + + final int value; + const AttachmentType(this.value); +} class Attachment { final spine_attachment _attachment; Attachment._(this._attachment); + + String getName() { + Pointer name = _bindings.spine_attachment_get_name(_attachment).cast(); + return name.toString(); + } + + AttachmentType getType() { + final type = _bindings.spine_attachment_get_type(_attachment); + return AttachmentType.values[type]; + } +} + +class SkinEntry { + final int slotIndex; + final String name; + final Attachment? attachment; + + SkinEntry(this.slotIndex, this.name, this.attachment); } -// FIXME class Skin { final spine_skin _skin; Skin._(this._skin); + + void setAttachment(int slotIndex, String name, Attachment? attachment) { + final nativeName = name.toNativeUtf8(); + _bindings.spine_skin_set_attachment(_skin, slotIndex, nativeName.cast(), attachment == null ? nullptr : attachment._attachment); + malloc.free(nativeName); + } + + Attachment? getAttachment(int slotIndex, String name) { + final nativeName = name.toNativeUtf8(); + final attachment = _bindings.spine_skin_get_attachment(_skin, slotIndex, nativeName.cast()); + malloc.free(nativeName); + if (attachment.address == nullptr.address) return null; + return Attachment._(attachment); + } + + void removeAttachment(int slotIndex, String name) { + final nativeName = name.toNativeUtf8(); + _bindings.spine_skin_remove_attachment(_skin, slotIndex, nativeName.cast()); + malloc.free(nativeName); + } + + String getName() { + Pointer name = _bindings.spine_skin_get_name(_skin).cast(); + return name.toDartString(); + } + + void addSkin(Skin other) { + _bindings.spine_skin_add_skin(_skin, other._skin); + } + + List getEntries() { + List result = []; + final entries = _bindings.spine_skin_get_entries(_skin); + int numEntries = entries.ref.numEntries; + for (int i = 0; i < numEntries; i++) { + final entry = entries.ref.entries[i]; + Pointer name = entry.name.cast(); + result.add(SkinEntry(entry.slotIndex, name.toDartString(), entry.attachment.address == nullptr.address ? null : Attachment._(entry.attachment))); + } + return result; + } + + List getBones() { + List bones = []; + final numBones = _bindings.spine_skin_get_num_bones(_skin); + final nativeBones = _bindings.spine_skin_get_bones(_skin); + for (int i = 0; i < numBones; i++) { + bones.add(BoneData._(nativeBones[i])); + } + return bones; + } + + List getConstraints() { + List constraints = []; + final numConstraints = _bindings.spine_skin_get_num_constraints(_skin); + final nativeConstraints = _bindings.spine_skin_get_constraints(_skin); + for (int i = 0; i < numConstraints; i++) { + final nativeConstraint = nativeConstraints[i]; + final type = _bindings.spine_constraint_data_get_type(nativeConstraint); + switch (type) { + case spine_constraint_type.SPINE_CONSTRAINT_IK: + constraints.add(IkConstraintData._(nativeConstraint)); + break; + case spine_constraint_type.SPINE_CONSTRAINT_TRANSFORM: + constraints.add(TransformConstraintData._(nativeConstraint)); + break; + case spine_constraint_type.SPINE_CONSTRAINT_PATH: + constraints.add(PathConstraintData._(nativeConstraint)); + break; + } + } + return constraints; + } } +// FIXME +class ConstraintData { + final spine_constraint_data _data; + + ConstraintData._(this._data); +} // FIXME -class IkConstraintData { - final spine_ik_constraint_data _data; - - IkConstraintData._(this._data); +class IkConstraintData extends ConstraintData { + IkConstraintData._(spine_ik_constraint_data data): super._(data); } // FIXME @@ -960,10 +1064,8 @@ class IkConstraint { } // FIXME -class TransformConstraintData { - final spine_transform_constraint_data _data; - - TransformConstraintData._(this._data); +class TransformConstraintData extends ConstraintData { + TransformConstraintData._(spine_transform_constraint_data data): super._(data); } // FIXME @@ -974,10 +1076,8 @@ class TransformConstraint { } // FIXME -class PathConstraintData { - final spine_path_constraint_data _data; - - PathConstraintData._(this._data); +class PathConstraintData extends ConstraintData { + PathConstraintData._(spine_path_constraint_data data): super._(data); } // FIXME diff --git a/spine-flutter/lib/spine_flutter_bindings_generated.dart b/spine-flutter/lib/spine_flutter_bindings_generated.dart index fd8b22bd2..3fad779b5 100644 --- a/spine-flutter/lib/spine_flutter_bindings_generated.dart +++ b/spine-flutter/lib/spine_flutter_bindings_generated.dart @@ -4552,6 +4552,257 @@ class SpineFlutterBindings { 'spine_bone_set_is_active'); late final _spine_bone_set_is_active = _spine_bone_set_is_activePtr.asFunction(); + + ffi.Pointer spine_attachment_get_name( + spine_attachment attachment, + ) { + return _spine_attachment_get_name( + attachment, + ); + } + + late final _spine_attachment_get_namePtr = _lookup< + ffi.NativeFunction Function(spine_attachment)>>( + 'spine_attachment_get_name'); + late final _spine_attachment_get_name = _spine_attachment_get_namePtr + .asFunction Function(spine_attachment)>(); + + int spine_attachment_get_type( + spine_attachment attachment, + ) { + return _spine_attachment_get_type( + attachment, + ); + } + + late final _spine_attachment_get_typePtr = + _lookup>( + 'spine_attachment_get_type'); + late final _spine_attachment_get_type = _spine_attachment_get_typePtr + .asFunction(); + + void spine_skin_set_attachment( + spine_skin skin, + int slotIndex, + ffi.Pointer name, + spine_attachment attachment, + ) { + return _spine_skin_set_attachment( + skin, + slotIndex, + name, + attachment, + ); + } + + late final _spine_skin_set_attachmentPtr = _lookup< + ffi.NativeFunction< + ffi.Void Function(spine_skin, ffi.Int32, ffi.Pointer, + spine_attachment)>>('spine_skin_set_attachment'); + late final _spine_skin_set_attachment = + _spine_skin_set_attachmentPtr.asFunction< + void Function( + spine_skin, int, ffi.Pointer, spine_attachment)>(); + + spine_attachment spine_skin_get_attachment( + spine_skin skin, + int slotIndex, + ffi.Pointer name, + ) { + return _spine_skin_get_attachment( + skin, + slotIndex, + name, + ); + } + + late final _spine_skin_get_attachmentPtr = _lookup< + ffi.NativeFunction< + spine_attachment Function(spine_skin, ffi.Int32, + ffi.Pointer)>>('spine_skin_get_attachment'); + late final _spine_skin_get_attachment = + _spine_skin_get_attachmentPtr.asFunction< + spine_attachment Function(spine_skin, int, ffi.Pointer)>(); + + void spine_skin_remove_attachment( + spine_skin skin, + int slotIndex, + ffi.Pointer name, + ) { + return _spine_skin_remove_attachment( + skin, + slotIndex, + name, + ); + } + + late final _spine_skin_remove_attachmentPtr = _lookup< + ffi.NativeFunction< + ffi.Void Function(spine_skin, ffi.Int32, + ffi.Pointer)>>('spine_skin_remove_attachment'); + late final _spine_skin_remove_attachment = _spine_skin_remove_attachmentPtr + .asFunction)>(); + + ffi.Pointer spine_skin_get_name( + spine_skin skin, + ) { + return _spine_skin_get_name( + skin, + ); + } + + late final _spine_skin_get_namePtr = + _lookup Function(spine_skin)>>( + 'spine_skin_get_name'); + late final _spine_skin_get_name = _spine_skin_get_namePtr + .asFunction Function(spine_skin)>(); + + void spine_skin_add_skin( + spine_skin skin, + spine_skin other, + ) { + return _spine_skin_add_skin( + skin, + other, + ); + } + + late final _spine_skin_add_skinPtr = + _lookup>( + 'spine_skin_add_skin'); + late final _spine_skin_add_skin = _spine_skin_add_skinPtr + .asFunction(); + + ffi.Pointer spine_skin_get_entries( + spine_skin skin, + ) { + return _spine_skin_get_entries( + skin, + ); + } + + late final _spine_skin_get_entriesPtr = _lookup< + ffi.NativeFunction< + ffi.Pointer Function( + spine_skin)>>('spine_skin_get_entries'); + late final _spine_skin_get_entries = _spine_skin_get_entriesPtr + .asFunction Function(spine_skin)>(); + + void spine_skin_entries_dispose( + ffi.Pointer entries, + ) { + return _spine_skin_entries_dispose( + entries, + ); + } + + late final _spine_skin_entries_disposePtr = _lookup< + ffi.NativeFunction< + ffi.Void Function( + ffi.Pointer)>>('spine_skin_entries_dispose'); + late final _spine_skin_entries_dispose = _spine_skin_entries_disposePtr + .asFunction)>(); + + int spine_skin_get_num_bones( + spine_skin skin, + ) { + return _spine_skin_get_num_bones( + skin, + ); + } + + late final _spine_skin_get_num_bonesPtr = + _lookup>( + 'spine_skin_get_num_bones'); + late final _spine_skin_get_num_bones = + _spine_skin_get_num_bonesPtr.asFunction(); + + ffi.Pointer spine_skin_get_bones( + spine_skin skin, + ) { + return _spine_skin_get_bones( + skin, + ); + } + + late final _spine_skin_get_bonesPtr = _lookup< + ffi.NativeFunction< + ffi.Pointer Function( + spine_skin)>>('spine_skin_get_bones'); + late final _spine_skin_get_bones = _spine_skin_get_bonesPtr + .asFunction Function(spine_skin)>(); + + int spine_skin_get_num_constraints( + spine_skin skin, + ) { + return _spine_skin_get_num_constraints( + skin, + ); + } + + late final _spine_skin_get_num_constraintsPtr = + _lookup>( + 'spine_skin_get_num_constraints'); + late final _spine_skin_get_num_constraints = + _spine_skin_get_num_constraintsPtr.asFunction(); + + ffi.Pointer spine_skin_get_constraints( + spine_skin skin, + ) { + return _spine_skin_get_constraints( + skin, + ); + } + + late final _spine_skin_get_constraintsPtr = _lookup< + ffi.NativeFunction< + ffi.Pointer Function( + spine_skin)>>('spine_skin_get_constraints'); + late final _spine_skin_get_constraints = _spine_skin_get_constraintsPtr + .asFunction Function(spine_skin)>(); + + spine_skin spine_skin_create( + ffi.Pointer name, + ) { + return _spine_skin_create( + name, + ); + } + + late final _spine_skin_createPtr = + _lookup)>>( + 'spine_skin_create'); + late final _spine_skin_create = _spine_skin_createPtr + .asFunction)>(); + + void spine_skin_dispose( + spine_skin skin, + ) { + return _spine_skin_dispose( + skin, + ); + } + + late final _spine_skin_disposePtr = + _lookup>( + 'spine_skin_dispose'); + late final _spine_skin_dispose = + _spine_skin_disposePtr.asFunction(); + + int spine_constraint_data_get_type( + spine_constraint_data data, + ) { + return _spine_constraint_data_get_type( + data, + ); + } + + late final _spine_constraint_data_get_typePtr = + _lookup>( + 'spine_constraint_data_get_type'); + late final _spine_constraint_data_get_type = + _spine_constraint_data_get_typePtr + .asFunction(); } class spine_atlas extends ffi.Struct { @@ -4596,6 +4847,21 @@ abstract class spine_event_type { static const int SPINE_EVENT_TYPE_EVENT = 5; } +abstract class spine_attachment_type { + static const int SPINE_ATTACHMENT_REGION = 0; + static const int SPINE_ATTACHMENT_MESH = 1; + static const int SPINE_ATTACHMENT_CLIPPING = 2; + static const int SPINE_ATTACHMENT_BOUNDING_BOX = 3; + static const int SPINE_ATTACHMENT_PATH = 4; + static const int SPINE_ATTACHMENT_POINT = 5; +} + +abstract class spine_constraint_type { + static const int SPINE_CONSTRAINT_IK = 0; + static const int SPINE_CONSTRAINT_TRANSFORM = 1; + static const int SPINE_CONSTRAINT_PATH = 2; +} + abstract class spine_transform_mode { static const int SPINE_TRANSFORM_MODE_NORMAL = 0; static const int SPINE_TRANSFORM_ONLY_TRANSLATION = 1; @@ -4679,6 +4945,25 @@ class spine_skeleton_drawable extends ffi.Struct { typedef spine_skeleton = ffi.Pointer; typedef spine_animation_state = ffi.Pointer; typedef spine_animation_state_events = ffi.Pointer; + +class spine_skin_entry extends ffi.Struct { + @ffi.Int32() + external int slotIndex; + + external ffi.Pointer name; + + external spine_attachment attachment; +} + +typedef spine_attachment = ffi.Pointer; + +class spine_skin_entries extends ffi.Struct { + @ffi.Int32() + external int numEntries; + + external ffi.Pointer entries; +} + typedef spine_bone_data = ffi.Pointer; typedef spine_slot_data = ffi.Pointer; typedef spine_skin = ffi.Pointer; @@ -4691,7 +4976,7 @@ typedef spine_track_entry = ffi.Pointer; typedef spine_event = ffi.Pointer; typedef spine_bone = ffi.Pointer; typedef spine_slot = ffi.Pointer; -typedef spine_attachment = ffi.Pointer; typedef spine_ik_constraint = ffi.Pointer; typedef spine_transform_constraint = ffi.Pointer; typedef spine_path_constraint = ffi.Pointer; +typedef spine_constraint_data = ffi.Pointer; diff --git a/spine-flutter/src/spine_flutter.cpp b/spine-flutter/src/spine_flutter.cpp index 9e75e88c6..4959b5543 100644 --- a/spine-flutter/src/spine_flutter.cpp +++ b/spine-flutter/src/spine_flutter.cpp @@ -37,7 +37,7 @@ FFI_PLUGIN_EXPORT int spine_minor_version() { FFI_PLUGIN_EXPORT spine_atlas* spine_atlas_load(const char *atlasData) { if (!atlasData) return nullptr; int length = (int)strlen(atlasData); - auto atlas = new Atlas(atlasData, length, "", (TextureLoader*)nullptr, false); + auto atlas = new (__FILE__, __LINE__) Atlas(atlasData, length, "", (TextureLoader*)nullptr, false); spine_atlas *result = SpineExtension::calloc(1, __FILE__, __LINE__); result->atlas = atlas; result->numImagePaths = (int)atlas->getPages().size(); @@ -369,14 +369,14 @@ void spine_render_command_dispose(spine_render_command *cmd) { FFI_PLUGIN_EXPORT spine_skeleton_drawable *spine_skeleton_drawable_create(spine_skeleton_data skeletonData) { spine_skeleton_drawable *drawable = SpineExtension::calloc(1, __FILE__, __LINE__); - drawable->skeleton = new Skeleton((SkeletonData*)skeletonData); - AnimationState *state = new AnimationState(new AnimationStateData((SkeletonData*)skeletonData)); + drawable->skeleton = new (__FILE__, __LINE__) Skeleton((SkeletonData*)skeletonData); + AnimationState *state = new (__FILE__, __LINE__) AnimationState(new AnimationStateData((SkeletonData*)skeletonData)); drawable->animationState = state; state->setManualTrackEntryDisposal(true); EventListener *listener = new EventListener(); drawable->animationStateEvents = listener; state->setListener(listener); - drawable->clipping = new SkeletonClipping(); + drawable->clipping = new (__FILE__, __LINE__) SkeletonClipping(); return drawable; } @@ -1959,3 +1959,137 @@ FFI_PLUGIN_EXPORT void spine_bone_set_is_active(spine_bone bone, int isActive) { Bone *_bone = (Bone*)bone; _bone->setActive(isActive); } + +// Attachment +FFI_PLUGIN_EXPORT const char* spine_attachment_get_name(spine_attachment attachment) { + if (attachment == nullptr) return nullptr; + Attachment *_attachment = (Attachment*)attachment; + return _attachment->getName().buffer(); +} + +FFI_PLUGIN_EXPORT spine_attachment_type spine_attachment_get_type(spine_attachment attachment) { + if (attachment == nullptr) return SPINE_ATTACHMENT_REGION; + Attachment *_attachment = (Attachment*)attachment; + if (_attachment->getRTTI().isExactly(RegionAttachment::rtti)) { + return SPINE_ATTACHMENT_REGION; + } else if (_attachment->getRTTI().isExactly(MeshAttachment::rtti)) { + return SPINE_ATTACHMENT_MESH; + } else if (_attachment->getRTTI().isExactly(ClippingAttachment::rtti)) { + return SPINE_ATTACHMENT_CLIPPING; + } else if (_attachment->getRTTI().isExactly(BoundingBoxAttachment::rtti)) { + return SPINE_ATTACHMENT_BOUNDING_BOX; + } else if (_attachment->getRTTI().isExactly(PathAttachment::rtti)) { + return SPINE_ATTACHMENT_PATH; + } else if (_attachment->getRTTI().isExactly(PointAttachment::rtti)) { + return SPINE_ATTACHMENT_POINT; + } else { + return SPINE_ATTACHMENT_REGION; + } +} + +// Skin +FFI_PLUGIN_EXPORT void spine_skin_set_attachment(spine_skin skin, int slotIndex, const char* name, spine_attachment attachment) { + if (skin == nullptr) return; + Skin *_skin = (Skin*)skin; + _skin->setAttachment(slotIndex, name, (Attachment*)attachment); +} + +FFI_PLUGIN_EXPORT spine_attachment spine_skin_get_attachment(spine_skin skin, int slotIndex, const char* name) { + if (skin == nullptr) return nullptr; + Skin *_skin = (Skin*)skin; + return _skin->getAttachment(slotIndex, name); +} + +FFI_PLUGIN_EXPORT void spine_skin_remove_attachment(spine_skin skin, int slotIndex, const char* name) { + if (skin == nullptr) return; + Skin *_skin = (Skin*)skin; + _skin->removeAttachment(slotIndex, name); +} + +FFI_PLUGIN_EXPORT const char* spine_skin_get_name(spine_skin skin) { + if (skin == nullptr) return nullptr; + Skin *_skin = (Skin*)skin; + return _skin->getName().buffer(); +} + +FFI_PLUGIN_EXPORT void spine_skin_add_skin(spine_skin skin, spine_skin other) { + if (skin == nullptr) return; + if (other == nullptr) return; + Skin *_skin = (Skin*)skin; + _skin->addSkin((Skin*)other); +} + +FFI_PLUGIN_EXPORT spine_skin_entries *spine_skin_get_entries(spine_skin skin) { + if (skin == nullptr) return nullptr; + Skin *_skin = (Skin*)skin; + spine_skin_entries *entries = SpineExtension::getInstance()->calloc(1, __FILE__, __LINE__); + { + Skin::AttachmentMap::Entries mapEntries = _skin->getAttachments(); + while (mapEntries.hasNext()) entries->numEntries++; + } + { + entries->entries = SpineExtension::getInstance()->calloc(entries->numEntries, __FILE__, __LINE__); + Skin::AttachmentMap::Entries mapEntries = _skin->getAttachments(); + int i = 0; + while (mapEntries.hasNext()) { + Skin::AttachmentMap::Entry entry = mapEntries.next(); + entries->entries[i++] = { (int)entry._slotIndex, entry._name.buffer(), entry._attachment }; + } + } + return entries; +} + +FFI_PLUGIN_EXPORT void spine_skin_entries_dispose(spine_skin_entries *entries) { + if (entries == nullptr) return; + SpineExtension::getInstance()->free(entries->entries, __FILE__, __LINE__); + SpineExtension::getInstance()->free(entries, __FILE__, __LINE__); +} + +FFI_PLUGIN_EXPORT int spine_skin_get_num_bones(spine_skin skin) { + if (skin == nullptr) return 0; + Skin *_skin = (Skin*)skin; + return _skin->getBones().size(); +} + +FFI_PLUGIN_EXPORT spine_bone_data* spine_skin_get_bones(spine_skin skin) { + if (skin == nullptr) return nullptr; + Skin *_skin = (Skin*)skin; + return (spine_bone_data*)_skin->getBones().buffer(); +} + +FFI_PLUGIN_EXPORT int spine_skin_get_num_constraints(spine_skin skin) { + if (skin == nullptr) return 0; + Skin *_skin = (Skin*)skin; + return _skin->getConstraints().size(); +} + +FFI_PLUGIN_EXPORT spine_constraint_data* spine_skin_get_constraints(spine_skin skin) { + if (skin == nullptr) return nullptr; + Skin *_skin = (Skin*)skin; + return (spine_constraint_data*)_skin->getConstraints().buffer(); +} + +FFI_PLUGIN_EXPORT spine_skin spine_skin_create(const char* name) { + if (name == nullptr) return nullptr; + return new (__FILE__, __LINE__) Skin(name); +} + +FFI_PLUGIN_EXPORT void spine_skin_dispose(spine_skin skin) { + if (skin == nullptr) return; + Skin *_skin = (Skin*)skin; + delete _skin; +} + +FFI_PLUGIN_EXPORT spine_constraint_type spine_constraint_data_get_type(spine_constraint_data data) { + if (data == nullptr) return SPINE_CONSTRAINT_IK; + ConstraintData *_data = (ConstraintData*)data; + if (_data->getRTTI().isExactly(IkConstraintData::rtti)) { + return SPINE_CONSTRAINT_IK; + } else if (_data->getRTTI().isExactly(TransformConstraintData::rtti)) { + return SPINE_CONSTRAINT_TRANSFORM; + } else if (_data->getRTTI().isExactly(PathConstraintData::rtti)) { + return SPINE_CONSTRAINT_PATH; + } else { + return SPINE_CONSTRAINT_IK; + } +} diff --git a/spine-flutter/src/spine_flutter.h b/spine-flutter/src/spine_flutter.h index 895b58d43..51bcc82f5 100644 --- a/spine-flutter/src/spine_flutter.h +++ b/spine-flutter/src/spine_flutter.h @@ -31,6 +31,8 @@ typedef void* spine_slot; typedef void* spine_slot_data; typedef void* spine_skin; typedef void* spine_attachment; +typedef void* spine_constraint; +typedef void* spine_constraint_data; typedef void* spine_ik_constraint; typedef void* spine_ik_constraint_data; typedef void* spine_transform_constraint; @@ -79,6 +81,21 @@ typedef enum spine_event_type { SPINE_EVENT_TYPE_EVENT } spine_event_type; +typedef enum spine_attachment_type { + SPINE_ATTACHMENT_REGION = 0, + SPINE_ATTACHMENT_MESH, + SPINE_ATTACHMENT_CLIPPING, + SPINE_ATTACHMENT_BOUNDING_BOX, + SPINE_ATTACHMENT_PATH, + SPINE_ATTACHMENT_POINT, +} spine_attachment_type; + +typedef enum spine_constraint_type { + SPINE_CONSTRAINT_IK, + SPINE_CONSTRAINT_TRANSFORM, + SPINE_CONSTRAINT_PATH +} spine_constraint_type; + typedef enum spine_transform_mode { SPINE_TRANSFORM_MODE_NORMAL = 0, SPINE_TRANSFORM_ONLY_TRANSLATION, @@ -119,6 +136,17 @@ typedef struct spine_skeleton_drawable { spine_render_command *renderCommand; } spine_skeleton_drawable; +typedef struct spine_skin_entry { + int slotIndex; + const char* name; + spine_attachment attachment; +} spine_skin_entry; + +typedef struct spine_skin_entries { + int numEntries; + spine_skin_entry* entries; +} spine_skin_entries; + FFI_PLUGIN_EXPORT int spine_major_version(); FFI_PLUGIN_EXPORT int spine_minor_version(); FFI_PLUGIN_EXPORT void spine_report_leaks(); @@ -417,4 +445,23 @@ FFI_PLUGIN_EXPORT float spine_bone_get_world_rotation_y(spine_bone bone); FFI_PLUGIN_EXPORT float spine_bone_get_world_scale_x(spine_bone bone); FFI_PLUGIN_EXPORT float spine_bone_get_world_scale_y(spine_bone bone); FFI_PLUGIN_EXPORT int spine_bone_get_is_active(spine_bone bone); -FFI_PLUGIN_EXPORT void spine_bone_set_is_active(spine_bone bone, int isActive); \ No newline at end of file +FFI_PLUGIN_EXPORT void spine_bone_set_is_active(spine_bone bone, int isActive); + +FFI_PLUGIN_EXPORT const char* spine_attachment_get_name(spine_attachment attachment); +FFI_PLUGIN_EXPORT spine_attachment_type spine_attachment_get_type(spine_attachment attachment); + +FFI_PLUGIN_EXPORT void spine_skin_set_attachment(spine_skin skin, int slotIndex, const char* name, spine_attachment attachment); +FFI_PLUGIN_EXPORT spine_attachment spine_skin_get_attachment(spine_skin skin, int slotIndex, const char* name); +FFI_PLUGIN_EXPORT void spine_skin_remove_attachment(spine_skin skin, int slotIndex, const char* name); +FFI_PLUGIN_EXPORT const char* spine_skin_get_name(spine_skin skin); +FFI_PLUGIN_EXPORT void spine_skin_add_skin(spine_skin skin, spine_skin other); +FFI_PLUGIN_EXPORT spine_skin_entries *spine_skin_get_entries(spine_skin skin); +FFI_PLUGIN_EXPORT void spine_skin_entries_dispose(spine_skin_entries *entries); +FFI_PLUGIN_EXPORT int spine_skin_get_num_bones(spine_skin skin); +FFI_PLUGIN_EXPORT spine_bone_data* spine_skin_get_bones(spine_skin skin); +FFI_PLUGIN_EXPORT int spine_skin_get_num_constraints(spine_skin skin); +FFI_PLUGIN_EXPORT spine_constraint_data* spine_skin_get_constraints(spine_skin skin); +FFI_PLUGIN_EXPORT spine_skin spine_skin_create(const char* name); +FFI_PLUGIN_EXPORT void spine_skin_dispose(spine_skin skin); + +FFI_PLUGIN_EXPORT spine_constraint_type spine_constraint_data_get_type(spine_constraint_data data); \ No newline at end of file