diff --git a/src/main/java/eu/crushedpixel/replaymod/events/GuiReplayOverlay.java b/src/main/java/eu/crushedpixel/replaymod/events/GuiReplayOverlay.java index bd414c10..955f7d52 100755 --- a/src/main/java/eu/crushedpixel/replaymod/events/GuiReplayOverlay.java +++ b/src/main/java/eu/crushedpixel/replaymod/events/GuiReplayOverlay.java @@ -11,10 +11,7 @@ import eu.crushedpixel.replaymod.recording.ConnectionEventHandler; import eu.crushedpixel.replaymod.registry.ReplayGuiRegistry; import eu.crushedpixel.replaymod.replay.ReplayHandler; import eu.crushedpixel.replaymod.replay.ReplayProcess; -import eu.crushedpixel.replaymod.settings.RenderOptions; import eu.crushedpixel.replaymod.utils.MouseUtils; -import eu.crushedpixel.replaymod.video.frame.FrameRenderer; -import eu.crushedpixel.replaymod.video.frame.DefaultFrameRenderer; import net.minecraft.client.Minecraft; import net.minecraft.client.gui.Gui; import net.minecraft.client.gui.GuiChat; @@ -186,19 +183,7 @@ public class GuiReplayOverlay extends Gui { if(hover) { playOrPause(); } else if(mouseX >= exportButtonX && mouseX <= exportButtonX + 20 && mouseY >= exportButtonY && exportButtonY <= exportButtonY + 20) { - // TODO Put all those settings into a nice little GUI - FrameRenderer renderer = new DefaultFrameRenderer(); -// FrameRenderer renderer = new TilingReadPixelFrameRenderer(mc.displayWidth*3, mc.displayHeight*2); -// FrameRenderer renderer = new TilingReadPixelFrameRenderer(3840, 2160); -// FrameRenderer renderer = new StereoscopicFrameRenderer(); -// FrameRenderer renderer = new CubicFrameRenderer(false); -// FrameRenderer renderer = new EquirectangularFrameRenderer(false); - RenderOptions options = new RenderOptions(renderer); - options.setLinearMovement(ReplayMod.replaySettings.isLinearMovement()); - options.setWaitForChunks(ReplayMod.replaySettings.getWaitForChunks()); - options.setFps(ReplayMod.replaySettings.getVideoFramerate()); - options.setQuality((float) ReplayMod.replaySettings.getVideoQuality()); - ReplayHandler.startPath(options); + mc.displayGuiScreen(new GuiRenderSettings()); } if(mouseX >= timelineX + 4 && mouseX <= width - 18 && mouseY >= 11 && mouseY <= 29) { diff --git a/src/main/java/eu/crushedpixel/replaymod/gui/GuiConstants.java b/src/main/java/eu/crushedpixel/replaymod/gui/GuiConstants.java index 45265fc9..2612be86 100755 --- a/src/main/java/eu/crushedpixel/replaymod/gui/GuiConstants.java +++ b/src/main/java/eu/crushedpixel/replaymod/gui/GuiConstants.java @@ -87,4 +87,17 @@ public class GuiConstants { public static final int PLAYER_OVERVIEW_HIDE_ALL = 1010; public static final int PLAYER_OVERVIEW_SHOW_ALL = 0101; public static final int PLAYER_OVERVIEW_REMEMBER = -10; + + public static final int RENDER_SETTINGS_RENDERER_DROPDOWN = 9001; + public static final int RENDER_SETTINGS_RENDER_BUTTON = 9002; + public static final int RENDER_SETTINGS_CANCEL_BUTTON = 9003; + public static final int RENDER_SETTINGS_RESOLUTION_CHECKBOX = 9004; + public static final int RENDER_SETTINGS_RESOLUTION_X = 9005; + public static final int RENDER_SETTINGS_RESOLUTION_Y = 9006; + public static final int RENDER_SETTINGS_INTERPOLATION_BUTTON = 9007; + public static final int RENDER_SETTINGS_FORCECHUNKS_BUTTON = 9008; + public static final int RENDER_SETTINGS_FRAMERATE_SLIDER = 9009; + public static final int RENDER_SETTINGS_QUALITY_SLIDER = 9010; + public static final int RENDER_SETTINGS_YOUTUBE_READY = 9011; + public static final int RENDER_SETTINGS_STATIC_CAMERA = 9012; } diff --git a/src/main/java/eu/crushedpixel/replaymod/gui/GuiRenderSettings.java b/src/main/java/eu/crushedpixel/replaymod/gui/GuiRenderSettings.java new file mode 100644 index 00000000..154da302 --- /dev/null +++ b/src/main/java/eu/crushedpixel/replaymod/gui/GuiRenderSettings.java @@ -0,0 +1,323 @@ +package eu.crushedpixel.replaymod.gui; + +import eu.crushedpixel.replaymod.ReplayMod; +import eu.crushedpixel.replaymod.chat.ChatMessageHandler; +import eu.crushedpixel.replaymod.gui.elements.GuiDropdown; +import eu.crushedpixel.replaymod.gui.elements.GuiNumberInput; +import eu.crushedpixel.replaymod.gui.elements.listeners.SelectionListener; +import eu.crushedpixel.replaymod.replay.ReplayHandler; +import eu.crushedpixel.replaymod.settings.RenderOptions; +import eu.crushedpixel.replaymod.video.frame.*; +import net.minecraft.client.Minecraft; +import net.minecraft.client.gui.GuiButton; +import net.minecraft.client.gui.GuiScreen; +import net.minecraft.client.resources.I18n; +import net.minecraftforge.fml.client.config.GuiCheckBox; +import org.lwjgl.input.Keyboard; + +import java.awt.*; +import java.io.IOException; + +public class GuiRenderSettings extends GuiScreen { + + private GuiButton renderButton, cancelButton; + private GuiDropdown rendererDropdown; + + private int virtualY, virtualHeight; + private int leftBorder = 10; + + private GuiCheckBox customResolution, ignoreCamDir, youtubeExport; + private GuiNumberInput xRes, yRes; + private GuiButton interpolation, forceChunks; + private GuiVideoFramerateSlider framerateSlider; + private GuiVideoQualitySlider qualitySlider; + + private boolean initialized; + + private boolean linear = false; + private boolean waitForChunks = true; + + private final Minecraft mc = Minecraft.getMinecraft(); + + public GuiRenderSettings() { + //if not enough keyframes, abort and leave chat message + if(ReplayHandler.getPosKeyframeCount() < 2 && ReplayHandler.getTimeKeyframeCount() < 2) { + ReplayMod.chatMessageHandler.addLocalizedChatMessage("replaymod.chat.notenoughkeyframes", ChatMessageHandler.ChatMessageType.WARNING); + mc.displayGuiScreen(null); + return; + } + ReplayMod.replaySender.setReplaySpeed(0); + } + + @Override + public void initGui() { + if(!initialized) { + rendererDropdown = new GuiDropdown(GuiConstants.RENDER_SETTINGS_RENDERER_DROPDOWN, + fontRendererObj, 0, 0, 200, 5); + rendererDropdown.addSelectionListener(new RendererDropdownListener()); + + renderButton = new GuiButton(GuiConstants.RENDER_SETTINGS_RENDER_BUTTON, 0, 0, I18n.format("replaymod.gui.render")); + cancelButton = new GuiButton(GuiConstants.RENDER_SETTINGS_CANCEL_BUTTON, 0, 0, I18n.format("replaymod.gui.cancel")); + + customResolution = new GuiCheckBox(GuiConstants.RENDER_SETTINGS_RESOLUTION_CHECKBOX, 0, 0, I18n.format("replaymod.gui.rendersettings.customresolution"), false); + customResolution.enabled = false; + + xRes = new GuiNumberInput(GuiConstants.RENDER_SETTINGS_RESOLUTION_X, fontRendererObj, 0, 0, 50, 1, 100000, mc.displayWidth, false); + yRes = new GuiNumberInput(GuiConstants.RENDER_SETTINGS_RESOLUTION_Y, fontRendererObj, 0, 0, 50, 1, 100000, mc.displayHeight, false); + + xRes.setEnabled(false); + yRes.setEnabled(false); + + interpolation = new GuiButton(GuiConstants.RENDER_SETTINGS_INTERPOLATION_BUTTON, 0, 0, getInterpolationDisplayString()); + forceChunks = new GuiButton(GuiConstants.RENDER_SETTINGS_FORCECHUNKS_BUTTON, 0, 0, getForceChunksDisplayString()); + + framerateSlider = new GuiVideoFramerateSlider(GuiConstants.RENDER_SETTINGS_FRAMERATE_SLIDER, 0, 0, ReplayMod.replaySettings.getVideoFramerate(), + I18n.format("replaymod.gui.rendersettings.framerate")); + qualitySlider = new GuiVideoQualitySlider(GuiConstants.RENDER_SETTINGS_QUALITY_SLIDER, 0, 0, (float)ReplayMod.replaySettings.getVideoQuality(), + I18n.format("replaymod.gui.rendersettings.quality")); + + ignoreCamDir = new GuiCheckBox(GuiConstants.RENDER_SETTINGS_STATIC_CAMERA, 0, 0, I18n.format("replaymod.gui.rendersettings.stablecamera"), false); + youtubeExport = new GuiCheckBox(GuiConstants.RENDER_SETTINGS_YOUTUBE_READY, 0, 0, I18n.format("replaymod.gui.rendersettings.exportyoutube"), true); + ignoreCamDir.enabled = youtubeExport.enabled = false; + + for(RendererSettings r : RendererSettings.values()) { + rendererDropdown.addElement(r); + } + } + + virtualHeight = 200; + virtualY = (this.height-virtualHeight)/2; + + rendererDropdown.yPosition = virtualY + 15 + 5; + rendererDropdown.xPosition = leftBorder + 10 + fontRendererObj.getStringWidth(I18n.format("replaymod.gui.rendersettings.renderer") + ":")+10; + + cancelButton.width = renderButton.width = 100; + + cancelButton.xPosition = width-10-5-100; + renderButton.xPosition = cancelButton.xPosition-5-100; + + cancelButton.yPosition = renderButton.yPosition = virtualY+virtualHeight-5-18; + + buttonList.add(cancelButton); + buttonList.add(renderButton); + + customResolution.yPosition = virtualY + 15 + 5 + 20 + 10 + 5; + customResolution.xPosition = leftBorder + 10; + buttonList.add(customResolution); + + xRes.xPosition = customResolution.xPosition + 20 + fontRendererObj.getStringWidth(I18n.format("replaymod.gui.rendersettings.customresolution")); + yRes.xPosition = xRes.xPosition+xRes.width+5+fontRendererObj.getStringWidth("*")+8; + xRes.yPosition = yRes.yPosition = customResolution.yPosition-3; + + forceChunks.width = interpolation.width = framerateSlider.width = qualitySlider.width = 150; + + interpolation.xPosition = leftBorder+10; + interpolation.yPosition = xRes.yPosition+20+10; + buttonList.add(interpolation); + + forceChunks.xPosition = interpolation.xPosition+interpolation.width+10; + forceChunks.yPosition = interpolation.yPosition; + buttonList.add(forceChunks); + + framerateSlider.xPosition = interpolation.xPosition; + qualitySlider.xPosition = forceChunks.xPosition; + framerateSlider.yPosition = qualitySlider.yPosition = interpolation.yPosition + 20 + 10; + + buttonList.add(framerateSlider); + buttonList.add(qualitySlider); + + ignoreCamDir.xPosition = framerateSlider.xPosition; + youtubeExport.xPosition = qualitySlider.xPosition; + + ignoreCamDir.yPosition = youtubeExport.yPosition = framerateSlider.yPosition+20+10; + + buttonList.add(ignoreCamDir); + buttonList.add(youtubeExport); + + initialized = true; + } + + @Override + public void drawScreen(int mouseX, int mouseY, float partialTicks) { + drawGradientRect(leftBorder, virtualY, width - leftBorder, virtualY + virtualHeight, -1072689136, -804253680); + + this.drawCenteredString(fontRendererObj, I18n.format("replaymod.gui.rendersettings.title"), + this.width / 2, virtualY + 5, Color.WHITE.getRGB()); + + this.drawString(fontRendererObj, I18n.format("replaymod.gui.rendersettings.renderer") + ":", + leftBorder + 10, virtualY + 15 + 5 + 7, Color.WHITE.getRGB()); + + xRes.drawTextBox(); + yRes.drawTextBox(); + this.drawString(fontRendererObj, "*", xRes.xPosition + xRes.width + 5, xRes.yPosition + 3, Color.WHITE.getRGB()); + + super.drawScreen(mouseX, mouseY, partialTicks); + + rendererDropdown.drawTextBox(); + } + + @Override + protected void mouseClicked(int mouseX, int mouseY, int mouseButton) throws IOException { + if(!rendererDropdown.mouseClickedResult(mouseX, mouseY, mouseButton)) { + xRes.mouseClicked(mouseX, mouseY, mouseButton); + yRes.mouseClicked(mouseX, mouseY, mouseButton); + super.mouseClicked(mouseX, mouseY, mouseButton); + } + } + + @Override + protected void keyTyped(char typedChar, int keyCode) throws IOException { + if(keyCode == Keyboard.KEY_TAB) { + if(xRes.isFocused() && customResolution.isChecked()) { + xRes.setFocused(false); + yRes.setFocused(true); + } + else if(yRes.isFocused() && customResolution.isChecked()) { + yRes.setFocused(false); + xRes.setFocused(true); + } + return; + } + xRes.textboxKeyTyped(typedChar, keyCode); + yRes.textboxKeyTyped(typedChar, keyCode); + super.keyTyped(typedChar, keyCode); + } + + @Override + public void updateScreen() { + xRes.updateCursorCounter(); + yRes.updateCursorCounter(); + super.updateScreen(); + } + + @Override + protected void actionPerformed(GuiButton button) throws IOException { + if(!button.enabled) return; + if(button.id == GuiConstants.RENDER_SETTINGS_RENDER_BUTTON) { + startRendering(); + } else if(button.id == GuiConstants.RENDER_SETTINGS_CANCEL_BUTTON) { + mc.displayGuiScreen(null); + } else if(button.id == GuiConstants.RENDER_SETTINGS_RESOLUTION_CHECKBOX) { + boolean enabled = ((GuiCheckBox)button).isChecked(); + xRes.setEnabled(enabled); + yRes.setEnabled(enabled); + } else if(button.id == GuiConstants.RENDER_SETTINGS_INTERPOLATION_BUTTON) { + linear = !linear; + button.displayString = getInterpolationDisplayString(); + } else if(button.id == GuiConstants.RENDER_SETTINGS_FORCECHUNKS_BUTTON) { + waitForChunks = !waitForChunks; + button.displayString = getForceChunksDisplayString(); + } + } + + private String getInterpolationDisplayString() { + return I18n.format("replaymod.gui.rendersettings.interpolation")+": "+ + (linear ? I18n.format("replaymod.gui.settings.interpolation.linear") : + I18n.format("replaymod.gui.settings.interpolation.cubic")); + } + + private String getForceChunksDisplayString() { + return I18n.format("replaymod.gui.rendersettings.forcechunks")+": "+ + (waitForChunks ? I18n.format("options.on") : I18n.format("options.off")); + } + + private enum RendererSettings { + DEFAULT("default"), + TILED("tiled"), + STEREOSCOPIC("stereoscopic"), + CUBIC("cubic"), + EQUIRECTANGULAR("equirectangular"); + + private String name, desc; + + RendererSettings(String name) { + this.name = "replaymod.gui.rendersettings.renderer."+name; + this.desc = name+".description"; + } + + @Override + public String toString() { + return I18n.format(name); + } + + public String getDescription() { + return desc; + } + } + + private void startRendering() { + FrameRenderer renderer = null; + + RendererSettings r = rendererDropdown.getElement(rendererDropdown.getSelectionIndex()); + if(r == RendererSettings.DEFAULT) { + renderer = new DefaultFrameRenderer(); + } else if(r == RendererSettings.TILED) { + renderer = new TilingFrameRenderer(getWidthSetting(), getHeightSetting()); + } else if(r == RendererSettings.STEREOSCOPIC) { + renderer = new StereoscopicFrameRenderer(); + } else if(r == RendererSettings.CUBIC) { + renderer = new CubicFrameRenderer(ignoreCamDir.isChecked()); + } else if(r == RendererSettings.EQUIRECTANGULAR) { + renderer = new EquirectangularFrameRenderer(ignoreCamDir.isChecked()); + } + + RenderOptions options = new RenderOptions(renderer); + + options.setLinearMovement(linear); + ReplayMod.replaySettings.setLinearMovement(linear); + + options.setWaitForChunks(waitForChunks); + ReplayMod.replaySettings.setWaitForChunks(waitForChunks); + + options.setFps(framerateSlider.getFPS()); + ReplayMod.replaySettings.setVideoFramerate(framerateSlider.getFPS()); + + options.setQuality(qualitySlider.getQuality()); + ReplayMod.replaySettings.setVideoQuality(qualitySlider.getQuality()); + + ReplayHandler.startPath(options); + } + + private int getWidthSetting() { + return customResolution.isChecked() ? xRes.getIntValue() : mc.displayWidth; + } + + private int getHeightSetting() { + return customResolution.isChecked() ? yRes.getIntValue() : mc.displayHeight; + } + + private class RendererDropdownListener implements SelectionListener { + @Override + public void onSelectionChanged(int selectionIndex) { + RendererSettings s = rendererDropdown.getElement(selectionIndex); + + if(s == RendererSettings.DEFAULT) { + customResolution.enabled = false; + xRes.setEnabled(false); + yRes.setEnabled(false); + youtubeExport.enabled = ignoreCamDir.enabled = false; + } else if(s == RendererSettings.TILED) { + customResolution.enabled = true; + xRes.setEnabled(customResolution.isChecked()); + yRes.setEnabled(customResolution.isChecked()); + youtubeExport.enabled = ignoreCamDir.enabled = false; + } else if(s == RendererSettings.STEREOSCOPIC) { + customResolution.enabled = false; + xRes.setEnabled(false); + yRes.setEnabled(false); + youtubeExport.enabled = ignoreCamDir.enabled = false; + } else if(s == RendererSettings.CUBIC) { + customResolution.enabled = false; + xRes.setEnabled(false); + yRes.setEnabled(false); + youtubeExport.enabled = true; + ignoreCamDir.enabled = false; + } else if(s == RendererSettings.EQUIRECTANGULAR) { + customResolution.enabled = false; + xRes.setEnabled(false); + yRes.setEnabled(false); + youtubeExport.enabled = ignoreCamDir.enabled = true; + } + } + } +} diff --git a/src/main/java/eu/crushedpixel/replaymod/gui/GuiVideoFramerateSlider.java b/src/main/java/eu/crushedpixel/replaymod/gui/GuiVideoFramerateSlider.java index 468b74d1..700fe73b 100755 --- a/src/main/java/eu/crushedpixel/replaymod/gui/GuiVideoFramerateSlider.java +++ b/src/main/java/eu/crushedpixel/replaymod/gui/GuiVideoFramerateSlider.java @@ -1,6 +1,5 @@ package eu.crushedpixel.replaymod.gui; -import eu.crushedpixel.replaymod.ReplayMod; import net.minecraft.client.Minecraft; import net.minecraft.client.gui.GuiButton; import net.minecraft.client.renderer.GlStateManager; @@ -34,7 +33,6 @@ public class GuiVideoFramerateSlider extends GuiButton { sliderValue = MathHelper.clamp_float(sliderValue, 0.0F, 1.0F); int f = denormalizeValue(sliderValue); this.displayString = displayKey + ": " + translate(f); - ReplayMod.replaySettings.setVideoFramerate(f); } mc.getTextureManager().bindTexture(buttonTextures); @@ -44,6 +42,10 @@ public class GuiVideoFramerateSlider extends GuiButton { } } + public int getFPS() { + return denormalizeValue(sliderValue); + } + private float normalizeValue(int val) { return (val - 10) / 110f; } diff --git a/src/main/java/eu/crushedpixel/replaymod/gui/GuiVideoQualitySlider.java b/src/main/java/eu/crushedpixel/replaymod/gui/GuiVideoQualitySlider.java index 49c079cd..733cdb15 100755 --- a/src/main/java/eu/crushedpixel/replaymod/gui/GuiVideoQualitySlider.java +++ b/src/main/java/eu/crushedpixel/replaymod/gui/GuiVideoQualitySlider.java @@ -1,6 +1,5 @@ package eu.crushedpixel.replaymod.gui; -import eu.crushedpixel.replaymod.ReplayMod; import net.minecraft.client.Minecraft; import net.minecraft.client.gui.GuiButton; import net.minecraft.client.renderer.GlStateManager; @@ -49,16 +48,19 @@ public class GuiVideoQualitySlider extends GuiButton { f = snapValue(f); sliderValue = normalizeValue(f); this.displayString = displayKey + ": " + translate(f); - ReplayMod.replaySettings.setVideoQuality(f); } mc.getTextureManager().bindTexture(buttonTextures); GlStateManager.color(1.0F, 1.0F, 1.0F, 1.0F); - this.drawTexturedModalRect(this.xPosition + (int) (sliderValue * (float) (this.width - 8)), this.yPosition, 0, 66, 4, 20); - this.drawTexturedModalRect(this.xPosition + (int) (sliderValue * (float) (this.width - 8)) + 4, this.yPosition, 196, 66, 4, 20); + this.drawTexturedModalRect(this.xPosition + (int)Math.ceil(sliderValue * (float) (this.width - 8)), this.yPosition, 0, 66, 4, 20); + this.drawTexturedModalRect(this.xPosition + (int)Math.ceil(sliderValue * (float) (this.width - 8)) + 4, this.yPosition, 196, 66, 4, 20); } } + public float getQuality() { + return snapValue(denormalizeValue(sliderValue)); + } + private float snapValue(float val) { int i = Math.round(val * 10); return i / 10f; diff --git a/src/main/java/eu/crushedpixel/replaymod/gui/elements/GuiDropdown.java b/src/main/java/eu/crushedpixel/replaymod/gui/elements/GuiDropdown.java index 9d869baa..774ed81b 100755 --- a/src/main/java/eu/crushedpixel/replaymod/gui/elements/GuiDropdown.java +++ b/src/main/java/eu/crushedpixel/replaymod/gui/elements/GuiDropdown.java @@ -111,6 +111,12 @@ public class GuiDropdown extends GuiTextField { @Override public void mouseClicked(int xPos, int yPos, int mouseButton) { + mouseClickedResult(xPos, yPos, mouseButton); + } + + + public boolean mouseClickedResult(int xPos, int yPos, int mouseButton) { + boolean success = false; if(xPos > xPosition + width - height && xPos < xPosition + width && yPos > yPosition && yPos < yPosition + height) { open = !open; } else { @@ -119,6 +125,7 @@ public class GuiDropdown extends GuiTextField { if(yPos > yPosition + height && yPos < yPosition + height + requiredHeight) { int clickedIndex = (int) Math.floor((yPos - (yPosition + height)) / dropoutElementHeight) + upperIndex; this.selectionIndex = clickedIndex; + success = true; fireSelectionChangeEvent(); } open = false; @@ -126,6 +133,7 @@ public class GuiDropdown extends GuiTextField { open = false; } } + return success; } @Override diff --git a/src/main/java/eu/crushedpixel/replaymod/replay/ReplayProcess.java b/src/main/java/eu/crushedpixel/replaymod/replay/ReplayProcess.java index b82182a4..a2d80152 100755 --- a/src/main/java/eu/crushedpixel/replaymod/replay/ReplayProcess.java +++ b/src/main/java/eu/crushedpixel/replaymod/replay/ReplayProcess.java @@ -78,6 +78,8 @@ public class ReplayProcess { } public static void startReplayProcess(RenderOptions renderOptions) { + mc.displayGuiScreen(null); + ReplayHandler.selectKeyframe(null); resetProcess(); diff --git a/src/main/resources/assets/replaymod/lang/en_US.lang b/src/main/resources/assets/replaymod/lang/en_US.lang index 5d7f3bcf..f6057389 100644 --- a/src/main/resources/assets/replaymod/lang/en_US.lang +++ b/src/main/resources/assets/replaymod/lang/en_US.lang @@ -73,6 +73,7 @@ replaymod.gui.register=Register replaymod.gui.mail=Email Address replaymod.gui.loading=Loading replaymod.gui.pleasewait=Please wait +replaymod.gui.render=Render replaymod.gui.minutes=min replaymod.gui.seconds=sec @@ -235,3 +236,29 @@ replaymod.gui.editkeyframe.campitch=Camera Pitch replaymod.gui.editkeyframe.camyaw=Camera Yaw replaymod.gui.editkeyframe.camroll=Camera Roll replaymod.gui.editkeyframe.timelineposition=Timeline Position + +#Render Settings GUI +replaymod.gui.rendersettings.title=Rendering Options +replaymod.gui.rendersettings.renderer=Rendering Method + +replaymod.gui.rendersettings.renderer.default=Default Rendering +replaymod.gui.rendersettings.renderer.tiled=Tiled Rendering +replaymod.gui.rendersettings.renderer.stereoscopic=Stereoscopic Rendering +replaymod.gui.rendersettings.renderer.cubic=Cubic Rendering +replaymod.gui.rendersettings.renderer.equirectangular=Equirectangular Rendering + +replaymod.gui.rendersettings.renderer.default.description=Renders the video with your current resolution. Fastest Rendering Option. +replaymod.gui.rendersettings.renderer.tiled.description=Renders the video with a custom resolution, even if it's larger than your screen. +replaymod.gui.rendersettings.renderer.stereoscopic.description=Renders the video as a steroscopic (side-by-side) 3D movie, useable by different 3D technologies. +replaymod.gui.rendersettings.renderer.cubic.description=Renders the video with a 360 degree panoramic view, using Cubic Projection. This is useable by several 360 degree video players (and the Oculus Rift), for example VR Player. +replaymod.gui.rendersettings.renderer.equirectangular.description=Renders the video with a 360 degree panoramic view, using Equirectangular Projection. This is useable by YouTube's new 360 degree video function, and several video players (and the Oculus Rift), for example VR Player. + +replaymod.gui.rendersettings.customresolution=Custom Video Resolution +replaymod.gui.rendersettings.resolution=Video Resolution +replaymod.gui.rendersettings.interpolation=Path Interpolation +replaymod.gui.rendersettings.forcechunks=Force Render Chunks +replaymod.gui.rendersettings.framerate=Video Framerate +replaymod.gui.rendersettings.quality=Video Quality + +replaymod.gui.rendersettings.stablecamera=Ignore Camera Rotation +replaymod.gui.rendersettings.exportyoutube=Export for YouTube \ No newline at end of file