2D Toolkit Forum

2D Toolkit => Support => Topic started by: bitsofbas on May 07, 2013, 05:33:27 pm

Title: Import from TexturePacker spritesheet
Post by: bitsofbas on May 07, 2013, 05:33:27 pm
Hi!

Just started Unity and 2dtk a couple of days ago, so please be gentle :-)

I've got a sprite sheet created in TexturePacker ( which reads animations created in flash and also filters identical frames and more goodness ) so I wanted to use this sprite sheet with 2dtk, but I can only find info on doing this at runtime. As the sheet contains a whole bunch of animations, I'd prefer importing this sheet straight into the editor so I can set up my animations.

How can I do this ( if possible at all )?

Cheers,
bas
Title: Re: Import from TexturePacker spritesheet
Post by: unikronsoftware on May 07, 2013, 09:41:07 pm
It isn't possible directly, but, it is possible to write a bit of editor script to do it.
1. Import the texturepacker atlas and create a sprite collection data object as you would at runtime.
2. Create a prefab in the project and assign the object to it.
3. Important: Save the assigned material as an asset in the project.
4. Rebuild the index.

You'll obviously be responsible in updating it when the texture packer atlas changes, etc. but apart from that it should work fine.
Title: Re: Import from TexturePacker spritesheet
Post by: bitsofbas on May 08, 2013, 09:40:48 am
I'm afraid this is a little over my head at this stage. Just starting out with Unity and 2dtk and I haven't quite yet touched editor scripting.

Going to give it a shot though because I would really like this to work. It would be great if you could give me some more details on how to do this, but obviously I completely understand if you don't :-)

Thanks!
Title: Re: Import from TexturePacker spritesheet
Post by: bitsofbas on May 08, 2013, 04:56:23 pm
Man, I learned a LOT today! I think I've managed to follow your ( in my eyes, cryptic ;-) steps and I think I actually made something which works. Unity really is a joy to work with :-)

Just in case someone is looking to do the same, I'm attaching the .cs

Instructions:
* DISCLAMER: USE AT YOUR OWN RISK. This is one of the first things I ever wrote in Unity, so it wouldn't hurt to have a look at the script and make sure for yourself it's safe to use.
* Add the .cs to a folder named Editor
* Create your .png and .bytes files in TexturePacker. They should both have the same name
* Select from within Unity the png atlas file(s)
* From the menu: 2D Toolkit/Make TexturePacker Sprite Collection

Now you'll find a new Material and the Sprite Collection in the same folder.


One question though, I did this:

Code: [Select]
tk2dRuntime.SpriteCollectionSize scs = tk2dRuntime.SpriteCollectionSize.Explicit( 1, 640 );
But I'm not sure those are the best values to use. Any suggestions?


edit: Updated version. Don't use the previous one!
Title: Re: Import from TexturePacker spritesheet
Post by: unikronsoftware on May 08, 2013, 05:06:52 pm
Well done for getting it to work so quickly :)
I hadn't got around to replying to this but you've managed to sort it out.

The sprite collection size - use the ortho size for the camera you'll be using this in (this selection is pretty arbitrary, but 10-20 works best with built in Unity physics out of the box). For the height, use the height of the native resolution of the game - so if its iPhone4 landscape, use 640.

Hope that helps.
Title: Re: Import from TexturePacker spritesheet
Post by: bitsofbas on May 08, 2013, 05:25:48 pm
Is that "native resolution" a value I can get from somewhere? Or do I just put a static value in?

Thanks for your help!
Title: Re: Import from TexturePacker spritesheet
Post by: unikronsoftware on May 08, 2013, 05:46:23 pm
The native resolution is what resolution you're planning to have your game run at. Eg. if you're creating your game for iPhone4 in landscape, the native resolution would be 960x640.
Title: Re: Import from TexturePacker spritesheet
Post by: bitsofbas on May 09, 2013, 02:59:45 pm
Ok, got it. Sizing to fit screen etc is probably more basic-Unity related, so I'll just read up on that on my own.

Another question I'd like to ask... To run as little textures as possible, my bitmap font is also in the TexturePacker atlas. You think it's possible to hook that into your font classes somehow? Can you give me a hint about where to start ( if at all ) ?

Cheers,
bas
Title: Re: Import from TexturePacker spritesheet
Post by: unikronsoftware on May 09, 2013, 03:14:55 pm
That will be a bit harder - by the time its in texture packer you've already lost all the rest of the information required for the font... Not impossible though.
You need to generate a tk2dFontData object.
For every character you'll need a tk2dFontChar.
p0 and p1 are the geometry extrema. uv0 and uv1 corresponding UV values.
advance can be p1.x - p0.x to advance by exactly the same size as the character, but you might want a bit of "spacing".
You can ignore "channel" and "gradientUv" and possibly kerning.

