Added Screenshot export settings GUI
This commit is contained in:
@@ -2,24 +2,12 @@ package com.replaymod.extras.advancedscreenshots;
|
|||||||
|
|
||||||
import com.replaymod.core.ReplayMod;
|
import com.replaymod.core.ReplayMod;
|
||||||
import com.replaymod.extras.Extra;
|
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.ReplayModReplay;
|
|
||||||
import com.replaymod.replay.events.ReplayDispatchKeypressesEvent;
|
import com.replaymod.replay.events.ReplayDispatchKeypressesEvent;
|
||||||
import net.minecraft.client.Minecraft;
|
import net.minecraft.client.Minecraft;
|
||||||
import net.minecraft.client.gui.GuiControls;
|
import net.minecraft.client.gui.GuiControls;
|
||||||
import net.minecraft.client.gui.GuiScreen;
|
|
||||||
import net.minecraft.crash.CrashReport;
|
|
||||||
import net.minecraft.util.ScreenShotHelper;
|
|
||||||
import net.minecraftforge.common.MinecraftForge;
|
import net.minecraftforge.common.MinecraftForge;
|
||||||
import net.minecraftforge.fml.common.eventhandler.SubscribeEvent;
|
import net.minecraftforge.fml.common.eventhandler.SubscribeEvent;
|
||||||
import org.lwjgl.input.Keyboard;
|
import org.lwjgl.input.Keyboard;
|
||||||
import org.lwjgl.util.Dimension;
|
|
||||||
import org.lwjgl.util.ReadableDimension;
|
|
||||||
|
|
||||||
import java.io.File;
|
|
||||||
|
|
||||||
public class AdvancedScreenshots implements Extra {
|
public class AdvancedScreenshots implements Extra {
|
||||||
|
|
||||||
@@ -43,66 +31,11 @@ public class AdvancedScreenshots implements Extra {
|
|||||||
&& Keyboard.getEventKeyState()
|
&& Keyboard.getEventKeyState()
|
||||||
&& keyCode == mc.gameSettings.keyBindScreenshot.getKeyCode()) {
|
&& keyCode == mc.gameSettings.keyBindScreenshot.getKeyCode()) {
|
||||||
|
|
||||||
if (GuiScreen.isCtrlKeyDown()) {
|
ReplayMod.instance.runLater(() -> {
|
||||||
ReplayMod.instance.runLater(this::createEquirectangularScreenshot);
|
new GuiCreateScreenshot(mod).display();
|
||||||
|
});
|
||||||
|
|
||||||
event.setCanceled(true);
|
event.setCanceled(true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
private void createEquirectangularScreenshot() {
|
|
||||||
try {
|
|
||||||
// take 360° screenshot
|
|
||||||
File screenshotFolder = new File(mc.mcDataDir, "screenshots");
|
|
||||||
screenshotFolder.mkdir();
|
|
||||||
File screenshotFile = ScreenShotHelper.getTimestampedPNGFileForDirectory(screenshotFolder);
|
|
||||||
|
|
||||||
int height = 4 * 4320;
|
|
||||||
int width = 2 * height;
|
|
||||||
|
|
||||||
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);
|
|
||||||
|
|
||||||
new GuiUploadScreenshot(ReplayModReplay.instance.getReplayHandler().getOverlay(), mod, screenshotFile).open();
|
|
||||||
} catch (OutOfMemoryError e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
CrashReport report = CrashReport.makeCrashReport(e, "Creating Equirectangular Screenshot");
|
|
||||||
Minecraft.getMinecraft().crashed(report);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,87 @@
|
|||||||
|
package com.replaymod.extras.advancedscreenshots;
|
||||||
|
|
||||||
|
import com.replaymod.core.ReplayMod;
|
||||||
|
import com.replaymod.render.RenderSettings;
|
||||||
|
import com.replaymod.render.gui.GuiRenderSettings;
|
||||||
|
import com.replaymod.replay.ReplayModReplay;
|
||||||
|
import de.johni0702.minecraft.gui.container.GuiContainer;
|
||||||
|
import de.johni0702.minecraft.gui.container.GuiPanel;
|
||||||
|
import de.johni0702.minecraft.gui.element.GuiLabel;
|
||||||
|
import de.johni0702.minecraft.gui.layout.GridLayout;
|
||||||
|
import de.johni0702.minecraft.gui.layout.VerticalLayout;
|
||||||
|
import net.minecraft.crash.CrashReport;
|
||||||
|
import net.minecraft.util.ScreenShotHelper;
|
||||||
|
import net.minecraftforge.common.config.Configuration;
|
||||||
|
import net.minecraftforge.common.config.Property;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
|
||||||
|
import static com.replaymod.core.utils.Utils.error;
|
||||||
|
import static com.replaymod.render.ReplayModRender.LOGGER;
|
||||||
|
|
||||||
|
public class GuiCreateScreenshot extends GuiRenderSettings {
|
||||||
|
|
||||||
|
private final ReplayMod mod;
|
||||||
|
|
||||||
|
public GuiCreateScreenshot(ReplayMod mod) {
|
||||||
|
super(null, null);
|
||||||
|
|
||||||
|
this.mod = mod;
|
||||||
|
|
||||||
|
resetChildren(settingsList.getListPanel()).addElements(new VerticalLayout.Data(0.5),
|
||||||
|
new GuiLabel().setI18nText("replaymod.gui.advancedscreenshots.title"), mainPanel, new GuiPanel(),
|
||||||
|
new GuiLabel().setI18nText("replaymod.gui.rendersettings.advanced"), advancedPanel, new GuiPanel());
|
||||||
|
|
||||||
|
resetChildren(mainPanel).addElements(new GridLayout.Data(1, 0.5),
|
||||||
|
new GuiLabel().setI18nText("replaymod.gui.rendersettings.renderer"), renderMethodDropdown,
|
||||||
|
new GuiLabel().setI18nText("replaymod.gui.advancedscreenshots.resolution"), videoResolutionPanel,
|
||||||
|
new GuiLabel().setI18nText("replaymod.gui.rendersettings.outputfile"), outputFileButton);
|
||||||
|
|
||||||
|
resetChildren(advancedPanel).addElements(null, nametagCheckbox, new GuiPanel().setLayout(
|
||||||
|
new GridLayout().setCellsEqualSize(false).setColumns(2).setSpacingX(5).setSpacingY(15))
|
||||||
|
.addElements(new GridLayout.Data(0, 0.5),
|
||||||
|
new GuiLabel().setI18nText("replaymod.gui.rendersettings.stabilizecamera"), stabilizePanel,
|
||||||
|
chromaKeyingCheckbox, chromaKeyingColor));
|
||||||
|
|
||||||
|
exportArguments.setText(""); // To disable any preset-based checks
|
||||||
|
buttonPanel.removeElement(queueButton);
|
||||||
|
renderButton.setI18nLabel("replaymod.gui.advancedscreenshots.create").onClick(() -> {
|
||||||
|
// Closing this GUI ensures that settings are saved
|
||||||
|
getMinecraft().displayGuiScreen(null);
|
||||||
|
|
||||||
|
mod.runLater(() -> {
|
||||||
|
try {
|
||||||
|
RenderSettings settings = save(false);
|
||||||
|
|
||||||
|
boolean success = new ScreenshotRenderer(settings).renderScreenshot();
|
||||||
|
if (success) {
|
||||||
|
new GuiUploadScreenshot(ReplayModReplay.instance.getReplayHandler().getOverlay(), mod,
|
||||||
|
settings).open();
|
||||||
|
}
|
||||||
|
|
||||||
|
} catch (Throwable t) {
|
||||||
|
error(LOGGER, GuiCreateScreenshot.this, CrashReport.makeCrashReport(t, "Rendering video"), () -> {});
|
||||||
|
display(); // Re-show the render settings gui and the new error popup
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private <T extends GuiContainer<?>> T resetChildren(T container) {
|
||||||
|
new ArrayList<>(container.getChildren()).forEach(container::removeElement);
|
||||||
|
return container;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected File generateOutputFile(RenderSettings.EncodingPreset encodingPreset) {
|
||||||
|
File screenshotFolder = new File(getMinecraft().mcDataDir, "screenshots");
|
||||||
|
return ScreenShotHelper.getTimestampedPNGFileForDirectory(screenshotFolder);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected Property getConfigProperty(Configuration configuration) {
|
||||||
|
return configuration.get("screenshotsettings", "settings", "{}",
|
||||||
|
"Last state of the screenshot settings GUI. Internal use only.");
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -3,6 +3,7 @@ package com.replaymod.extras.advancedscreenshots;
|
|||||||
import com.replaymod.core.ReplayMod;
|
import com.replaymod.core.ReplayMod;
|
||||||
import com.replaymod.core.SettingsRegistry;
|
import com.replaymod.core.SettingsRegistry;
|
||||||
import com.replaymod.extras.Setting;
|
import com.replaymod.extras.Setting;
|
||||||
|
import com.replaymod.render.RenderSettings;
|
||||||
import de.johni0702.minecraft.gui.container.GuiContainer;
|
import de.johni0702.minecraft.gui.container.GuiContainer;
|
||||||
import de.johni0702.minecraft.gui.container.GuiPanel;
|
import de.johni0702.minecraft.gui.container.GuiPanel;
|
||||||
import de.johni0702.minecraft.gui.element.GuiButton;
|
import de.johni0702.minecraft.gui.element.GuiButton;
|
||||||
@@ -14,7 +15,6 @@ import de.johni0702.minecraft.gui.popup.AbstractGuiPopup;
|
|||||||
import org.lwjgl.util.ReadableColor;
|
import org.lwjgl.util.ReadableColor;
|
||||||
|
|
||||||
import java.awt.*;
|
import java.awt.*;
|
||||||
import java.io.File;
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.net.URI;
|
import java.net.URI;
|
||||||
|
|
||||||
@@ -22,10 +22,10 @@ public class GuiUploadScreenshot extends AbstractGuiPopup<GuiUploadScreenshot> {
|
|||||||
|
|
||||||
public final ReplayMod mod;
|
public final ReplayMod mod;
|
||||||
|
|
||||||
public final File screenshotFile;
|
public final RenderSettings renderSettings;
|
||||||
|
|
||||||
public final GuiLabel successLabel = new GuiLabel()
|
public final GuiLabel successLabel = new GuiLabel()
|
||||||
.setI18nText("replaymod.gui.advancedscreenshots.finished.description.360")
|
.setI18nText("replaymod.gui.advancedscreenshots.finished.description")
|
||||||
.setColor(ReadableColor.BLACK);
|
.setColor(ReadableColor.BLACK);
|
||||||
|
|
||||||
public final GuiLabel veerLabel = new GuiLabel()
|
public final GuiLabel veerLabel = new GuiLabel()
|
||||||
@@ -56,11 +56,18 @@ public class GuiUploadScreenshot extends AbstractGuiPopup<GuiUploadScreenshot> {
|
|||||||
.with(neverOpenLabel, new HorizontalLayout.Data(0.5))
|
.with(neverOpenLabel, new HorizontalLayout.Data(0.5))
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
public GuiUploadScreenshot(GuiContainer container, ReplayMod mod, File screenshotFile) {
|
public GuiUploadScreenshot(GuiContainer container, ReplayMod mod, RenderSettings renderSettings) {
|
||||||
super(container);
|
super(container);
|
||||||
this.mod = mod;
|
this.mod = mod;
|
||||||
this.screenshotFile = screenshotFile;
|
this.renderSettings = renderSettings;
|
||||||
|
|
||||||
|
boolean veer = renderSettings.getRenderMethod() == RenderSettings.RenderMethod.EQUIRECTANGULAR;
|
||||||
|
|
||||||
|
if (renderSettings.getRenderMethod() == RenderSettings.RenderMethod.EQUIRECTANGULAR) {
|
||||||
|
successLabel.setI18nText("replaymod.gui.advancedscreenshots.finished.description.360");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (veer) {
|
||||||
veerUploadButton.onClick(() -> {
|
veerUploadButton.onClick(() -> {
|
||||||
try {
|
try {
|
||||||
Desktop.getDesktop().browse(URI.create("https://veer.tv/upload"));
|
Desktop.getDesktop().browse(URI.create("https://veer.tv/upload"));
|
||||||
@@ -68,10 +75,11 @@ public class GuiUploadScreenshot extends AbstractGuiPopup<GuiUploadScreenshot> {
|
|||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
}
|
||||||
|
|
||||||
showOnDiskButton.onClick(() -> {
|
showOnDiskButton.onClick(() -> {
|
||||||
try {
|
try {
|
||||||
Desktop.getDesktop().browse(URI.create("file://" + screenshotFile.getAbsolutePath()));
|
Desktop.getDesktop().browse(URI.create("file://" + renderSettings.getOutputFile().getAbsolutePath()));
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
@@ -86,10 +94,16 @@ public class GuiUploadScreenshot extends AbstractGuiPopup<GuiUploadScreenshot> {
|
|||||||
close();
|
close();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
popup.addElements(new VerticalLayout.Data(0.5), successLabel);
|
||||||
|
|
||||||
|
if (veer) {
|
||||||
|
popup.addElements(new VerticalLayout.Data(0.5),
|
||||||
|
veerLabel,
|
||||||
|
veerUploadButton);
|
||||||
|
}
|
||||||
|
|
||||||
popup.addElements(new VerticalLayout.Data(0.5),
|
popup.addElements(new VerticalLayout.Data(0.5),
|
||||||
successLabel,
|
successLabel,
|
||||||
veerLabel,
|
|
||||||
veerUploadButton,
|
|
||||||
showOnDiskButton,
|
showOnDiskButton,
|
||||||
closeButton);
|
closeButton);
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,65 @@
|
|||||||
|
package com.replaymod.extras.advancedscreenshots;
|
||||||
|
|
||||||
|
import com.replaymod.render.RenderSettings;
|
||||||
|
import com.replaymod.render.capturer.RenderInfo;
|
||||||
|
import com.replaymod.render.hooks.ChunkLoadingRenderGlobal;
|
||||||
|
import com.replaymod.render.rendering.Pipelines;
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
import net.minecraft.client.Minecraft;
|
||||||
|
import net.minecraft.crash.CrashReport;
|
||||||
|
import org.lwjgl.util.Dimension;
|
||||||
|
import org.lwjgl.util.ReadableDimension;
|
||||||
|
|
||||||
|
@RequiredArgsConstructor
|
||||||
|
public class ScreenshotRenderer implements RenderInfo {
|
||||||
|
|
||||||
|
private final Minecraft mc = Minecraft.getMinecraft();
|
||||||
|
|
||||||
|
private final RenderSettings settings;
|
||||||
|
|
||||||
|
public boolean renderScreenshot() throws Throwable {
|
||||||
|
try {
|
||||||
|
int displayWidthBefore = mc.displayWidth;
|
||||||
|
int displayHeightBefore = mc.displayHeight;
|
||||||
|
|
||||||
|
ChunkLoadingRenderGlobal clrg = new ChunkLoadingRenderGlobal(mc.renderGlobal);
|
||||||
|
|
||||||
|
Pipelines.newPipeline(settings.getRenderMethod(),this,
|
||||||
|
new ScreenshotWriter(settings.getOutputFile())).run();
|
||||||
|
|
||||||
|
clrg.uninstall();
|
||||||
|
|
||||||
|
mc.resize(displayWidthBefore, displayHeightBefore);
|
||||||
|
return true;
|
||||||
|
} catch (OutOfMemoryError e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
CrashReport report = CrashReport.makeCrashReport(e, "Creating Equirectangular Screenshot");
|
||||||
|
Minecraft.getMinecraft().crashed(report);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ReadableDimension getFrameSize() {
|
||||||
|
return new Dimension(settings.getVideoWidth(), settings.getVideoHeight());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getTotalFrames() {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public float updateForNextFrame() {
|
||||||
|
return mc.timer.renderPartialTicks;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public RenderSettings getRenderSettings() {
|
||||||
|
return new RenderSettings(
|
||||||
|
null, null, settings.getVideoWidth(), settings.getVideoHeight(), 0, 0, null,
|
||||||
|
true, true, true, true, null,
|
||||||
|
false, RenderSettings.AntiAliasing.NONE, null, null, false
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -427,7 +427,7 @@ public class GuiRenderSettings extends GuiScreen implements Closeable {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
private File generateOutputFile(RenderSettings.EncodingPreset encodingPreset) {
|
protected File generateOutputFile(RenderSettings.EncodingPreset encodingPreset) {
|
||||||
String fileName = new SimpleDateFormat("yyyy_MM_dd_HH_mm_ss").format(new Date());
|
String fileName = new SimpleDateFormat("yyyy_MM_dd_HH_mm_ss").format(new Date());
|
||||||
File folder = ReplayModRender.instance.getVideoFolder();
|
File folder = ReplayModRender.instance.getVideoFolder();
|
||||||
return new File(folder, fileName + "." + encodingPreset.getFileExtension());
|
return new File(folder, fileName + "." + encodingPreset.getFileExtension());
|
||||||
@@ -447,7 +447,7 @@ public class GuiRenderSettings extends GuiScreen implements Closeable {
|
|||||||
config.save();
|
config.save();
|
||||||
}
|
}
|
||||||
|
|
||||||
private Property getConfigProperty(Configuration configuration) {
|
protected Property getConfigProperty(Configuration configuration) {
|
||||||
return configuration.get("rendersettings", "settings", "{}",
|
return configuration.get("rendersettings", "settings", "{}",
|
||||||
"Last state of the render settings GUI. Internal use only.");
|
"Last state of the render settings GUI. Internal use only.");
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user