Handle file drop events directly into the client

This commit is contained in:
Sollace 2018-06-07 19:56:34 +02:00
parent f39d55826c
commit 6cc976f1f8
5 changed files with 222 additions and 54 deletions

View file

@ -7,6 +7,8 @@ public final class Later extends Thread {
protected Later(int delay, Runnable runnable) { protected Later(int delay, Runnable runnable) {
super(runnable); super(runnable);
this.delay = delay; this.delay = delay;
setDaemon(true);
setName("Later#" + getId());
} }
public static void performLater(int delay, Runnable callable) { public static void performLater(int delay, Runnable callable) {

View file

@ -0,0 +1,184 @@
package com.voxelmodpack.hdskins.gui;
import java.awt.Canvas;
import java.awt.Frame;
import java.awt.dnd.DropTarget;
import java.awt.dnd.DropTargetListener;
import java.awt.event.ComponentAdapter;
import java.awt.event.ComponentEvent;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.awt.event.WindowStateListener;
import java.io.Closeable;
import java.io.IOException;
import java.util.TooManyListenersException;
import javax.imageio.ImageIO;
import javax.swing.JFrame;
import org.lwjgl.LWJGLException;
import org.lwjgl.opengl.Display;
import org.lwjgl.opengl.DisplayMode;
import com.google.common.collect.Lists;
import com.voxelmodpack.hdskins.Later;
import net.minecraft.client.Minecraft;
import net.minecraft.util.ResourceLocation;
public class GLWindow implements Closeable {
static GLWindow instance = null;
public static GLWindow current() {
if (instance == null) {
instance = new GLWindow();
}
return instance;
}
private final DropTarget dt;
private final JFrame frame;
private DropTargetListener saved = null;
private final int frameX = 15;
private final int frameY = 36;
private final Minecraft mc = Minecraft.getMinecraft();
private int state = 0;
private GLWindow() {
int x = Display.getX();
int y = Display.getY();
int w = Display.getWidth() + frameX;
int h = Display.getHeight() + frameY;
Canvas canvas = new Canvas();
frame = new JFrame(Display.getTitle());
frame.setResizable(Display.isResizable());
frame.setLocation(x, y);
frame.setSize(w, h);
frame.getContentPane().setLayout(null);
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
frame.addWindowListener(new WindowAdapter() {
@Override
public void windowClosing(WindowEvent windowEvent) {
Minecraft.getMinecraft().shutdown();
}
});
frame.addComponentListener(new ComponentAdapter() {
@Override
public void componentResized(ComponentEvent componentEvent) {
canvas.setBounds(0, 0, frame.getWidth() - frameX, frame.getHeight() - frameY);
}
});
frame.addWindowStateListener(new WindowStateListener() {
@Override
public void windowStateChanged(WindowEvent event) {
state = event.getNewState();
Later.performLater(1, () -> {
canvas.setBounds(0, 0, frame.getWidth() - frameX, frame.getHeight() - frameY);
});
}
});
setIcons(frame);
frame.getContentPane().add(canvas);
frame.setVisible(true);
try {
Display.setParent(canvas);
} catch (LWJGLException e) {
e.printStackTrace();
}
if (Display.getWidth() == Display.getDesktopDisplayMode().getWidth()) {
frame.setExtendedState(Frame.MAXIMIZED_BOTH);
}
state = frame.getExtendedState();
if (mc.isFullScreen()) {
try {
Display.setFullscreen(true);
} catch (LWJGLException e) {
e.printStackTrace();
}
}
dt = new DropTarget();
canvas.setDropTarget(dt);
}
private final void setIcons(JFrame frame) {
try {
frame.setIconImages(Lists.newArrayList(
ImageIO.read(mc.getResourceManager().getResource(new ResourceLocation("icons/icon_16x16.png")).getInputStream()),
ImageIO.read(mc.getResourceManager().getResource(new ResourceLocation("icons/icon_32x32.png")).getInputStream())
));
} catch (IOException e) {
e.printStackTrace();
}
}
public void setDropTargetListener(DropTargetListener dtl) {
if (saved != null) {
dt.removeDropTargetListener(saved);
}
if (dtl != null) {
try {
dt.addDropTargetListener(dtl);
} catch (TooManyListenersException e) { }
saved = dtl;
}
}
public static void dispose() {
if (instance != null) {
try {
instance.close();
} catch (IOException ignored) {
}
}
}
@Override
public void close() throws IOException {
mc.addScheduledTask(() -> {
try {
Display.setParent(null);
} catch (LWJGLException e) {
e.printStackTrace();
}
try {
if (mc.isFullScreen()) {
Display.setFullscreen(true);
} else {
if ((state & JFrame.MAXIMIZED_BOTH) == JFrame.MAXIMIZED_BOTH) {
Display.setLocation(0, 0);
Display.setDisplayMode(Display.getDesktopDisplayMode());
} else {
Display.setDisplayMode(new DisplayMode(mc.displayWidth, mc.displayHeight));
Display.setLocation(frame.getX(), frame.getY());
}
Display.setResizable(false);
Display.setResizable(true);
}
} catch (LWJGLException e) {
e.printStackTrace();
}
frame.setVisible(false);
frame.dispose();
instance = null;
});
}
}

View file

@ -35,18 +35,15 @@ import net.minecraft.util.text.TextFormatting;
import org.apache.commons.io.FilenameUtils; import org.apache.commons.io.FilenameUtils;
import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.LogManager;
import org.lwjgl.BufferUtils; import org.lwjgl.BufferUtils;
import org.lwjgl.opengl.Display;
import org.lwjgl.opengl.GL11; import org.lwjgl.opengl.GL11;
import org.lwjgl.util.glu.GLU; import org.lwjgl.util.glu.GLU;
import java.awt.Color;
import java.awt.Window.Type;
import java.awt.dnd.DropTarget;
import java.awt.image.BufferedImage; import java.awt.image.BufferedImage;
import java.io.File; import java.io.File;
import java.io.IOException; import java.io.IOException;
import java.nio.DoubleBuffer; import java.nio.DoubleBuffer;
import java.nio.file.Path; import java.nio.file.Path;
import javax.annotation.Nullable; import javax.annotation.Nullable;
import javax.imageio.ImageIO; import javax.imageio.ImageIO;
import javax.swing.*; import javax.swing.*;
@ -91,8 +88,6 @@ public class GuiSkins extends GuiScreen implements FutureCallback<SkinUploadResp
private float uploadOpacity = 0.0F; private float uploadOpacity = 0.0F;
private float lastPartialTick; private float lastPartialTick;
private static JFrame fileDrop;
private static GuiSkins instance; private static GuiSkins instance;
private MinecraftProfileTexture.Type textureType = SKIN; private MinecraftProfileTexture.Type textureType = SKIN;
@ -177,7 +172,7 @@ public class GuiSkins extends GuiScreen implements FutureCallback<SkinUploadResp
@Override @Override
public void initGui() { public void initGui() {
Later.performLater(1, this::enableDnd); enableDnd();
this.initPanoramaRenderer(); this.initPanoramaRenderer();
this.buttonList.clear(); this.buttonList.clear();
@ -197,44 +192,9 @@ public class GuiSkins extends GuiScreen implements FutureCallback<SkinUploadResp
} }
private void enableDnd() { private void enableDnd() {
if (fileDrop != null) { GLWindow.current().setDropTargetListener((FileDropListener) files -> {
fileDrop.setVisible(true);
fileDrop.requestFocusInWindow();
fileDrop.setLocation(Display.getX(), Display.getY());
return;
}
fileDrop = new JFrame("Skin Drop");
fileDrop.setType(Type.UTILITY);
fileDrop.setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);
fileDrop.setResizable(false);
fileDrop.setTitle("Skin Drop");
fileDrop.setSize(256, 256);
fileDrop.setAlwaysOnTop(true);
fileDrop.getRootPane().setWindowDecorationStyle(JRootPane.NONE);
fileDrop.setLocation(Display.getX(), Display.getY());
fileDrop.getContentPane().setLayout(null);
JPanel panel = new JPanel();
panel.setBorder(BorderFactory.createMatteBorder(1, 1, 1, 1, Color.GRAY));
panel.setBounds(10, 11, 230, 205);
fileDrop.getContentPane().add(panel);
JLabel txtInst = new JLabel("Drop skin file here");
txtInst.setHorizontalAlignment(SwingConstants.CENTER);
txtInst.setVerticalAlignment(SwingConstants.CENTER);
panel.add(txtInst);
DropTarget dt = new DropTarget();
fileDrop.setDropTarget(dt);
try {
dt.addDropTargetListener((FileDropListener) files -> {
files.stream().findFirst().ifPresent(instance::loadLocalFile); files.stream().findFirst().ifPresent(instance::loadLocalFile);
}); });
fileDrop.setVisible(true);
fileDrop.requestFocusInWindow();
} catch (Exception e) {
e.printStackTrace();
}
} }
private void initPanoramaRenderer() { private void initPanoramaRenderer() {
@ -247,14 +207,6 @@ public class GuiSkins extends GuiScreen implements FutureCallback<SkinUploadResp
localPlayer.releaseTextures(); localPlayer.releaseTextures();
remotePlayer.releaseTextures(); remotePlayer.releaseTextures();
HDSkinManager.clearSkinCache(); HDSkinManager.clearSkinCache();
Later.performLater(1, () -> {
if (!(Minecraft.getMinecraft().currentScreen instanceof GuiSkins)) {
if (fileDrop != null) {
fileDrop.setVisible(false);
}
}
});
} }
private void onFileOpenDialogClosed(JFileChooser fileDialog, int dialogResult) { private void onFileOpenDialogClosed(JFileChooser fileDialog, int dialogResult) {
@ -307,7 +259,7 @@ public class GuiSkins extends GuiScreen implements FutureCallback<SkinUploadResp
this.selectedSkin = null; this.selectedSkin = null;
this.localPlayer.releaseTextures(); this.localPlayer.releaseTextures();
this.openFileThread = new ThreadOpenFilePNG(this.mc, I18n.format("hdskins.open.title"), this::onFileOpenDialogClosed); this.openFileThread = new ThreadOpenFilePNG(this.mc, I18n.format("hdskins.open.title"), this::onFileOpenDialogClosed);
this.openFileThread.setParent(fileDrop).start(); this.openFileThread.start();
guiButton.enabled = false; guiButton.enabled = false;
} }

View file

@ -0,0 +1,29 @@
package com.voxelmodpack.hdskins.mixin;
import java.io.IOException;
import org.lwjgl.LWJGLException;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import com.voxelmodpack.hdskins.gui.GLWindow;
import net.minecraft.client.Minecraft;
import net.minecraft.crash.CrashReport;
@Mixin(Minecraft.class)
public class MixinMinecraft {
//public void displayCrashReport(CrashReport crashReportIn)
@Inject(method = "displayCrashReport(Lnet/minecraft/crash/CrashReport;)V", at = @At("HEAD"))
private void onGameCrash(CrashReport report, CallbackInfo info) {
GLWindow.dispose();
}
@Inject(method = "init()V", at = @At("RETURN"))
private void onInit(CallbackInfo info) throws LWJGLException, IOException {
GLWindow.current();
}
}

View file

@ -4,6 +4,7 @@
"package": "com.voxelmodpack.hdskins.mixin", "package": "com.voxelmodpack.hdskins.mixin",
"refmap": "hdskins.mixin.refmap.json", "refmap": "hdskins.mixin.refmap.json",
"mixins": [ "mixins": [
"MixinMinecraft",
"MixinGuiMainMenu", "MixinGuiMainMenu",
"MixinImageBufferDownload", "MixinImageBufferDownload",
"MixinPlayerInfo", "MixinPlayerInfo",