diff options
6 files changed, 132 insertions, 55 deletions
diff --git a/build.gradle b/build.gradle index 996b549..35e80c1 100644 --- a/build.gradle +++ b/build.gradle @@ -75,9 +75,11 @@ dependencies { forge("net.minecraftforge:forge:1.8.9-11.15.1.2318-1.8.9") lwjgl "org.lwjgl:lwjgl:3.3.0" + lwjgl "org.lwjgl:lwjgl-stb:3.3.0" lwjgl "org.lwjgl:lwjgl-tinyfd:3.3.0" lwjgl "org.lwjgl:lwjgl-nanovg:3.3.0" lwjglNative "org.lwjgl:lwjgl:3.3.0:natives-windows" + lwjglNative "org.lwjgl:lwjgl-stb:3.3.0:natives-windows" lwjglNative "org.lwjgl:lwjgl-tinyfd:3.3.0:natives-windows" lwjglNative "org.lwjgl:lwjgl-nanovg:3.3.0:natives-windows" implementation lwjglJar.outputs.files diff --git a/src/main/java/io/polyfrost/oneconfig/lwjgl/IOUtil.java b/src/main/java/io/polyfrost/oneconfig/lwjgl/IOUtil.java index eb830df..f5105fb 100644 --- a/src/main/java/io/polyfrost/oneconfig/lwjgl/IOUtil.java +++ b/src/main/java/io/polyfrost/oneconfig/lwjgl/IOUtil.java @@ -1,65 +1,53 @@ package io.polyfrost.oneconfig.lwjgl; -import java.io.IOException; -import java.io.InputStream; +import org.apache.commons.io.IOUtils; + +import java.io.*; +import java.net.URL; import java.nio.Buffer; import java.nio.ByteBuffer; -import java.nio.channels.Channels; -import java.nio.channels.ReadableByteChannel; -import java.nio.channels.SeekableByteChannel; -import java.nio.file.Files; -import java.nio.file.Path; -import java.nio.file.Paths; - -import static org.lwjgl.BufferUtils.createByteBuffer; -import static org.lwjgl.system.MemoryUtil.memSlice; +import java.nio.ByteOrder; -@SuppressWarnings("RedundantCast") -final class IOUtil { +public final class IOUtil { private IOUtil() { } - private static ByteBuffer resizeBuffer(ByteBuffer buffer, int newCapacity) { - ByteBuffer newBuffer = createByteBuffer(newCapacity); - ((Buffer) buffer).flip(); - newBuffer.put(buffer); - return newBuffer; - } - - static ByteBuffer resourceToByteBuffer(String resource, int bufferSize) throws IOException { - ByteBuffer buffer; - - Path path = Paths.get(resource); - if (Files.isReadable(path)) { - try (SeekableByteChannel fc = Files.newByteChannel(path)) { - buffer = createByteBuffer((int)fc.size() + 1); - while (fc.read(buffer) != -1) { - //noinspection UnnecessarySemicolon - ; - } - } + /** + * Taken from legui under MIT License + * https://github.com/SpinyOwl/legui/blob/develop/LICENSE + */ + @SuppressWarnings("RedundantCast") + public static ByteBuffer resourceToByteBuffer(String path) throws IOException { + byte[] bytes; + path = path.trim(); + if (path.startsWith("http")) { + bytes = IOUtils.toByteArray(new URL(path)); } else { - try ( - InputStream source = IOUtil.class.getResourceAsStream(resource); - ReadableByteChannel rbc = Channels.newChannel(source) - ) { - buffer = createByteBuffer(bufferSize); - - while (true) { - int bytes = rbc.read(buffer); - if (bytes == -1) { - break; - } - if (buffer.remaining() == 0) { - buffer = resizeBuffer(buffer, buffer.capacity() * 3 / 2); // 50% - } - } + InputStream stream; + File file = new File(path); + if (file.exists() && file.isFile()) { + stream = new FileInputStream(file); + } else { + stream = IOUtil.class.getResourceAsStream(path); + } + if (stream == null) { + throw new FileNotFoundException(path); } + bytes = IOUtils.toByteArray(stream); } + ByteBuffer data = ByteBuffer.allocateDirect(bytes.length).order(ByteOrder.nativeOrder()) + .put(bytes); + ((Buffer) data).flip(); + return data; + } - ((Buffer) buffer).flip(); - return memSlice(buffer); + public static ByteBuffer resourceToByteBufferNullable(String path) { + try { + return resourceToByteBuffer(path); + } catch (Exception ignored) { + return null; + } } }
\ No newline at end of file diff --git a/src/main/java/io/polyfrost/oneconfig/lwjgl/NanoVGUtils.java b/src/main/java/io/polyfrost/oneconfig/lwjgl/NanoVGUtils.java index f8dcafb..fc556fe 100644 --- a/src/main/java/io/polyfrost/oneconfig/lwjgl/NanoVGUtils.java +++ b/src/main/java/io/polyfrost/oneconfig/lwjgl/NanoVGUtils.java @@ -1,13 +1,18 @@ package io.polyfrost.oneconfig.lwjgl; +import io.polyfrost.oneconfig.lwjgl.image.Image; +import io.polyfrost.oneconfig.lwjgl.image.ImageLoader; import net.minecraft.client.Minecraft; import net.minecraft.client.renderer.GlStateManager; import net.minecraft.client.shader.Framebuffer; import org.lwjgl.nanovg.NVGColor; +import org.lwjgl.nanovg.NVGPaint; import org.lwjgl.opengl.Display; import org.lwjgl.opengl.GL11; import java.io.IOException; +import java.nio.ByteBuffer; +import java.util.ArrayList; import java.util.function.LongConsumer; import static org.lwjgl.nanovg.NanoVG.*; @@ -20,6 +25,7 @@ public final class NanoVGUtils { } private static long vg = -1; private static int font = -1; + private static final ArrayList<ByteBuffer> fontBuffers = new ArrayList<>(); public static void setupAndDraw(LongConsumer consumer) { if (vg == -1) { @@ -30,7 +36,9 @@ public final class NanoVGUtils { } if (font == -1) { try { - font = nvgCreateFontMem(vg, "custom-font", IOUtil.resourceToByteBuffer("/assets/oneconfig/font/Inter-Bold.ttf", 200 * 1024), 0); + ByteBuffer buffer = IOUtil.resourceToByteBuffer("/assets/oneconfig/font/Inter-Bold.ttf"); + font = nvgCreateFontMem(vg, "custom-font", buffer, 0); + fontBuffers.add(buffer); } catch (IOException e) { e.printStackTrace(); } @@ -57,22 +65,26 @@ public final class NanoVGUtils { public static void drawRect(long vg, float x, float y, float width, float height, int color) { nvgBeginPath(vg); nvgRect(vg, x, y, width, height); - color(vg, color); + NVGColor nvgColor = color(vg, color); nvgFill(vg); + nvgColor.free(); } public static void drawRoundedRect(long vg, float x, float y, float width, float height, int color, float radius) { nvgBeginPath(vg); nvgRoundedRect(vg, x, y, width, height, radius); color(vg, color); + NVGColor nvgColor = color(vg, color); nvgFill(vg); + nvgColor.free(); } public static void drawCircle(long vg, float x, float y, float radius, int color) { nvgBeginPath(vg); nvgCircle(vg, x, y, radius); - color(vg, color); + NVGColor nvgColor = color(vg, color); nvgFill(vg); + nvgColor.free(); } public static void drawString(long vg, String text, float x, float y, int color, float size) { @@ -80,14 +92,29 @@ public final class NanoVGUtils { nvgFontSize(vg, size); nvgFontFace(vg, "custom-font"); nvgTextAlign(vg, NVG_ALIGN_LEFT | NVG_ALIGN_MIDDLE); - color(vg, color); + NVGColor nvgColor = color(vg, color); nvgText(vg, x, y, text); nvgFill(vg); + nvgColor.free(); + } + + public static void drawImage(long vg, String fileName, float x, float y, float width, float height) { + if (ImageLoader.INSTANCE.loadImage(vg, fileName)) { + NVGPaint imagePaint = NVGPaint.calloc(); + Image image = ImageLoader.INSTANCE.getImage(fileName); + nvgBeginPath(vg); + nvgImagePattern(vg, x, y, width, height, 0, image.getReference(), 1, imagePaint); + nvgRect(vg, x, y, width, height); + nvgFillPaint(vg, imagePaint); + nvgFill(vg); + imagePaint.free(); + } } - public static void color(long vg, int color) { - NVGColor nvgColor = NVGColor.create(); + public static NVGColor color(long vg, int color) { + NVGColor nvgColor = NVGColor.calloc(); nvgRGBA((byte) (color >> 16 & 0xFF), (byte) (color >> 8 & 0xFF), (byte) (color & 0xFF), (byte) (color >> 24 & 0xFF), nvgColor); nvgFillColor(vg, nvgColor); + return nvgColor; } } diff --git a/src/main/java/io/polyfrost/oneconfig/lwjgl/image/Image.java b/src/main/java/io/polyfrost/oneconfig/lwjgl/image/Image.java new file mode 100644 index 0000000..2ed7276 --- /dev/null +++ b/src/main/java/io/polyfrost/oneconfig/lwjgl/image/Image.java @@ -0,0 +1,20 @@ +package io.polyfrost.oneconfig.lwjgl.image; + +import java.nio.ByteBuffer; + +public class Image { + private final int reference; + private final ByteBuffer buffer; + public Image(int reference, ByteBuffer buffer) { + this.reference = reference; + this.buffer = buffer; + } + + public ByteBuffer getBuffer() { + return buffer; + } + + public int getReference() { + return reference; + } +} diff --git a/src/main/java/io/polyfrost/oneconfig/lwjgl/image/ImageLoader.java b/src/main/java/io/polyfrost/oneconfig/lwjgl/image/ImageLoader.java new file mode 100644 index 0000000..b0cb6d4 --- /dev/null +++ b/src/main/java/io/polyfrost/oneconfig/lwjgl/image/ImageLoader.java @@ -0,0 +1,39 @@ +package io.polyfrost.oneconfig.lwjgl.image; + +import io.polyfrost.oneconfig.lwjgl.IOUtil; +import org.lwjgl.nanovg.NanoVG; +import org.lwjgl.stb.STBImage; + +import java.nio.ByteBuffer; +import java.util.HashMap; + +public class ImageLoader { + private final HashMap<String, Image> imageHashMap = new HashMap<>(); + public static ImageLoader INSTANCE = new ImageLoader(); + + public boolean loadImage(long vg, String fileName) { + if (!imageHashMap.containsKey(fileName)) { + int[] width = {0}; + int[] height = {0}; + int[] channels = {0}; + + ByteBuffer image = IOUtil.resourceToByteBufferNullable(fileName); + if (image == null) { + return false; + } + + ByteBuffer buffer = STBImage.stbi_load_from_memory(image, width, height, channels, 4); + if (buffer == null) { + return false; + } + + imageHashMap.put(fileName, new Image(NanoVG.nvgCreateImageRGBA(vg, width[0], height[0], NanoVG.NVG_IMAGE_REPEATX | NanoVG.NVG_IMAGE_REPEATY | NanoVG.NVG_IMAGE_GENERATE_MIPMAPS, buffer), buffer)); + return true; + } + return true; + } + + public Image getImage(String fileName) { + return imageHashMap.get(fileName); + } +} diff --git a/src/main/java/io/polyfrost/oneconfig/test/TestNanoVGGui.java b/src/main/java/io/polyfrost/oneconfig/test/TestNanoVGGui.java index 67e0a68..3f2fa27 100644 --- a/src/main/java/io/polyfrost/oneconfig/test/TestNanoVGGui.java +++ b/src/main/java/io/polyfrost/oneconfig/test/TestNanoVGGui.java @@ -15,6 +15,7 @@ public class TestNanoVGGui extends GuiScreen { NanoVGUtils.drawRect(vg, 0, 0, 300, 300, Color.BLUE.getRGB()); NanoVGUtils.drawRoundedRect(vg, 305, 305, 100, 100, Color.YELLOW.getRGB(), 8); NanoVGUtils.drawString(vg, "Hello!", 500, 500, Color.WHITE.getRGB(), 50); + NanoVGUtils.drawImage(vg, "/assets/oneconfig/textures/hudsettings.png", 10, 10, 400, 400); }); } } |