Add 360° screenshot feature when pressing Ctrl + Screenshot Keybind

This commit is contained in:
CrushedPixel
2017-09-27 00:16:39 +02:00
parent adfe6a2bfc
commit 9671ee605d
6 changed files with 168 additions and 1 deletions

View File

@@ -1,6 +1,7 @@
package com.replaymod.extras; package com.replaymod.extras;
import com.replaymod.core.ReplayMod; import com.replaymod.core.ReplayMod;
import com.replaymod.extras.advancedscreenshots.AdvancedScreenshots;
import com.replaymod.extras.playeroverview.PlayerOverview; import com.replaymod.extras.playeroverview.PlayerOverview;
import com.replaymod.extras.urischeme.UriSchemeExtra; import com.replaymod.extras.urischeme.UriSchemeExtra;
import com.replaymod.extras.youtube.YoutubeUpload; import com.replaymod.extras.youtube.YoutubeUpload;
@@ -27,6 +28,7 @@ public class ReplayModExtras {
public static ReplayModExtras instance; public static ReplayModExtras instance;
private static final List<Class<? extends Extra>> builtin = Arrays.asList( private static final List<Class<? extends Extra>> builtin = Arrays.asList(
AdvancedScreenshots.class,
PlayerOverview.class, PlayerOverview.class,
UriSchemeExtra.class, UriSchemeExtra.class,
YoutubeUpload.class, YoutubeUpload.class,

View File

@@ -0,0 +1,93 @@
package com.replaymod.extras.advancedscreenshots;
import com.replaymod.core.ReplayMod;
import com.replaymod.extras.Extra;
import com.replaymod.render.RenderSettings;
import com.replaymod.render.capturer.RenderInfo;
import com.replaymod.render.hooks.ChunkLoadingRenderGlobal;
import com.replaymod.render.rendering.Pipelines;
import com.replaymod.replay.events.ReplayDispatchKeypressesEvent;
import net.minecraft.client.Minecraft;
import net.minecraft.client.gui.GuiControls;
import net.minecraft.client.gui.GuiScreen;
import net.minecraft.util.ScreenShotHelper;
import net.minecraftforge.common.MinecraftForge;
import net.minecraftforge.fml.common.eventhandler.SubscribeEvent;
import org.lwjgl.input.Keyboard;
import org.lwjgl.util.Dimension;
import org.lwjgl.util.ReadableDimension;
import java.io.File;
public class AdvancedScreenshots implements Extra {
private final Minecraft mc = Minecraft.getMinecraft();
@Override
public void register(ReplayMod mod) throws Exception {
MinecraftForge.EVENT_BUS.register(this);
}
@SubscribeEvent
public void onDispatchKeypresses(ReplayDispatchKeypressesEvent.Pre event) {
int i = Keyboard.getEventKey() == 0 ? Keyboard.getEventCharacter() : Keyboard.getEventKey();
// all the conditions required to trigger a screenshot condensed in a single if statement
if (i != 0 && !Keyboard.isRepeatEvent()
&& (!(mc.currentScreen instanceof GuiControls) || ((GuiControls) mc.currentScreen).time <= mc.getSystemTime() - 20L)
&& Keyboard.getEventKeyState()
&& i == mc.gameSettings.keyBindScreenshot.getKeyCode()) {
if (GuiScreen.isCtrlKeyDown()) {
ReplayMod.instance.runLater(() -> {
// take 360° screenshot
File screenshotFolder = new File(mc.mcDataDir, "screenshots");
screenshotFolder.mkdir();
File screenshotFile = ScreenShotHelper.getTimestampedPNGFileForDirectory(screenshotFolder);
int width = 8640;
int height = 4320;
int displayWidthBefore = mc.displayWidth;
int displayHeightBefore = mc.displayHeight;
ChunkLoadingRenderGlobal clrg = new ChunkLoadingRenderGlobal(mc.renderGlobal);
Pipelines.newEquirectangularPipeline(new RenderInfo() {
@Override
public ReadableDimension getFrameSize() {
return new Dimension(width, height);
}
@Override
public int getTotalFrames() {
return 1;
}
@Override
public float updateForNextFrame() {
return mc.timer.renderPartialTicks;
}
@Override
public RenderSettings getRenderSettings() {
return new RenderSettings(
null, null, width, height, 0, 0, null,
true, true, true, true, null,
false, RenderSettings.AntiAliasing.NONE, null, null, false
);
}
}, new ScreenshotWriter(screenshotFile)).run();
clrg.uninstall();
// the Equirectangular rendering changes mc.displayWidth and mc.displayHeight,
// so we have to reset it to the previous value
mc.resize(displayWidthBefore, displayHeightBefore);
});
event.setCanceled(true);
}
}
}
}

View File

@@ -0,0 +1,56 @@
package com.replaymod.extras.advancedscreenshots;
import com.replaymod.core.ReplayMod;
import com.replaymod.core.utils.Utils;
import com.replaymod.extras.ReplayModExtras;
import com.replaymod.render.frame.RGBFrame;
import com.replaymod.render.rendering.FrameConsumer;
import com.replaymod.replay.ReplayModReplay;
import net.minecraft.crash.CrashReport;
import org.lwjgl.util.ReadableDimension;
import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
public class ScreenshotWriter implements FrameConsumer<RGBFrame> {
private final File outputFile;
public ScreenshotWriter(File outputFile) {
this.outputFile = outputFile;
}
@Override
public void consume(RGBFrame frame) {
try {
final ReadableDimension frameSize = frame.getSize();
BufferedImage img = new BufferedImage(frameSize.getWidth(), frameSize.getHeight(), BufferedImage.TYPE_INT_RGB);
for (int y = 0; y < frameSize.getHeight(); y++) {
for (int x = 0; x < frameSize.getWidth(); x++) {
byte r = frame.getByteBuffer().get();
byte g = frame.getByteBuffer().get();
byte b = frame.getByteBuffer().get();
int color = ((r & 0xff) << 16) | ((g & 0xff) << 8) | (b & 0xff);
img.setRGB(x, y, color);
}
}
ImageIO.write(img, "PNG", outputFile);
} catch (Throwable t) {
CrashReport report = CrashReport.makeCrashReport(t, "Exporting frame");
ReplayMod.instance.runLater(() -> Utils.error(ReplayModExtras.LOGGER,
ReplayModReplay.instance.getReplayHandler().getOverlay(),
report, null));
}
}
@Override
public void close() throws IOException {
}
}

View File

@@ -3,6 +3,7 @@ package com.replaymod.replay;
import com.replaymod.core.utils.WrappedTimer; import com.replaymod.core.utils.WrappedTimer;
import com.replaymod.replay.camera.CameraController; import com.replaymod.replay.camera.CameraController;
import com.replaymod.replay.camera.CameraEntity; import com.replaymod.replay.camera.CameraEntity;
import com.replaymod.replay.events.ReplayDispatchKeypressesEvent;
import net.minecraft.client.Minecraft; import net.minecraft.client.Minecraft;
import net.minecraft.client.gui.GuiScreen; import net.minecraft.client.gui.GuiScreen;
import net.minecraft.client.settings.GameSettings; import net.minecraft.client.settings.GameSettings;
@@ -11,6 +12,7 @@ import net.minecraft.crash.CrashReport;
import net.minecraft.util.ReportedException; import net.minecraft.util.ReportedException;
import net.minecraft.util.Timer; import net.minecraft.util.Timer;
import net.minecraftforge.client.ForgeHooksClient; import net.minecraftforge.client.ForgeHooksClient;
import net.minecraftforge.common.MinecraftForge;
import net.minecraftforge.fml.common.FMLCommonHandler; import net.minecraftforge.fml.common.FMLCommonHandler;
import org.lwjgl.input.Keyboard; import org.lwjgl.input.Keyboard;
import org.lwjgl.input.Mouse; import org.lwjgl.input.Mouse;
@@ -122,7 +124,9 @@ public class InputReplayTimer extends WrappedTimer {
} }
// Twitch, screenshot, fullscreen, etc. (stuff that works everywhere) // Twitch, screenshot, fullscreen, etc. (stuff that works everywhere)
mc.dispatchKeypresses(); if (!MinecraftForge.EVENT_BUS.post(new ReplayDispatchKeypressesEvent.Pre())) {
mc.dispatchKeypresses();
}
if (pressed) { if (pressed) {
// This might be subject to change as vanilla shaders are still kinda unused in 1.8 // This might be subject to change as vanilla shaders are still kinda unused in 1.8

View File

@@ -0,0 +1,9 @@
package com.replaymod.replay.events;
import net.minecraftforge.fml.common.eventhandler.Cancelable;
import net.minecraftforge.fml.common.eventhandler.Event;
@Cancelable
public abstract class ReplayDispatchKeypressesEvent extends Event {
public static class Pre extends ReplayDispatchKeypressesEvent {}
}

View File

@@ -117,5 +117,8 @@ public net.minecraft.client.renderer.GlStateManager$FogState
public net.minecraft.client.renderer.GlStateManager$BooleanState public net.minecraft.client.renderer.GlStateManager$BooleanState
public net.minecraft.client.renderer.GlStateManager$BooleanState * public net.minecraft.client.renderer.GlStateManager$BooleanState *
# ScreenShotHelper
public net.minecraft.util.ScreenShotHelper func_74290_a(Ljava/io/File;)Ljava/io/File; # getTimestampedPNGFileForDirectory
# Example # Example
# public net.minecraft.package.ClassName func_some_id(Ljava/lang/Class;IZS)V # methodName # public net.minecraft.package.ClassName func_some_id(Ljava/lang/Class;IZS)V # methodName