GMS 2.3+ Get all Attachments from a Slot in Spine

Kezarus

Member
Quick one, is there a way to get all attachments in a slot from a Spine sprite? For example, all beards attachments in the beardSlot. Can't find anything pointing to a solution in the manual.

Thanks!
 

Nocturne

Friendly Tyrant
Forum Staff
Admin
Quick answer.. no. There is no way to get all the attachment strings for a slot. This might actually be something worth suggesting to YYG that they add as I can see why it would be useful, and it shouldn't be difficult to add, since they must be storing the attachment strings somewhere! That said, you could do one of two things:

1) create an array for each slot with all the attachment strings in it (so you'd need to know what they are beforehand and copy the names from Spine into GM)
2) use the skeleton_attachment_create() function to manually define all the possible attachments within GM on game start or something. That way you can generate your own attachment strings and store them.

Neither of these suggestions is ideal, and both require a fair bit of work, but I can't really think of any other way to get a list of all attachments for a slot other than pre-preparing them beforehand. :(
 

Kezarus

Member
Hey, Noc! Thanks for the answer! Well, I was looking to make an internal char customization screen, quick and dirty style. But when I faced this I switched to the "correct" way. So I put every name into a global array of objects where I could filter them afterwards by race and gender. I used a GDrive spreadsheet to make the code for me, as it's about +150 lines and it's better to visualizate as I could mark and see columns for race and gender easily.

Each line that goes into the global array looks like this:
GML:
new CharCustom("Beard06","Soul Patch","|ELVEN_MALE|SYLVAN_MALE|HUMAN_MALE|DARK ELVEN_MALE|GOBLIN_MALE|"),
This is the filter method:
GML:
function filterCharCustom(type, filter = ""){
    //type as CharCustomType
    //as string like CUSTOM_ENABLE_FOR_ALL "ELVEN_MALE|DWARVEN_MALE|"
    //returns an array of CharCustom
    var result = [];
    filter = "|"+string_upper(filter)+"|";

   
    var arrToFilter = [];
   
    switch(type){
        case CharCustomType.Gender:        arrToFilter = global.customGender; break;
        case CharCustomType.Race:        arrToFilter = global.customRace; break;
        case CharCustomType.Beard:        arrToFilter = global.customBeard; break;
        case CharCustomType.Hair:        arrToFilter = global.customHair; break;
        case CharCustomType.EarExtra:    arrToFilter = global.customEarExtra; break;
        case CharCustomType.Eyebrow:    arrToFilter = global.customEyebrow; break;
        case CharCustomType.Eye:        arrToFilter = global.customEye; break;
        case CharCustomType.Mouth:        arrToFilter = global.customMouth; break;
        case CharCustomType.OnSkin:        arrToFilter = global.customOnSkin; break;
        case CharCustomType.ColorSkin:    arrToFilter = global.customColorSkin; break;
        case CharCustomType.ColorHair:    arrToFilter = global.customColorHair; break;
        case CharCustomType.ColorEyes:    arrToFilter = global.customColorEyes; break;
    }
   
    var valueNow; //as CharCustom
    for (var i=0; i<array_length(arrToFilter); ++i) {
        valueNow = arrToFilter[i];
       
        if( filter == "" || valueNow.enabledFor == "" ||
            string_pos(filter, valueNow.enabledFor) != 0 ){
           
            array_push(result, valueNow);
        }
    }
   
    return result;
}
And this is the object:
GML:
//THE CUSTOMIZATION ITEMS FOR CHARS
function CharCustom(_id, _name, _enabledFor) constructor {
    keyId = _id;
    name = _name;
    enabledFor = _enabledFor; //"DWARF_MALE|DWARF_FEMALE|"
}
My only concern are bloody memory leaks. Do I have to destroy the structs in the arrays? (well, that would be a pain...)

Also, is there a better way to do this?


Thanks!
Kezarus

p.s.: now I see that I could use only ONE array and make another column as Custom Type to be filtered instead of many arrays, but... ow, well... ¯\_(ツ)_/¯
 

Kezarus

Member
Hmmm I cannot check the code just now but I think you might get this info from sprite_get_info() function

Russell
Hey, thanks for the answers @rwkay! =]

So, I just checked the manual and it says nothing about attachments on sprite_get_info(). Maybe it's in there (in one of the maps), but it's not documented?


Cheers!
Kezarus
 

rwkay

YoYo Games Staff
YYG Staff
Cou
Maybe it's in there (in one of the maps), but it's not documented?
Could be! I checked the code and there is definitely an array of slots and on the slot it has an attachmentName (not sure if that is the info you are after)

Russell
 

Kezarus

Member
Thanks! That seems to be to one.

I was about to test it, but the new GMS update killed me on my tracs. Gonna have to update Spine before anything else.
 

Kezarus

Member
Heh... that only took me a second. (update Spine and make it work in GMS) Wow! XD

Unfortunately, sprite_get_info() don't provide the info that I need. Like, it have the attachment it's set now, but there is a list of attachments that should be possible, but I can't find it in the structure. (like ElfEar and HumanEar in the SlotEar)

Anyways, maybe it's for the best, so I could make things properly like listing everything by gender and race. If I just listed all pieces and randomize I would definetly have a bearded elven female. So... maybe a function that really list all attachments it's not really needed? If you were in a pinch to list all attachments, maybe, but list things properly seems the best way.

What do you think?

By the way, the above code could cause a Memory Leak? o___Ô?


Cheers!
 

rIKmAN

Member
Unfortunately, sprite_get_info() don't provide the info that I need. Like, it have the attachment it's set now, but there is a list of attachments that should be possible, but I can't find it in the structure. (like ElfEar and HumanEar in the SlotEar)
There are definite use cases for this and the info is already there so querying it to find all available attatchments should be possible.

It's much easier/better to query the possible attachments based on the existing skeleton data than have to manually keep track of them yourself outside of it and introduce the possibility of missing one, incorrect spellings etc - basically human error that doesn't happen if the data is pulled directly from the skeleton itself.

There's already skeleton_slot_list() to return all slots, a companion function to return all attachments for a slot makes sense.
Maybe skeleton_attachments_list(), skeleton_slot_list_attachments() or something like that.

Could you file it as a suggestion if you get a spare minute or two?
 

Kezarus

Member
Hmm, ok @rIKmAN, you're the resident Spine speciallist here after all. =]

Ok, made a ticket for that. Maybe it helps other people.

By the way, the above code could cause a Memory Leak? Should I open another topic? XD


Cheers!
Kezarus
 

rIKmAN

Member
Hmm, ok @rIKmAN, you're the resident Spine speciallist here after all. =]

Ok, made a ticket for that. Maybe it helps other people.

By the way, the above code could cause a Memory Leak? Should I open another topic? XD


Cheers!
Kezarus
Thanks for filing that, it's not a necessity but would be really helpful and cut down on the manual work needed between artist/coder if you can simply query the skeleton to find out what the attachments are and what they have been named by the artist etc. It just removes a few extra steps and saves time and possible human error.

For the memory leak, all structs are garbage collected when there are no remaining references to them, so as long as this is the case the the GC should clean them up on the next step after there are no more references to them. You can also flag them manually for GC yourself using the delete operator.
 
Top