Lwjgl Native Cursor

Hey Leute.
Hab eben versuch den native cursor mit lwjgl zu setzen.
Irgendetwas stimmt da aber vorn und hinten nicht.

Ich hab lange gegoogelt, aber letzendlich läuft es doch darauf hinaus,
die RGB werte in ein buffer zu packen und… ja? oder nicht?

Hier mein Code:

BufferedImage bi = ImageIO.read(AGL.getInputStreamFromRoot(getClass(), "cursor.png"));
IntBuffer buffer = BufferUtils.createIntBuffer(bi.getWidth() * bi.getHeight());
int rgbs[] = new int[bi.getWidth() * bi.getHeight()];
for(int i = 0; i < rgbs.length; i++){
	rgbs** = Color.BLUE.getRGB();//bi.getRGB(i % bi.getWidth(), i / bi.getWidth()); //als test, ob es mit einer farbe funktiniert
}
buffer.put(rgbs);
buffer.flip();
Mouse.setNativeCursor(new Cursor(bi.getWidth(), bi.getHeight(), 0, bi.getHeight() - 1, 1, buffer, null));

Das Ergebniss ist irgendwie erstaunlich, aber nicht richtig:

jemand eine idee?
Danke!

[QUOTE=mymaksimus]jemand eine idee?[/QUOTE]Jep… der IntBuffer muss im Format RGBA sein. “getRGB()” liefert aber stets ARGB. Daraus folgt, dass die Farbwerte um 8 Stellen nach links gerollt werden müssen (“Integer.rotateLeft(value, 8)”).

KSKB mit leerem Fenster wo nichts gemacht wird, außer den Cursor zu setzen… (ja, ich könnte auch danach suchen, aber … hm.)

Laut doku will er jedenfalls ARGB (was mich auch im ersten Moment irritiert hat)

[QUOTE=Marco13]Laut doku will er jedenfalls ARGB (was mich auch im ersten Moment irritiert hat)[/QUOTE]:eek: tatsächlich… das ja seltsam.
Eine weitere mögliche Fehlerquelle, die aber erst zum Tragen kommt, wenn der Cursor tatsächlich ein Bild ist… Origin der Bilder ist links unten, beim BI aber links oben. Das würde das Bild aber auch nur horizontal gespiegelt widergeben und nicht so ein kaudawelsch. Überprüf halt nach dem Aufruf der “setNativeCursor()”-Methode mal, wieviel Werte des IntBuffers verwendet wurden. “position()” sollte da halt einen Wert != 0, bestenfalls “capacity()” liefern. Wenn da 0 bei raus kommt, setzt die “set()”-Methode den Buffer leider zurück. Zuletzt kann man stat “flip()” evtl. auch mal “rewind()” versuchen.

Jop, werde eure ratschlaege zu herzen nehmen. ^^
Hab total vergessen dass es getRgb ja eventuell nur Rgb zurueckgeben koennte… ^^ ein cursor ohne transparenz macht generell wenig sin :smiley:
Danke euch

Sorry Leute… Ich dachte es wäre gelöst.
Ist es aber leider nicht :frowning:

Also rotateLeft hat leider nichts gebracht, dafür aber das Bild in ein neues zu kopieren - aber mit Type INT_ARGB -_-
Das Ergebniss sieht schon mal… vielversprechender aus.

Bei folgendem Code:

			BufferedImage rawImage = ImageIO.read(AGL.getInputStreamFromRoot(getClass(), "cursor.png"));
			BufferedImage rawImageCopy = new BufferedImage(rawImage.getWidth(), rawImage.getHeight(), BufferedImage.TYPE_INT_ARGB);
			rawImageCopy.getGraphics().drawImage(rawImage, 0, 0, null);
			IntBuffer buffer = BufferUtils.createIntBuffer(rawImageCopy.getWidth() * rawImageCopy.getHeight());
			int rgbs[] = new int[rawImageCopy.getWidth() * rawImageCopy.getHeight()];
			for(int i = 0; i < rgbs.length; i++){
				rgbs** = rawImageCopy.getRGB(i % rawImageCopy.getWidth(), i / rawImageCopy.getWidth());
			}
			buffer.put(rgbs);
			buffer.rewind();
			Mouse.setNativeCursor(new Cursor(rawImageCopy.getWidth(), rawImageCopy.getHeight(), 0, rawImageCopy.getHeight() - 1, 1, buffer, null));