At the moment the font code can't handle Texture Packer rotated textures but if you can get all the non-rotated glyphs to work, adding support for that won't be too much work.
Title: Re: Import from TexturePacker spritesheet
Post by: bitsofbas on May 09, 2013, 03:24:14 pm
by the time its in texture packer you've already lost all the rest of the information required for the font...
I still have my bmfont xml though and the fonts are not fragmented in TexturePacker ( which is not optimal, but probably more comfortable to keep things together ) so just by knowing my font-area offset in the atlas, I can track all the characters.

Like last time, I don't immediately understand what you mean, but I'm sure it will start making sense as I start investigating.

Thanks again!
Title: Re: Import from TexturePacker spritesheet
Post by: unikronsoftware on May 09, 2013, 03:59:27 pm
If you've got your BMFont XML it should be a lot simpler, also the font not being fragmented makes it so much easier. I was explaining assuming you were going to reconstruct glyphs from the little fragments in the atlas.

In this case, take a look at the tk2dFontBuilder.cs class - that imports the bmfont and but assumes it uses the full texture. You need to do almost all of that, skipping the material (use the same material as the sprite collection you have created) and for the final UVs, you want to scale and offset it to match the region of the atlas your font texture is in.
Title: Re: Import from TexturePacker spritesheet
Post by: bitsofbas on May 10, 2013, 04:34:29 pm
The font thing doesn't look too complicated, so I'll just assume it can be done and delay the actual coding until my game really needs it.

In the meantime a more pressing matter has surged; I'm experiencing disastrous side effects on my SpriteAnimation when using my script from the beginning of this thread. -- The problem seems to be that upon updating the SpriteCollectionData, my animation clips sometimes get orphaned from their Collection ( and just opening a clip makes the whole animation editor crash, so I can't fix the broken clips and have to start from scratch with all the animations ).

Can it be that when running my script twice and overwriting a previous SpriteCollectionData, I should copy a certain unique identifier value from the old to the new one? If so, which variable would that be?

Thanks again!
Title: Re: Import from TexturePacker spritesheet
Post by: unikronsoftware on May 10, 2013, 06:00:37 pm
If you run your script again, it will create a new prefab every time. Instead of doing that, you should check to see if the prefab exists, and ReplacePrefab if it already exists.

Creating a new prefab will kill all existing connections to it, as far as Unity is concerned they are completely different assets.
Title: Re: Import from TexturePacker spritesheet
Post by: bitsofbas on May 10, 2013, 06:31:50 pm
Awesome! Thanks! I'll update the script tomorrow for those who downloaded it.
Title: Re: Import from TexturePacker spritesheet
Post by: bitsofbas on May 11, 2013, 02:54:07 pm
So I've changed some things to get the prefab replaced instead of newly created. Truth is, I don't notice much of a difference.

What worries me is that after replacing the Sprite Collection Prefab, upon opening the Animation editor and adding a new clip, the default Collection is set to "-" ( the dropdown can be changed to the real Collection though ). This is the same behaviour I got before changing the Prefab replacing/overwriting code.

The "-" seems to be the name for a "transient sprite collection", as you call it in your code @ tk2dSpriteGuiUtility.cs line 231. - I'm not sure if this is just an insignificant remainder of instantiating a SpriteCollection by code, or if it could be responsible for losing my animations the other day.

Thanks, and sorry to keep bugging you with this.
Title: Re: Import from TexturePacker spritesheet
Post by: unikronsoftware on May 11, 2013, 03:26:15 pm
I can't remember off hand how you replace the contents of a prefab without breaking the connection, but... you can work around this quite nicely by simply loading the prefab in, replacing the contents manually, and then SetDirty & commit.

Code: [Select]
if (System.IO.File.Exists(prefabPath)) {
tk2dSpriteCollectionData prefabObject = AssetDatabase.LoadAssetAtPath(prefabPath, typeof(tk2dSpriteCollectionData)) as tk2dSpriteCollectionData;

prefabObject.spriteDefinitions = scd.spriteDefinitions;
prefabObject.materials = scd.materials;
prefabObject.spriteCollectionName = scd.spriteCollectionName;

EditorUtility.SetDirty(prefabObject);
AssetDatabase.SaveAssets();
}

Don't forget that you want to handle the material in the same way, i.e. don't keep overwriting it but rather if it exists, load it in, fix up, setdirty.
Title: Re: Import from TexturePacker spritesheet
Post by: bitsofbas on May 11, 2013, 07:12:21 pm
Yup, much better now! I've updated the file from a couple of posts back.

Thanks!
Title: Re: Import from TexturePacker spritesheet
Post by: bitsofbas on May 12, 2013, 02:30:29 pm
Oh noes! I thought everything was working just fine now, but I'm still getting errors when changing my TexturePacker atlas.

Most of the animations keep working, but their sprites have been changed. Others simply crash with this error:

