Use MethodHandles to select LWJGL 3.3 methods if needed

This commit is contained in:
embeddedt 2023-03-04 10:36:11 -05:00
parent a54e7b831a
commit 1c9935e298
No known key found for this signature in database
GPG Key ID: A69433EC199B5613

View File

@ -11,12 +11,119 @@ import org.lwjgl.stb.STBRPNode;
import org.lwjgl.stb.STBRPRect;
import org.lwjgl.stb.STBRectPack;
import static java.lang.invoke.MethodHandles.*;
import static java.lang.invoke.MethodType.*;
import java.lang.invoke.MethodHandle;
import java.sql.Ref;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Stream;
/* Source: https://github.com/GTNewHorizons/lwjgl3ify/blob/f21364cd3d178aef863458a2faa1f5718a4e350d/src/main/java/me/eigenraven/lwjgl3ify/textures/StbStitcher.java */
public class StbStitcher {
/* Most of this logic is to allow use of LWJGL versions where coordinates are short and versions where they are int */
private static final MethodHandle MH_rect_shortSet, MH_rect_intSet, MH_rect_intX, MH_rect_intY, MH_rect_shortX,
MH_rect_shortY;
static {
MethodHandle shortM = null, intM = null;
List<ReflectiveOperationException> exceptions = new ArrayList<>();
try {
intM = publicLookup().findVirtual(STBRPRect.class, "set", methodType(STBRPRect.class,
int.class, /* id */
int.class,
int.class,
int.class,
int.class,
boolean.class));
} catch(ReflectiveOperationException e) {
exceptions.add(e);
}
try {
shortM = publicLookup().findVirtual(STBRPRect.class, "set", methodType(STBRPRect.class,
int.class, /* id */
short.class,
short.class,
short.class,
short.class,
boolean.class));
} catch(ReflectiveOperationException e) {
exceptions.add(e);
}
if(shortM == null && intM == null) {
IllegalStateException e = new IllegalStateException("An STBRPRect set method could not be located");
exceptions.forEach(e::addSuppressed);
throw e;
}
MH_rect_shortSet = shortM;
MH_rect_intSet = intM;
/* Now look for X methods */
exceptions.clear();
try {
intM = publicLookup().findVirtual(STBRPRect.class, "x", methodType(int.class));
} catch(ReflectiveOperationException e) {
exceptions.add(e);
}
try {
shortM = publicLookup().findVirtual(STBRPRect.class, "x", methodType(short.class));
} catch(ReflectiveOperationException e) {
exceptions.add(e);
}
if(shortM == null && intM == null) {
IllegalStateException e = new IllegalStateException("An STBRPRect x() method could not be located");
exceptions.forEach(e::addSuppressed);
throw e;
}
MH_rect_shortX = shortM;
MH_rect_intX = intM;
/* Assume that Y is the same */
try {
if(MH_rect_shortX != null) {
MH_rect_shortY = publicLookup().findVirtual(STBRPRect.class, "y", methodType(short.class));
MH_rect_intY = null;
} else { /* it must be int */
MH_rect_intY = publicLookup().findVirtual(STBRPRect.class, "y", methodType(int.class));
MH_rect_shortY = null;
}
} catch(ReflectiveOperationException e) {
throw new IllegalStateException("An STBRPRect y() method could not be located", e);
}
}
private static STBRPRect setWrapper(STBRPRect rect, int id, int width, int height, int x, int y, boolean was_packed) {
try {
if(MH_rect_shortSet != null)
return (STBRPRect)MH_rect_shortSet.invokeExact(rect, id, (short)width, (short)height, (short)0, (short)0, false);
else
return (STBRPRect)MH_rect_intSet.invokeExact(rect, id, width, height, 0, 0, false);
} catch(Throwable e) {
throw new AssertionError(e);
}
}
private static int getX(STBRPRect rect) {
try {
if(MH_rect_shortX != null)
return (short)MH_rect_shortX.invokeExact(rect);
else
return (int)MH_rect_intX.invokeExact(rect);
} catch(Throwable e) {
throw new AssertionError(e);
}
}
private static int getY(STBRPRect rect) {
try {
if(MH_rect_shortX != null)
return (short)MH_rect_shortY.invokeExact(rect);
else
return (int)MH_rect_intY.invokeExact(rect);
} catch(Throwable e) {
throw new AssertionError(e);
}
}
public static Pair<Pair<Integer, Integer>, List<LoadableSpriteInfo>> packRects(Stitcher.Holder[] holders) {
int holderSize = holders.length;
@ -36,7 +143,9 @@ public class StbStitcher {
int height = holder.height;
// The ID here is just the array index, for easy lookup later
rectBuf.get(j).set(j, (short)width, (short)height, (short)0, (short)0, false);
STBRPRect rect = rectBuf.get(j);
setWrapper(rect, j, width, height, 0, 0, false);
sqSize += (width * height);
}
@ -63,7 +172,7 @@ public class StbStitcher {
}
// Initialize the sprite now with the position and size that we've calculated so far
infoList.add(new LoadableSpriteInfo(holder.spriteInfo, width, height, rect.x(), rect.y()));
infoList.add(new LoadableSpriteInfo(holder.spriteInfo, width, height, getX(rect), getY(rect)));
//holder.spriteInfo.initSprite(size, size, rect.x(), rect.y(), false);
}