So I can load the skin in my assetManager like this:
manager.load(skinAtlas, TextureAtlas.class);
manager.load(menuSkin, Skin.class, new SkinLoader.SkinParameter(skinAtlas));
But if I want to add .ttf fonts at runtime how will I do this? i.e:
skin = new Skin();
skin.add("smallFont", smallFontT, BitmapFont.class);
skin.load(assetManager.getManager().get(assetManager.menuSkin, Skin.class)); //this does not work
If your Json styles don't rely on that particular font, you can add it to an existing skin at any time after you get the Skin object reference from the asset manager after the Skin has been loaded. Use skin.add("smallFont", smallFontT) to add your font to the existing skin.
You can also specify other objects to add to the skin before the JSON file, so the JSON file can rely on them. But to do this with AssetManager, those assets must be loaded before the AssetManager loads the JSON file to a Skin.
So you could first load those assets directly without an AssetManager, or you could load them using the AssetManager (add them to the manager and finishLoading on the manager before adding the skin to the manager). Either way, you need to get a reference to each of the assets your JSON will need to reference.
Then put them in an ObjectMap. For example:
ObjectMap<String, Object> resources = new ObjectMap<String, Object>();
resources.put("smallFont", smallFontT); //assuming smallFontT is a reference to a BitmapFont object
Then these resources can be put into your SkinParameter:
manager.load(skinAtlas, TextureAtlas.class); //I'm assuming skinAtlas is a String path to your atlas
manager.load(menuSkin, Skin.class, new SkinLoader.SkinParameter(skinAtlas, resources));
Now styles in your JSON can reference a font by the name "smallFont".
Related
I use different fonts for different screens. some of the fonts are only few letters, so it would be inefficient to generate an atlas for each font.So is there a way to make all of my fonts use a single Atlas?
You can use a constructor that takes a TextureRegion. For example, if your font and image were named myFont.fnt and myFont.png, you can put myFont.png in with the rest of your sprite source images and pack it into the texture atlas. Put the .fnt files in with the rest of your assets. Then after loading the texture atlas:
myFont = new BitmapFont(Gdx.files.internal("myFont.fnt"), myTextureAtlas.findRegion("myFont"));
To use it in a Skin, you'll want to add it to a Skin before loading the Json file:
skin = new Skin(); // instantiate blank skin
skin.add(myFont, "myFont");
skin.load(Gdx.files.internal("mySkin.json"));
The Json file can reference the font by the name you use when adding it to the skin.
Although, I'd highly advise using AssetManager for everything. In this case, your skin Json could define the font normally. The only extra step you need beyond loading everything to the asset manager the usual way would be to add a BitmapFontLoader.BitmapFontParameter that specifies the TextureAtlas that contains the region. The AssetManager will use this to determine that the BitmapFont is dependent on the atlas, so it will load them in the correct order.
BitmapFontLoader.BitmapFontParameter fontParam = new BitmapFontLoader.BitmapFontParameter(){{
atlasName = "mySkin.pack";
}};
assetManager.load("myFont.fnt", BitmapFont.class, fontParam);
The atlas should be the same one the skin uses.
I can load a Bitmap Font just fine with the following code:
BitmapFont font= new BitmapFont(
Gdx.files.internal( "Fonts/MyFont.fnt" ),
Gdx.files.internal( "Fonts/MyFont.png" ),
false );
but I'm trying to implement the AssetManager instead. So I recoded that snippet with the following code:
AssetManager assetManager = new AssetManager();
assetManager.load( "Fonts/MyFont.fnt", BitmapFont.class );
assetManager.load( "Fonts/MyFont.png", Texture.class );
assetManager.finishLoading();
BitmapFont font = assetManager.get( "Fonts/MyFont.fnt" );
If failed of course. The the call to the finishLoading() method returned a message indicating:
Couldn't load dependencies of asset: "Fonts/MyFont.fnt"
Ok. that makes sense, because I didn't do anything with the texture. So how do I pass the texture file as dependency? github.com/libgdx/libgdx/wiki/Managing-your-assets says:
BitmapFontLoader is a good example of an asynchronous loader that also
has dependencies that need to be loaded before the actual asset can be
loaded (in that case it's the texture storing the glyphs). Again, you
can do pretty much anything with this.
Well Duh! I guess they assume, "... if you only knew how!" But, their example doesn't show how - as a matter of fact their example shows pretty much what I've written. So, I'm stumped. All Google seems to be able to find are examples of what to do with TTF fonts, but nothing for regular old Bitmap Fonts.
Does anyone have an example of the solution to this error. Thanks a million!
When you use the AssetManager to load a BitmapFont is uses the BitmapFontLoader class. In the Libgdx api docs is says (api)
AssetLoader for BitmapFont instances. Loads the font description file (.fnt) asynchronously, loads the Texture containing the glyphs as a dependency.
The glyphs texture is automatically loaded as a dependency of the font. However, to know which file to load as the texture it checks in the .fnt file for the location of the texture.
I suspect that the reason that the font loaded successfully without using the AssetManager was because you manually added the Texture of the font as a parameter.
BitmapFont font= new BitmapFont(
Gdx.files.internal( "Fonts/MyFont.fnt" ),
Gdx.files.internal( "Fonts/MyFont.png" ), // This lets it know what texture to use
false );
When you used the AssetManager on the other hand it could not find/load the texture dependency. To fix this, open the .fnt file and make sure that the file="something.png" points to your fonts texture glyphs. (It must be the same as the name of the png. In your case file="MyFont.png")
That hopefully will solve your problem.
My tried and tested code:
AssetManager manager = new AssetManager();
manager.load("fonts/MyFont.fnt", BitmapFont.class);
manager.finishLoading();
font = manager.get("fonts/MyFont.fnt", BitmapFont.class);
An extract of the MyFont.fnt file:
info face=font size=54 bold=0 italic=0 charset= unicode= stretchH=100 smooth=1
aa=1 padding=2,2,2,2 spacing=0,0 outline=0 common lineHeight=50 base=43 scaleW=243
scaleH=511 pages=1 packed=0
page id=0 file="MyFont.png" <-- The important part
Hopefully that will solve your problem!
Also please note, as I was testing out the AssetManager I noticed that it only loaded when the .fnt was in basic text. When I tried use a .fnt file which used tags (like html) the texture failed to load. I used littera to generate the bitmap font I used for my test.
I have a project where I load an external file with asset symbols (assets.swf) into the main swf and then add the symbols to the display when needed. I want the classes associated with each symbol to be linked to a custom class at runtime in the document class. I'd really like to avoid defining the custom classes in the assets fla through the symbol properties.
In AS2, this was possible with Object.registerClass as below:
Object.registerClass("assetID",AssetClass);
this.attachMovie("assetID", "asset_mc", 0);
So the symbol was independent of the class it is linked to at runtime.
In AS3, I'm seeing references to registerClassAlias but there is very little reliable documentation of it available online.
Does anyone know of a way of doing what I'd like to do with registerClassAlias or any other way?
thanks!!!
matt
First, you need to load your asset symbol and keep a reference to the loader.
assetsLoader.load(new URLRequest("assets.swf"));
When the loading is done you can retrieve your assets within the loaded SWF ApplicationDomain.
var assetClass:Class = assetsLoader.contentLoaderInfo.applicationDomain.getDefinition("MyAssetClass") as Class;
var asset:* = new assetClass();
Note: MyAssetClass should be defined inside assets.swf!
If you want further informations, you can read this article.
I have external swf (ext.swf) that is loaded in my FlashDevelop as3 project.
When I make check (objectsList[0] is Class1) I am getting false even though
the objectsList[0] element is Class1. The Class1 is in the ext.swf
But when I write command like (objectListInExternalSwf[0] is Class1) in external
swf and then use that swf in my project and make check (objectsList[0] is Class1)
I get true.
My question is: do I have to use all the classes in my external swf so the compiler
have to put them in the swf so they can be used in other projects where the swf is loaded as external?
By default, when you load an SWF, its content will be placed into a separate ApplicationDomain. So even if you have the same class, Flash will consider it as different.
To share the same class definition, you have to be in the same ApplicationDomain (or inherit from the same) :
var l : Loader = new Loader;
l.load( new URLRequest("foo.swf"),
new LoaderContext(false, new ApplicationDomain(ApplicationDomain.currentDomain));
I'm doing a Flex 3 project wherein I've to load SWF based on the availability of required file. And the loaded SWF file will be placed in a container (a Panel) at a particular location i.e. coordinates. This I don't want to do in MXML as the SWFLoader container shows a cross marked box if the file is unavailable.
So friends is there any solution?
Create a new URLRequest object with the url of the file.
Create a new Loader object.
Call the Loader object's load() method, passing the URLRequest instance as a parameter.
Call the addChild() method on a display object container (such as the main timeline of a Flash document) to add the Loader instance to the display list.
Source: Loading an external SWF file.