Starling-Framework
Starling-Framework copied to clipboard
Loading bitmap font texture from texture atlas
Not sure if this is the expected behavior, but I sure wasn't expecting it to work this way :)
I have a bitmap font texture inside texture atlas named "board/font/digits" and an xml file "digits.fnt", where I changed the file name to match my texture path inside texture atlas (so it's "board/font/digits" as well). However, when I try to load the xml file using AssetManager, I get an error because it it tries to load "digits" texture instead of the full name I wanted it to use. The magic is happening here:
protected function getName(rawAsset:Object):String
{
/* ... */
if (name)
{
name = name.replace(/%20/g, " "); // URLs use '%20' for spaces
name = getBasenameFromUrl(name);
if (name) return name;
else throw new ArgumentError("Could not extract name from String '" + rawAsset + "'");
}
/* ... */
}
Not sure why this is processed using getBasenameFromUrl()
, hopefully it is a bug :)
Also, even if AssetManager fails when loading this font, I'd still like to be able to access the XML file it loaded, but it looks like I can't (even when keepFontXmls
is set to true
).
PS This was just asked in the forums 4 days ago: http://forum.starling-framework.org/topic/merging-font-atlases-and-assetmanager-issue
Oh, didn't see that one. Thanks, Jeff.
No problem, just wanted to link this for Daniel so he can get a wider context for what people either expect or don't expect from the AssetManager naming requirements.
Thanks a lot for the report, to both of you!
Hm ... this is a little tricky, because it's hard to know what users would expect to be used as a texture name.
Yes, you've got the relative path in your atlas, but developers might just as well not have the full path in there, but just the name. And the font xml might contain a "file" attribute that contains just the filename (because image file and XML typically lie in the same folder), or a full / relative path.
The reason I made the "file" part go through the "getName" method is that this string typically contains a path (i.e. it will contain at least a file extension). The atlas "name", on the other hand, is exactly what it claims to be: a name. So it's not processed that in any way.
So, if I now simply change that (i.e. remove the "getName" call and remove just the file extension instead), it would work for you (and dsirijus), but it would fail for many other developers.
An easy fix on your side would be to override "getName" and make it handle paths in a different way, e.g. if you detect that you received a string that contains "/font/".
I can't think of anything I could do inside the AssetManager to make this work — but I'm open to suggestions, of course! :smile:
My suggestion is extending the BitmapFont format a bit, so there's a separate attribute which would contain a full atlas path. Then everybody could add this attribute to their files and voila :)
Another thing could be adding a property to AssetManager like processTextureFontPath
set to true
by default, so the current behavior would not change, but it could be changed if the user wanted it to.
My suggestion is extending the BitmapFont format a bit, so there's a separate attribute which would contain a full atlas path. Then everybody could add this attribute to their files and voila :)
A good idea, but would that really help that much? As long as the bitmap font tools (Glyph Designer etc.) don't support this, developers would still have to edit the xml file manually, so you haven't gained much.
If anything, I'd need to add a property "name" where you can add a name that is then used without processing it further. If that's found, it would take precedence over "file". That way, all old font files would be processed just like before.
Another thing could be adding a property to AssetManager like processTextureFontPath set to true by default, so the current behavior would not change, but it could be changed if the user wanted it to.
I don't like that idea very much. If I start adding properties for such small nuances the API will quickly become confusing and bloated.
Another idea: I could check if the file property ends with a file suffix (e.g. ".xml"). If it doesn't, it's very likely that it's not a path, but a name, and I could treat it as such.
But, again, you'd have to edit the XML manually. We probably can't get around that without support from the bitmap font tools. So it's either the suffix-check or the new name property. I'm leaning towards the latter, actually!
<page id="0" file="font/digits.png" name="font/digits" />
Another idea: I could check if the file property ends with a file suffix (e.g. ".xml"). If it doesn't, it's very likely that it's not a path, but a name, and I could treat it as such.
But, again, you'd have to edit the XML manually. We probably can't get around that without support from the bitmap font tools. So it's either the suffix-check or the new name property. I'm leaning towards the latter, actually!
I don't have problem with editing the file, so both methods work for me :) I'd just suggest to change the parameter's name (if you choose to go this way) to something related to texture atlas, so it would be more obvious what this is for (e.g. textureAtlasPath
).
I'd vote for not having to manually edit the .fnt file. Sure, I can do it, but I can't add it into a scripted build process. Sticking to the format if possible sounds good to me...
How would you do it then? Is there an editor which supports such things? I can't really see a way of doing this without having to edit the file.
Just for the record, I managed to work around this by creating a script which merges different texture atlases into one meta-atlas, where one of the sub-atlases holds my fonts with the paths unaltered, so AssetManager's way of parsing fonts works without changing anything (so I can use bitmap font tools without having to edit the files manually).
Probably this issue still deserves a though once you start working on Starling 2.0, but as for now - I'm good with how it works at the moment.
That's a smart way of doing it, great idea! But yes, I'll keep this in mind. Right now, I'm leaning toward adding that "name" attribute.