darkFunction to Orx Converter

edited May 2016 in Projects - Tools
I've created a darkFunction to Orx converter.

darkfunction_converter_screenshot105.png

Read about the darkFunction editor here:
https://forum.orx-project.org/discussion/6268#Comment_6268

Takes darkFunction .sprite files (XML), which contain coordinates for the packed sprite sheet, and converts to Orx INI fragments.

This takes the pain out of doing it manually, and is repeatable for tweaking.

Latest version here:
https://forum.orx-project.org/uploads/legacy/fbfiles/files/DarkFunctionToOrx19.zip

C# 2.0 source can be found here: orx/DarkFunctionToOrx

Comments

  • jimjim
    edited July 2013
    Thats very cool, thanks :) One thing Orx is missing in its default setting is texture offset, of course I can implement it, but supporting it directly would make it more clear.
  • edited July 2013
    Hi Jim. Do you mean supporting a TextureCorner config in a orxGRAPHIC structure? The docs say it is there. You must mean something else.
  • edited May 2016
    Version 1.01 added.

    (See first post for updated version)
  • jimjim
    edited July 2013
    I was talking about texture offset I found in other texture packing software like Texture Packer (paid) and ShoeBox (free for any use).

    So, texture offset is same as texture corner, but only thing is, its a relative measure. For example,my image TextureSize is (350,400,0) with transparent pixel, when I crop it using gimp, I get TextureSize = (150,200,0). But I need my TextureSize to be (350,400,0) in my game. So, the solution is , I will be using cropped image, but I will need some extra information. Those are, offsetX,offsetY and original image size if needed for anything.

    How, the offset is used ? Whenever I draw a sprite on a screen, we add texture offset to sprite position. Offset is calculated from BottomLeft corner of texture. In the example, texture offsetX and offsetY is 100 pixel respectively.
    We draw our sprite as orxObject_SetPosition(objectPosition + offsetX,objectPoitionY+offsetY); We have to consider scaling offset value if our sprite is scaled. Its the basic idea of texture offset. I am showing an image if that helps.
    enemy_00.png

    This is the link to ShoeBox explaining how it packs its sprite,
    http://renderhjs.net/shoebox/packSprites.htm
    Texture offset is also beneficial for animation, when you want to change position of some of frames of you animation on runtime.
  • edited July 2013
    Hi Jim, thanks for the explanation and image diagram. My sprites also start with the surrounding empty area which is my original size and I let darkFunction crop it.

    So I read through what you wrote a couple of times but I couldn't get the why of what you were doing. Was it so the helicopter could be shaken.. or jump slightly in a direction from a round taking damage?

    I do remember coming across ShoeBox but it put me off being an Adobe Air app for whatever reason.
  • jimjim
    edited August 2013
    Okay, sorry I was not giving any real reason, yeah, I am taking your example, you have a shake effect with some particle when your helicopter takes a damage, if you crop the sprites you would not get it right. Also think all of your sprites are not same size when you crop them, but for animation to be right you need them to be same size. Texture offset is a good solution to this problem. Also many sprite animation software like SpriteHelper uses this techniques in their animation. If you don't want adobe app then there is another java based texture packer which is for libgdx but can be used with other engine, but it uses JSON which should be no problem to parse.
    https://code.google.com/p/libgdx/wiki/TexturePacker
  • edited August 2013
    Cool no worries, so I was on the right track then.

    I had intended to alter the setPosition dynamically per frame with events to get my different sized frames to work properly. Might not be wise then.

    But here is my concern... If my frames were all the same size, and there was some surrounding transparency, aren't those areas affected by collisions.

    To put it another way: does a bullet not affect your helicopter when it strikes the helicopter's border?
  • edited August 2013
    Well such offset should be reported to the pivot.
    With the image you have as an example, if your original pivot was (0,0,0), to work seamlessly with the cropped version it should become (-100,-100,0). Given your example, if your pivot was "center", there's no need to change it as the cropping is perfectly symmetrical.

    Regarding the physics body part, one can specify their actual size when the whole image doesn't fit the needs.
  • edited August 2013
    PS: If you look at the current exporter I wrote for TexturePacker, you will notice that I report the cropping offset to the pivot when needed.
  • jimjim
    edited August 2013
    Hmm, did not realize one could specify pivot as such, then setting up the pivot should work. How would pivot work if the image is scaled, I guess its value also scaled. If I set pivot to (-100,-100,0) then scaling the image to half should also affect the pivot I guess. If that's the case then pivot can be used instead offset.
  • edited August 2013
    Yes, actually the pivot is expressed in local space, so its value won't change with transformations, but the renderer accounts for it so visually it'll look like it's affected by scale/rotation.

    PS: The advantage is that your position remains fixed as left untouched, and won't have any side effects (like with physics, for example).
  • edited August 2013
    Yep I checked out pivot last night with some crazy values and get a nice offset so that's good.

    But I also looked into that other problem, where sprites are all the same size. I loaded up a demo project last night and took the main sprite which was just a ball.

    I increased the size of the image's canvas so there was extra transparent space. When added back to the game, I turned on the debug so I could see the collision area around the sprite body (box type).

    It was of course as big as the canvas which I assumed. So leaves a problem with extra spacing colliding.

    However, seeing a pivot can be given to each frame defined, this means the canvas for each frame CAN be reduced to its smallest area.

    Which is why iarwain said he also exports the pivot data with his TexturePacker exporter. Ok I get it now.

    So I am best to try and do the same with the darkFunction editor.
  • edited August 2013
    Well, that's what I meant when I wrote that the size could be defined when the image size, it wasn't very clear, sorry.

    When you have a bigger canvas that doesn't match the desired size of your physics part(s), you can simply define the sizes in config: Center/Radius for sphere, TopLeft/BottomRight (corners) for box, VertexList for mesh.
    Those are expressed in a local space whose origin is the pivot.

    It's only when they are not provided that orx will use the size of the canvas.
    Let's take the example of our helicopter, when using the large version, assuming we have the pivot in the center, ie. (175, 200, 0), on can define a box with TopLeft = (-75, -100, 0) and BottomRight = (75, 100, 0) that will match the smaller box drawn on the picture.
  • edited August 2013
    Ok that's all cool, and we have some good options.

    So I went back and had a look at the animation tools in darkFunction. The software saves an .anim file which contains the pivot (offset) points for each frame.

    I'll add support for pivots in the converter this evening.

    This is going to make my process easily repeatable and life SOOOOO much easier.
  • jimjim
    edited August 2013
    I gave some thought on pivot, one thing thats bugging me is, rotation is affected by pivot. So, when I set pivot to Left Bottom or Top Right, what would be its actual value in pixel ? Though setting it center will have no effect on offset. I will get into more details once I get home.
  • jimjim
    edited August 2013
    In the image, with cropped version, Bottom Left is (0,0), Center (75,100),Top Right is (150,200). And when I want offset into account, Bottom Left is (-100,-100), Center (175,200) and Top Right (250,300) considering original image size to be (350,400).

    But again the problem is when I use actual value of (0,0) as pivot, its value should actually be (-100,-100) as I am referring to the original non cropped image. When I set pivot to (350,400) its actual value should be (250,300).

    It looks like, one has to subtract the offset manually which is (-100,-100) from whatever value is present in the pivot, to make it transparent to the user.

    So, user would treat the image as a (350,400) sized image when in reality the image is cropped and its cropped size is (150,200).

    For example, I told my artist to make me an explosion animation of size 256x256 each frame, he made me a sprite sheet with cropping. Now, each image size is different, and I don't need to know their individual size. All I know is their size is same which is 256x256, then I set their pivot to Bottom Left or set it to (0,0) hoping that there would be no problem. But when I play the animation, its not right, because pivot is set to (0,0) for cropped image which has different size hence their pivot is same but they are drawn in different position. Would not it be logical, when I set pivot to (0,0) it would take offset into account and makes its value according to offset for each frame.

    Also, when I ask for sprite size what would it return ? it would return different value, but I was expecting their size to be 256x256.

    I hope you guys can understand what I am talking about :)
  • edited May 2016
    Version 1.02 added. Contains support for the .anim file format for generating offset values.

    darkFunctionConverter-b04d0c214fb9faa39b8a4eec496c0ccb.png

    See first post for updated version.
  • jimjim
    edited August 2013
    Does your converter works with heavyducker, sample files that came with DarkFunction ? Because I am getting this error while trying to parse the file

    3TjbD.png
  • edited August 2013
    Oh. You don't want that.

    Those files might contain multiple sprites per frame which I'm not supporting yet, but it shouldn't crash. And should produce something at least. I'll try the samples and get it fixed.

    (Update)
    Found a number of problems. I'll get these sorted out. Looks like I'll have to build in multiple sprite support. Not too comfortable with this side yet as I only use single sprites. Nevermind.
  • edited August 2013
    Gosh, Jim, you've been working me. I've reworked a lot of the code to accept multiple animations per spritesheet.

    But... it still won't convert the "heavyducker" sample because it contains multiple sprites per cell which I am not sure we can format for an INI? Not sure how to deal with that but it certainly caters for enough for now.

    Download file has been moved to the original post at the top.

    Ok better get back the game code.
  • jimjim
    edited August 2013
    I am not sure I fully understand multiple sprites per cell, but can't we think our object with multiple child and each child has their own animation. So, here each child would have a single sprite with animation of its own.

    Let's consider, our character is composed of 1 head, 1 torso, 2 hands and 2 legs. So, our character object would have,
    [Object]
    ChildList = Head # Torso # Hands # Legs
    
    [Head]
    ;separate animaation for Head
    AnimationList = Walk # Jump # Run ; animation list for head
    [Torso]
    ; separate animation list for torso
    [Hands]
    ; Hands would have two child, Left/Right which will be responsible for their own animation list
    [Legs]
    ;just like Hands
    

    Still I am not sure if its gonna work, its still in theory.
  • edited August 2013
    Looks like you've got the idea because this is exactly what it's about.

    In darkFunction's anim editor, you drop a sprite into a cell. Then move to the next cell and drop another sprite into that cell.

    In this way you make up an animation.

    However... you don't have to drop just a single sprite into a cell, you can drop several into that one cell. That just blows my mind. I can't see myself using animations that complex.

    But as you hint at, these are basically composite sprites making up one object.

    I'd be interested to see if iarwain thinks your config is valid or not when he gets himself back online properly.
  • edited August 2013
    jim wrote:
    In the image, with cropped version, Bottom Left is (0,0), Center (75,100),Top Right is (150,200). And when I want offset into account, Bottom Left is (-100,-100), Center (175,200) and Top Right (250,300) considering original image size to be (350,400).
    Actually Top Left is (0, 0), Bottom Left, in your case, would be (0, 200).
    But again the problem is when I use actual value of (0,0) as pivot, its value should actually be (-100,-100) as I am referring to the original non cropped image. When I set pivot to (350,400) its actual value should be (250,300).

    It looks like, one has to subtract the offset manually which is (-100,-100) from whatever value is present in the pivot, to make it transparent to the user.
    You have to subtract the exact same offset you would give otherwise. Instead of having two variables, there's only one.

    Think of the pivot as being the application point of your graphic onto the world.
    In the case of an explosion, you probably want to use a pivot that points to the epicentre of your explosion. If you explosion is round, the epicentre is probably in its middle.
    For example, I told my artist to make me an explosion animation of size 256x256 each frame, he made me a sprite sheet with cropping. Now, each image size is different, and I don't need to know their individual size. All I know is their size is same which is 256x256, then I set their pivot to Bottom Left or set it to (0,0) hoping that there would be no problem. But when I play the animation, its not right, because pivot is set to (0,0) for cropped image which has different size hence their pivot is same but they are drawn in different position. Would not it be logical, when I set pivot to (0,0) it would take offset into account and makes its value according to offset for each frame.

    Having a pivot at (0, 0) (Top Left, not Bottom Left) only makes sense if that's the position you want to use when "overlaying" your graphic on the world. I feel like all this would be much clearer with a drawing than long sentences. :)
    Also, when I ask for sprite size what would it return ? it would return different value, but I was expecting their size to be 256x256.
    Well, it's you who define the size of the graphic, so it'll give you that same exact size. :) If you need to store an alternate size that doesn't vary when the actual size changes, you can use the config system with whichever key you want, something like RealSize = (256, 256, 0) that you could then retrieve at runtime using the orxConfig_* API.
    I hope you guys can understand what I am talking about :)
    I think I do, at least a bit, however I don't see where there's a problem at all. If you crop a graphic, you should then update the pivot with the cropping, that's about it.
    If you don't want to subtract manually, you can always create an Offset config variable, and then, in code at init, apply those Offset to the Pivot values. That would probably take ~10 lines of code and give you any flexibility you'd want.

    Let me know if I missed your point. :)
  • edited August 2013
    Silly me. I have a mistake in the converter. I forgot that KeyData animation lines have to start from 1, not 0:

    http://orx-project.org/wiki/en/orx/config/settings_structure/orxanim

    This is why my single frame animations were not playing, and others seemed to give a warning.

    Will fix shortly. Also need to add duration time support.
  • jimjim
    edited August 2013
    Was out for vacation :) Okay, now I got it all about pivot.
    I think you have missed my config demonstration on multiple sprite animation for a single object. Is it possible to have multiple animation for single object, consider all of them have same number of frame and time interval ?
  • edited August 2013
    I got that ok. But like you said, is it valid orx config?

    If it is, perhaps I can complete the functionality by allowing it the converter.

    Right now it just does enough that I need + a little more.
  • edited August 2013
    sausage wrote:
    I got that ok. But like you said, is it valid orx config?
    Well I have to admit I'm not sure I fully understand that part! :)
  • jimjim
    edited August 2013
    But I think if we can assign multiple animation on a single object, and somehow play them simultaneously, then we can implement darkfunction animation into ORX. Iarwain can you assure, we can play multiple animation on a single object or can I have an object which have multiple child and they have animation of their own ?
  • edited August 2013
    There can only be one animation at one time on a single object.
    However you can have children with their own animation.
  • jimjim
    edited August 2013
    Yeah, actually I was talking about child, as you can see, in the config, I made Head,Torso,Legs,Hands child of object.
    So, child of child can also have animations ? This way it would be very easy to simulate darkFunction animation system, which is kind of close to skeletal animation.
  • edited August 2013
    Yes, that can be done. However, in order to simulate skeletal animation you'll currently need to combine traditional animation and orxFXs.
  • jimjim
    edited October 2013
    I gave some more thought on multi-sprite animation in DarkFunction, I tried to do it from config. I was kind of right about the way I wanted to go but now I see I hit a dead end. Its still possible to do but using only config is not possible. So here is what I did, it does not do much, head just go up and down but I shows what I was talking about. In config
    [StickMan]
    ChildList = Head # Torso # LeftLeg # RightLeg
    Position = (100,100,0)
    
    [Head]
    Graphic = HeadG
    AnimationSet = HeadAnimSet
    Position = (50,-200,0)
    
    [HeadG]
    Texture = ../data/anim/head.png
    
    [HeadAnimSet]
    AnimationList = HeadIdle # HeadJump
    LinkList = HeadIdleLoop # HeadIdle2Jump #  HeadJump2Idle  # HeadJumpLoop    
    
    [HeadJumpLoop]
    Source = HeadJump
    Destination = HeadJump
    
    [HeadIdleLoop]
    Source = HeadIdle
    Destination = HeadIdle
    
    [HeadJump2Idle]
    Source = HeadJump
    Destination = HeadIdle
    
    [HeadIdle2Jump]
    Source = HeadIdle
    Destination = HeadJump
    
    [HeadJump]
    DefaultKeyDuration = .5
    KeyData1 = HeadJumpAnim1
    KeyData2 = HeadJumpAnim2
    
    [HeadIdle]
    DefaultKeyDuration = .5
    KeyData1 = HeadIdleAnim1
    
    [HeadJumpAnim1 @ HeadG]
    Pivot = (0,20,0)
    
    [HeadJumpAnim2 @ HeadG]
    Pivot = (0,0,0)
    
    [HeadIdleAnim1 @ HeadG]
    Pivot = (0,0,0)
    
    ; others are defined as same way
    
    Then in code
    // get objects from object event create then set animation as 
    orxObject_SetTargetAnim(head,"HeadJump");
    orxObject_SetTargetAnim(head,"TorsoJump");
    orxObject_SetTargetAnim(leftLeg,"LeftLegJump");
    orxObject_SetTargetAnim(rightLeg,"RightLegJump");
    
    It was all good now, but when I tried to apply Rotation on key frame it does not work, as I can see we can only define Pivot and Flip for "Graphics" but not Rotation.
    As we can define Angle in DarkFunction, without rotation it is not possible to make a complete darkfuntion anim importer. Though we can apply Rotation from code, using KeyEventValue as Rotation, I have to look more into it.

    One more thing, is there any gotcha the way I defined my animation for multi-sprite or there could be a better way to achieve this type of animation?
  • edited October 2013
    Jim, you and I scarily follow similar developments paths, and every time I look for a concept I am working on, I find your posts :)

    It seems I do need a multi-sprite support, as my head and arm of my character will be separate from the rest of the body.

    So I'll be looking very closely at the converter to support this.

    But I don't intend for orx to handle the two parts for me... I'll have twin configs for all the animation and links: one for body and one for arm & head.

    Then I'll ensure in my code that the two objects stay together or make one object a child of the other. Cross that bridge when I come to it.
  • jimjim
    edited October 2013
    Yep, I will be going this way too, one thing I did not mention is, the example animation in DarkFuntion editor is a mess, its way too complicated to handle manually, there each frame consist of around 30 individual sprite, which is insane.

    So, in my implementation I would be using fixed and less amount of sprites. It would be really a cool addition to orx, because I have not seen this type of animation often, of course it is different than skeletal, it is still frame based animation.

    If DarkFunction does not work, I might make an animation tool like DF but with some features that I wanted, as I was talking to a java guy who is a friend of mine.
  • edited October 2013
    I'll certainly be able to take in two or more layers of animations, but I'll be splitting them up into their own animation sets.

    Perhaps with some autonaming... though maybe I should be more strict that the naming largely coming from how things are configured in darkFunction. I dunno.

    I'll have to take a look again how I went about it.

    There's some messy recursive code in there which I don't like.

    Once I get my anim calculation stuff done, I'll get back onto this. Hopefully next week.
  • jimjim
    edited November 2013
    Bump, I wanted iarwain to see the code I posted earlier, is it okay to manage multi-sprite animation this way ?
    Only thing I had to do manually is, rotation per frame, which I have to set from code not a big deal though.

    I think when, animation channel would be available it would take orx animation to a new level. I am not clear about features of animation channel but I think it would be possible to add FX or transform (rotation, scale ) per frame or per key.
  • edited November 2013
    Yes, it looks fine to me! :)

    And yes you're right about animations channel. It's the first step for skeletal animation to separate keys into different channels (sprite, transforms, events, ...).
  • edited May 2016
    V1.05 added. This version finally supports multiple layers of animation. Each layer becomes an ANIM config section of its own.

    I've changed the interface as well. Now, you browse for the anim, file rather than the sprite file. The sprite file is determined from the anim file, checked for existence and autoloaded.

    Instructions on the wiki will be updated shortly.

    darkfunction_converter_screenshot105.png

    See first post for updated version.
  • jimjim
    edited November 2013
    Oh, great :) Gonna check it tomorrow. Btw how did you handle sprite angle ? I mean where did you store angle data in config ?
  • edited November 2013
    No I haven't supported angle. Hmmmm.....

    Because each sprite frame in darkFunction can have an angle, ie, the angle can be animated, the closest we could have in orx is a custom EventName/Value pair.

    So perhaps we could have:

    KeyEventName1 = Angle
    KeyEventValue1 = 13
    KeyEventName2 = Angle
    KeyEventValue2 = 45

    This would be quite possible and then the rotation in degrees would have to be handled and rotated with your own code.
  • edited May 2016
    New version 1.9 has been released. I realised that I had never allowed the standalone conversion of a spritesheet.

    Before now, an animation had to be defined as well.

    DarkFunctionToOrx19.png

    https://forum.orx-project.org/uploads/legacy/fbfiles/files/DarkFunctionToOrx19.zip
Sign In or Register to comment.