Why do I get ArrayIndexOutOfBoundsException when I build an imageView with JavaFX? - exception

I have various places in my JavaFx app where I insert images(png/gif). It usually works with one exception. What I do:
I put the images in a specific directory under resources.
I load them like this:
ImageView openView = new ImageView("/pics/logo.png");
An alternative that also works is:
InputStream resourceAsStream = classParameter.getResourceAsStream("/pics/logo.png");
Image image = new Image(resourceAsStream);
ImageView openView = new ImageView(image);
The problem:
There is one gif that has a white background. When I insert it in the app it works, but if I insert the same gif after it is transformed (to add transparency for background) I get :
ObjectProperty [bean: javafx.scene.image.Image#2ac5919d, name: exception, value: java.lang.ArrayIndexOutOfBoundsException: 4096]
If I open it for view, the transformed gif is displayed as expected.
Any ideas on why is this exception thrown?
Stack trace:
java.lang.ArrayIndexOutOfBoundsException: 4096
at com.sun.javafx.iio.gif.GIFImageLoader2$LZWDecoder.readString(GIFImageLoader2.java:388)
at com.sun.javafx.iio.gif.GIFImageLoader2.decodeImage(GIFImageLoader2.java:148)
at com.sun.javafx.iio.gif.GIFImageLoader2.load(GIFImageLoader2.java:209)
at com.sun.javafx.iio.ImageStorage.loadAll(ImageStorage.java:368)
at com.sun.javafx.iio.ImageStorage.loadAll(ImageStorage.java:328)
at com.sun.javafx.tk.quantum.PrismImageLoader2.loadAll(PrismImageLoader2.java:119)
at com.sun.javafx.tk.quantum.PrismImageLoader2.<init>(PrismImageLoader2.java:70)
at com.sun.javafx.tk.quantum.QuantumToolkit.loadImage(QuantumToolkit.java:648)
at javafx.scene.image.Image.loadImage(Image.java:1036)
at javafx.scene.image.Image.initialize(Image.java:785)
at javafx.scene.image.Image.<init>(Image.java:599)
at javafx.scene.image.ImageView.<init>(ImageView.java:167)
at helpers.Helpers.setImageView(Helpers.java:173)

I managed to make it work by using another gif editing tool. So the problem was the conversion. Even if the initial gif seemed fine, under the hood it made JavaFx crash. (Won't share here the name of the tools that work and that didn't work, since it may be against stackoverflow policy).

Related

TiledMapTileLayer wont cast from TileLayer

I'm trying to get cells from a tile layer in libgdx (for a tiled map). A lot of examples I see say to cast a layer to TiledMapTileLayer, but this doesn't work.
TiledMap tiledMap = new TmxMapLoader().load("start.tmx");
TiledMapTileLayer obsLayer = (TileMapTileLayer) tiledMap.getLayers().get("obs");
I get this exception:
Exception in thread "LWJGL Application" java.lang.ClassCastException: com.badlogic.gdx.maps.MapLayer cannot be cast to com.badlogic.gdx.maps.tiled.TiledMapTileLayer
at net.myname.mygame.Game.create(Game.java:66)
at com.badlogic.gdx.backends.lwjgl.LwjglApplication.mainLoop(LwjglApplication.java:149)
at com.badlogic.gdx.backends.lwjgl.LwjglApplication$1.run(LwjglApplication.java:126)
My guess is the library was updated to work differently, but I don't see any examples doing things in a new way. Anyone know what to do?
I'm using libgdx 1.9.9
Oh wait, I guess my map got reverted accidentally. Was using a object layer before but changed it to a tile layer. Changing to a tile layer instead of an object layer makes it work.

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.

Changing materials in Forge

We are currently making the client retrieve the object states when the page loads (which will cause the 'pending' objects in the model to turn into different colors). Then we poll for changes to update the coloring (Firstly: pending object gets colored when the viewer loads, and then we keep polling to check and change state again, to make Forge render those in a different color and store their old color/material. When the polling received a change that an object should no longer be colored, it tells Forge to use the old color/material again.
The problem:
We've found out what the problem is, but we couldn't find out how to fix it. The problem is that changing materials in Forge doesn't work after startup anymore, it only works in the first ~3 seconds or so (the materials were used to show the colors).
However, setting overlays works even after the first ~3 seconds, (showing overlays instead of materials to show the colors).
This is not what we want to achieve. This looks unoptimized, because overlays will be shown through everything.
The materials, however, seem to be 'locked', as in, they cannot be changed anymore after the first ~3 seconds. It seems like they aren't refreshed or something
In the examples, we found they used viewer.impl.invalidate(true) to refresh the Forge viewer, but that doesn't do anything after ~3 seconds.
We've also tried every combination of viewer.impl.invalidate(true, true, true) as well as setting material.needsUpdate to true, as well as trying to re-render the entire scene.
We also found this: https://github.com/mrdoob/three.js/issues/790, but we couldn't find a good way to do that in Forge, we tried viewer.requestSilentRender() but that didn't do anything either.
Anyway, we've tried everything we could come up with and could find online to make the materials work, but nothing made a difference.
We are looking to find someone that's more experienced with how Forge works that can see what the material code is doing wrong.
As for the content, here is all the code you will need to understand what is happening:
DROPBOX LINK
And here is a small part of the "index.html" file that sets the color:
try
{
viewer.restoreAllColorOverlays(); //for materials instead of overlays: viewer.restoreAllColorMaterials();
$.each(colors, function(color, selectionIds)
{
viewer.setColorOverlay(selectionIds, color); //for materials instead of overlays: viewer.setColorMaterial(selectionIds, color);
});
}
catch(error)
{
console.error(error);
}
I have no idea how you implement your app, so I only tell what I found in your codes. If you want to resolve the issue you addressed, you can consider providing a reproducible case demonstrating that, I will gladly pass it to our dev team. Those following items should be in the reproducible case:
A short exact description of what you are trying to achieve. The behavior you observe versus what you expect, and why this is a problem.
A complete yet minimal sample source model to run a test in.
A complete yet minimal Forge app that can be run and debugged with a simple procedure to analyze its behavior lives in the sample model.
A complete yet minimal pure three.js app that can be run and demonstrated the shader effect you want. Note. Forge Viewer is using r71 three.js.
Detailed step-by-step instructions for reproducing the issue, e.g. which element to pick, what command to launch etc.
If your reproducible case could not be posted here publicly, please send it to the forge.help#autodesk.com and remove sensitive data or information before you send.
=== Something I found in your codes:
I found here are some wrong types and missing actions in your ColorMaterial extension. The color property of an material should the a type of the THREE.Color. Here is my modification:
Autodesk.Viewing.Viewer3D.prototype.setColorMaterial = function(objectIds, color)
{
if( !(color instanceof THREE.Color) ) throw 'Invalid argument: Color';
var material = new THREE.MeshPhongMaterial
({
color: color,
opacity: 0.8,
transparent: true
});
viewer.impl.matman().addMaterial( 'ColorMaterial-' + new Date().getTime(), material, true );
// ...........
};
Its' result is here:
In the ColorOverlay extension, The type of material color property is also wrong, it should be a type of THREE.Color, too. Changing it into THREE.Color should work fine. In addition, overlay is covers on 3D objects, so you should call viewer.hide() with your setColorOverlay() together. Otherwise, it won't look like a transparent object.
Without hidding 3D object of the wall:
hide 3D object of the wall:

cocos2d-x tiledMap create return null?

I am currently following Ray's tutorial on cocos2d-x tile map and my very simple code is not working at all.
So here is my code,
_tileMap = TMXTiledMap::create("TileMap.tmx");
this->addChild(_tileMap);
and according to the debugger, _tileMap is null, which causes a crash on the addChild method.
Do anyone have any idea why this is happening?
p.s _tileMap is declared as a TMXTiledMap* in header, TileMap.tmx is totally filled with stuff and TileMap.tmx along with other things are imported into the resource folder using creating folder reference.
Have you try "Tile layer format" with "Base64(uncompressed) ?
I have same symptom as like you, but I get out from stock by change tile layer format from cvs to Base64(uncompressed).
enter image description here

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 ...)