Code: [Select]
IndexOutOfRangeException: Array index is out of range.
tk2dEditor.SpriteAnimationEditor.TimelineEditor.DrawFrameGroupEx (Rect r, .tk2dSpriteAnimationClip clip, tk2dEditor.SpriteAnimationEditor.FrameGroup fg, Boolean highlighted, Boolean showTime, Boolean playHighlight) (at Assets/TK2DROOT/tk2d/Editor/Sprites/SpriteAnimationEditor/tk2dSpriteAnimationClipTimelineEditor.cs:525)
tk2dEditor.SpriteAnimationEditor.TimelineEditor.DrawFrameGroups (Int32 controlId, Rect frameGroupRect, .tk2dSpriteAnimationClip clip, System.Collections.Generic.List`1 frameGroups, Single clipTimeMarker) (at Assets/TK2DROOT/tk2d/Editor/Sprites/SpriteAnimationEditor/tk2dSpriteAnimationClipTimelineEditor.cs:211)
tk2dEditor.SpriteAnimationEditor.TimelineEditor.Draw (Int32 windowWidth, .tk2dSpriteAnimationClip clip, System.Collections.Generic.List`1 frameGroups, Single clipTimeMarker) (at Assets/TK2DROOT/tk2d/Editor/Sprites/SpriteAnimationEditor/tk2dSpriteAnimationClipTimelineEditor.cs:158)
tk2dEditor.SpriteAnimationEditor.ClipEditor.Draw (Int32 windowWidth) (at Assets/TK2DROOT/tk2d/Editor/Sprites/SpriteAnimationEditor/tk2dSpriteAnimationClipEditor.cs:564)
tk2dSpriteAnimationEditorPopup.OnGUI () (at Assets/TK2DROOT/tk2d/Editor/Sprites/SpriteAnimationEditor/tk2dSpriteAnimationEditorPopup.cs:480)
System.Reflection.MonoMethod.Invoke (System.Object obj, BindingFlags invokeAttr, System.Reflection.Binder binder, System.Object[] parameters, System.Globalization.CultureInfo culture) (at /Applications/buildAgent/work/b59ae78cff80e584/mcs/class/corlib/System.Reflection/MonoMethod.cs:222)

The changed atlas sprites are not part of any animation, but they obviously do change the order of the sprite atlas data ( looks like TexturePacker exports the sprites alphabetically, so adding a new sprite starting with "a" changes the positions of all other sprites ) It's as if the animation is keeping track of the sprites by sequential index instead of by name. If that makes sense.

Any ideas what could be happening here? Or what to do about it?

( Worst case scenario, I could use an additional file describing the contents of each animation and use that to build the Animation object from scratch every time I have to refresh. Skipping your Animation editor. )
Title: Re: Import from TexturePacker spritesheet
Post by: unikronsoftware on May 12, 2013, 03:08:17 pm
2D Toolkit internally maintains indices for sprites. So, instead of referring to sprites by name, it refers to them by sprite collection - index. Works fine internally as we have full control over it but in your case, texture packer is reordering everything as it sorts stuff by name.

An easy solution to this, assuming you're already doing that replace prefab contents thing I suggested before -
Instead of replacing the spriteDefinitions array directly, fix it up by using name. So lets say you have A (old) and B (new).
1. Foreach B, find one with the same name in A, overwrite the index in A. (i.e. spritecollection.spriteDefinitions[indexA] = newColl.spriteDefinitions[indexB];
2. Foreach B, find ones which have been deleted in A, and clear them, setting name = ""; (that is sufficient).
3. Foreach B which doesn't exist in A, find an empty slot (name = ""), or insert a new one to the end of the list.

Keep the indicies constant, and everything should work correctly. You shouldn't need to fix up animations, but rather as I explained, keep the indicies intact.
Title: Re: Import from TexturePacker spritesheet
Post by: Finnegan on May 19, 2013, 08:45:21 pm
Hi!

I'm moving to Unity and 2D Toolkit from cocos2d-iPhone, so I have a TexturePacker license.

Will the use of textures increase performance of my games? Or should I just import individual sprites?

Thanks!
Title: Re: Import from TexturePacker spritesheet
Post by: unikronsoftware on May 19, 2013, 08:54:57 pm
You can import individual sprites if you want, that is no problem at all - 2D Toolkit will atlas your sprites. Importing texturepacker atlases in as assets, as opposed to at runtime, isn't officially supported at the moment.
Title: Re: Import from TexturePacker spritesheet
Post by: pxlweaver on May 27, 2013, 06:56:00 pm
Bitsofbas' script works great - the only thing I'm stuck on is trying to see if I can generate colliders for a Texture Packer atlas. Any ideas?
Title: Re: Import from TexturePacker spritesheet
Post by: unikronsoftware on May 27, 2013, 06:57:37 pm
You'll have to create them manually, its not supported at this point. The current sprite collection editor doesn't support editing data on already laid out atlases. Its planned for a future update, together with some more advanced atlasing schemes, but its not as high priority as other features.