diff options
| author | isxander <xander@isxander.dev> | 2024-04-11 18:43:06 +0100 |
|---|---|---|
| committer | isxander <xander@isxander.dev> | 2024-04-11 18:43:06 +0100 |
| commit | 04fe933f4c24817100f3101f088accf55a621f8a (patch) | |
| tree | feff94ca3ab4484160e69a24f4ee38522381950e /common/src/main/java/dev/isxander/yacl3/gui/image | |
| parent | 831b894fdb7fe3e173d81387c8f6a2402b8ccfa9 (diff) | |
| download | YetAnotherConfigLib-04fe933f4c24817100f3101f088accf55a621f8a.tar.gz YetAnotherConfigLib-04fe933f4c24817100f3101f088accf55a621f8a.tar.bz2 YetAnotherConfigLib-04fe933f4c24817100f3101f088accf55a621f8a.zip | |
Extremely fragile and broken multiversion build with stonecutter
Diffstat (limited to 'common/src/main/java/dev/isxander/yacl3/gui/image')
7 files changed, 0 insertions, 686 deletions
diff --git a/common/src/main/java/dev/isxander/yacl3/gui/image/ImageRenderer.java b/common/src/main/java/dev/isxander/yacl3/gui/image/ImageRenderer.java deleted file mode 100644 index d3fb4bf..0000000 --- a/common/src/main/java/dev/isxander/yacl3/gui/image/ImageRenderer.java +++ /dev/null @@ -1,11 +0,0 @@ -package dev.isxander.yacl3.gui.image; - -import net.minecraft.client.gui.GuiGraphics; - -public interface ImageRenderer { - int render(GuiGraphics graphics, int x, int y, int renderWidth, float tickDelta); - - void close(); - - default void tick() {} -} diff --git a/common/src/main/java/dev/isxander/yacl3/gui/image/ImageRendererFactory.java b/common/src/main/java/dev/isxander/yacl3/gui/image/ImageRendererFactory.java deleted file mode 100644 index d9d2e2d..0000000 --- a/common/src/main/java/dev/isxander/yacl3/gui/image/ImageRendererFactory.java +++ /dev/null @@ -1,24 +0,0 @@ -package dev.isxander.yacl3.gui.image; - -public interface ImageRendererFactory { - /** - * Prepares the image. This can be run off-thread, - * and should NOT contain any GL calls whatsoever. - */ - ImageSupplier prepareImage() throws Exception; - - default boolean requiresOffThreadPreparation() { - return true; - } - - interface ImageSupplier { - ImageRenderer completeImage() throws Exception; - } - - interface OnThread extends ImageRendererFactory { - @Override - default boolean requiresOffThreadPreparation() { - return false; - } - } -} diff --git a/common/src/main/java/dev/isxander/yacl3/gui/image/ImageRendererManager.java b/common/src/main/java/dev/isxander/yacl3/gui/image/ImageRendererManager.java deleted file mode 100644 index 2f7ef50..0000000 --- a/common/src/main/java/dev/isxander/yacl3/gui/image/ImageRendererManager.java +++ /dev/null @@ -1,127 +0,0 @@ -package dev.isxander.yacl3.gui.image; - -import com.mojang.blaze3d.systems.RenderSystem; -import dev.isxander.yacl3.gui.image.impl.AnimatedDynamicTextureImage; -import dev.isxander.yacl3.impl.utils.YACLConstants; -import dev.isxander.yacl3.platform.YACLPlatform; -import net.minecraft.client.Minecraft; -import net.minecraft.resources.ResourceLocation; -import net.minecraft.server.packs.resources.Resource; - -import java.util.List; -import java.util.Map; -import java.util.Optional; -import java.util.concurrent.*; -import java.util.function.BiFunction; -import java.util.function.Predicate; -import java.util.function.Supplier; - -public class ImageRendererManager { - private static final ExecutorService SINGLE_THREAD_EXECUTOR = Executors.newSingleThreadExecutor(task -> new Thread(task, "YACL Image Prep")); - - private static final Map<ResourceLocation, CompletableFuture<ImageRenderer>> IMAGE_CACHE = new ConcurrentHashMap<>(); - static final Map<ResourceLocation, ImageRenderer> PRELOADED_IMAGE_CACHE = new ConcurrentHashMap<>(); - - static final List<PreloadedImageFactory> PRELOADED_IMAGE_FACTORIES = List.of( - new PreloadedImageFactory( - location -> location.getPath().endsWith(".webp"), - AnimatedDynamicTextureImage::createWEBPFromResource - ), - new PreloadedImageFactory( - location -> location.getPath().endsWith(".gif"), - AnimatedDynamicTextureImage::createGIFFromResource - ) - ); - - public static <T extends ImageRenderer> Optional<T> getImage(ResourceLocation id) { - if (PRELOADED_IMAGE_CACHE.containsKey(id)) { - return Optional.of((T) PRELOADED_IMAGE_CACHE.get(id)); - } - - if (IMAGE_CACHE.containsKey(id)) { - // warn developers if they don't put their webp/gif images `/textures` folder - if (YACLPlatform.isDevelopmentEnv()) { - if (PRELOADED_IMAGE_FACTORIES.stream().anyMatch(factory -> factory.predicate().test(id))) { - YACLConstants.LOGGER.error("Image '{}' not preloaded. MAKE SURE THAT ALL YACL WEBP/GIF IMAGES ARE INSIDE YOUR ASSETS `/textures` FOLDER, ELSE THEY WILL NOT BE PRELOADED!!! THIS ERROR WILL NOT APPEAR IN PROD", id); - } - } - - return Optional.ofNullable((T) IMAGE_CACHE.get(id).getNow(null)); - } - - return Optional.empty(); - } - - @SuppressWarnings("unchecked") - public static <T extends ImageRenderer> CompletableFuture<T> registerImage(ResourceLocation id, ImageRendererFactory factory) { - if (IMAGE_CACHE.containsKey(id)) { - return (CompletableFuture<T>) IMAGE_CACHE.get(id); - } - - var future = new CompletableFuture<ImageRenderer>(); - IMAGE_CACHE.put(id, future); - - SINGLE_THREAD_EXECUTOR.submit(() -> { - Supplier<Optional<ImageRendererFactory.ImageSupplier>> supplier = - factory.requiresOffThreadPreparation() - ? new CompletedSupplier<>(safelyPrepareFactory(id, factory)) - : () -> safelyPrepareFactory(id, factory); - - Minecraft.getInstance().execute(() -> completeImageFactory(id, supplier, future)); - }); - - return (CompletableFuture<T>) future; - } - - private static void completeImageFactory(ResourceLocation id, Supplier<Optional<ImageRendererFactory.ImageSupplier>> supplier, CompletableFuture<ImageRenderer> future) { - RenderSystem.assertOnRenderThread(); - - ImageRendererFactory.ImageSupplier completableImage = supplier.get().orElse(null); - if (completableImage == null) { - return; - } - - // sanity check - this should never happen - if (future.isDone()) { - YACLConstants.LOGGER.error("Image '{}' was already completed", id); - return; - } - - ImageRenderer image; - try { - image = completableImage.completeImage(); - } catch (Exception e) { - YACLConstants.LOGGER.error("Failed to create image '{}'", id, e); - return; - } - - future.complete(image); - } - - public static void closeAll() { - SINGLE_THREAD_EXECUTOR.shutdownNow(); - IMAGE_CACHE.values().removeIf(future -> { - if (future.isDone()) { - future.join().close(); - } - return true; - }); - } - - static Optional<ImageRendererFactory.ImageSupplier> safelyPrepareFactory(ResourceLocation id, ImageRendererFactory factory) { - try { - return Optional.of(factory.prepareImage()); - } catch (Exception e) { - YACLConstants.LOGGER.error("Failed to prepare image '{}'", id, e); - IMAGE_CACHE.remove(id); - return Optional.empty(); - } - } - - public record PreloadedImageFactory(Predicate<ResourceLocation> predicate, BiFunction<Resource, ResourceLocation, ImageRendererFactory> factory) { - } - - private record CompletedSupplier<T>(T get) implements Supplier<T> { - } - -} diff --git a/common/src/main/java/dev/isxander/yacl3/gui/image/YACLImageReloadListener.java b/common/src/main/java/dev/isxander/yacl3/gui/image/YACLImageReloadListener.java deleted file mode 100644 index bac8c56..0000000 --- a/common/src/main/java/dev/isxander/yacl3/gui/image/YACLImageReloadListener.java +++ /dev/null @@ -1,102 +0,0 @@ -package dev.isxander.yacl3.gui.image; - -import dev.isxander.yacl3.impl.utils.YACLConstants; -import net.minecraft.CrashReport; -import net.minecraft.CrashReportCategory; -import net.minecraft.ReportedException; -import net.minecraft.resources.ResourceLocation; -import net.minecraft.server.packs.resources.PreparableReloadListener; -import net.minecraft.server.packs.resources.Resource; -import net.minecraft.server.packs.resources.ResourceManager; -import net.minecraft.util.profiling.ProfilerFiller; - -import java.util.ArrayList; -import java.util.List; -import java.util.Map; -import java.util.Optional; -import java.util.concurrent.CompletableFuture; -import java.util.concurrent.Executor; -import java.util.function.Function; - -public class YACLImageReloadListener implements PreparableReloadListener { - @Override - public CompletableFuture<Void> reload( - PreparationBarrier preparationBarrier, - ResourceManager resourceManager, - ProfilerFiller preparationsProfiler, - ProfilerFiller reloadProfiler, - Executor backgroundExecutor, - Executor gameExecutor - ) { - YACLConstants.LOGGER.info("YACL is reloading images"); - Map<ResourceLocation, Resource> imageResources = resourceManager.listResources( - "textures", - location -> ImageRendererManager.PRELOADED_IMAGE_FACTORIES - .stream() - .anyMatch(factory -> factory.predicate().test(location)) - ); - - // extreme mojang hackery. - // for some reason this wait method needs to be called for the reload - // instance to be marked as complete - if (imageResources.isEmpty()) { - preparationBarrier.wait(null); - } - - List<CompletableFuture<?>> futures = new ArrayList<>(imageResources.size()); - - for (Map.Entry<ResourceLocation, Resource> entry : imageResources.entrySet()) { - ResourceLocation location = entry.getKey(); - Resource resource = entry.getValue(); - - ImageRendererFactory imageFactory = ImageRendererManager.PRELOADED_IMAGE_FACTORIES - .stream() - .filter(factory -> factory.predicate().test(location)) - .map(factory -> factory.factory().apply(resource, location)) - .findAny() - .orElseThrow(); - - CompletableFuture<Optional<ImageRenderer>> imageFuture = - CompletableFuture.supplyAsync( - () -> ImageRendererManager.safelyPrepareFactory( - location, imageFactory - ), - backgroundExecutor - ) - .thenCompose(preparationBarrier::wait) - .thenApplyAsync(imageSupplierOpt -> { - if (imageSupplierOpt.isEmpty()) { - return Optional.empty(); - } - ImageRendererFactory.ImageSupplier supplier = imageSupplierOpt.get(); - - ImageRenderer imageRenderer; - try { - imageRenderer = supplier.completeImage(); - } catch (Exception e) { - YACLConstants.LOGGER.error("Failed to create image '{}'", location, e); - return Optional.empty(); - } - - ImageRendererManager.PRELOADED_IMAGE_CACHE.put(location, imageRenderer); - - return Optional.of(imageRenderer); - }, gameExecutor); - - futures.add(imageFuture); - - imageFuture.whenComplete((result, throwable) -> { - if (throwable != null) { - CrashReport crashReport = CrashReport.forThrowable(throwable, "Failed to load image"); - CrashReportCategory category = crashReport.addCategory("YACL Gui"); - category.setDetail("Image identifier", location.toString()); - throw new ReportedException(crashReport); - } - }); - } - - YACLConstants.LOGGER.info("YACL has found {} images", imageResources.size()); - - return CompletableFuture.allOf(futures.toArray(CompletableFuture[]::new)); - } -} diff --git a/common/src/main/java/dev/isxander/yacl3/gui/image/impl/AnimatedDynamicTextureImage.java b/common/src/main/java/dev/isxander/yacl3/gui/image/impl/AnimatedDynamicTextureImage.java deleted file mode 100644 index 2136f56..0000000 --- a/common/src/main/java/dev/isxander/yacl3/gui/image/impl/AnimatedDynamicTextureImage.java +++ /dev/null @@ -1,294 +0,0 @@ -package dev.isxander.yacl3.gui.image.impl; - -import com.mojang.blaze3d.Blaze3D; -import com.mojang.blaze3d.platform.GlConst; -import com.mojang.blaze3d.platform.GlStateManager; -import com.mojang.blaze3d.platform.NativeImage; -import com.twelvemonkeys.imageio.plugins.webp.WebPImageReaderSpi; -import dev.isxander.yacl3.debug.DebugProperties; -import dev.isxander.yacl3.gui.image.ImageRendererFactory; -import dev.isxander.yacl3.impl.utils.YACLConstants; -import net.minecraft.CrashReport; -import net.minecraft.CrashReportCategory; -import net.minecraft.ReportedException; -import net.minecraft.client.Minecraft; -import net.minecraft.client.gui.GuiGraphics; -import net.minecraft.resources.ResourceLocation; -import net.minecraft.server.packs.resources.Resource; -import net.minecraft.server.packs.resources.ResourceManager; -import net.minecraft.util.FastColor; - -import javax.imageio.ImageIO; -import javax.imageio.ImageReader; -import javax.imageio.metadata.IIOMetadata; -import javax.imageio.metadata.IIOMetadataNode; -import java.awt.*; -import java.awt.image.BufferedImage; -import java.io.FileInputStream; -import java.io.IOException; -import java.io.InputStream; -import java.lang.reflect.Field; -import java.nio.file.Path; -import java.util.List; -import java.util.stream.IntStream; - -public class AnimatedDynamicTextureImage extends DynamicTextureImage { - private int currentFrame; - private double lastFrameTime; - - private final double[] frameDelays; - private final int frameCount; - - private final int packCols, packRows; - private final int frameWidth, frameHeight; - - public AnimatedDynamicTextureImage(NativeImage image, int frameWidth, int frameHeight, int frameCount, double[] frameDelayMS, int packCols, int packRows, ResourceLocation uniqueLocation) { - super(image, uniqueLocation); - this.frameWidth = frameWidth; - this.frameHeight = frameHeight; - this.frameCount = frameCount; - this.frameDelays = frameDelayMS; - this.packCols = packCols; - this.packRows = packRows; - } - - @Override - public int render(GuiGraphics graphics, int x, int y, int renderWidth, float tickDelta) { - if (image == null) return 0; - - float ratio = renderWidth / (float)frameWidth; - int targetHeight = (int) (frameHeight * ratio); - - int currentCol = currentFrame % packCols; - int currentRow = (int) Math.floor(currentFrame / (double)packCols); - - graphics.pose().pushPose(); - graphics.pose().translate(x, y, 0); - graphics.pose().scale(ratio, ratio, 1); - - if (DebugProperties.IMAGE_FILTERING) { - GlStateManager._texParameter(GlConst.GL_TEXTURE_2D, GlConst.GL_TEXTURE_MAG_FILTER, GlConst.GL_LINEAR); - GlStateManager._texParameter(GlConst.GL_TEXTURE_2D, GlConst.GL_TEXTURE_MIN_FILTER, GlConst.GL_LINEAR); - } - - graphics.blit( - uniqueLocation, - 0, 0, - frameWidth * currentCol, frameHeight * currentRow, - frameWidth, frameHeight, - this.width, this.height - ); - graphics.pose().popPose(); - - if (frameCount > 1) { - double timeMS = Blaze3D.getTime() * 1000; - if (lastFrameTime == 0) lastFrameTime = timeMS; - if (timeMS - lastFrameTime >= frameDelays[currentFrame]) { - currentFrame++; - lastFrameTime = timeMS; - } - if (currentFrame >= frameCount - 1) - currentFrame = 0; - } - - return targetHeight; - } - - public static ImageRendererFactory createGIFFromTexture(ResourceLocation textureLocation) { - return () -> { - ResourceManager resourceManager = Minecraft.getInstance().getResourceManager(); - Resource resource = resourceManager.getResource(textureLocation).orElseThrow(); - - return createGIFSupplier(resource.open(), textureLocation); - }; - } - - public static ImageRendererFactory createGIFFromResource(Resource resource, ResourceLocation resourceLocation) { - return () -> createGIFSupplier(resource.open(), resourceLocation); - } - - public static ImageRendererFactory createGIFFromPath(Path path, ResourceLocation uniqueLocation) { - return () -> createGIFSupplier(new FileInputStream(path.toFile()), uniqueLocation); - } - - public static ImageRendererFactory createWEBPFromTexture(ResourceLocation textureLocation) { - return () -> { - ResourceManager resourceManager = Minecraft.getInstance().getResourceManager(); - Resource resource = resourceManager.getResource(textureLocation).orElseThrow(); - - return createWEBPSupplier(resource.open(), textureLocation); - }; - } - - public static ImageRendererFactory createWEBPFromResource(Resource resource, ResourceLocation resourceLocation) { - return () -> createWEBPSupplier(resource.open(), resourceLocation); - } - - public static ImageRendererFactory createWEBPFromPath(Path path, ResourceLocation uniqueLocation) { - return () -> createWEBPSupplier(new FileInputStream(path.toFile()), uniqueLocation); - } - - private static ImageRendererFactory.ImageSupplier createGIFSupplier(InputStream is, ResourceLocation uniqueLocation) { - try (is) { - ImageReader reader = ImageIO.getImageReadersBySuffix("gif").next(); - reader.setInput(ImageIO.createImageInputStream(is)); - - AnimFrameProvider animFrameFunction = i -> { - IIOMetadata metadata = reader.getImageMetadata(i); - String metaFormatName = metadata.getNativeMetadataFormatName(); - IIOMetadataNode root = (IIOMetadataNode) metadata.getAsTree(metaFormatName); - IIOMetadataNode graphicsControlExtensionNode = (IIOMetadataNode) root.getElementsByTagName("GraphicControlExtension").item(0); - int delay = Integer.parseInt(graphicsControlExtensionNode.getAttribute("delayTime")) * 10; - - return new AnimFrame(delay, 0, 0); - }; - - return createFromImageReader(reader, animFrameFunction, uniqueLocation); - } catch (Exception e) { - CrashReport crashReport = CrashReport.forThrowable(e, "Failed to load GIF image"); - CrashReportCategory category = crashReport.addCategory("YACL Gui"); - category.setDetail("Image identifier", uniqueLocation.toString()); - throw new ReportedException(crashReport); - } - } - - private static ImageRendererFactory.ImageSupplier createWEBPSupplier(InputStream is, ResourceLocation uniqueLocation) { - try (is) { - ImageReader reader = new WebPImageReaderSpi().createReaderInstance(); - reader.setInput(ImageIO.createImageInputStream(is)); - - int numImages = reader.getNumImages(true); // Force reading of all frames - AnimFrameProvider animFrameFunction = i -> null; - if (numImages > 1) { - // WebP reader does not expose frame delay, prepare for reflection hell - Class<?> webpReaderClass = Class.forName("com.twelvemonkeys.imageio.plugins.webp.WebPImageReader"); - Field framesField = webpReaderClass.getDeclaredField("frames"); - framesField.setAccessible(true); - java.util.List<?> frames = (List<?>) framesField.get(reader); - - Class<?> animationFrameClass = Class.forName("com.twelvemonkeys.imageio.plugins.webp.AnimationFrame"); - Field durationField = animationFrameClass.getDeclaredField("duration"); - durationField.setAccessible(true); - Field boundsField = animationFrameClass.getDeclaredField("bounds"); - boundsField.setAccessible(true); - - animFrameFunction = i -> { - Rectangle bounds = (Rectangle) boundsField.get(frames.get(i)); - return new AnimFrame((int) durationField.get(frames.get(i)), bounds.x, bounds.y); - }; - // that was fun - } - - return createFromImageReader(reader, animFrameFunction, uniqueLocation); - } catch (Throwable e) { - CrashReport crashReport = CrashReport.forThrowable(e, "Failed to load WEBP image"); - CrashReportCategory category = crashReport.addCategory("YACL Gui"); - category.setDetail("Image identifier", uniqueLocation.toString()); - throw new ReportedException(crashReport); - } - } - - private static ImageRendererFactory.ImageSupplier createFromImageReader(ImageReader reader, AnimFrameProvider animationProvider, ResourceLocation uniqueLocation) throws Exception { - if (reader.isSeekForwardOnly()) { - throw new RuntimeException("Image reader is not seekable"); - } - - int frameCount = reader.getNumImages(true); - - // Because this is being backed into a texture atlas, we need a maximum dimension - // so you can get the texture atlas size. - // Smaller frames are given black borders - int frameWidth = IntStream.range(0, frameCount).map(i -> { - try { - return reader.getWidth(i); - } catch (IOException e) { - throw new RuntimeException(e); - } - }).max().orElseThrow(); - int frameHeight = IntStream.range(0, frameCount).map(i -> { - try { - return reader.getHeight(i); - } catch (IOException e) { - throw new RuntimeException(e); - } - }).max().orElseThrow(); - - // Packs the frames into an optimal 1:1 texture. - // OpenGL can only have texture axis with a max of 32768 pixels, - // and packing them to that length is not efficient, apparently. - double ratio = frameWidth / (double)frameHeight; - int cols = (int)Math.ceil(Math.sqrt(frameCount) / Math.sqrt(ratio)); - int rows = (int)Math.ceil(frameCount / (double)cols); - - NativeImage image = new NativeImage(NativeImage.Format.RGBA, frameWidth * cols, frameHeight * rows, false); - -// // Fill whole atlas with black, as each frame may have different dimensions -// // that would cause borders of transparent pixels to appear around the frames -// for (int x = 0; x < frameWidth * cols; x++) { -// for (int y = 0; y < frameHeight * rows; y++) { -// image.setPixelRGBA(x, y, 0xFF000000); -// } -// } - - BufferedImage bi = null; - Graphics2D graphics = null; - - // each frame may have a different delay - double[] frameDelays = new double[frameCount]; - - for (int i = 0; i < frameCount; i++) { - AnimFrame frame = animationProvider.get(i); - if (frameCount > 1) // frame will be null if not animation - frameDelays[i] = frame.durationMS; - - if (bi == null) { - // first frame... - bi = reader.read(i); - graphics = bi.createGraphics(); - } else { - // WebP reader sometimes provides delta frames, (only the pixels that changed since the last frame) - // so instead of overwriting the image every frame, we draw delta frames on top of the previous frame - // to keep a complete image. - BufferedImage deltaFrame = reader.read(i); - graphics.drawImage(deltaFrame, frame.xOffset, frame.yOffset, null); - } - - // Each frame may have different dimensions, so we need to center them. - int xOffset = (frameWidth - bi.getWidth()) / 2; - int yOffset = (frameHeight - bi.getHeight()) / 2; - - for (int w = 0; w < bi.getWidth(); w++) { - for (int h = 0; h < bi.getHeight(); h++) { - int rgb = bi.getRGB(w, h); - int r = FastColor.ARGB32.red(rgb); - int g = FastColor.ARGB32.green(rgb); - int b = FastColor.ARGB32.blue(rgb); - int a = FastColor.ARGB32.alpha(rgb); - - int col = i % cols; - int row = (int) Math.floor(i / (double)cols); - - image.setPixelRGBA( - frameWidth * col + w + xOffset, - frameHeight * row + h + yOffset, - FastColor.ABGR32.color(a, b, g, r) // NativeImage uses ABGR for some reason - ); - } - } - } - - if (graphics != null) - graphics.dispose(); - reader.dispose(); - - return () -> new AnimatedDynamicTextureImage(image, frameWidth, frameHeight, frameCount, frameDelays, cols, rows, uniqueLocation); - } - - @FunctionalInterface - private interface AnimFrameProvider { - AnimFrame get(int frame) throws Exception; - } - - private record AnimFrame(int durationMS, int xOffset, int yOffset) {} - -} diff --git a/common/src/main/java/dev/isxander/yacl3/gui/image/impl/DynamicTextureImage.java b/common/src/main/java/dev/isxander/yacl3/gui/image/impl/DynamicTextureImage.java deleted file mode 100644 index 2d2abb9..0000000 --- a/common/src/main/java/dev/isxander/yacl3/gui/image/impl/DynamicTextureImage.java +++ /dev/null @@ -1,72 +0,0 @@ -package dev.isxander.yacl3.gui.image.impl; - -import com.mojang.blaze3d.platform.GlConst; -import com.mojang.blaze3d.platform.GlStateManager; -import com.mojang.blaze3d.platform.NativeImage; -import com.mojang.blaze3d.systems.RenderSystem; -import dev.isxander.yacl3.debug.DebugProperties; -import dev.isxander.yacl3.gui.image.ImageRenderer; -import dev.isxander.yacl3.gui.image.ImageRendererFactory; -import net.minecraft.client.Minecraft; -import net.minecraft.client.gui.GuiGraphics; -import net.minecraft.client.renderer.texture.DynamicTexture; -import net.minecraft.client.renderer.texture.TextureManager; -import net.minecraft.resources.ResourceLocation; - -import java.io.FileInputStream; -import java.nio.file.Path; - -public class DynamicTextureImage implements ImageRenderer { - protected static final TextureManager textureManager = Minecraft.getInstance().getTextureManager(); - - protected NativeImage image; - protected DynamicTexture texture; - protected final ResourceLocation uniqueLocation; - protected final int width, height; - - public DynamicTextureImage(NativeImage image, ResourceLocation location) { - RenderSystem.assertOnRenderThread(); - - this.image = image; - this.texture = new DynamicTexture(image); - this.uniqueLocation = location; - textureManager.register(this.uniqueLocation, this.texture); - this.width = image.getWidth(); - this.height = image.getHeight(); - } - - @Override - public int render(GuiGraphics graphics, int x, int y, int renderWidth, float tickDelta) { - if (image == null) return 0; - - float ratio = renderWidth / (float)this.width; - int targetHeight = (int) (this.height * ratio); - - graphics.pose().pushPose(); - graphics.pose().translate(x, y, 0); - graphics.pose().scale(ratio, ratio, 1); - - if (DebugProperties.IMAGE_FILTERING) { - GlStateManager._texParameter(GlConst.GL_TEXTURE_2D, GlConst.GL_TEXTURE_MAG_FILTER, GlConst.GL_LINEAR); - GlStateManager._texParameter(GlConst.GL_TEXTURE_2D, GlConst.GL_TEXTURE_MIN_FILTER, GlConst.GL_LINEAR); - } - - graphics.blit(uniqueLocation, 0, 0, 0, 0, this.width, this.height, this.width, this.height); - - graphics.pose().popPose(); - - return targetHeight; - } - - @Override - public void close() { - image.close(); - image = null; - texture = null; - textureManager.release(uniqueLocation); - } - - public static ImageRendererFactory fromPath(Path imagePath, ResourceLocation location) { - return (ImageRendererFactory.OnThread) () -> () -> new DynamicTextureImage(NativeImage.read(new FileInputStream(imagePath.toFile())), location); - } -} diff --git a/common/src/main/java/dev/isxander/yacl3/gui/image/impl/ResourceTextureImage.java b/common/src/main/java/dev/isxander/yacl3/gui/image/impl/ResourceTextureImage.java deleted file mode 100644 index abbeec7..0000000 --- a/common/src/main/java/dev/isxander/yacl3/gui/image/impl/ResourceTextureImage.java +++ /dev/null @@ -1,56 +0,0 @@ -package dev.isxander.yacl3.gui.image.impl; - -import com.mojang.blaze3d.platform.GlConst; -import com.mojang.blaze3d.platform.GlStateManager; -import dev.isxander.yacl3.debug.DebugProperties; -import dev.isxander.yacl3.gui.image.ImageRenderer; -import dev.isxander.yacl3.gui.image.ImageRendererFactory; -import net.minecraft.client.gui.GuiGraphics; -import net.minecraft.resources.ResourceLocation; - -public class ResourceTextureImage implements ImageRenderer { - private final ResourceLocation location; - private final int width, height; - private final int textureWidth, textureHeight; - private final float u, v; - - public ResourceTextureImage(ResourceLocation location, float u, float v, int width, int height, int textureWidth, int textureHeight) { - this.location = location; - this.width = width; - this.height = height; - this.textureWidth = textureWidth; - this.textureHeight = textureHeight; - this.u = u; - this.v = v; - } - - @Override - public int render(GuiGraphics graphics, int x, int y, int renderWidth, float tickDelta) { - float ratio = renderWidth / (float)this.width; - int targetHeight = (int) (this.height * ratio); - - graphics.pose().pushPose(); - graphics.pose().translate(x, y, 0); - graphics.pose().scale(ratio, ratio, 1); - - if (DebugProperties.IMAGE_FILTERING) { - GlStateManager._texParameter(GlConst.GL_TEXTURE_2D, GlConst.GL_TEXTURE_MAG_FILTER, GlConst.GL_LINEAR); - GlStateManager._texParameter(GlConst.GL_TEXTURE_2D, GlConst.GL_TEXTURE_MIN_FILTER, GlConst.GL_LINEAR); - } - - graphics.blit(location, 0, 0, this.u, this.v, this.width, this.height, this.textureWidth, this.textureHeight); - - graphics.pose().popPose(); - - return targetHeight; - } - - @Override - public void close() { - - } - - public static ImageRendererFactory createFactory(ResourceLocation location, float u, float v, int width, int height, int textureWidth, int textureHeight) { - return (ImageRendererFactory.OnThread) () -> () -> new ResourceTextureImage(location, u, v, width, height, textureWidth, textureHeight); - } -} |