Und Folgendem cursor.png:

Erhalte ich folgenden Cursor:

Da getRGB anscheinend doch die alpha information enthält.
Laut GrepCode, ColorModel#getRGB(x, y):

public int More ...getRGB(Object inData) {
         return (getAlpha(inData) << 24)
             | (getRed(inData) << 16)
             | (getGreen(inData) << 8)
             | (getBlue(inData) << 0);
}

Moin,

das liegt an der Größe, folgendes funktioniert:


import java.awt.geom.AffineTransform;
import java.awt.image.AffineTransformOp;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.io.InputStream;
import java.nio.IntBuffer;

import javax.imageio.ImageIO;

import org.lwjgl.BufferUtils;
import org.lwjgl.LWJGLException;
import org.lwjgl.input.Cursor;
import org.lwjgl.input.Mouse;
import org.lwjgl.opengl.ContextAttribs;
import org.lwjgl.opengl.Display;
import org.lwjgl.opengl.DisplayMode;
import org.lwjgl.opengl.PixelFormat;


public final class KskbCursor {

    private static final int WIDTH = 1200;
    private static final int HEIGHT = 800;


    public static void main(final String[] args) throws LWJGLException, IOException {

        final DisplayMode displayMode = new DisplayMode(WIDTH, HEIGHT);
        final PixelFormat pixelFormat = new PixelFormat();
        final ContextAttribs contextAttribs = new ContextAttribs();

        new KskbCursor().run(displayMode, pixelFormat, contextAttribs);

    }


    void run(final DisplayMode displayMode, final PixelFormat pixelFormat, final ContextAttribs contextAttribs) throws LWJGLException, IOException {

        Display.setDisplayMode(displayMode);
        Display.create(pixelFormat, contextAttribs);

        final InputStream is = getClass().getResourceAsStream("cursor2.png");
        initCursor(is);
        is.close();

        while (!Display.isCloseRequested())
            Display.update();

        Display.destroy();

    }


    private void initCursor(final InputStream is) throws LWJGLException, IOException {

        final BufferedImage image = flipImage(ImageIO.read(is));

        final int width = image.getWidth();
        final int height = image.getHeight();

        final int[] pixels = image.getRGB(0, 0, width, height, null, 0, width);

        final IntBuffer buffer = BufferUtils.createIntBuffer(pixels.length);
        buffer.put(pixels);
        buffer.rewind();

        Mouse.setNativeCursor(new Cursor(width, height, 0, height - 1, 1, buffer, null));

    }


    private BufferedImage flipImage(final BufferedImage image) {

        final AffineTransform tx = AffineTransform.getScaleInstance(1, -1);
        tx.translate(0, -image.getHeight());

        final AffineTransformOp op = new AffineTransformOp(tx, AffineTransformOp.TYPE_NEAREST_NEIGHBOR);
        final BufferedImage result = op.filter(image, null);

        return result;

    }


}

Viele Grüße
Fancy

Das bild an sich ist also zu gross? Oder zu klein? (O.o) Mist das hab ich gar nicht ausprobiert oO
Was sind denn die minimums / maximums? Kann man solche dinge irgebdwo nachlesen?

Nein, es war nicht power of two. Die Funktion gibt das ans Betriebssystem weiter, entsprechend hängt es vom Betriebssystem ab, was gültig ist. Unter Windows 7 scheint es z.B. A8R8G8B8 mit Abmessungen von 2^n und einem Alpha von 0.0 oder 1.0 zu sein. Auf anderen Betriebssystemen oder Versionen, können das andere Werte sein.

Ich würde diese Funktion ohnehin nicht nutzen. Ein einfaches texturiertes Rechteck fügt sich imho wesentlich sauberer in den Render-Loop ein.

Viele Grüße
Fancy

Naja mal sehen.
Danke :slight_smile: