Spine - Animation ModuleMonkey Programming Forums/User Modules/Spine - Animation Module
Please read the wiki for some instructions.
If anyone would like to contribute to this project then please do, the help would be greatly appreciated.
Enjoy, for free :D
Hey there monkey brains, I have been beavering away at some more monkey developments. This time I have created a module and it has been sponsored by Tony from Playniax/Ignition.
Thanks should go to him as I'm sure this will benefit a lot of monkey games.
So he tasked me to create a monkey module to support the spine runtime. I have nearly finished this, but for now here is a little demo.
| I'm going to start a big project this week. I was thinking on going with Spriter. Are there any benefits from using Spine over Spriter? |
| After using Spriter, and using Spine ... Spine is definitely nicer to work with. I used the csharp runtime to port over to monkey, and everything bar 1 is using arrays so it should be super quick in monkey projects.|
Spine has stuff like multiple timelines and custom curves, which spriter doesn't have (last time I checked).
Spriter seem to be in a loop of endless refactoring wher-as Spine seems to be stable already. One can only assume that their future releases will have some exciting stuff.
I guess at the end of the day its just preference for one tool vs another, but Spine definitely is the better tool out of the two.
Do you know if it is possible to change the bitmap of a given area (as instance, eyes closing) depending on animation progress as in Spritter? Also, is it possible to modify the Z_Order at any point if the animation requests it? That's the only big things I can't see in any of the running samples I've been looking at.
| You can change images used during animation, not sure about zorder. I am not at pc now but will check tomorrow. |
| Spriter does now have multiple timelines per object, but I agree that Spine still "feels" the better of the two.|
My worry would be keeping the module up-to-date as it evolves on their side, or has this been factored into the sponsoring?
Either way, more choice is always better, and this module will be a great addition to the community, so thanks :)
| Me like ;) |
| Nicely done!|
I don't mind paying for decent software, but my reason for supporting Spriter was the price point - with the free version of Spriter you will be able to do most of the important things, and the full version is only $25... whereas the full version of Spine is normally $75 (on sale right now for $60), which can put it out of reach for some people (and the trial doesnt allow you to export).
Spriter seem to be in a loop of endless refactoring
Oh yes... they do like to tinker! How many times do they want to change the GUI!?!
| I own both but have only really used Spine. The Spriter updates painted a picture of software that is unfinished and a design process that is meandering. That's fine, but I'm tired of using "not quite there" tools.|
Spine is far from perfect -- it's missing a bunch of utility features when operating on animations for a start -- but it felt more assured from the off.
I was going to convert the C# runtime myself, so this will save some time, assuming that it's going to be open-source so that we can integrate it with our own atlas solutions etc.
| Sweet! |
| I had a play just now with spine, the image changing is key framable.. you simply attach multiple slots to a bone and you can animate which slot is the current one. There is a radio style button on the tree view which indicates which slot is active.|
It seems that draw order isn't keyframable yet, but it looks like the interface is ready for such a feature.
The module will be completely open source.
I have ported it over from csharp and applied some optimisation. Ontop I have created a monkeycentric interface for supplying your own loaders and whatnot. For example this is the default image loader spine will use:
format_codebox('Class SpineDefaultImageLoader Implements SpineImageLoader
Global instance:= New SpineDefaultImageLoader
' --- load an image ---
'if we had an engine we could use cached images here if we wanted
Method OnFreeImage:Void(image:Image, path:String)
' --- free an image ---
'do nothing as we just let the GC do the rest
'if we had an engine we could free cached images here if we wanted
There is also be a SpineEntity which encapsulates a skeleton + data + api so it is nice and easy to use!
| Looking Sweet! |
I agree that Spine feels better, but it's good for us to have competition and options!
| @Skn3: Many thanks for the info. I've been playing also with the editor and it looks rock solid, and very intuitive. Great tool if you ask me! |
| Fantastic! |
| Just coding in some bone manipulation stuff. You can manipulate bones using local or world coords, which is quite handy!... literally :P|
format_code('currentEntity.SetBoneScale("right arm", 4.0, True)')
| Looking great! |
| This looks awesome! |
| Another full demo here:|
Might take a while to download, its over 2 meg!
| Looks ace! |
| To change character is "E" key, isn't it? |
| Yup should be E to change the entity. A changes animation. S changes skin. |
| Very cool - nice demo :) |
| Agreed, very nice! |
| The collision response in the second demo where it is reporting what body part is under the mouse - is that your own code or is that a feature of the Spine API you have simply hooked into? |
| Even more awesome!! |
| Hey there are some built in bits for calculate the matrix /vertices values but then I am using a standard point in poly collision function to test. Also transform the point into region space using the matrix values. |
| Absolutely amazing! Wonna use it now :D|
When do you think is your module done?
| It's probably going to be released early this week so you guys can test and play with it. |
| Great! |
| Yea, awesome :) Perfect timing! |
| Hello Playniax,|
Will the module be a part of Ignition or a stand alone module? Nice work by the way Skn3.
| No, it will be (and stay) a standalone module 100% free :)|
I will make some integration with Ignition later.
| Great news and very generous. |
How hard do you think it will be to integrate it with Ignition? I would like to have iLayerSprites animated using Spine if possible.
| I have no idea how hard it will be but that is what I would like too :) |
| @Playniax - Thank you for your contribution (in addition to DreamShard Studios) to allow Skn3 to do his magic. Can't wait to see the integration with Ignition! |
get the repo :)
| Great job Skn3!!!|
A little present from us (DreamShard Studios and Playniax) to the community.
| Thanks! |
| Great job! Thanks Skn3 and all funders! |
| Thank you! |
| Is interpolation also included in your module? I mean the graph function in spine, where you can accellerate and slower down the animation between two keys. |
| Hey zwer99 yup should be. |
| Yea, pretty nice, thx! |
Suggestion: Move the source to a source folder and have your module structure there. Examples make reference to "skn3.monkeyspine" /src/skn3/monkeyspine/sourcehere ? then it is easier for people to download and install module updates.
Going to play with this as soon as I have free time!
| Absolutely amazing - I just included it into my game and it's so cool!|
Thanks a lot!
I found a small thing: GetFlipX wants to return a float-value, but flipX is a bool-value.
| Updated repo, anyone following this please update your link.|
Also fixed the get flip return types, cheers Zwer99.
About the module structure/source folder. Your best option is to create a folder on your disk called skn3. Then checkout the repo into skn3/monkeyspine.
| Just a small update:|
Moved monkeyspine into root module folder.
Now just install monkeyspine into your modules dir and do "Import monkeyspine"
| Skn3, how about to rename it to spine or spineimporter and leave repository name as monkeyspine? |
| It was gonna be just "spine" but as it added to list of official spine libs, I thought it would make sense to keep everything "monkeyspine". Would it be confusing to have monkeyspine repo but module name spine ?|
http://esotericsoftware.com/spine-runtimes/ monkey is on there now, w00t :)
| Yes, I suggest to leave the repository name as it is. But I think "Import spine" sounds a little bit better than "Import monkeyspine". As you know, I have flixel-monkey repository, but the module name is flixel. So far no one was confused. But maybe I'm wrong |
| Ok updated now and the module is now just "Import spine"|
| Nice! Thank you, Jonathan! |
| Skn3: am I right to assume that spine only exports a json with the animations, and to use this with your module, we need to also export the atlas with your tool? Any small step-by-step guide of how to put everything together? How can I associate the spine json images with the atlas-generated images? (haven't tried yet, but just want to be sure I understand it before getting my hands dirty on the process) |
| Yeah spine doesn't export any images. Just the json.|
You don't have to use the MakeAtlas tool. There should be an example of loading unpacked images. You are free to write your own loader if you want.
little bit of info here...
Spine seems to use file names to name its entities, as does my MakeAtlas tool. It should be a matter of picking sensible image filenames and the rest is automatic.
| Ok! I wasn't aware of the wiki page! sorry for wasting your time, I'll take a look and hopefully I won't need to ask more obvious things XD |
| hah RTFM ;) |
| updated repo with a ton of typo-ish bugs fixed, thanks ziggy for finding these :D |
| @skn3: Be ready for a second round of fixes! This time in a single pull request, but it may require your attention XD (I feel I'm spamming a bit the repository) |
| haha spam away :D |
| Great ziggy! (and Skn3) |
| Any way to know if an unlooped animation has finished? Something like |
Also, a way to know current position of the animation in the timeline? The current "millisec" or similar?
Handling resources. How could I unload the loaded Atlas (completely discard it) and also discard a SpineEntity? I want to release all graphical resources between levels but I can't find a clean way to do it, sure I'm missing something...
| Updated the repo with these features added :) |
| Thanks for the new functionality! It's vey very handy! Spine is looking soo good... |
| w00t :D look forward to seeing what you make of it. |
| Another update today|
Thanks ziggy for adding the GetAtlas method to spine entity()
' - added spineEntity.GetAtlas() to get atlas of spine entity (thanks ziggy)
' - added SpineLoadAtlas() function to load an atlas outside of creating a spine entity
' - added SpineAtlas.Use() so that the spine glue will reference count an atlas
' - changed SpineAtlas.Free(force=false) added a force flag which will force teh atlas to be freed.
' If force is false and atlas is being used by something else then only a reference count will be decreased
If you have implemented a custom atlas for your engine, you will need to update your implementation of the interface. See the glueatlas.monkey for more details. Specifically look at how SpineMakeAtlasJSONAtlas handles the Use() and Free() methods.
| The RefCounting on SpineAtlas is super sexy. Thanks! |
| bug: If I use the makeatlas tool and select the Trim invisible edges option, as the spine objects are midhandled, the images that do not have uniform centers (more space at the top or at the left, etc) are misplaced. It seems the module or the makeatlast tool is not taking into account original size and current offset to calculate the midhandling of images??? |
| Will look at this Monday. Not sure why its doing it although I'm sure the fix is pretty straightforward. |
This has been fixed and the repo is now updated.
format_code('region.image.SetHandle(offsetX + (originalWidth / 2.0), offsetY + (originalHeight / 2.0))')
I would highly advise to pre-crop all your source images. It is not as convenient but spine doesn't seem to trim images edges.
To see what I mean:
1) import an image into spine that has lots of white space
2) Drag the image onto a bone
3) hover over the image to see its outline
4) *gasp* at the blank space!
It treats the entire image (regardless of content) as the attachment. This will also affect the spineentity collision stuff because of the region/bounding box.
So in short, pre-trim your images before packing and before building your skeleton.
| Thanks for taking a look to it! |
| Does Spine allow you to swap out graphics in real-time yet?|
ie. Different clothes for characters, adding/removing weapons etc?
If so, how does it handle these - are all assets loaded at start up or are they loaded as needed (thinking about large wardrobes with many characters here)
| Yes, it can be done. Haven't look at the API level, but I think it is as easy as attaching a new image to the named "socket". Also, you can have the same animation and load different texture atlas, as it is separated, so you can have the typical walk / jump / die / etc. animation and use it on all your characters. |
| The ways ziggy says works and there is also a built in skin ability to swap entire image sets with alterable dimensions. By this I mean you could have one skeleton animation of walking and appy different skins ontop. Skins do not need to have identical sized body parts.|
This would require all skins be loaded for a character but i reckon you could utilise the custom atlas loaders some how to get around this.
See example1 with the "s" keypress for skin changing.
| small update:|
' - added SetAlpha() and GetAlpha() to spineentity
| Great! |
| I know this is more a Spine question than a module question, but as users of Spine you can hopefully help me out.|
I am wondering how Spine handles multiple animations?
Rigged Man Character
If you want to make an animation where your man enters/exits the vehicle, are you able to import the 2 animations into a new project and begin animating with their saved rigs all intact etc?
I ask as I am using Spriter at the moment and I'm having real issues with this exact problem as you can't seem to import scml files at all right now.
I also tried getting the Spine Trial to check for myself but the installer freezes and fails trying to get v1.4.18.
| You rig your character and then you can switch the editor mode. In this other mode you can create separate animations beit run, jump, enter car or whatever. |
Not sure about combining the two though.
| Thanks for the reply Skn3.|
The problem I have is that I am trying to avoid having one large file which contains every animation for every object the character might possibly use in the game.
Without the ability to import already done animations, it would mean having to recreate my character rig from scratch in each new animation I wanted.
Of course I could just have every possible animation that might happen in the game at some point in the one large character file (all cloned from the character rig), but this seems wrong to me as half of the animations may never get used depending on the path and actions of the player, and there will be hundreds of possible combinations.
I'm working on iOS so memory is a concern, and loading a massive file at startup with all the animations seems wasteful compared to a method where I can load each animation as I need it, saving memory.
However to make this method work, I need to be able to drag/import already made rigs into a new scene and begin animating with everything intact.
Sorry for the ramble, it's hard to explain what I mean, hope that made sense.
| Hey rik,|
Nah it makers sense. The main memory hog will be graphics data. The beauty of spine and spriter is that your graphics usage is reduced a great deal. Animation data is going to be nominal so depending on your project it might just be easier to load everything needed at the start of your game/level.
| Hello, I have an slot that is semi transparent in the top of the Z-Order and it is preventing me from being able to detect clicks on "behind it" slots. any way to make a slot not clickable, so we can detect clicks on whatever is behind it?|
EDIT: Or a way to detect if a given X and Y coordinate is "inside" a given slot (ignoring Z-Order)? that would do it too!
| Hey Ziggy,|
An update ye shall have!
' - added PointInsideSlot() and RectOverlapsSlot() methods to spineentity. There are two versions of the method one accepst name:String and the other slot:SpineSlot
| Thanks!!!!! It's VERY appreciated! |
| Just bought Spine - looking forward to using it along with this module, thanks :) |
| Skn3: It seems the PointInsideSlot does not take into account the relative position of the slot into the Spineentity. It reacts as if the slot is centered and fais to provide proper feedback when it is not. Not sure how/where to fix it.|
Also, is there any easy way to get the world location of a given slot? (it's sort of the same requirement)
| Hey ziggy,|
Hmm weird it shouldn't be doing that as it uses the same code as the others that were working. I'll be able to take a look on Monday when I am back from a camping trip.
| I'm pretty impressed with Spine, but would like a pointer if possible.|
I have a simple test animation, with 1 bone that has 1 image attached, and it plays perfectly in Monkey.
However I am trying to get the MouseOver functionality you have in the examples, where the bounding box appears around whatever is under the mouse.
I was planning on using this method for collision detection (what is under the mouse), but even though I have tried using the code from the examples, it never seems to register anything when my bone/image is under the mouse, overSlot always = Null.
It's probably my code, but I may be missing something in the setup of the animation.
Do I have to have multiple bones or anything set in Spine for it to work?
Any help appreciated.
I'll be able to take a look on Monday when I am back from a camping trip.How I wish I was camping instead of spending time in front of the computer... XD
Thanks, if you need my spine projects or anything, just let me know. I appreciate it a lot!
| Hey ziggy, I don't suppose you would be able to help me out or have any ideas what my problem might be would you?|
Is your PointInsideSlot issue related to my problem?
I know sk3n is on holiday, but Monday seems a long time away so hopefully you can help in the meantime while sk3n relaxes :)
Is your PointInsideSlot issue related to my problem?It could be as I haven't managed to get this function working
| Actually scratch that - it can't be that as what I'm after is already working in the examples.|
| back from camping trip!!!! Sucks to be infront of a computer now :(|
' - added GetFirstSlot() GetLastSlot() GetNextSlot(slot) GetPreviousSlot(slot) for iterating over slots in spine entity
' - added FindFirstSlotWithAttachment() FindLastSlotWithAttachment() FindNextSlotWithAttachment(slot) FindPreviousSloWithAttachmentt(slot) for iterating over attachment slots in spine entity
' - changed RectOverlapsSlot() and PointInsideSlot() so precision param is boolean
Ok so the collision functions were working I think. As far as a I can see there was confusion with how the methods work. I changed it so slot collision checking is either precise (point/rect to transformed-poly) or in-precise (point/rect to bounding box)
So the two slot collision methods now default to precise. Before they were defaulting to bounding boxes. Check example1. You can press 'w' to switch between whole-entity or slot checking. When in slot checking mode you can press left/right to switch between which slot to check.
The demo now defaults to precise checking mode (precision = 2)
Also, to get the world position of a slot you can do GetSlotX("name",True) True indicates we want the world value. I think most of the slot methods have a world flag.
| It always sucks to be back in front of a PC after any time away doing non-PC things, you'll get used to it again :)|
Are there any plans to update the module to include the new Events stuff?
| Might move the desk into the garden. lol|
I was going to wait until they implemented keyframable zorder and then update the runtime in one big go. With other bits they had implemeneted.
I will keep an eye on this, if they take ages then I might just do the event stuff early. Depends when I get a free moment.
| You might need a brolly, it's about to piss down here lol!|
Yeah that sounds great mate, I'm not pushing for it at all but it's nice to know that it is on your radar for the future.
I only bought Spine recently and I love it (disappointed ex-Spriter user) - so thanks again to Playniax and you for making it happen with such a fully featured module. :)
PS. Any ideas on my question in post #87?
| Computers are waterproof right? hah|
Whoops missed #87
Have you attached the images to bones/slots in spine? The collision detection is done on slots with attachments. An attachment is something like an image.
So you create a bone, drag an image onto the bone in the right-hand tree. It should then ask you if you want to create a new slot. The name you enter here, is the name you use within the runtime.
If you just drag the image onto the scene it gets added as a slot to the root bone. To fix this, you simply drag teh slot (in the right-tree) onto the bone. Voila!
Does that help?
| Very possibly - although I can't see anywhere you are using explicit slot names within the code (except the head), just GetSlotAtPoint().|
I think it may be my rig setup, but I have to go out for a couple of hours now so I will start fresh when I get back with a clear head.
Thanks for the quick reply. :)
| Just managed to sit down and look at this again.|
For ease I was just loading separate images rather than using an atlas, as I realised that the built-in Spine Atlas isn't supported (unless I'm doing something wrong) and I had to use your Make Atlas Tool so it was just easier to not faff about while testing.
However that was the problem - once I used your tool and exported an atlas and then tagged my rig onto the end of 'example1' it worked perfectly first time.
| Excellent! I'll look at supporting the new built in texture atlas when I do the full update. |
| That sounds great sk3n. :)|
Sorry for the barrage of questions, but I have another...
I have a simple menu animation (slide_in, slide_out) which I am calling at the relevant time with SetAnimation(), however I will randomly get a 'flicker' or 'jump' when changing to 'slide_out' as the animation starts.
I say random as sometimes it will display perfectly a few times, then flicker, then return to normal. Other times it will flicker 4-5 times on the bounce, then be fine for a few, then flicker again - really random.
It's almost as if it is jumping a few frames into the animation as the start position rather than at 0.
It is almost certainly my code rather than yours, but I was after clarification that SetAnimation() is all I need to do, and is the recommended way to do it.
Wow, programming is weird sometimes!
I had messed around for a couple of hours trying to sort this out and got nowhere (large project, migrating from Spriter->Spine), and 30 seconds after I post this message I solve it!
It was so simple I now feel stupid lol - the problem was where I had my .Update() for the menu - it seems in Spine it has to be *after* everything else, whereas in Spriter it worked fine *before* everything else.
With it being a large project I couldn't see the wood for the trees!
Sorry for the life story of a post lol, but I'll leave it here in case anyone else is as silly as me. :)
| Just a heads up, Keyable Draw Order is now in! :)|
Also, is it possible to change the alpha of a slot?
| Haha what a long post but I am glad it worked out without me having to do anything ;D|
Looks like I will be scheduling some time to update this beast :)
I should be able to add slot alpha.
| You sir, are the man! :)|
Looking forward to it!
| I seem to be hogging this thread - sorry!|
I have noticed that SpineEntities are drawing blurred or distorted depending on the #MOJO_IMAGE_FILTERING_ENABLED flag, and I think I have narrowed it down to the Image.MidHandle flag used in LoadImage().
I've made a separate thread regarding it HERE, but anything drawn from Spine is coming out looking like 'Image1' in both the pics I posted in this thread, rather than 'Image2' which is what I want.
EDIT: Solved (again lol!)
It turned out to be that images (and SpineEntities) were being drawn at Float co-ordinates. I fixed this by adding .5 to my SetPosition() calls.
I could probably add .5 to the position inside Spine, but that would take forever so it's easier for me to do it in code.
| I could potentially add a flag to draw at int offsets? I'll do this when I do the other bits. |
| That would be good! :)|
It was caused by me having odd sized images (ie. 101x101) and then in Spine putting it at 0,0 which meant the handle was (50.5,50.5), and even though i was drawing it at Int co-ordinates in Monkey the half pixel stored in the Spine file was causing it to be off.
I seem to be hogging this thread - sorry!
Not at all! It just means that YOU are one that is trying to use it and helping Skn3 work issues out or add new features :)
The more you do of it, the better the code will be :)
| Sorry for taking ages folks. I will get around to this, but been very busy. |
| I've been busy too, but I'm going back to using Spine tomorrow. Anything I should be aware of? I mean, current module is still compatible with latest editor version? |
As long as you don't use any of the new features in Spine since the last module update (keyable draw order, events) then the exported json doesn't change, so yeah it is still working with the current module - minus the new stuff.
Is there some way to get slot collisions with working with images that are not loaded from an atlas (like my problem earlier in this thread - which I solved by creating an atlas) as sometimes I don't want to have to use an atlas just to test a few buttons or whatever.
If there a is a reason that's fine, I just want to make sure it's not me missing something when it is in fact possible.
Lastly,do you have a rough ETA of the update?
Not rushing you for an exact time, it's just so I can plan a rough date for adding in the new features to my project.
| Will do my best to get it done tomorrow. :D at least to get project loading done from latest editor. |
| Sweet - looking forward to it sk3n.|
Could you try and get the slot alpha in there as well pleeeeeease? :)
| MASSIVE UPDATE ALERT!|
So I didn't manage to get this finished last night in the wee early hours, but I got it done in my lunch break and this evening. I'm hoping that covers everything and you can get on with your projects as I am incredibly busy with work. Fingers crossed.
Most importantly this now works with the event and draw order.
Check example 5 for the new functionality. Example file is also loading from spines built in texture format. Note that rotation is not supported yet, so disable this when you export your texture from spine.
This update may break your existing implementations a little as I did some reworking of the atlas loaders.
Time for me to go have a beer. CYA!
' - MASSIVE UPDATE
' - added support for native spine texture atlas
' - changed so default texture atlas loader type is the spine texture atlas loader
' - renamed the seperate image loader to SpineSeperateImageLoader
' - fixed file stream wrapper so eof works
' - added event callback to SpineEntityCallback interface
' - implemented spine events
' - implemeneted spine draw order
' - added SetSnapToPixels() to spineentity, this will draw images at int coordinates
' - Added GetSlotAlpha() and SetSlotAlpha()
' - fixed seperate image loader collisions + bounding not working')
| Enjoy you beer mate, you deserve it!|
Huuuge thanks for the update, will get this put into action over the weekend!
| The new update seems to work great sk3n, thank you :)|
SetSnapToPixels(True) doesn't seem to do anything?
At least it doesn't change anything for me, I still need to SetPosition() the SpineEntity at a value of xxx.5 so they draw without being malformed.
It's not a big issue and I think to be safe I will go through all my images and make sure they are even sizes (224x120 as opposed to 223x119), but it would be good if I could get this working as I have hundreds of images :)
Also, I know you are having a break from this module so I am posting this here more for future reference than requesting an update.
Spine really does just get better and better! :)
| Hey rik,|
Cool will add the bounding box to the long todolist.
check line 330 of gluespineentity.monkey
attachment.Region.Draw(Int(attachment.WorldX), Int(attachment.WorldY), attachment.WorldRotation, attachment.WorldScaleX, attachment.WorldScaleY, attachment.Vertices)
attachment.Region.Draw(attachment.WorldX, attachment.WorldY, attachment.WorldRotation, attachment.WorldScaleX, attachment.WorldScaleY, attachment.Vertices)
It should be drawing all images at int coordinates? Am I missunderstanding the issue at hand?
| Hey sk3n,|
I did look at the snapToPixels code in spineentity.monkey, and I think I possibly explained it badly, so I will try again with another example...
I have an image that is 101x101 in size.
In Spine, I place this image at 0,0.
I load the SpineEntity in Monkey, and do a SpineEntity.SetPosition(400,300)
The image will appear distorted, as per this thread
Now as GfK correctly assumed in that thread, it is because the image is being drawn at Float co-ordinates, as even though in Monkey I am placing it at say 400,300, because of the size of the image being 101x101 and its placement in Spine at 0,0, I guess the MidHandle becomes 50.5,50.5, meaning it is drawing the Float MidHandle at Int screen co-ordinates....I think?
It can be fixed by either going into the Spine file and placing the image at 0.5,0.5 or any other .5 value, or by padding images by a pixel so that they are even sizes - ie. Pad by 1 pixel to 102x102 - but I have a huge amount of images so if this can be fixed in the module that would be awesome and save a great deal of time.
It happens if either the width or height is odd, or both, but not if they are both even.
I hope that made sense?
| Oh I see!|
Well I spent 10 minutes on my break and have updated the spine module with a fix.
The atlas loaders were in charge of setting the image handles. I have now moved the responsibility of image handles to the spine entity each time it renders. This means that image handles are always 0,0 but the atlas_region draw method now has extra handleX and handleY params.
Let me know if this works.
You might need to update your implementations a little if you have any custom atlas loaders.
| Sounds great I will try it out tomorrow.|
Thanks mate, didn't expect a fix so quick! :)
| Free form deformation announced in the last update is the same sort of thing used in the recently released games Dragon's Crown and Rayman Legends|
| Gonna be tricky to implement that in monkey as images are hardcoded to quads...|
hmmm... any bright ideas anyone?
| rewrite the blit algo itself in native openGL and pray that mark incorporates it in some sort of MeshWarp() thing in official mojo? <:)|
| posted 3 days ago.. whoops :D|
I guess that would be the only option really. I think I'll wait for this to mature in the spine runtimes first though. The event/draworder hadn't even been ported to the c# runtime (which monkey version is based off) so I had to splice that in from another runtime.
| Hey sk3n,|
I love Spine, and will be using it a lot in the future as well as on my current project, so I was wondering if I could get a pointer as to how to incorporate it into the F1 help or the docs in Monkey?
I realise I can just make a list of commands etc for my personal reference, but I thought if I could get some info as to how to do it "properly" so to speak, then you could add it to your distro and it would be a small thank you for the work you have done and the super fast updates you have provided.
I know it's not much - but every little helps, right? :)
Also, could have a quick explanation as to how the fix for odd sized images works please?
| Hey that would be cool. Thanks :D|
I havn't done any f1 / monkey docs yet, so not best person to ask that one.
Odd image fix:
When an image is loaded into spine, it always gets added as an atlas region instance. Even if you are using the separate image loader it will fake adding it as a fake atlas region. When the atlas regions were getting added, their handle's were being set to the center. All drawing operations would then simply draw at 0,0 and it was up to the image drawing routines to do the centring using monkeys built in handle stuff.
So the fix has removed the auto mid handles on the atals regions. Now the glue entity will manually setup the drawing matrix and draw at mid point. The mid point calculation is worked out for each render, so we have the ability to int those center points if we want.
Hopefully that makes sense?
np, I'll have a search on the forum and make another post if needed, it's probably won't be until the weekend at the earliest though - what with a small indie game called GTA5 being out :)
The odd image fix, yep that makes sense, however - what is the change in the Monkey code - ie. What command(s) should I be amending to add in the HandleX/HandleY, and is it as simple as just adding 0.5 to both new MidHandle() values?
I have looked through the code but I can't see reference to them anywhere?
Also, I am having problems when scaling on a single axis.
Everything looks great in Spine, but in Monkey the animation becomes distorted, although scaling on both axis together works fine.
I am scaling a main parent bone, which has all other bones as children of it, but it seems like the children don't scale properly with the parent bone (on either single axis), and I'm not sure if it is some error on my part or something in the module, although as I say it looks fine in the editor itself.
I've uploaded a simple example showing the issue:
Exported movie from Spine: here
Same anim looped in Monkey: here
Anyone had any similar probs?
| Hi again,|
It seems to be an issue with rotating the bones during setup, but I will look into more and try and see what is happening.
I am using the latest version from the repo, it said rev 26 when I downloaded it.
| Hey rikman. I will try and have a look soon but fairly swamped with work. Sorry for delay. Hopefully it will be a quickfix! |
| Hey mate, no worries.|
Thanks for the reply :)
| Hey RikMan,|
It is on my todo and I will get it done the first free moment I have. Its bugging me that there is an issue that isn't fixed. Code-C-D haha.
| Hey mate,|
As I said no worries, I appreciate how busy you must be :)
I had another play earlier hoping to narrow the problem down a little to save you time when you get around to looking at it, and it seems the problem comes from rotating the bones in Setup Mode within Spine.
If I leave the bone set at default 0 rotation, then scaling the bone along Y works fine.
If I rotate the bone (not the image) so it is vertical at a rotation of 90 then the problems begin, and it seems the Monkey runtime scales along the X axis (due to rotation on the bone?) rather then the Y as it does in Spine.
I also noticed that scaling the "root" bone has no effect in Monkey, although doing so within Spine scales the entire skeleton and children as expected.
I'm not sure if this is a bug or not?
Let me know if me setting up a Spine project and Monkey code to show the problem would help you out, and if so I'll get it sorted and host it for you to download.
| Hey rikamn,|
Cheers for starting looking into this. I haven't forgotten. I am working to a deadline at mo and pulling some very long hours in the process, so will take a look once I become freed up.
| Hey Sk3n,|
OK mate, thanks.
| Just out of interest - has anyone else using the Spine module come across this issue at all, or is it just me? |
| Nobody else?|
| I'll be using Spine again in some weeks, but not lately so can't realy answer |
| Thanks for the reply ziggy :)|
Could I send you over some Spine files for you to test in Monkey just so I can confirm its not a problem specific to my setup?
| OK well I have a bit of info regarding my deformed animation problem, and a couple more questions (suprise!).|
So I emailed Nate the author of Spine and he kindly checked out my files from post #126, and reported back that they work fine in LibGDX.
He also said that it looks like there is a problem with non-uniform scaling in the runtime I am using (Monkey), so I hope that may narrow down the issue for sk3n when he gets around to reading this thread again.
A couple of questions:
1) I was playing with creating/setting attachments/slots at runtime, and hit a bit of a problem, whereby they don't seem to be accessible from the entity loaded with x = New SpineEntity.
The SetAttachment/GetAttachment methods are in spineskeleton.monkey, and the SpineEntity has marked all it's Fields as private, so when I try and do a entity.skeleton.SetAttachment() I get an error telling me it's not accessible as they are private.
For now I have commented out the "Private" declaration and it works fine, but obviously this is not the intended usage, so I was wondering what the correct way to do this is?
I am hoping to be able create slots/attachments/skins at runtime when needed.
eg. Having a single slot and programmatically creating and loading images/attachments during the game to use this single slot, rather than having multiple images loaded into memory at once if they are not all needed.
2) sk3n, is there any rough ETA on when you may get around to looking at the deforming issue? Just an rough idea...a day, a week, a month etc?
Fixed - was an issue with my screenshot code being called before the images were rendered.
| Hey rikman,|
I might be able to have a look this week. My deadline is coming to an end so it will be good to get spine fixed up. I' have been reading the posts but just doing some interesting work hours so not so much in a forum posting mood ;)
Currently the fiancé is patiently dealing with me eat sleep work all day and night .
So I'll let you know this week .
| Hey sk3n,|
I just popped on to add a question to my previous post, doing some strange hours myself atm :)
That's cool mate, good to hear you are still alive - though by the sounds of it your fiance might be changing that status soon lol :P
Look forward to hearing from you :)
New Kickstarter for new features! Meshes, Free-form deformation, Skinning, Inverse kinematic pinning
| freeform deformation seems like it might be a bigger bitch than initially anticipated. Splitting into quads may not be so bad if quads are required for the feature to work in Spine. Otherwise, the same triangulation / convex splitting algo needs to be used for everything to work the same. I was looking into the Hertel-Mehlhorn algorithm earlier for DrawPoly / path bezier improvements on OGL targets; if there's a good use for splitting polygons into convex ones in the monkey spine module, there's maybe a good place to start researching just in case the solution is not-obvious+complex. |
| Ok I have a couple of free hours now. On a strict deadline of relaxation ;D. Lets see if I can get this problem fixed!|
P.S. not looking forward to hacking freeform transformation into mojo. Infact without webgl I don't think its possible on html5 target. Maybe the monkey mojo gl roadmap feature will be done by then?
PPS (why am I writting as if its a letter???)
Hey Nobu, I'm kind hoping that we wont have to triangulate any meshes as it should all surely be implemented before the animation has been exported?
' - added SetDebugHideImages() to entity so we can disable drawing of images
' - fixed issue where transform/scale/rotation animation was being ignored for root bone, cheers rikman
' - made atlas, data and skeleton fields in spineentity public for hackables, cheers rikman
' - fixed issue where scale on single axis was deforming in monkey, cheers rikman.
Repo updated hurrah with a fix (hopefully) :D
So the issue was fairly easy once I found it. In spineentity OnCalculate() it would apply the external spineentity position/scale/rotation to the rootbone. This is good as it means we can position the entity easily and still keep the spine system running as it expects. The issue was it was overriding the bones calculated animation values. So if you look at teh code now it is applying the details properly.
This seems to have fixed all issues for me (See example6)
I tested it best as I understood the issue and I see normal deformation.
Time to go back to relaxation :D
| AWWWWEESSSSSSSOMMMMMEEEE!!! :D|
Won't have time to test/play with this till later tonight as it's roast dinner at the parents today, but I will say a pre-emptive thank you and let you know if I have any problems later, but hopefully not!
Thanks again mate, can't wait to get my hands on the fixes :)
| sk3n, sorry it took to long to get around to trying the update mate, but everything seems to be fine upon a quick first inspection :)|
No doubt I will be back at some point to ask more questions, but I always try and sort them myself before bothering you.
I am still struggling with the SetSnapToPixels(True) not seeming to do anything, but will get my head into that this week and report back.
Thanks for your hard work! :)
| Back again - sorry sk3n you must hate me!|
This time there seems to be a Mac/iOS specific bug to do with alpha in animations.
Basically I have an animation which starts off with an alpha value of 0.0, and I fade it in to 1.0 as the animation runs.
This works fine when using HTML5/GLFW on Windows, but if the same code and animation is run on a Mac (HTML5/GLFW) or on iOS then the animation seems to load with an alpha value of 1.0 meaning it is displayed straight away on screen.
If I run the animations (fade_in/fade_out) then after the first run it all works fine and fades in and out as expected, it is just wrong when the animation is loaded for the first time.
I also noticed that after running the animations with alpha set in Spine, that anything written with DrawText after the spineEntity.Render() also fades in and out with the animation.
Hopefully it's just a value being set/not set somewhere and is a simple fix, and as I say it's specific to iOS and Mac (glfw and html5)
| Hey Rikman,|
I am back from a week of sunning it in the sun so I am glad to come back and find the fix worked :D
With the alpha issue, just as a try out, what happens if you ensure keyframes are set at the start of the animation in spine?
I noticed some issues here when exporting animations from spine so it could be related.
Let me know if this does anything before I dive in and have another look.
| Hey mate, glad you had a good holiday :)|
In the animation I am using (just a simple scaled/alpha'd rect) it has 3 animations: idle, fade_in, fade_out.
All 3 have keyframes set at the very start of the animation - idle and fade_in are set to 0 alpha and 0 scale, and fade out is set to 1.0 alpha and 1.0 scale - not sue if that is important or not in this case.
As I said it runs fine on PC, it's just the first load on mac/ios where the alpha seems to reverse.
If you need any more info let me know :)
Edit: I've hosted the test project to show the issue on my Dropbox here so it might save you the hassle of having to mess around setting one up yourself.
I forgot to mention there are 2 events in the animation, not sure if that is anything to do with it, but thought I should mention it in case it helps you narrow down the problem. Also as I said it works fine in Windows, it's just when run on a Mac or iOS that the issue shows up.
| There are lots of things like this in the source code:|
format_code('Throw SpineException("Invalid atlas page image '" + path + "'")')
That should be something like this, isn't it?
format_code('Throw New SpineException("Invalid atlas page image '" + path + "'")')
| I'm unable to load a simple map.|
that's the code I'm using:
bosque = New SpineEntity("worldmap/nivel1.json", "wordlmap/nivel1.atlas")
Print "uncought exception!"
I've used the Spine texture packing system. The worst part of it, is that it refuses to use the Try/catch block properly, as it fails with an uncaught Monkey exception when the line 510 of the glueatlas throws a New SpineException, so I think I'm doing something wrong, but also, I think there is a bug on Monkey exception handling.
Both files (the json and the atlas) are properly copied to the build directory and on the right location.
| Hey Rikman,|
I will investigate this week when I get a spare moment.
Have you verified that the image paths for the provided atlas are correct?
You will see around line 57...
format_code('Local imagesDir:String = SpineExtractDir(path)')
and then around line 103...
format_code('pageFilePath = SpineCombinePaths(imagesDir, line)')
This is how it builds the images path, so make sure everything is valid here.
| Hello skn3: Managed to find out what was happening. It was that I had selected the "Rotate" into the spine atlas exporter and the try/catch I was debugging was not containing the SpineEntity creation, so it was not handled.|
I got it working now, but I'm having wrongly placed bitmaps when I enable the trim whitespace in the spine texture atlas creator. Not sure if it's a Spine bug, or something wrong in the module.
Is there any way to not have all the spine runtime debug information being sent to the output console?
| All fixed. It was my being stupid. |
| skn3: How can I know the X and Y coordinates where a slot is being drawn? If I use the Bone.WordX and Bone.WorldY I don't get expected results. |
| See GetSlotPosition() in gluespineentity.monkey, you can pass in a world param to return the slots world coord. |
| Thanks! It works perfect! |
| Does anybody know how to programatically modify the image of a given slot? |
| Before the last update I played around with it and the following seemed to work, although I had to make fields in SpineEntity public, sk3n fixed that in v15 but I have not tested this with that version yet.|
The image would change once but then stick unless I did the OnCalculate().
| Sorry didn't get round to testing and fixing alpha issue. Had a friendly bout of the shits post holiday. Haha.|
Defo next week when I'm at full steam :)
| Hi, maybe it's a bug.|
Check out this example and try to walk right, then try to walk left (done in spine with negativ scale values)
| I use flipped rigs in my game to mirror left/right and they work fine, although I am not using negative scale values, I just use format_code('SpineEntity.SetFlip(True, False)')|
Are you doing a SpineEntity.SetScale(-1,0) to try and flip?
| Thx rIKmAN,|
will solve my problem, but I didn't use "Spine Entity.SetScale(-1,0)". I had created two separate animations in spine and wanted to use them like:
Method SetDirection:Void(dX:Int = 0)
If (spine.GetX() > dX) Then
direction = DIRECTION_LEFT
Print "[walk left]"
direction = DIRECTION_RIGHT
Print "[walk right]"
| This should be a simple fix, will investigate this week. |
I guess you mean you are setting a negative scale inside Spine?
Unless you have direction specific animation (meaning right and left are different, which is unusual for a walk anim) then you can just create your animations facing one direction in Spine, and then flip them at runtime.
This way you only have to create animations facing one direction, and they will be exactly the same going the other direction when flipped in Monkey.
Method New(x:Int, y:Int)
' Load the pet we created in Spine (facing right) into char_right
Self.char_right = New SpineEntity("char_right.json", "", SpineSeperateImageLoader.instance)
' Load the same pet again into "char_left"
Self.char_left = New SpineEntity("char_right.json", "", SpineSeperateImageLoader.instance)
' This time flip the pet on x to make it face left
Now you can just call "pet_left" as if it were a real left facing animation you created in Spine.
You can also use variables to hold the direction and just SetFlip as needed on a single "char_right" animation to save loading the "char_right" SpineEntity into memory twice (for left and right), but the above is for ease of use.
Hope you found the imodium! :P
| Haha about 12 in one day! |
| I dont know if this question still has the same answer: Spine or Spriter?|
I already bought Spriter, but not yet started developing. Which is easier to start with and how far is the progress of the monkey modules?
Has therevills stopped developing his module? Last code update was at 15th of march..
The Spine module is more feature complete than the Spriter module.
The Spine module was funded by a member of the forums (Playniax?), whereas therevills made the Spriter module for the features he needed in the game he was working on at the time, but he was kind enough to share his work with the community.
I own both and would 100% recommend Spine over Spriter all day long.
I have uploaded a couple of example projects to my DropBox HERE to hopefully make it easier for you to find/fix the bugs.
There are 2 example within the .rar file, and all include the .monkey file, the .json and the .spine files.
There is the previous alpha issue I mentioned, which only gives the error when run on a Mac or on iOS, although the DrawText text does also disappear under Windows (although he animation alpha works fine)
Example is names "alphaTest".
I also came across another bug earlier tonight to do with the draworder.
It seems that the first run of an animation observes the draworder correctly, but any subsequent runs of the animation after that the draworder gets ignored.
The example for this is called "drawOrderTest".
Also, it may or may not be related to the above problem but I also noticed that setting a draworder keyframe without any changes to the draworder within Spine causes a "Null Object Access" when run in Monkey.
I was trying to set a keyframe at the start of the animation as a "base" for the draworder, but it doesn't matter where the keyframe is in the timeline - it errors if there are no changes and you set a keyframe.
This may be intended behaviour but thought I would mention it in case it was related to the draworder bug I just described.
Hope those examples might save you some time trying to recreate them.
PS. 12 imodium!? lmao!
Mount sk3n, the new "worlds biggest volcano" :)
| A little bit late, but gonna look at this now... |
' - fixed issue with draworder not resetting for non loopd animations (cheers rikman)
I was unable to replicate the alpha issue, even with your example?
- windows (glfw)
- mac (glfw)
idle animation showed nothing, fade-in and fade-out worked perfectly.
I am using monkey 76a
| hmmm strange, though I am using v74a so I will update when I get home later and re-check, and see if it still happens.|
Thanks for the draworder fix :)
| let me know once you have a chance. What version of iOS? what graphics card in your mac? what version of osx? |
| Sorry for the delay, I will be re-testing this in the next few hours.|
I've just noticed that v76a is not listed on the Product Update page, only v76d - will this be OK to test with or could it introduce more issues?
Also, I have been trying to get the width/height of the current frame, and on the official forums something called hitTest() has been mentioned, which seems to be something from the official runtimes, and also some code from the author here
Could you shed any light on if this is possible with Monkey without implementing bounding boxes, as I'm trying to get the dimensions to roll my own basic collision code until then.
| check in gluespineentity around line 462|
There are lots of collision/hit testing routines I built in with varying precision.
v76d should be ok, I dont know if it will make any difference to the alpha issue, but something could have changed which is meant it was fixed for me?
| Hey sk3n,|
Just updated XCode and Monkey and the alpha is working fine, tested on both my devices :) Apologies for the false report.
re: collision api - I used the RectOverlaps funtions a while ago for animated buttons and completely forgot about it, doh! :)
Am I right in thinking the bounding box stuff would be needed for detecting collisions on non-rectangular shaped images?
ie. A T shape where it only detects a hit on the T itself, rather then the whitespace around the T (the containing rect)
I think this may answer my question, but just want clarification :)
format_code(''here we could go one step further and check pixels.. but no.. not really in current monkey!')
Thanks mate! :)
' 0 - entity bounds
' 1 - region bounds
' 2 - region rect
0 will check if collision with rect bound of entire actor. The bound rect is never rotated so imagine that the collision area would be bigger if you had a rotated rectangular region in your actor.
1 will do the same as 0 but per region instead of the entire actor.
2 will test collision, per region and will use the regions rotation as well.
Currently there is no way to avoid white space detection unless you just split your image regions up by hand. So your "T" could be split into 3 separate regions for finer collision detection.
| Just to let everyone know that Soap and Playniax have recently donated some cash to this module. The support is very helpful so everyone should offer them lots of thanks :D |
| Skn3 how much of the new features from their current kickstarter are you going to be able to adopt out of the box? Or are you going to have to wait for mojo enhancements ? |
| Thanks again for the draworder fix skn3 - just realised I've been calling you sk3n throughout this whole thread - doh!|
Big thanks to Soap and Playniax for the donations - I will also be donating for sure once I get some spare cash, things are pretty tight for me at the moment but I will definately show my appreciation for your work on this module once circumstances allow.
I have a quick question about SetSlotColor().
If I load an entity and call SetSlotColor at the start it displays fine, but then when I call SetAnimation() the slot loses the colour I previously set and seems to revert back to 255,255,255.
If I call SetSlotColor() again after changing the animation with SetAnimation() then it works fine, but I was wondering if this was intended behaviour or a bug?
I expected the slot to retain its colour information through all animations until another SetSlotColor() was called rather than revert back with each animation change, as that is going to be a lot of SetSlotColor calls.
I think it's a bug but I thought I would check that it wasn't intended for some reason before I start adding loads of SetSlotColor() calls after all my animation changes.
| Has anyone had any success or got any information on how to mix animations? |
| Continued here:|