TmxMapLoader to use packed tileset - libgdx

In the old libgdx map api, they used to have
map = TiledLoader.createMap(Gdx.files.internal("maps/testmap.tmx"));
atlas = new TileAtlas(map, Gdx.files.internal("maps"));
tileMapRenderer = new TileMapRenderer(map, atlas, 8, 8);
However in the new libgdx the rule changes, to load a tilemap there is no longer needed to use map packer first. You can directly use the .tmx file with the tileset png. Something like following will work, and then call render.
TiledMap map = new TmxMapLoader().load("maps/testmap.tmx");
My question is the original tileselt.png that used to generate the .tmx file, it's size is not power of two. So I still have to either use Texture packer or a map packer to pack it for using.
I could not successfully associate the packed file with the .tmx;
Is there anyway to approach this issue?
Thanks

If you target GLES 1.0, you will need power-of-two tilesets. Some devices might allow non-power-of-two with GLES 1.0, but that isn't guaranteed. With GLES 2.0 this restriction is lifted, but you still might get better performance out of power-of-two.
You can still use the TiledMapPacker-produced maps, you will just need to load the map with AtlasTmxMapLoader instead of TmxMapLoader.

They do not need to be power of two. If you have Problems with it like you get the power of two error set Texture.setEnforcePotImages(false); inside of your MainClass.
You do not need the packer anymore so i think you cant associate the packer to the tmx file.
If you use the TmxMapLoader the tilesets need to be inside of the same folder of the .tmxfile.
If they are inside of an different directory you need to configure the source path inside of the .tmx file. here is an Example:
<tileset firstgid="257" name="mountain" tilewidth="32" tileheight="32">
<image source="mountain.png" width="512" height="512"/>
</tileset>
is the regular output of Tiled. If the Tileset is inside of for example config it you need to change it like this:
<tileset firstgid="257" name="mountain" tilewidth="32" tileheight="32">
<image source="config/mountain.png" width="512" height="512"/>
</tileset>
But it still need to be a subfolder of the path where the tmx file is.
Regards hope that may helps.

Related

Cesium PinBuilder using "fromMakiIconId"

I started using cesium for representing 3d maps and was trying to add Point of Interest data on top of this 3d view. I tried local png icons and it worked. I also realized can add icons from built in assets. I tried the below code and it worked perfect. I have a various set of PoIs but could not find the labels using which I can add them onto the map.
For example to add a hospital i referred hospital in the iconid.
var hospitalPin = Cesium.when(
pinBuilder.fromMakiIconId("hospital", Cesium.Color.RED, 48),
function (canvas) {
return viewer.entities.add({
name: "Hospital",
position: Cesium.Cartesian3.fromDegrees(77.311, 32.826),
billboard: {
image: canvas.toDataURL(),
verticalOrigin: Cesium.VerticalOrigin.BOTTOM,
},
});
}
);
In the similar way is there any reference for the icon Ids which I can use to make use of them in my code to represent the PoIs. Any help is appreciated.
I found the source images located at \Build\Cesium\Assets\Textures\maki from the cesium library which I think can be used.
The image you posted is from the PinBuilder docs, but check out the original source for that: It's a screenshot of the Cesium Sandcastle GeoJson Demo.
As you noticed, the images of the individual pins are stored in a folder called maki which has names like this:
airport.png
alcohol-shop.png
america-football.png
art-gallery.png
bakery.png
bank.png
bar.png
baseball.png
...
Just strip the .png off the end of the image filename, and that's it. That's the ID.
The dashes are allowed in the ID:
pinBuilder.fromMakiIconId("america-football", Cesium.Color.RED, 48)
But, the first few pins in the original screenshot don't have corresponding Maki icons, they're simple letters or numbers. You can build pins using text, using a different function, like this:
pinBuilder.fromText("A", Cesium.Color.RED, 48)
You may also use pins with Unicode characters on them.
pinBuilder.fromText("\u267b", Cesium.Color.RED, 48)
And finally, if you have a custom PNG file of your own, similar to a Maki icon but customized for your app's need, you may build a pin directly from the URL of the custom PNG file.
pinBuilder.fromUrl(url, Cesium.Color.RED, 48)

how to change a CesiumJS viewer's baselayer url

i am using a CesiumJS instance to display a base map of the earth using a imageryProvider from source A.
var viewer = new Cesium.Viewer('cesiumContainer', imageryProvider:providerA);
Now while using the Viewer I would like to be able to change this map to get images from providerB at a certain event.
I tried:
viewer.scene.imageryLayers.get(0).imageryProvider.url = providerB.url
However that does not seem to work and also feels quite like hack anyway.
I could not find anything in Cesium's documentation .
Is this at all possible without restarting / recreating the viewer instance?
I know that there is a Cesium.BaseLayerPicker (https://cesium.com/docs/cesiumjs-ref-doc/BaseLayerPicker.html)
However I do not see what method this picker calls on "select" )
Thanks a lot.
The BaseLayerPicker widget calls this code when the user selects a new layer.
There's a lot of boilerplate widget management in that block of code, but for your sake, only a couple of the lines are critical. First, the old existing active imagery layer is searched for, and removed:
imageryLayers.remove(layer);
Then, a new imagery provider is constructed and added at index 0, the first position, which is the base imagery layer:
imageryLayers.addImageryProvider(newProviders, 0);
You can directly change the URL of the provider but you should also change appropriate parameters("layers" in case of WMS, "layer", "style", "format", "tileMatrixSetID " ... in case of WMTS) depending on the type of provider(WMS or WMTS).

How to make two or more different font files use a common Atlas in libgdx?

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.

Managing Bitmap Font assets in LibGdx

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.

libgdx TextureAtlas, and NinePatch's

I am making a simple game using libgdx. I have a TextureAtlas that has I ninepatch I am trying to use:
The image is saved as menu.9.png
I am using the following code:
Image bg = new Image(Room.iAtlas.findRegion("GUI/menu"));
bg.setBounds(guix-border,guiy-border,(border+radius)*2,(border+radius)*2);
batch.begin();
bg.draw(s,1);
batch.end();
The output is like this:
I really just have no idea what I am doing wrong, but it should be more like this(Except it would have the shapes on top of it, but I didn't add those):
(I created that by hand, i've never actually had 9patch working, and it doesn't have the ships because I didn't bother to edit those in)
It looks like your "nine patch" isn't being treated as a real nine path, and is being treated as a "degenerate" nine patch (I had a very similar problem earlier: Loading nine-patch image as a Libgdx Scene2d Button background looks awful, though I wasn't using a TextureAtlas which is supposed to be the solution.)
Basically, when Libgdx reads the nine-patch out of your atlas, its supposed to read all the meta-data that describes how to chop the image up into 9 tiles (see https://code.google.com/p/libgdx/wiki/TexturePacker#NinePatches). I see a couple places this could go wrong:
Your texture isn't a valid nine-patch, and the meta-data is being ignored. (Check with the Android draw9patch tool.)
Your texture packer isn't processing the .9.png file correctly. Check the contents of the .txt file for your atlas, and see if it has "split" entries associated with the "menu.9.png" entry.
The texture lookup is just returning a regular TextureRegion wrapper for the nine-patch region, and isn't wrapping it in a NinePatch object. Try using TextureRegion.createNinePatch to make that more explicit. (I'm under the impression that this isn't necessary, but maybe it is ...)