package org.newdawn.slick.opengl;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.IntBuffer;
import org.lwjgl.LWJGLException;
import org.lwjgl.input.Cursor;
import org.newdawn.slick.util.Log;
import org.newdawn.slick.util.ResourceLoader;
/**
* A utility to load cursors (thanks go to Kappa for the animated cursor
* loader)
*
* @author Kevin Glass
* @author Kappa-One
*/
public class CursorLoader {
/** The single instnace of this loader to exist */
private static CursorLoader single = new CursorLoader();
/**
* Retrieve the single instance of this loader - convinient huh?
*
* @return The single instance of the cursor loader
*/
public static CursorLoader get() {
return single;
}
/**
* Create a new cursor loader
*/
private CursorLoader() {
}
/**
* Get a cursor based on a image reference on the classpath
*
* @param ref The reference to the image to be loaded
* @param x The x-coordinate of the cursor hotspot (left -> right)
* @param y The y-coordinate of the cursor hotspot (bottom -> top)
* @return The create cursor
* @throws IOException Indicates a failure to load the image
* @throws LWJGLException Indicates a failure to create the hardware cursor
*/
public Cursor getCursor(String ref,int x,int y) throws IOException, LWJGLException {
LoadableImageData imageData = null;
imageData = ImageDataFactory.getImageDataFor(ref);
imageData.configureEdging(false);
ByteBuffer buf = imageData.loadImage(ResourceLoader.getResourceAsStream(ref), true, true, null);
for (int i=0;i<buf.limit();i+=4) {
byte red = buf.get(i);
byte green = buf.get(i+1);
byte blue = buf.get(i+2);
byte alpha = buf.get(i+3);
buf.put(i+2, red);
buf.put(i+1, green);
buf.put(i, blue);
buf.put(i+3, alpha);
}
try {
int yspot = imageData.getHeight() - y - 1;
if (yspot < 0) {
yspot = 0;
}
return new Cursor(imageData.getTexWidth(), imageData.getTexHeight(), x, yspot, 1, buf.asIntBuffer(), null);
} catch (Throwable e) {
Log.info("Chances are you cursor is too small for this platform");
throw new LWJGLException(e);
}
}
/**
* Get a cursor based on a set of image data
*
* @param buf The image data (stored in RGBA) to load the cursor from
* @param x The x-coordinate of the cursor hotspot (left -> right)
* @param y The y-coordinate of the cursor hotspot (bottom -> top)
* @param width The width of the image data provided
* @param height The height of the image data provided
* @return The create cursor
* @throws IOException Indicates a failure to load the image
* @throws LWJGLException Indicates a failure to create the hardware cursor
*/
public Cursor getCursor(ByteBuffer buf,int x,int y,int width,int height) throws IOException, LWJGLException {
for (int i=0;i<buf.limit();i+=4) {
byte red = buf.get(i);
byte green = buf.get(i+1);
byte blue = buf.get(i+2);
byte alpha = buf.get(i+3);
buf.put(i+2, red);
buf.put(i+1, green);
buf.put(i, blue);
buf.put(i+3, alpha);
}
try {
int yspot = height - y - 1;
if (yspot < 0) {
yspot = 0;
}
return new Cursor(width,height, x, yspot, 1, buf.asIntBuffer(), null);
} catch (Throwable e) {
Log.info("Chances are you cursor is too small for this platform");
throw new LWJGLException(e);
}
}
/**
* Get a cursor based on a set of image data
*
* @param imageData The data from which the cursor can read it's contents
* @param x The x-coordinate of the cursor hotspot (left -> right)
* @param y The y-coordinate of the cursor hotspot (bottom -> top)
* @return The create cursor
* @throws IOException Indicates a failure to load the image
* @throws LWJGLException Indicates a failure to create the hardware cursor
*/
public Cursor getCursor(ImageData imageData,int x,int y) throws IOException, LWJGLException {
ByteBuffer buf = imageData.getImageBufferData();
for (int i=0;i<buf.limit();i+=4) {
byte red = buf.get(i);
byte green = buf.get(i+1);
byte blue = buf.get(i+2);
byte alpha = buf.get(i+3);
buf.put(i+2, red);
buf.put(i+1, green);
buf.put(i, blue);
buf.put(i+3, alpha);
}
try {
int yspot = imageData.getHeight() - y - 1;
if (yspot < 0) {
yspot = 0;
}
return new Cursor(imageData.getTexWidth(), imageData.getTexHeight(), x, yspot, 1, buf.asIntBuffer(), null);
} catch (Throwable e) {
Log.info("Chances are you cursor is too small for this platform");
throw new LWJGLException(e);
}
}
/**
* Get a cursor based on a image reference on the classpath. The image
* is assumed to be a set/strip of cursor animation frames running from top to
* bottom.
*
* @param ref The reference to the image to be loaded
* @param x The x-coordinate of the cursor hotspot (left -> right)
* @param y The y-coordinate of the cursor hotspot (bottom -> top)
* @param width The x width of the cursor
* @param height The y height of the cursor
* @param cursorDelays image delays between changing frames in animation
*
* @return The created cursor
* @throws IOException Indicates a failure to load the image
* @throws LWJGLException Indicates a failure to create the hardware cursor
*/
public Cursor getAnimatedCursor(String ref,int x,int y, int width, int height, int[] cursorDelays) throws IOException, LWJGLException {
IntBuffer cursorDelaysBuffer = ByteBuffer.allocateDirect(cursorDelays.length*4).order(ByteOrder.nativeOrder()).asIntBuffer();
for (int i=0;i<cursorDelays.length;i++) {
cursorDelaysBuffer.put(cursorDelays[i]);
}
cursorDelaysBuffer.flip();
LoadableImageData imageData = new TGAImageData();
ByteBuffer buf = imageData.loadImage(ResourceLoader.getResourceAsStream(ref), false, null);
return new Cursor(width, height, x, y, cursorDelays.length, buf.asIntBuffer(), cursorDelaysBuffer);
}
}