Last active
February 1, 2016 05:59
-
-
Save tterrag1098/212afae4c9f12541b496 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package com.creatubbles.ctbmod.client.gui.upload; | |
import java.awt.Point; | |
import java.awt.Rectangle; | |
import java.io.File; | |
import java.io.FilenameFilter; | |
import java.util.Arrays; | |
import java.util.Collections; | |
import java.util.List; | |
import java.util.concurrent.Executors; | |
import java.util.concurrent.Future; | |
import lombok.Getter; | |
import lombok.Value; | |
import net.minecraft.client.Minecraft; | |
import net.minecraft.client.gui.Gui; | |
import net.minecraft.client.renderer.GlStateManager; | |
import net.minecraft.client.renderer.Tessellator; | |
import net.minecraft.client.renderer.WorldRenderer; | |
import net.minecraft.client.renderer.vertex.DefaultVertexFormats; | |
import net.minecraft.util.MathHelper; | |
import org.apache.commons.io.comparator.LastModifiedFileComparator; | |
import org.apache.commons.io.filefilter.FileFilterUtils; | |
import org.lwjgl.util.Dimension; | |
import com.creatubbles.ctbmod.client.gui.creator.OverlayBase; | |
import com.creatubbles.repack.endercore.api.client.gui.IGuiScreen; | |
import com.creatubbles.repack.endercore.client.gui.widget.GuiToolTip; | |
import com.google.common.collect.Lists; | |
import com.google.common.util.concurrent.ListenableFuture; | |
import com.google.common.util.concurrent.ListeningExecutorService; | |
import com.google.common.util.concurrent.MoreExecutors; | |
import static com.creatubbles.ctbmod.client.gui.upload.ThumbnailStitcher.*; | |
public class OverlayScreenshotThumbs extends OverlayBase<GuiScreenshotList> { | |
private static final ListeningExecutorService executor = MoreExecutors.listeningDecorator(Executors.newSingleThreadExecutor()); | |
private static ThumbnailStitcher prevStitcher = null; | |
private static File[] prevFiles = null; | |
private ThumbnailStitcher stitcher; | |
private Future<?> stitchTask; | |
private List<File> screenshots; | |
private List<ThumbnailAndLocation> thumbnails = Lists.newArrayList(); | |
private ListenableFuture<?> listTask; | |
private int thumbSize = 64; | |
private int padding = 16; | |
@Getter | |
private int pages; | |
@Getter | |
private int page; | |
public OverlayScreenshotThumbs(int x, int y, Dimension dimension) { | |
super(x, y, dimension); | |
final File[] files = new File(Minecraft.getMinecraft().mcDataDir, "screenshots").listFiles((FilenameFilter) FileFilterUtils.suffixFileFilter(".png")); | |
if (Arrays.equals(files, prevFiles)) { | |
stitcher = prevStitcher; | |
} else { | |
prevFiles = files; | |
if (prevStitcher != null) { | |
prevStitcher.dispose(); | |
} | |
stitcher = prevStitcher = new ThumbnailStitcher(); | |
stitchTask = executor.submit(new Runnable() { | |
@Override | |
public void run() { | |
stitcher.loadFiles(files); | |
} | |
}); | |
} | |
screenshots = Lists.newArrayList(files); | |
Collections.sort(screenshots, LastModifiedFileComparator.LASTMODIFIED_REVERSE); | |
} | |
@Value | |
private class ThumbnailAndLocation { | |
private Rectangle slot; | |
private Point location; | |
private Rectangle bounds; | |
private GuiToolTip tooltip; | |
private int page; | |
private ThumbnailAndLocation(File f, Point p, int page) { | |
this.slot = new Rectangle(stitcher.getRect(f)); | |
this.location = p; | |
this.page = page; | |
int widthOff = ((WIDTH - slot.width) / 2); | |
int heightOff = ((HEIGHT - slot.height) / 2); | |
slot.x += widthOff; | |
slot.y += heightOff; | |
bounds = new Rectangle(p.x + (widthOff / 2), p.y + (heightOff / 2), 64 - widthOff, 64 - heightOff); | |
List<String> tt = Lists.newArrayList(); | |
tt.add(f.getName()); | |
tooltip = new GuiToolTip(bounds, tt); | |
} | |
} | |
@Override | |
public void init(IGuiScreen screen) { | |
super.init(screen); | |
thumbnails.clear(); | |
Runnable listBuilder = new Runnable() { | |
public void run() { | |
int perRow = (getWidth() - padding) / (padding + thumbSize); | |
int perCol = (getHeight() - padding) / (padding + thumbSize); | |
System.out.println(screenshots.size()); | |
pages = (int) Math.ceil(((double) screenshots.size() / (perRow * perCol))); | |
page = MathHelper.clamp_int(page, 0, pages - 1); | |
int xOff = (getWidth() - (padding + ((thumbSize + padding) * perRow))) / 2; | |
int yOff = (getHeight() - (padding + ((thumbSize + padding) * perCol))) / 2; | |
int row = 0, col = 0, page = 0; | |
for (File f : screenshots) { | |
int x = getX() + xOff + padding + ((thumbSize + padding) * col); | |
int y = getY() + yOff + padding + ((thumbSize + padding) * row); | |
thumbnails.add(new ThumbnailAndLocation(f, new Point(x, y), page)); | |
if (++col >= perRow) { | |
col = 0; | |
row++; | |
} | |
if (row >= perCol) { | |
row = col = 0; | |
page++; | |
} | |
} | |
} | |
}; | |
if (stitchTask == null || stitchTask.isDone()) { | |
listBuilder.run(); | |
} else { | |
listTask = executor.submit(listBuilder); | |
} | |
} | |
public void onListBuilt(Runnable toRun) { | |
if (listTask == null || listTask.isDone()) { | |
toRun.run(); | |
} else { | |
listTask.addListener(toRun, MoreExecutors.sameThreadExecutor()); | |
} | |
} | |
@Override | |
protected void doDraw(int mouseX, int mouseY, float partialTick) { | |
super.doDraw(mouseX, mouseY, partialTick); | |
WorldRenderer worldrenderer = Tessellator.getInstance().getWorldRenderer(); | |
Minecraft.getMinecraft().getTextureManager().bindTexture(Gui.optionsBackground); | |
GlStateManager.color(1.0F, 1.0F, 1.0F, 1.0F); | |
float f = 32.0F; | |
worldrenderer.begin(7, DefaultVertexFormats.POSITION_TEX_COLOR); | |
int left = getX(), top = getY(); | |
int right = left + getWidth(), bottom = top + getHeight(); | |
worldrenderer.pos(left, bottom, 0.0D).tex(left / f, bottom / f).color(32, 32, 32, 255).endVertex(); | |
worldrenderer.pos(right, bottom, 0.0D).tex(right / f, bottom / f).color(32, 32, 32, 255).endVertex(); | |
worldrenderer.pos(right, top, 0.0D).tex(right / f, top/ f).color(32, 32, 32, 255).endVertex(); | |
worldrenderer.pos(left, top, 0.0D).tex(left / f, top / f).color(32, 32, 32, 255).endVertex(); | |
Tessellator.getInstance().draw(); | |
GlStateManager.enableTexture2D(); | |
GlStateManager.disableLighting(); | |
if (listTask == null || listTask.isDone()) { | |
Minecraft.getMinecraft().getTextureManager().bindTexture(stitcher.getRes()); | |
for (ThumbnailAndLocation thumb : thumbnails) { | |
if (thumb.getPage() == page) { | |
Rectangle bounds = thumb.getBounds(); | |
Rectangle slot = thumb.getSlot(); | |
if (bounds.contains(mouseX, mouseY)) { | |
drawRect(bounds.x - 1, bounds.y - 1, bounds.x + bounds.width + 1, bounds.y + bounds.height + 1, 0xFFFFFFFF); | |
} | |
drawScaledCustomSizeModalRect(bounds.x, bounds.y, slot.x, slot.y, slot.width, slot.height, bounds.width, bounds.height, stitcher.getWidth(), stitcher.getHeight()); | |
} | |
} | |
} else { | |
drawCenteredString(Minecraft.getMinecraft().fontRendererObj, "Loading...", left + getWidth() / 2, top + getHeight() / 2, 0xFFFFFF); | |
} | |
} | |
public void page(int delta) { | |
this.page = MathHelper.clamp_int(page + delta, 0, pages - 1); | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package com.creatubbles.ctbmod.client.gui.upload; | |
import java.awt.Color; | |
import java.awt.Graphics2D; | |
import java.awt.Image; | |
import java.awt.Rectangle; | |
import java.awt.image.BufferedImage; | |
import java.io.File; | |
import java.util.Map; | |
import java.util.Map.Entry; | |
import javax.imageio.ImageIO; | |
import lombok.Getter; | |
import lombok.SneakyThrows; | |
import net.minecraft.client.Minecraft; | |
import net.minecraft.util.ResourceLocation; | |
import org.lwjgl.opengl.GL11; | |
import com.creatubbles.ctbmod.client.gui.LazyLoadedTexture; | |
import com.creatubbles.ctbmod.client.gui.creator.OverlayCreationList; | |
import com.google.common.collect.Maps; | |
public class ThumbnailStitcher { | |
public static final int WIDTH = 128; | |
public static final int HEIGHT = WIDTH; | |
private static final int MAX_SIZE = Minecraft.getGLMaximumTextureSize(); | |
private BufferedImage map; | |
@Getter | |
private ResourceLocation res = OverlayCreationList.LOADING_TEX; | |
private Map<File, Rectangle> rects = Maps.newHashMap(); | |
@SneakyThrows | |
public void loadFiles(final File... files) { | |
Map<File, Image> images = Maps.newHashMap(); | |
int type = -1; | |
for (File f : files) { | |
BufferedImage img = ImageIO.read(f); | |
if (type == -1) { | |
type = img.getType(); | |
} | |
int w = img.getWidth(), h = img.getHeight(); | |
int scaledW, scaledH; | |
if (w > h) { | |
scaledW = WIDTH; | |
scaledH = (int) (((double) h / w) * HEIGHT); | |
} else { | |
scaledH = HEIGHT; | |
scaledW = (int) (((double) w / h) * WIDTH); | |
} | |
images.put(f, img.getScaledInstance(scaledW, scaledH, BufferedImage.SCALE_SMOOTH)); | |
} | |
double sqrt = Math.sqrt(images.size()); | |
int width = (int) sqrt; | |
if (sqrt != width) { | |
width++; | |
} | |
width *= WIDTH; | |
int scaled = 2 << (32 - Integer.numberOfLeadingZeros(width - 1)) - 1; | |
if (scaled > MAX_SIZE) { | |
throw new IllegalStateException("Cannot load thumbnail sheet, not enough size! Max: " + MAX_SIZE + " Needed: " + scaled); | |
} | |
map = new BufferedImage(scaled, scaled, BufferedImage.TYPE_4BYTE_ABGR); | |
Graphics2D out = map.createGraphics(); | |
try { | |
int x, y; | |
x = y = 0; | |
for (Entry<File, Image> e : images.entrySet()) { | |
BufferedImage full = new BufferedImage(WIDTH, HEIGHT, BufferedImage.TYPE_4BYTE_ABGR); | |
Image thumb = e.getValue(); | |
int w = thumb.getWidth(null), h = thumb.getHeight(null); | |
Graphics2D transcribe = full.createGraphics(); | |
try { | |
transcribe.setColor(new Color(0, 0, 0, 0)); | |
transcribe.fillRect(0, 0, WIDTH, HEIGHT); | |
transcribe.drawImage(thumb, Math.max(0, h - w) / 2, Math.max(0, w - h) / 2, null); | |
} finally { | |
transcribe.dispose(); | |
} | |
out.drawImage(full, x, y, null); | |
rects.put(e.getKey(), new Rectangle(x, y, w, h)); | |
x += WIDTH; | |
if (x >= width) { | |
x = 0; | |
y += HEIGHT; | |
} | |
} | |
} finally { | |
out.dispose(); | |
} | |
final LazyLoadedTexture tex = new LazyLoadedTexture(map); | |
Minecraft.getMinecraft().addScheduledTask(new Runnable() { | |
@Override | |
public void run() { | |
tex.uploadTexture(); | |
ResourceLocation loc = new ResourceLocation("ctbmod", files[0].getParentFile().getName()); | |
Minecraft.getMinecraft().getTextureManager().loadTexture(loc, tex); | |
res = loc; | |
} | |
}); | |
} | |
public Rectangle getRect(File f) { | |
return rects.get(f); | |
} | |
public int getWidth() { | |
return map.getWidth(); | |
} | |
public int getHeight() { | |
return map.getHeight(); | |
} | |
public void dispose() { | |
GL11.glDeleteTextures(Minecraft.getMinecraft().getTextureManager().getTexture(res).getGlTextureId()); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment