Custom Mouse Cursor from PNG

I have a .png file containing my mouse cursor image. I’ve had a search around to no avail. I tried loading the image’s data buffer in to a JmeCursor and ended up having a kernel panic (!), so won’t try that again. I could disable the cursor altogether and have a textured Quad whose coordinates I update, but then I would then have to set up nifty gui interaction somehow.

I figure there is a better way to do this! Does anybody have any helpful resources or examples for custom cursors?

http://hub.jmonkeyengine.org/forum/topic/custom-mouse-cursor-committed/

I saw that but the early examples in the thread seemed out-of-sync with what’s currently in Jme3 and the later examples seem to require .cur/.ico/.ani files.

Anyway, a bit of guesswork based on the first post brings me to this, which worked - thanks:

[java] Texture cursorTexture = assetManager.loadTexture(“Textures/cursors/point.png”);

    Image image = cursorTexture.getImage();
    ByteBuffer imgByteBuff = image.getData(0);
    imgByteBuff.rewind();
    IntBuffer imgIntBuff = imgByteBuff.asIntBuffer();
    
    JmeCursor c = new JmeCursor();
    c.setHeight(image.getHeight());
    c.setWidth(image.getWidth());
    c.setNumImages(1);
    c.setyHotSpot(image.getHeight()-3);
    c.setxHotSpot(3);
    c.setImagesData(imgIntBuff);
    
    inputManager.setMouseCursor(c);[/java]

Just in case someone comes across this thread from Google or something: the above doesn’t work - you end up with weird colors. Still stuck with this, seems I might have to convert to .ico files.

Okay, after lots of trial and error and more guesswork, seems that the cursor wants it in ARGB not RGBA format… so this works with the correct colors:

[java] Texture cursorTexture = assetManager.loadTexture(“Textures/cursors/point.png”);

    Image image = cursorTexture.getImage();
    ByteBuffer imgByteBuff = (ByteBuffer) image.getData(0).rewind();
    IntBuffer curIntBuff = BufferUtils.createIntBuffer(image.getHeight() * image.getWidth());
    
    while (imgByteBuff.hasRemaining()) {
        int rgba = imgByteBuff.getInt();
        int argb = ((rgba & 255) << 24) | (rgba >> 8);
        curIntBuff.put(argb);
    }
    
    JmeCursor c = new JmeCursor();
    c.setHeight(image.getHeight());
    c.setWidth(image.getWidth());
    c.setNumImages(1);
    c.setyHotSpot(image.getHeight()-3);
    c.setxHotSpot(3);
    c.setImagesData((IntBuffer) curIntBuff.rewind());
    
    inputManager.setMouseCursor(c);[/java]
3 Likes

Thank you for posting this correction. I still have some problems with the cursors being really weird. With your code I can at least figure out the outlines of the cursor. Texture says the format is ABGR8. So after your code I tried to convert the bits to ARGB and even tried to load it as a BufferedImage and read the ARGB values there. No luck. Is this feature supposed to work or am I just not getting it?

This happens:
[video]Jme cursor problem - YouTube

This video is private

Oops, now it should work, as unlisted. Sorry

Take a look here for a few working cursor files to cross verify

aero_working.ani works ok. Here is the PNG I’m trying to load: https://dl.dropboxusercontent.com/u/90134918/Point.png

Make it an ani file then, there is some good freeware tool RealWorld Cursor Editor that can help you with this greatly.

Oh… I was not hoping to have to do that :slight_smile: I already have problems with every format I’m trying to use (MP2s no library in JAVA can extract etc.). So I was happy to find this cursor thing as a ready deal. I’m doing automatic conversion of an old game assets (the user must have the game installed and everything should be automatic from that point on). So now I have to code an ANI tool as well. Oh well. Thanks anyway, I’ll find a way to make them ANI,

Hm you could split them into seperate images, and make a own cursor manager level, that just swiches the individual images.

The problem is the PNG. Not all were animated like the example I gave. I cannot get even a static PNG to load. It looks similar still. Distorded.

I created a simple 32x32 PNG with GIMP. I am not able to load it as expected. But when I ask the texture to give me the data:
[java]
Image image = cursorTexture.getImage();
ByteBuffer imgByteBuff = image.getData(0);
[/java]

The size is 4x the image heightwidth. And the IntBuffer constructed for the JmeCursor is just heightwidth. Is the getData(0) giving all the channels (ABGR) as separate?

Ok, I think I figured it out, at least the color things were correct as @ledneb stated. The problem is the size and partial transparencies. Partial transparencies seem not to exist in cursor. But what caused the distortion was the image size! I think maximum size is 80px, height nor width can’t exceed this…

@tonihele said: Ok, I think I figured it out, at least the color things were correct as @ledneb stated. The problem is the size and partial transparencies. Partial transparencies seem not to exist in cursor. But what caused the distortion was the image size! I think maximum size is 80px, height nor width can't exceed this...

In fact this are mostly windows limitation, they do not exist on mac and linux.