Merge branch 'johni/1.13-pre' into johni/blend
This commit is contained in:
@@ -1,12 +1,29 @@
|
||||
package com.replaymod.render;
|
||||
|
||||
import com.replaymod.core.versions.MCVer;
|
||||
import de.johni0702.minecraft.gui.utils.lwjgl.ReadableColor;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.Getter;
|
||||
import net.minecraft.client.resources.I18n;
|
||||
import org.lwjgl.util.ReadableColor;
|
||||
import net.minecraft.util.Util;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.Arrays;
|
||||
import java.util.Comparator;
|
||||
import java.util.Optional;
|
||||
|
||||
import static com.replaymod.render.ReplayModRender.LOGGER;
|
||||
|
||||
//#if MC>=11300
|
||||
import org.apache.maven.artifact.versioning.ComparableVersion;
|
||||
//#else
|
||||
//#if MC>=10800
|
||||
//$$ import net.minecraftforge.fml.common.versioning.ComparableVersion;
|
||||
//#else
|
||||
//$$ import cpw.mods.fml.common.versioning.ComparableVersion;
|
||||
//#endif
|
||||
//#endif
|
||||
|
||||
@Data
|
||||
public class RenderSettings {
|
||||
@@ -21,6 +38,14 @@ public class RenderSettings {
|
||||
public String getDescription() {
|
||||
return I18n.format("replaymod.gui.rendersettings.renderer." + name().toLowerCase() + ".description");
|
||||
}
|
||||
|
||||
public boolean isSpherical() {
|
||||
return this == EQUIRECTANGULAR || this == ODS;
|
||||
}
|
||||
|
||||
public boolean hasFixedAspectRatio() {
|
||||
return this == EQUIRECTANGULAR || this == ODS || this == CUBIC;
|
||||
}
|
||||
}
|
||||
|
||||
public enum EncodingPreset {
|
||||
@@ -49,7 +74,7 @@ public class RenderSettings {
|
||||
}
|
||||
|
||||
public String getValue() {
|
||||
return "-y -f rawvideo -pix_fmt rgb24 -s %WIDTH%x%HEIGHT% -r %FPS% -i - %FILTERS%" + preset;
|
||||
return "-y -f rawvideo -pix_fmt bgra -s %WIDTH%x%HEIGHT% -r %FPS% -i - %FILTERS%" + preset;
|
||||
}
|
||||
|
||||
public String getFileExtension() {
|
||||
@@ -94,7 +119,9 @@ public class RenderSettings {
|
||||
private final boolean stabilizePitch;
|
||||
private final boolean stabilizeRoll;
|
||||
private final ReadableColor chromaKeyingColor;
|
||||
private final boolean inject360Metadata;
|
||||
private final int sphericalFovX;
|
||||
private final int sphericalFovY;
|
||||
private final boolean injectSphericalMetadata;
|
||||
private final AntiAliasing antiAliasing;
|
||||
|
||||
private final String exportCommand;
|
||||
@@ -131,12 +158,66 @@ public class RenderSettings {
|
||||
}
|
||||
|
||||
public String getVideoFilters() {
|
||||
if (antiAliasing == AntiAliasing.NONE) {
|
||||
return "";
|
||||
} else {
|
||||
StringBuilder filters = new StringBuilder();
|
||||
|
||||
if (antiAliasing != AntiAliasing.NONE) {
|
||||
double factor = 1.0 / antiAliasing.getFactor();
|
||||
return String.format("-vf scale=iw*%1$s:ih*%1$s ", factor);
|
||||
filters.append(String.format("-filter:v scale=iw*%1$s:ih*%1$s ", factor));
|
||||
}
|
||||
|
||||
return filters.toString();
|
||||
}
|
||||
|
||||
public String getExportCommandOrDefault() {
|
||||
return exportCommand.isEmpty() ? findFFmpeg() : exportCommand;
|
||||
}
|
||||
|
||||
private static String findFFmpeg() {
|
||||
switch (Util.getOSType()) {
|
||||
case WINDOWS:
|
||||
// Allow windows users to unpack the ffmpeg archive into a sub-folder of their .minecraft folder
|
||||
File inDotMinecraft = new File(MCVer.mcDataDir(MCVer.getMinecraft()), "ffmpeg/bin/ffmpeg.exe");
|
||||
if (inDotMinecraft.exists()) {
|
||||
LOGGER.debug("FFmpeg found in .minecraft/ffmpeg");
|
||||
return inDotMinecraft.getAbsolutePath();
|
||||
}
|
||||
break;
|
||||
case OSX:
|
||||
// The PATH doesn't seem to be set as expected on OSX, therefore we check some common locations ourselves
|
||||
for (String path : new String[]{"/usr/local/bin/ffmpeg", "/usr/bin/ffmpeg"}) {
|
||||
File file = new File(path);
|
||||
if (file.exists()) {
|
||||
LOGGER.debug("Found FFmpeg at {}", path);
|
||||
return path;
|
||||
} else {
|
||||
LOGGER.debug("FFmpeg not located at {}", path);
|
||||
}
|
||||
}
|
||||
// Homebrew doesn't seem to reliably symlink its installed binaries either
|
||||
File homebrewFolder = new File("/usr/local/Cellar/ffmpeg");
|
||||
String[] homebrewVersions = homebrewFolder.list();
|
||||
if (homebrewVersions != null) {
|
||||
Optional<File> latestOpt = Arrays.stream(homebrewVersions)
|
||||
.map(ComparableVersion::new) // Convert file name to comparable version
|
||||
.sorted(Comparator.reverseOrder()) // Sort for latest version
|
||||
.map(ComparableVersion::toString) // Convert back to file name
|
||||
.map(v -> new File(new File(homebrewFolder, v), "bin/ffmpeg")) // Convert to binary files
|
||||
.filter(File::exists) // Filter invalid installations (missing executable)
|
||||
.findFirst(); // Take first one
|
||||
if (latestOpt.isPresent()) {
|
||||
File latest = latestOpt.get();
|
||||
LOGGER.debug("Found {} versions of FFmpeg installed with homebrew, chose {}",
|
||||
homebrewVersions.length, latest);
|
||||
return latest.getAbsolutePath();
|
||||
}
|
||||
}
|
||||
break;
|
||||
case LINUX: // Linux users are entrusted to have their PATH configured correctly (most package manager do this)
|
||||
case SOLARIS: // Never heard of anyone running this mod on Solaris having any problems
|
||||
case UNKNOWN: // Unknown OS, just try to use "ffmpeg"
|
||||
}
|
||||
LOGGER.debug("Using default FFmpeg executable");
|
||||
return "ffmpeg";
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,65 +1,57 @@
|
||||
package com.replaymod.render;
|
||||
|
||||
import com.replaymod.core.Module;
|
||||
import com.replaymod.core.ReplayMod;
|
||||
import com.replaymod.render.utils.RenderJob;
|
||||
import com.replaymod.replay.events.ReplayCloseEvent;
|
||||
import net.minecraft.crash.CrashReport;
|
||||
import net.minecraft.util.ReportedException;
|
||||
import net.minecraftforge.common.config.Configuration;
|
||||
import org.apache.commons.io.FileUtils;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
|
||||
//#if MC>=10800
|
||||
import net.minecraftforge.fml.common.Mod;
|
||||
import net.minecraftforge.fml.common.event.FMLPreInitializationEvent;
|
||||
import net.minecraftforge.fml.common.eventhandler.SubscribeEvent;
|
||||
//#if MC>=11300
|
||||
import net.minecraftforge.eventbus.api.SubscribeEvent;
|
||||
//#else
|
||||
//$$ import net.minecraftforge.fml.common.eventhandler.SubscribeEvent;
|
||||
//#endif
|
||||
//#else
|
||||
//$$ import cpw.mods.fml.common.Mod;
|
||||
//$$ import cpw.mods.fml.common.event.FMLPreInitializationEvent;
|
||||
//$$ import cpw.mods.fml.common.eventhandler.SubscribeEvent;
|
||||
//#endif
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Path;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import static com.replaymod.core.versions.MCVer.*;
|
||||
|
||||
@Mod(modid = ReplayModRender.MOD_ID,
|
||||
version = "@MOD_VERSION@",
|
||||
acceptedMinecraftVersions = "@MC_VERSION@",
|
||||
acceptableRemoteVersions = "*",
|
||||
//#if MC>=10800
|
||||
clientSideOnly = true,
|
||||
//#endif
|
||||
useMetadata = true)
|
||||
public class ReplayModRender {
|
||||
public static final String MOD_ID = "replaymod-render";
|
||||
|
||||
@Mod.Instance(MOD_ID)
|
||||
public class ReplayModRender implements Module {
|
||||
{ instance = this; }
|
||||
public static ReplayModRender instance;
|
||||
|
||||
private ReplayMod core;
|
||||
|
||||
public static Logger LOGGER;
|
||||
public static Logger LOGGER = LogManager.getLogger();
|
||||
|
||||
private Configuration configuration;
|
||||
private final List<RenderJob> renderQueue = new ArrayList<>();
|
||||
|
||||
public ReplayModRender(ReplayMod core) {
|
||||
this.core = core;
|
||||
|
||||
core.getSettingsRegistry().register(Setting.class);
|
||||
}
|
||||
|
||||
public ReplayMod getCore() {
|
||||
return core;
|
||||
}
|
||||
|
||||
@Mod.EventHandler
|
||||
public void preInit(FMLPreInitializationEvent event) {
|
||||
LOGGER = event.getModLog();
|
||||
core = ReplayMod.instance;
|
||||
configuration = new Configuration(event.getSuggestedConfigurationFile());
|
||||
|
||||
@Override
|
||||
public void initClient() {
|
||||
FML_BUS.register(this);
|
||||
|
||||
core.getSettingsRegistry().register(Setting.class);
|
||||
}
|
||||
|
||||
@SubscribeEvent
|
||||
@@ -69,17 +61,17 @@ public class ReplayModRender {
|
||||
|
||||
public File getVideoFolder() {
|
||||
String path = core.getSettingsRegistry().get(Setting.RENDER_PATH);
|
||||
File folder = new File(path.startsWith("./") ? core.getMinecraft().mcDataDir : null, path);
|
||||
File folder = new File(path.startsWith("./") ? mcDataDir(core.getMinecraft()) : null, path);
|
||||
try {
|
||||
FileUtils.forceMkdir(folder);
|
||||
} catch (IOException e) {
|
||||
throw new ReportedException(CrashReport.makeCrashReport(e, "Cannot create video folder."));
|
||||
throw newReportedException(CrashReport.makeCrashReport(e, "Cannot create video folder."));
|
||||
}
|
||||
return folder;
|
||||
}
|
||||
|
||||
public Configuration getConfiguration() {
|
||||
return configuration;
|
||||
public Path getRenderSettingsPath() {
|
||||
return mcDataDir(core.getMinecraft()).toPath().resolve("config/replaymod-rendersettings.json");
|
||||
}
|
||||
|
||||
public List<RenderJob> getRenderQueue() {
|
||||
|
||||
@@ -1,19 +1,18 @@
|
||||
package com.replaymod.render;
|
||||
|
||||
import com.replaymod.core.versions.MCVer;
|
||||
import com.replaymod.render.frame.RGBFrame;
|
||||
import com.replaymod.render.rendering.FrameConsumer;
|
||||
import com.replaymod.render.rendering.VideoRenderer;
|
||||
import com.replaymod.render.utils.ByteBufferPool;
|
||||
import com.replaymod.render.utils.StreamPipe;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import de.johni0702.minecraft.gui.utils.lwjgl.ReadableDimension;
|
||||
import net.minecraft.crash.CrashReport;
|
||||
import net.minecraft.crash.CrashReportCategory;
|
||||
import net.minecraft.util.Util;
|
||||
import org.apache.commons.exec.CommandLine;
|
||||
import org.apache.commons.io.FileUtils;
|
||||
import org.apache.commons.io.IOUtils;
|
||||
import org.apache.commons.io.output.TeeOutputStream;
|
||||
import org.lwjgl.util.ReadableDimension;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.File;
|
||||
@@ -22,17 +21,8 @@ import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
import java.nio.channels.Channels;
|
||||
import java.nio.channels.WritableByteChannel;
|
||||
import java.util.Arrays;
|
||||
import java.util.Comparator;
|
||||
import java.util.Optional;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
//#if MC>=10800
|
||||
import net.minecraftforge.fml.common.versioning.ComparableVersion;
|
||||
//#else
|
||||
//$$ import cpw.mods.fml.common.versioning.ComparableVersion;
|
||||
//#endif
|
||||
|
||||
import static com.replaymod.render.ReplayModRender.LOGGER;
|
||||
import static org.apache.commons.lang3.Validate.isTrue;
|
||||
|
||||
@@ -64,7 +54,7 @@ public class VideoWriter implements FrameConsumer<RGBFrame> {
|
||||
.replace("%BITRATE%", String.valueOf(settings.getBitRate()))
|
||||
.replace("%FILTERS%", settings.getVideoFilters());
|
||||
|
||||
String executable = settings.getExportCommand().isEmpty() ? findFFmpeg() : settings.getExportCommand();
|
||||
String executable = settings.getExportCommandOrDefault();
|
||||
LOGGER.info("Starting {} with args: {}", executable, commandArgs);
|
||||
String[] cmdline;
|
||||
try {
|
||||
@@ -78,7 +68,7 @@ public class VideoWriter implements FrameConsumer<RGBFrame> {
|
||||
} catch (IOException e) {
|
||||
throw new NoFFmpegException(e);
|
||||
}
|
||||
File exportLogFile = new File(Minecraft.getMinecraft().mcDataDir, "export.log");
|
||||
File exportLogFile = new File(MCVer.mcDataDir(MCVer.getMinecraft()), "export.log");
|
||||
OutputStream exportLogOut = new TeeOutputStream(new FileOutputStream(exportLogFile), ffmpegLog);
|
||||
new StreamPipe(process.getInputStream(), exportLogOut).start();
|
||||
new StreamPipe(process.getErrorStream(), exportLogOut).start();
|
||||
@@ -86,54 +76,6 @@ public class VideoWriter implements FrameConsumer<RGBFrame> {
|
||||
channel = Channels.newChannel(outputStream);
|
||||
}
|
||||
|
||||
private String findFFmpeg() {
|
||||
switch (Util.getOSType()) {
|
||||
case WINDOWS:
|
||||
// Allow windows users to unpack the ffmpeg archive into a sub-folder of their .minecraft folder
|
||||
File inDotMinecraft = new File(Minecraft.getMinecraft().mcDataDir, "ffmpeg/bin/ffmpeg.exe");
|
||||
if (inDotMinecraft.exists()) {
|
||||
LOGGER.debug("FFmpeg found in .minecraft/ffmpeg");
|
||||
return inDotMinecraft.getAbsolutePath();
|
||||
}
|
||||
break;
|
||||
case OSX:
|
||||
// The PATH doesn't seem to be set as expected on OSX, therefore we check some common locations ourselves
|
||||
for (String path : new String[]{"/usr/local/bin/ffmpeg", "/usr/bin/ffmpeg"}) {
|
||||
File file = new File(path);
|
||||
if (file.exists()) {
|
||||
LOGGER.debug("Found FFmpeg at {}", path);
|
||||
return path;
|
||||
} else {
|
||||
LOGGER.debug("FFmpeg not located at {}", path);
|
||||
}
|
||||
}
|
||||
// Homebrew doesn't seem to reliably symlink its installed binaries either
|
||||
File homebrewFolder = new File("/usr/local/Cellar/ffmpeg");
|
||||
String[] homebrewVersions = homebrewFolder.list();
|
||||
if (homebrewVersions != null) {
|
||||
Optional<File> latestOpt = Arrays.stream(homebrewVersions)
|
||||
.map(ComparableVersion::new) // Convert file name to comparable version
|
||||
.sorted(Comparator.reverseOrder()) // Sort for latest version
|
||||
.map(ComparableVersion::toString) // Convert back to file name
|
||||
.map(v -> new File(new File(homebrewFolder, v), "bin/ffmpeg")) // Convert to binary files
|
||||
.filter(File::exists) // Filter invalid installations (missing executable)
|
||||
.findFirst(); // Take first one
|
||||
if (latestOpt.isPresent()) {
|
||||
File latest = latestOpt.get();
|
||||
LOGGER.debug("Found {} versions of FFmpeg installed with homebrew, chose {}",
|
||||
homebrewVersions.length, latest);
|
||||
return latest.getAbsolutePath();
|
||||
}
|
||||
}
|
||||
break;
|
||||
case LINUX: // Linux users are entrusted to have their PATH configured correctly (most package manager do this)
|
||||
case SOLARIS: // Never heard of anyone running this mod on Solaris having any problems
|
||||
case UNKNOWN: // Unknown OS, just try to use "ffmpeg"
|
||||
}
|
||||
LOGGER.debug("Using default FFmpeg executable");
|
||||
return "ffmpeg";
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() throws IOException {
|
||||
IOUtils.closeQuietly(outputStream);
|
||||
@@ -182,9 +124,9 @@ public class VideoWriter implements FrameConsumer<RGBFrame> {
|
||||
}
|
||||
CrashReport report = CrashReport.makeCrashReport(t, "Exporting frame");
|
||||
CrashReportCategory exportDetails = report.makeCategory("Export details");
|
||||
exportDetails.addCrashSection("Export command", settings.getExportCommand());
|
||||
exportDetails.addCrashSection("Export args", commandArgs);
|
||||
Minecraft.getMinecraft().crashed(report);
|
||||
MCVer.addDetail(exportDetails, "Export command", settings::getExportCommand);
|
||||
MCVer.addDetail(exportDetails, "Export args", commandArgs::toString);
|
||||
MCVer.getMinecraft().crashed(report);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -5,10 +5,16 @@ import com.replaymod.render.blend.BlendMeshBuilder;
|
||||
import com.replaymod.render.blend.Exporter;
|
||||
import com.replaymod.render.blend.data.DMesh;
|
||||
import com.replaymod.render.blend.data.DObject;
|
||||
import net.minecraft.client.model.ModelBox;
|
||||
import net.minecraft.client.model.ModelRenderer;
|
||||
import org.lwjgl.opengl.GL11;
|
||||
|
||||
//#if MC>=11300
|
||||
import net.minecraft.client.renderer.entity.model.ModelBox;
|
||||
import net.minecraft.client.renderer.entity.model.ModelRenderer;
|
||||
//#else
|
||||
//$$ import net.minecraft.client.model.ModelBox;
|
||||
//$$ import net.minecraft.client.model.ModelRenderer;
|
||||
//#endif
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import static com.replaymod.core.versions.MCVer.*;
|
||||
|
||||
@@ -4,8 +4,8 @@ import com.replaymod.render.frame.OpenGlFrame;
|
||||
import com.replaymod.render.rendering.Frame;
|
||||
import com.replaymod.render.utils.ByteBufferPool;
|
||||
import com.replaymod.render.utils.PixelBufferObject;
|
||||
import net.minecraft.client.renderer.OpenGlHelper;
|
||||
import org.lwjgl.opengl.GL11;
|
||||
import org.lwjgl.opengl.GL12;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.nio.ByteBuffer;
|
||||
@@ -19,7 +19,7 @@ public abstract class MultiFramePboOpenGlFrameCapturer<F extends Frame, D extend
|
||||
super(worldRenderer, renderInfo);
|
||||
|
||||
data = type.getEnumConstants();
|
||||
int bufferSize = framePixels * 3 * data.length;
|
||||
int bufferSize = framePixels * 4 * data.length;
|
||||
pbo = new PixelBufferObject(bufferSize, PixelBufferObject.Usage.READ);
|
||||
otherPBO = new PixelBufferObject(bufferSize, PixelBufferObject.Usage.READ);
|
||||
}
|
||||
@@ -47,7 +47,7 @@ public abstract class MultiFramePboOpenGlFrameCapturer<F extends Frame, D extend
|
||||
ByteBuffer pboBuffer = pbo.mapReadOnly();
|
||||
|
||||
OpenGlFrame[] frames = new OpenGlFrame[data.length];
|
||||
int frameBufferSize = getFrameWidth() * getFrameHeight() * 3;
|
||||
int frameBufferSize = getFrameWidth() * getFrameHeight() * 4;
|
||||
for (int i = 0; i < frames.length; i++) {
|
||||
ByteBuffer frameBuffer = ByteBufferPool.allocate(frameBufferSize);
|
||||
pboBuffer.limit(pboBuffer.position() + frameBufferSize);
|
||||
@@ -79,17 +79,10 @@ public abstract class MultiFramePboOpenGlFrameCapturer<F extends Frame, D extend
|
||||
protected OpenGlFrame captureFrame(int frameId, D captureData) {
|
||||
pbo.bind();
|
||||
|
||||
GL11.glPixelStorei(GL11.GL_PACK_ALIGNMENT, 1);
|
||||
GL11.glPixelStorei(GL11.GL_UNPACK_ALIGNMENT, 1);
|
||||
|
||||
int offset = captureData.ordinal() * getFrameWidth() * getFrameHeight() * 3;
|
||||
if (OpenGlHelper.isFramebufferEnabled()) {
|
||||
frameBuffer().bindFramebufferTexture();
|
||||
GL11.glGetTexImage(GL11.GL_TEXTURE_2D, 0, GL11.GL_RGB, GL11.GL_UNSIGNED_BYTE, offset);
|
||||
frameBuffer().unbindFramebufferTexture();
|
||||
} else {
|
||||
GL11.glReadPixels(0, 0, getFrameWidth(), getFrameHeight(), GL11.GL_RGB, GL11.GL_UNSIGNED_BYTE, offset);
|
||||
}
|
||||
int offset = captureData.ordinal() * getFrameWidth() * getFrameHeight() * 4;
|
||||
frameBuffer().bindFramebuffer(true);
|
||||
GL11.glReadPixels(0, 0, getFrameWidth(), getFrameHeight(), GL12.GL_BGRA, GL11.GL_UNSIGNED_BYTE, offset);
|
||||
frameBuffer().unbindFramebuffer();
|
||||
|
||||
pbo.unbind();
|
||||
return null;
|
||||
|
||||
@@ -6,14 +6,11 @@ import com.replaymod.render.frame.ODSOpenGlFrame;
|
||||
import com.replaymod.render.frame.OpenGlFrame;
|
||||
import com.replaymod.render.rendering.FrameCapturer;
|
||||
import com.replaymod.render.shader.Program;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import de.johni0702.minecraft.gui.utils.lwjgl.ReadableDimension;
|
||||
import net.minecraft.crash.CrashReport;
|
||||
import net.minecraft.util.ReportedException;
|
||||
import net.minecraft.util.ResourceLocation;
|
||||
import org.lwjgl.util.ReadableDimension;
|
||||
|
||||
//#if MC>=10800
|
||||
import net.minecraft.client.renderer.GlStateManager;
|
||||
import static net.minecraft.client.renderer.GlStateManager.*;
|
||||
//#else
|
||||
//$$ import com.replaymod.render.hooks.GLStateTracker.BooleanState;
|
||||
@@ -36,9 +33,7 @@ public class ODSFrameCapturer implements FrameCapturer<ODSOpenGlFrame> {
|
||||
private final Program.Uniform leftEyeVariable;
|
||||
|
||||
private final BooleanState[] previousStates = new BooleanState[3];
|
||||
private final BooleanState previousFogState;
|
||||
|
||||
private final Minecraft mc = Minecraft.getMinecraft();
|
||||
private BooleanState previousFogState;
|
||||
|
||||
public ODSFrameCapturer(WorldRenderer worldRenderer, final RenderInfo renderInfo, int frameSize) {
|
||||
RenderInfo fakeInfo = new RenderInfo() {
|
||||
@@ -62,9 +57,9 @@ public class ODSFrameCapturer implements FrameCapturer<ODSOpenGlFrame> {
|
||||
@Override
|
||||
public float updateForNextFrame() {
|
||||
if (call++ % 2 == 0) {
|
||||
shaderProgram.stopUsing();
|
||||
unbindProgram();
|
||||
partialTicks = renderInfo.updateForNextFrame();
|
||||
shaderProgram.use();
|
||||
bindProgram();
|
||||
}
|
||||
return partialTicks;
|
||||
}
|
||||
@@ -78,30 +73,43 @@ public class ODSFrameCapturer implements FrameCapturer<ODSOpenGlFrame> {
|
||||
right = new CubicStereoFrameCapturer(worldRenderer, fakeInfo, frameSize);
|
||||
try {
|
||||
shaderProgram = new Program(vertexResource, fragmentResource);
|
||||
shaderProgram.use();
|
||||
leftEyeVariable = shaderProgram.getUniformVariable("leftEye");
|
||||
directionVariable = shaderProgram.getUniformVariable("direction");
|
||||
setTexture("texture", 0);
|
||||
setTexture("lightMap", 1);
|
||||
linkState(0, "textureEnabled");
|
||||
linkState(1, "lightMapEnabled");
|
||||
linkState(2, "hurtTextureEnabled");
|
||||
final Program.Uniform uniform = shaderProgram.getUniformVariable("fogEnabled");
|
||||
previousFogState = fog();
|
||||
uniform.set(previousFogState.currentState);
|
||||
fog(new BooleanState(previousFogState.capability) {
|
||||
@Override
|
||||
public void setState(boolean state) {
|
||||
super.setState(state);
|
||||
uniform.set(state);
|
||||
}
|
||||
});
|
||||
shaderProgram.stopUsing();
|
||||
} catch (Exception e) {
|
||||
throw new ReportedException(CrashReport.makeCrashReport(e, "Creating ODS shaders"));
|
||||
throw newReportedException(CrashReport.makeCrashReport(e, "Creating ODS shaders"));
|
||||
}
|
||||
}
|
||||
|
||||
private void bindProgram() {
|
||||
shaderProgram.use();
|
||||
setTexture("texture", 0);
|
||||
setTexture("lightMap", 1);
|
||||
linkState(0, "textureEnabled");
|
||||
linkState(1, "lightMapEnabled");
|
||||
linkState(2, "hurtTextureEnabled");
|
||||
final Program.Uniform uniform = shaderProgram.getUniformVariable("fogEnabled");
|
||||
previousFogState = fog();
|
||||
uniform.set(previousFogState.currentState);
|
||||
fog(new BooleanState(previousFogState.capability) {
|
||||
{ currentState = previousFogState.currentState; }
|
||||
@Override
|
||||
public void setState(boolean state) {
|
||||
super.setState(state);
|
||||
uniform.set(state);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void unbindProgram() {
|
||||
for (int i = 0; i < previousStates.length; i++) {
|
||||
previousStates[i].currentState = texture2DState(i).currentState;
|
||||
texture2DState(i, previousStates[i]);
|
||||
}
|
||||
previousFogState.currentState = fog().currentState;
|
||||
fog(previousFogState);
|
||||
shaderProgram.stopUsing();
|
||||
}
|
||||
|
||||
private void setTexture(String texture, int i) {
|
||||
shaderProgram.getUniformVariable(texture).set(i);
|
||||
}
|
||||
@@ -111,6 +119,7 @@ public class ODSFrameCapturer implements FrameCapturer<ODSOpenGlFrame> {
|
||||
previousStates[id] = texture2DState(id);
|
||||
uniform.set(previousStates[id].currentState);
|
||||
texture2DState(id, new BooleanState(previousStates[id].capability) {
|
||||
{ currentState = previousStates[id].currentState; }
|
||||
@Override
|
||||
public void setState(boolean state) {
|
||||
super.setState(state);
|
||||
@@ -126,12 +135,12 @@ public class ODSFrameCapturer implements FrameCapturer<ODSOpenGlFrame> {
|
||||
|
||||
@Override
|
||||
public ODSOpenGlFrame process() {
|
||||
shaderProgram.use();
|
||||
bindProgram();
|
||||
leftEyeVariable.set(true);
|
||||
CubicOpenGlFrame leftFrame = left.process();
|
||||
leftEyeVariable.set(false);
|
||||
CubicOpenGlFrame rightFrame = right.process();
|
||||
shaderProgram.stopUsing();
|
||||
unbindProgram();
|
||||
|
||||
if (leftFrame != null && rightFrame != null) {
|
||||
return new ODSOpenGlFrame(leftFrame, rightFrame);
|
||||
@@ -144,10 +153,6 @@ public class ODSFrameCapturer implements FrameCapturer<ODSOpenGlFrame> {
|
||||
left.close();
|
||||
right.close();
|
||||
shaderProgram.delete();
|
||||
for (int i = 0; i < previousStates.length; i++) {
|
||||
texture2DState(i, previousStates[i]);
|
||||
}
|
||||
fog(previousFogState);
|
||||
}
|
||||
|
||||
private class CubicStereoFrameCapturer extends CubicPboOpenGlFrameCapturer {
|
||||
|
||||
@@ -1,16 +1,17 @@
|
||||
package com.replaymod.render.capturer;
|
||||
|
||||
import com.replaymod.core.versions.MCVer;
|
||||
import com.replaymod.render.frame.OpenGlFrame;
|
||||
import com.replaymod.render.rendering.Frame;
|
||||
import com.replaymod.render.rendering.FrameCapturer;
|
||||
import com.replaymod.render.utils.ByteBufferPool;
|
||||
import de.johni0702.minecraft.gui.utils.lwjgl.Dimension;
|
||||
import de.johni0702.minecraft.gui.utils.lwjgl.ReadableDimension;
|
||||
import de.johni0702.minecraft.gui.utils.lwjgl.WritableDimension;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.renderer.OpenGlHelper;
|
||||
import net.minecraft.client.shader.Framebuffer;
|
||||
import org.lwjgl.opengl.GL11;
|
||||
import org.lwjgl.util.Dimension;
|
||||
import org.lwjgl.util.ReadableDimension;
|
||||
import org.lwjgl.util.WritableDimension;
|
||||
import org.lwjgl.opengl.GL12;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.nio.ByteBuffer;
|
||||
@@ -30,7 +31,7 @@ public abstract class OpenGlFrameCapturer<F extends Frame, D extends CaptureData
|
||||
protected int framesDone;
|
||||
private Framebuffer frameBuffer;
|
||||
|
||||
private final Minecraft mc = Minecraft.getMinecraft();
|
||||
private final Minecraft mc = MCVer.getMinecraft();
|
||||
|
||||
public OpenGlFrameCapturer(WorldRenderer worldRenderer, RenderInfo renderInfo) {
|
||||
this.worldRenderer = worldRenderer;
|
||||
@@ -64,7 +65,7 @@ public abstract class OpenGlFrameCapturer<F extends Frame, D extends CaptureData
|
||||
|
||||
protected Framebuffer frameBuffer() {
|
||||
if (frameBuffer == null) {
|
||||
frameBuffer = Minecraft.getMinecraft().getFramebuffer();
|
||||
frameBuffer = mc.getFramebuffer();
|
||||
}
|
||||
return frameBuffer;
|
||||
}
|
||||
@@ -96,30 +97,28 @@ public abstract class OpenGlFrameCapturer<F extends Frame, D extends CaptureData
|
||||
}
|
||||
|
||||
protected OpenGlFrame captureFrame(int frameId, D captureData) {
|
||||
GL11.glPixelStorei(GL11.GL_PACK_ALIGNMENT, 1);
|
||||
GL11.glPixelStorei(GL11.GL_UNPACK_ALIGNMENT, 1);
|
||||
|
||||
ByteBuffer buffer = ByteBufferPool.allocate(getFrameWidth() * getFrameHeight() * 3);
|
||||
if (OpenGlHelper.isFramebufferEnabled()) {
|
||||
frameBuffer().bindFramebufferTexture();
|
||||
GL11.glGetTexImage(GL11.GL_TEXTURE_2D, 0, GL11.GL_RGB, GL11.GL_UNSIGNED_BYTE, buffer);
|
||||
frameBuffer().unbindFramebufferTexture();
|
||||
} else {
|
||||
GL11.glReadPixels(0, 0, getFrameWidth(), getFrameHeight(), GL11.GL_RGB, GL11.GL_UNSIGNED_BYTE, buffer);
|
||||
}
|
||||
ByteBuffer buffer = ByteBufferPool.allocate(getFrameWidth() * getFrameHeight() * 4);
|
||||
frameBuffer().bindFramebuffer(true);
|
||||
GL11.glReadPixels(0, 0, getFrameWidth(), getFrameHeight(), GL12.GL_BGRA, GL11.GL_UNSIGNED_BYTE, buffer);
|
||||
frameBuffer().unbindFramebuffer();
|
||||
buffer.rewind();
|
||||
|
||||
return new OpenGlFrame(frameId, new Dimension(getFrameWidth(), getFrameHeight()), buffer);
|
||||
}
|
||||
|
||||
protected void resize(int width, int height) {
|
||||
if (width != mc.displayWidth || height != mc.displayHeight) {
|
||||
setWindowSize(width, height);
|
||||
//#if MC>=11300
|
||||
Framebuffer fb = mc.getFramebuffer();
|
||||
if (fb.framebufferWidth != width || fb.framebufferHeight != height) {
|
||||
fb.createFramebuffer(width, height);
|
||||
}
|
||||
}
|
||||
|
||||
private void setWindowSize(int width, int height) {
|
||||
mc.resize(width, height);
|
||||
mc.mainWindow.framebufferWidth = width;
|
||||
mc.mainWindow.framebufferHeight = height;
|
||||
//#else
|
||||
//$$ if (width != mc.displayWidth || height != mc.displayHeight) {
|
||||
//$$ mc.resize(width, height);
|
||||
//$$ }
|
||||
//#endif
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
package com.replaymod.render.capturer;
|
||||
|
||||
import com.replaymod.render.RenderSettings;
|
||||
import org.lwjgl.util.ReadableDimension;
|
||||
import de.johni0702.minecraft.gui.utils.lwjgl.ReadableDimension;
|
||||
|
||||
public interface RenderInfo {
|
||||
ReadableDimension getFrameSize();
|
||||
|
||||
@@ -3,9 +3,9 @@ package com.replaymod.render.capturer;
|
||||
import com.replaymod.render.frame.OpenGlFrame;
|
||||
import com.replaymod.render.utils.ByteBufferPool;
|
||||
import com.replaymod.render.utils.PixelBufferObject;
|
||||
import net.minecraft.client.renderer.OpenGlHelper;
|
||||
import de.johni0702.minecraft.gui.utils.lwjgl.ReadableDimension;
|
||||
import org.lwjgl.opengl.GL11;
|
||||
import org.lwjgl.util.ReadableDimension;
|
||||
import org.lwjgl.opengl.GL12;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.nio.ByteBuffer;
|
||||
@@ -18,7 +18,7 @@ public class SimplePboOpenGlFrameCapturer extends OpenGlFrameCapturer<OpenGlFram
|
||||
super(worldRenderer, renderInfo);
|
||||
|
||||
ReadableDimension size = renderInfo.getFrameSize();
|
||||
bufferSize = size.getHeight() * size.getWidth() * 3;
|
||||
bufferSize = size.getHeight() * size.getWidth() * 4;
|
||||
pbo = new PixelBufferObject(bufferSize, PixelBufferObject.Usage.READ);
|
||||
otherPBO = new PixelBufferObject(bufferSize, PixelBufferObject.Usage.READ);
|
||||
}
|
||||
@@ -64,16 +64,9 @@ public class SimplePboOpenGlFrameCapturer extends OpenGlFrameCapturer<OpenGlFram
|
||||
protected OpenGlFrame captureFrame(int frameId, CaptureData data) {
|
||||
pbo.bind();
|
||||
|
||||
GL11.glPixelStorei(GL11.GL_PACK_ALIGNMENT, 1);
|
||||
GL11.glPixelStorei(GL11.GL_UNPACK_ALIGNMENT, 1);
|
||||
|
||||
if (OpenGlHelper.isFramebufferEnabled()) {
|
||||
frameBuffer().bindFramebufferTexture();
|
||||
GL11.glGetTexImage(GL11.GL_TEXTURE_2D, 0, GL11.GL_RGB, GL11.GL_UNSIGNED_BYTE, 0);
|
||||
frameBuffer().unbindFramebufferTexture();
|
||||
} else {
|
||||
GL11.glReadPixels(0, 0, getFrameWidth(), getFrameHeight(), GL11.GL_RGB, GL11.GL_UNSIGNED_BYTE, 0);
|
||||
}
|
||||
frameBuffer().bindFramebuffer(true);
|
||||
GL11.glReadPixels(0, 0, getFrameWidth(), getFrameHeight(), GL12.GL_BGRA, GL11.GL_UNSIGNED_BYTE, 0);
|
||||
frameBuffer().unbindFramebuffer();
|
||||
|
||||
pbo.unbind();
|
||||
return null;
|
||||
|
||||
@@ -5,7 +5,11 @@ import lombok.Getter;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
|
||||
//#if MC>=10800
|
||||
import net.minecraftforge.fml.common.eventhandler.Event;
|
||||
//#if MC>=11300
|
||||
import net.minecraftforge.eventbus.api.Event;
|
||||
//#else
|
||||
//$$ import net.minecraftforge.fml.common.eventhandler.Event;
|
||||
//#endif
|
||||
//#else
|
||||
//$$ import cpw.mods.fml.common.eventhandler.Event;
|
||||
//#endif
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
package com.replaymod.render.frame;
|
||||
|
||||
import com.replaymod.render.rendering.Frame;
|
||||
import de.johni0702.minecraft.gui.utils.lwjgl.ReadableDimension;
|
||||
import lombok.Getter;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.lwjgl.util.ReadableDimension;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
package com.replaymod.render.frame;
|
||||
|
||||
import com.replaymod.render.rendering.Frame;
|
||||
import de.johni0702.minecraft.gui.utils.lwjgl.ReadableDimension;
|
||||
import lombok.Getter;
|
||||
import org.apache.commons.lang3.Validate;
|
||||
import org.lwjgl.util.ReadableDimension;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
|
||||
@@ -18,9 +18,9 @@ public class RGBFrame implements Frame {
|
||||
private final ByteBuffer byteBuffer;
|
||||
|
||||
public RGBFrame(int frameId, ReadableDimension size, ByteBuffer byteBuffer) {
|
||||
Validate.isTrue(size.getWidth() * size.getHeight() * 3 == byteBuffer.remaining(),
|
||||
Validate.isTrue(size.getWidth() * size.getHeight() * 4 == byteBuffer.remaining(),
|
||||
"Buffer size is %d (cap: %d) but should be %d",
|
||||
byteBuffer.remaining(), byteBuffer.capacity(), size.getWidth() * size.getHeight() * 3);
|
||||
byteBuffer.remaining(), byteBuffer.capacity(), size.getWidth() * size.getHeight() * 4);
|
||||
this.frameId = frameId;
|
||||
this.size = size;
|
||||
this.byteBuffer = byteBuffer;
|
||||
|
||||
@@ -13,11 +13,12 @@ import de.johni0702.minecraft.gui.layout.HorizontalLayout;
|
||||
import de.johni0702.minecraft.gui.layout.VerticalLayout;
|
||||
import net.minecraft.crash.CrashReport;
|
||||
import net.minecraft.crash.CrashReportCategory;
|
||||
import net.minecraft.util.ReportedException;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
import static com.replaymod.core.versions.MCVer.addDetail;
|
||||
import static com.replaymod.core.versions.MCVer.newReportedException;
|
||||
import static com.replaymod.render.ReplayModRender.LOGGER;
|
||||
|
||||
public class GuiExportFailed extends GuiScreen {
|
||||
@@ -31,9 +32,9 @@ public class GuiExportFailed extends GuiScreen {
|
||||
// If they haven't, then this is probably a faulty ffmpeg installation and there's nothing we can do
|
||||
CrashReport crashReport = CrashReport.makeCrashReport(e, "Exporting video");
|
||||
CrashReportCategory details = crashReport.makeCategory("Export details");
|
||||
details.addCrashSection("Settings", settings);
|
||||
details.addCrashSection("FFmpeg log", e.getLog());
|
||||
throw new ReportedException(crashReport);
|
||||
addDetail(details, "Settings", settings::toString);
|
||||
addDetail(details, "FFmpeg log", e::getLog);
|
||||
throw newReportedException(crashReport);
|
||||
} else {
|
||||
// If they have, ask them whether it was intentional
|
||||
GuiExportFailed gui = new GuiExportFailed(e, doRestart);
|
||||
@@ -93,7 +94,9 @@ public class GuiExportFailed extends GuiScreen {
|
||||
oldSettings.isStabilizePitch(),
|
||||
oldSettings.isStabilizeRoll(),
|
||||
oldSettings.getChromaKeyingColor(),
|
||||
oldSettings.isInject360Metadata(),
|
||||
oldSettings.getSphericalFovX(),
|
||||
oldSettings.getSphericalFovY(),
|
||||
oldSettings.isInjectSphericalMetadata(),
|
||||
oldSettings.getAntiAliasing(),
|
||||
oldSettings.getExportCommand(),
|
||||
oldSettings.getEncodingPreset().getValue(),
|
||||
|
||||
@@ -27,10 +27,10 @@ import de.johni0702.minecraft.gui.layout.HorizontalLayout;
|
||||
import de.johni0702.minecraft.gui.popup.AbstractGuiPopup;
|
||||
import de.johni0702.minecraft.gui.popup.GuiYesNoPopup;
|
||||
import de.johni0702.minecraft.gui.utils.Colors;
|
||||
import de.johni0702.minecraft.gui.utils.lwjgl.Dimension;
|
||||
import de.johni0702.minecraft.gui.utils.lwjgl.ReadableDimension;
|
||||
import net.minecraft.client.gui.GuiErrorScreen;
|
||||
import net.minecraft.crash.CrashReport;
|
||||
import org.lwjgl.util.Dimension;
|
||||
import org.lwjgl.util.ReadableDimension;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import java.util.List;
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package com.replaymod.render.gui;
|
||||
|
||||
import com.google.common.base.Preconditions;
|
||||
import com.google.common.util.concurrent.FutureCallback;
|
||||
import com.google.common.util.concurrent.Futures;
|
||||
import com.google.gson.Gson;
|
||||
@@ -27,18 +28,22 @@ import de.johni0702.minecraft.gui.popup.GuiFileChooserPopup;
|
||||
import de.johni0702.minecraft.gui.utils.Colors;
|
||||
import de.johni0702.minecraft.gui.utils.Consumer;
|
||||
import de.johni0702.minecraft.gui.utils.Utils;
|
||||
import de.johni0702.minecraft.gui.utils.lwjgl.Color;
|
||||
import de.johni0702.minecraft.gui.utils.lwjgl.Dimension;
|
||||
import de.johni0702.minecraft.gui.utils.lwjgl.ReadableColor;
|
||||
import de.johni0702.minecraft.gui.utils.lwjgl.ReadableDimension;
|
||||
import net.minecraft.client.gui.GuiErrorScreen;
|
||||
import net.minecraft.client.resources.I18n;
|
||||
import net.minecraft.crash.CrashReport;
|
||||
import net.minecraftforge.common.config.Configuration;
|
||||
import net.minecraftforge.common.config.Property;
|
||||
import org.lwjgl.util.Color;
|
||||
import org.lwjgl.util.Dimension;
|
||||
import org.lwjgl.util.ReadableColor;
|
||||
import org.lwjgl.util.ReadableDimension;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import java.io.File;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.IOException;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.NoSuchFileException;
|
||||
import java.nio.file.Path;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.Date;
|
||||
import java.util.Map;
|
||||
@@ -128,7 +133,7 @@ public class GuiRenderSettings extends GuiScreen implements Closeable {
|
||||
new GuiLabel().setI18nText("replaymod.gui.rendersettings.renderer"), renderMethodDropdown,
|
||||
new GuiLabel().setI18nText("replaymod.gui.rendersettings.presets"), encodingPresetDropdown,
|
||||
new GuiLabel().setI18nText("replaymod.gui.rendersettings.customresolution"), videoResolutionPanel,
|
||||
new GuiLabel().setI18nText("replaymod.gui.settings.bitrate"), new GuiPanel().addElements(null,
|
||||
new GuiLabel().setI18nText("replaymod.gui.rendersettings.bitrate"), new GuiPanel().addElements(null,
|
||||
new GuiPanel().addElements(null, bitRateField, bitRateUnit).setLayout(new HorizontalLayout()),
|
||||
frameRateSlider).setLayout(new HorizontalLayout(HorizontalLayout.Alignment.RIGHT).setSpacing(3)),
|
||||
new GuiLabel().setI18nText("replaymod.gui.rendersettings.outputfile"), outputFileButton)
|
||||
@@ -149,8 +154,22 @@ public class GuiRenderSettings extends GuiScreen implements Closeable {
|
||||
.setI18nLabel("replaymod.gui.rendersettings.chromakey");
|
||||
public final GuiColorPicker chromaKeyingColor = new GuiColorPicker().setSize(30, 15);
|
||||
|
||||
public final GuiCheckbox inject360Metadata = new GuiCheckbox()
|
||||
.setI18nLabel("replaymod.gui.rendersettings.360metadata");
|
||||
public static final int MIN_SPHERICAL_FOV = 120;
|
||||
public static final int MAX_SPHERICAL_FOV = 360;
|
||||
public static final int SPHERICAL_FOV_STEP_SIZE = 5;
|
||||
public final GuiSlider sphericalFovSlider = new GuiSlider()
|
||||
.onValueChanged(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
sphericalFovSlider.setText(I18n.format("replaymod.gui.rendersettings.sphericalFov")
|
||||
+ ": " + (MIN_SPHERICAL_FOV + sphericalFovSlider.getValue() * SPHERICAL_FOV_STEP_SIZE) + "°");
|
||||
|
||||
updateInputs();
|
||||
}
|
||||
}).setSize(200, 20).setSteps((MAX_SPHERICAL_FOV - MIN_SPHERICAL_FOV) / SPHERICAL_FOV_STEP_SIZE);
|
||||
|
||||
public final GuiCheckbox injectSphericalMetadata = new GuiCheckbox()
|
||||
.setI18nLabel("replaymod.gui.rendersettings.sphericalmetadata");
|
||||
|
||||
public final GuiDropdownMenu<RenderSettings.AntiAliasing> antiAliasingDropdown = new GuiDropdownMenu<RenderSettings.AntiAliasing>()
|
||||
.setSize(200, 20).setValues(RenderSettings.AntiAliasing.values()).setSelected(RenderSettings.AntiAliasing.NONE);
|
||||
@@ -161,8 +180,7 @@ public class GuiRenderSettings extends GuiScreen implements Closeable {
|
||||
.addElements(new GridLayout.Data(0, 0.5),
|
||||
new GuiLabel().setI18nText("replaymod.gui.rendersettings.stabilizecamera"), stabilizePanel,
|
||||
chromaKeyingCheckbox, chromaKeyingColor,
|
||||
inject360Metadata,
|
||||
new GuiLabel(), // to show the anti-aliasing options in a new line
|
||||
injectSphericalMetadata, sphericalFovSlider,
|
||||
new GuiLabel().setI18nText("replaymod.gui.rendersettings.antialiasing"), antiAliasingDropdown));
|
||||
|
||||
public final GuiTextField exportCommand = new GuiTextField().setI18nHint("replaymod.gui.rendersettings.command")
|
||||
@@ -280,7 +298,13 @@ public class GuiRenderSettings extends GuiScreen implements Closeable {
|
||||
this.replayHandler = replayHandler;
|
||||
this.timeline = timeline;
|
||||
|
||||
String json = getConfigProperty(ReplayModRender.instance.getConfiguration()).getString();
|
||||
String json = "{}";
|
||||
try {
|
||||
json = new String(Files.readAllBytes(getSettingsPath()), StandardCharsets.UTF_8);
|
||||
} catch (NoSuchFileException | FileNotFoundException ignored) {
|
||||
} catch (IOException e) {
|
||||
LOGGER.error("Reading render settings:", e);
|
||||
}
|
||||
RenderSettings settings = new GsonBuilder()
|
||||
.registerTypeAdapter(RenderSettings.class, (InstanceCreator<RenderSettings>) type -> getDefaultRenderSettings())
|
||||
.registerTypeAdapter(ReadableColor.class, new Gson().getAdapter(Color.class))
|
||||
@@ -289,8 +313,13 @@ public class GuiRenderSettings extends GuiScreen implements Closeable {
|
||||
}
|
||||
|
||||
protected void updateInputs() {
|
||||
RenderSettings.RenderMethod renderMethod = renderMethodDropdown.getSelectedValue();
|
||||
|
||||
// Enable/Disable video with input
|
||||
videoWidth.setEnabled(!renderMethod.hasFixedAspectRatio());
|
||||
|
||||
// Validate video width and height
|
||||
String error = isResolutionValid();
|
||||
String error = updateResolution();
|
||||
if (error == null) {
|
||||
renderButton.setEnabled().setTooltip(null);
|
||||
videoWidth.setTextColor(Colors.WHITE);
|
||||
@@ -311,7 +340,7 @@ public class GuiRenderSettings extends GuiScreen implements Closeable {
|
||||
}
|
||||
|
||||
// Enable/Disable camera stabilization checkboxes
|
||||
switch (renderMethodDropdown.getSelectedValue()) {
|
||||
switch (renderMethod) {
|
||||
case CUBIC:
|
||||
case EQUIRECTANGULAR:
|
||||
case ODS:
|
||||
@@ -321,52 +350,94 @@ public class GuiRenderSettings extends GuiScreen implements Closeable {
|
||||
stabilizePanel.forEach(IGuiCheckbox.class).setDisabled();
|
||||
}
|
||||
|
||||
// Enable/Disable Spherical FOV slider
|
||||
sphericalFovSlider.setEnabled(renderMethod.isSpherical());
|
||||
|
||||
// Enable/Disable inject metadata checkbox
|
||||
if (encodingPresetDropdown.getSelectedValue().getFileExtension().equals("mp4")
|
||||
&& (renderMethodDropdown.getSelectedValue() == RenderSettings.RenderMethod.EQUIRECTANGULAR
|
||||
|| renderMethodDropdown.getSelectedValue() == RenderSettings.RenderMethod.ODS)) {
|
||||
inject360Metadata.setEnabled().setTooltip(null);
|
||||
&& renderMethod.isSpherical()) {
|
||||
injectSphericalMetadata.setEnabled().setTooltip(null);
|
||||
} else {
|
||||
inject360Metadata.setDisabled().setTooltip(new GuiTooltip().setColor(Colors.RED)
|
||||
.setI18nText("replaymod.gui.rendersettings.360metadata.error"));
|
||||
injectSphericalMetadata.setDisabled().setTooltip(new GuiTooltip().setColor(Colors.RED)
|
||||
.setI18nText("replaymod.gui.rendersettings.sphericalmetadata.error"));
|
||||
}
|
||||
}
|
||||
|
||||
protected String isResolutionValid() {
|
||||
protected String updateResolution() {
|
||||
RenderSettings.EncodingPreset preset = encodingPresetDropdown.getSelectedValue();
|
||||
RenderSettings.RenderMethod method = renderMethodDropdown.getSelectedValue();
|
||||
int videoWidth = this.videoWidth.getInteger();
|
||||
|
||||
int videoHeight = this.videoHeight.getInteger();
|
||||
int videoWidth;
|
||||
if (method.hasFixedAspectRatio()) {
|
||||
// cubic rendering requires an aspect ratio of 4:3,
|
||||
// therefore the height must be divisible by 3
|
||||
if (method == RenderSettings.RenderMethod.CUBIC && videoHeight % 3 != 0) {
|
||||
return "replaymod.gui.rendersettings.customresolution.warning.cubic.height";
|
||||
}
|
||||
|
||||
int sphericalFov = MIN_SPHERICAL_FOV + sphericalFovSlider.getValue() * SPHERICAL_FOV_STEP_SIZE;
|
||||
videoWidth = videoWidthForHeight(method, videoHeight, sphericalFov, sphericalFov);
|
||||
|
||||
this.videoWidth.setValue(videoWidth);
|
||||
} else {
|
||||
videoWidth = this.videoWidth.getInteger();
|
||||
}
|
||||
|
||||
// Make sure the export arguments haven't been changed manually
|
||||
if (exportArguments.getText().equals(preset.getValue())) {
|
||||
// Yuv420 requires both dimensions to be even
|
||||
if (preset.isYuv420()
|
||||
&& (videoWidth % 2 != 0 || videoHeight % 2 != 0)) {
|
||||
|
||||
if (method == RenderSettings.RenderMethod.CUBIC) {
|
||||
// cubic yuv rendering has the special case that the height must be
|
||||
// divisible by both 3 and 2 - tell the user about it with a special message
|
||||
return "replaymod.gui.rendersettings.customresolution.warning.yuv420.cubic";
|
||||
}
|
||||
|
||||
return "replaymod.gui.rendersettings.customresolution.warning.yuv420";
|
||||
}
|
||||
}
|
||||
|
||||
if (method == RenderSettings.RenderMethod.CUBIC
|
||||
&& (videoWidth * 3 / 4 != videoHeight || videoWidth * 3 % 4 != 0)) {
|
||||
return "replaymod.gui.rendersettings.customresolution.warning.cubic";
|
||||
}
|
||||
if (method == RenderSettings.RenderMethod.EQUIRECTANGULAR
|
||||
&& (videoWidth / 2 != videoHeight || videoWidth % 2 != 0)) {
|
||||
return "replaymod.gui.rendersettings.customresolution.warning.equirectangular";
|
||||
}
|
||||
if (method == RenderSettings.RenderMethod.ODS
|
||||
&& videoWidth != videoHeight) {
|
||||
return "replaymod.gui.rendersettings.customresolution.warning.ods";
|
||||
}
|
||||
//#if MC<10800
|
||||
//$$ if (method == RenderSettings.RenderMethod.BLEND) {
|
||||
//$$ return "replaymod.gui.rendersettings.no_blend_on_1_7_10";
|
||||
//$$ }
|
||||
//#endif
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
protected int videoWidthForHeight(RenderSettings.RenderMethod method, int height,
|
||||
int sphericalFovX, int sphericalFovY) {
|
||||
if (method.isSpherical()) {
|
||||
if (sphericalFovY < 180) {
|
||||
// calculate the non-cropped height of the video
|
||||
height = Math.round(height * 180 / (float) sphericalFovY);
|
||||
}
|
||||
|
||||
int width = height * 2;
|
||||
|
||||
if (sphericalFovX < 360) {
|
||||
// crop the resulting width
|
||||
width = Math.round(width * (float) sphericalFovX / 360);
|
||||
}
|
||||
|
||||
if (method == RenderSettings.RenderMethod.ODS) {
|
||||
width = Math.round(width / 2f);
|
||||
}
|
||||
|
||||
return width;
|
||||
|
||||
} else if (method == RenderSettings.RenderMethod.CUBIC) {
|
||||
Preconditions.checkArgument(height % 3 == 0);
|
||||
return height / 3 * 4;
|
||||
}
|
||||
|
||||
throw new IllegalArgumentException();
|
||||
}
|
||||
|
||||
public void load(RenderSettings settings) {
|
||||
renderMethodDropdown.setSelected(settings.getRenderMethod());
|
||||
encodingPresetDropdown.setSelected(settings.getEncodingPreset());
|
||||
@@ -402,7 +473,8 @@ public class GuiRenderSettings extends GuiScreen implements Closeable {
|
||||
chromaKeyingCheckbox.setChecked(true);
|
||||
chromaKeyingColor.setColor(settings.getChromaKeyingColor());
|
||||
}
|
||||
inject360Metadata.setChecked(settings.isInject360Metadata());
|
||||
sphericalFovSlider.setValue((settings.getSphericalFovX() - MIN_SPHERICAL_FOV) / SPHERICAL_FOV_STEP_SIZE);
|
||||
injectSphericalMetadata.setChecked(settings.isInjectSphericalMetadata());
|
||||
antiAliasingDropdown.setSelected(settings.getAntiAliasing());
|
||||
exportCommand.setText(settings.getExportCommand());
|
||||
exportArguments.setText(settings.getExportArguments());
|
||||
@@ -411,6 +483,8 @@ public class GuiRenderSettings extends GuiScreen implements Closeable {
|
||||
}
|
||||
|
||||
public RenderSettings save(boolean serialize) {
|
||||
int sphericalFov = MIN_SPHERICAL_FOV + sphericalFovSlider.getValue() * SPHERICAL_FOV_STEP_SIZE;
|
||||
|
||||
return new RenderSettings(
|
||||
renderMethodDropdown.getSelectedValue(),
|
||||
encodingPresetDropdown.getSelectedValue(),
|
||||
@@ -424,7 +498,8 @@ public class GuiRenderSettings extends GuiScreen implements Closeable {
|
||||
stabilizePitch.isChecked() && (serialize || stabilizePitch.isEnabled()),
|
||||
stabilizeRoll.isChecked() && (serialize || stabilizeRoll.isEnabled()),
|
||||
chromaKeyingCheckbox.isChecked() ? chromaKeyingColor.getColor() : null,
|
||||
inject360Metadata.isChecked() && (serialize || inject360Metadata.isEnabled()),
|
||||
sphericalFov, Math.min(180, sphericalFov),
|
||||
injectSphericalMetadata.isChecked() && (serialize || injectSphericalMetadata.isEnabled()),
|
||||
antiAliasingDropdown.getSelectedValue(),
|
||||
exportCommand.getText(),
|
||||
exportArguments.getText(),
|
||||
@@ -438,23 +513,24 @@ public class GuiRenderSettings extends GuiScreen implements Closeable {
|
||||
return new File(folder, fileName + "." + encodingPreset.getFileExtension());
|
||||
}
|
||||
|
||||
protected Path getSettingsPath() {
|
||||
return ReplayModRender.instance.getRenderSettingsPath();
|
||||
}
|
||||
|
||||
private RenderSettings getDefaultRenderSettings() {
|
||||
return new RenderSettings(RenderSettings.RenderMethod.DEFAULT, RenderSettings.EncodingPreset.MP4_DEFAULT, 1920, 1080, 60, 10 << 20, null,
|
||||
true, false, false, false, null, false, RenderSettings.AntiAliasing.NONE, "", RenderSettings.EncodingPreset.MP4_DEFAULT.getValue(), false);
|
||||
true, false, false, false, null, 360, 180, false, RenderSettings.AntiAliasing.NONE, "", RenderSettings.EncodingPreset.MP4_DEFAULT.getValue(), false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() {
|
||||
RenderSettings settings = save(true);
|
||||
String json = new Gson().toJson(settings);
|
||||
Configuration config = ReplayModRender.instance.getConfiguration();
|
||||
getConfigProperty(config).set(json);
|
||||
config.save();
|
||||
}
|
||||
|
||||
protected Property getConfigProperty(Configuration configuration) {
|
||||
return configuration.get("rendersettings", "settings", "{}",
|
||||
"Last state of the render settings GUI. Internal use only.");
|
||||
try {
|
||||
Files.write(getSettingsPath(), json.getBytes(StandardCharsets.UTF_8));
|
||||
} catch (IOException e) {
|
||||
LOGGER.error("Saving render settings:", e);
|
||||
}
|
||||
}
|
||||
|
||||
public ReplayHandler getReplayHandler() {
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package com.replaymod.render.gui;
|
||||
|
||||
import com.replaymod.core.SettingsRegistry;
|
||||
import com.replaymod.core.versions.MCVer;
|
||||
import com.replaymod.render.RenderSettings;
|
||||
import com.replaymod.render.ReplayModRender;
|
||||
import com.replaymod.render.Setting;
|
||||
@@ -13,13 +14,8 @@ import de.johni0702.minecraft.gui.layout.CustomLayout;
|
||||
import de.johni0702.minecraft.gui.layout.HorizontalLayout;
|
||||
import de.johni0702.minecraft.gui.layout.VerticalLayout;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import net.minecraft.util.Util;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.lwjgl.Sys;
|
||||
|
||||
import java.awt.*;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
|
||||
@RequiredArgsConstructor
|
||||
public class GuiRenderingDone extends GuiScreen {
|
||||
@@ -34,30 +30,7 @@ public class GuiRenderingDone extends GuiScreen {
|
||||
public final GuiButton openFolder = new GuiButton().onClick(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
File folder = videoFile.getParentFile();
|
||||
String path = folder.getAbsolutePath();
|
||||
|
||||
// First try OS specific methods
|
||||
try {
|
||||
switch (Util.getOSType()) {
|
||||
case WINDOWS:
|
||||
Runtime.getRuntime().exec(String.format("cmd.exe /C start \"Open file\" \"%s\"", path));
|
||||
return;
|
||||
case OSX:
|
||||
Runtime.getRuntime().exec(new String[]{"/usr/bin/open", path});
|
||||
return;
|
||||
}
|
||||
} catch (IOException e) {
|
||||
LogManager.getLogger().error("Cannot open file", e);
|
||||
}
|
||||
|
||||
// Otherwise try the java way
|
||||
try {
|
||||
Desktop.getDesktop().browse(folder.toURI());
|
||||
} catch (Throwable throwable) {
|
||||
// And if all fails, lwjgl
|
||||
Sys.openURL("file://" + path);
|
||||
}
|
||||
MCVer.openFile(videoFile.getParentFile());
|
||||
}
|
||||
}).setSize(200, 20).setI18nLabel("replaymod.gui.openfolder");
|
||||
|
||||
|
||||
@@ -11,18 +11,23 @@ import de.johni0702.minecraft.gui.element.GuiButton;
|
||||
import de.johni0702.minecraft.gui.element.GuiCheckbox;
|
||||
import de.johni0702.minecraft.gui.element.GuiLabel;
|
||||
import de.johni0702.minecraft.gui.element.advanced.GuiProgressBar;
|
||||
import de.johni0702.minecraft.gui.function.Tickable;
|
||||
import de.johni0702.minecraft.gui.layout.CustomLayout;
|
||||
import de.johni0702.minecraft.gui.layout.HorizontalLayout;
|
||||
import de.johni0702.minecraft.gui.utils.lwjgl.Dimension;
|
||||
import de.johni0702.minecraft.gui.utils.lwjgl.ReadableDimension;
|
||||
import de.johni0702.minecraft.gui.utils.lwjgl.ReadablePoint;
|
||||
import net.minecraft.client.renderer.texture.DynamicTexture;
|
||||
import net.minecraft.client.resources.I18n;
|
||||
import net.minecraft.util.ResourceLocation;
|
||||
import org.lwjgl.util.Dimension;
|
||||
import org.lwjgl.util.ReadableDimension;
|
||||
import org.lwjgl.util.ReadablePoint;
|
||||
|
||||
//#if MC>=11300
|
||||
import net.minecraft.client.renderer.texture.NativeImage;
|
||||
//#endif
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
|
||||
public class GuiVideoRenderer extends GuiScreen {
|
||||
public class GuiVideoRenderer extends GuiScreen implements Tickable {
|
||||
private static final ResourceLocation NO_PREVIEW_TEXTURE = new ResourceLocation("replaymod", "logo.jpg");
|
||||
|
||||
private final VideoRenderer renderer;
|
||||
@@ -135,7 +140,7 @@ public class GuiVideoRenderer extends GuiScreen {
|
||||
private int currentIndex = 0;
|
||||
|
||||
@Override
|
||||
public void draw(GuiRenderer guiRenderer, ReadableDimension size, RenderInfo renderInfo) {
|
||||
public void tick() {
|
||||
long current = System.currentTimeMillis();
|
||||
|
||||
//first, update the total render time (only if rendering is not paused and has already started)
|
||||
@@ -206,8 +211,6 @@ public class GuiVideoRenderer extends GuiScreen {
|
||||
int framesDone = renderer.getFramesDone(), framesTotal = renderer.getTotalFrames();
|
||||
progressBar.setI18nLabel("replaymod.gui.rendering.progress", framesDone, framesTotal);
|
||||
progressBar.setProgress((float) framesDone / framesTotal);
|
||||
|
||||
super.draw(guiRenderer, size, renderInfo);
|
||||
}
|
||||
|
||||
private String secToString(int seconds) {
|
||||
@@ -229,7 +232,11 @@ public class GuiVideoRenderer extends GuiScreen {
|
||||
final int videoHeight = videoSize.getHeight();
|
||||
|
||||
if (previewTexture == null) {
|
||||
previewTexture = new DynamicTexture(videoWidth, videoHeight);
|
||||
//#if MC>=11300
|
||||
previewTexture = new DynamicTexture(videoWidth, videoHeight, true);
|
||||
//#else
|
||||
//$$ previewTexture = new DynamicTexture(videoWidth, videoHeight);
|
||||
//#endif
|
||||
}
|
||||
|
||||
if (previewTextureDirty) {
|
||||
@@ -263,13 +270,27 @@ public class GuiVideoRenderer extends GuiScreen {
|
||||
ByteBuffer buffer = frame.getByteBuffer();
|
||||
buffer.mark();
|
||||
synchronized (this) {
|
||||
int[] data = previewTexture.getTextureData();
|
||||
// Optifine changes the texture data array to be three times as long (for use by shaders),
|
||||
// we only want to initialize the first third which is why we use the length of the buffer instead
|
||||
// of the length of the data array
|
||||
for (int i = 0; buffer.remaining() > 0; i++) {
|
||||
data[i] = 0xff << 24 | (buffer.get() & 0xff) << 16 | (buffer.get() & 0xff) << 8 | (buffer.get() & 0xff);
|
||||
//#if MC>=11300
|
||||
NativeImage data = previewTexture.getTextureData();
|
||||
assert data != null;
|
||||
for (int y = 0; y < data.getHeight(); y++) {
|
||||
for (int x = 0; x < data.getWidth(); x++) {
|
||||
int r = buffer.get() & 0xff;
|
||||
int g = buffer.get() & 0xff;
|
||||
int b = buffer.get() & 0xff;
|
||||
int value = 0xff << 24 | b << 16 | g << 8 | r;
|
||||
data.setPixelRGBA(x, y, value); // actually takes ABGR, not RGBA
|
||||
}
|
||||
}
|
||||
//#else
|
||||
//$$ int[] data = previewTexture.getTextureData();
|
||||
//$$ // Optifine changes the texture data array to be three times as long (for use by shaders),
|
||||
//$$ // we only want to initialize the first third which is why we use the length of the buffer instead
|
||||
//$$ // of the length of the data array
|
||||
//$$ for (int i = 0; buffer.remaining() > 0; i++) {
|
||||
//$$ data[i] = 0xff << 24 | (buffer.get() & 0xff) << 16 | (buffer.get() & 0xff) << 8 | (buffer.get() & 0xff);
|
||||
//$$ }
|
||||
//#endif
|
||||
previewTextureDirty = true;
|
||||
}
|
||||
buffer.reset();
|
||||
|
||||
@@ -3,8 +3,6 @@ package com.replaymod.render.hooks;
|
||||
|
||||
import com.replaymod.render.utils.JailingQueue;
|
||||
import net.minecraft.client.renderer.RegionRenderCacheBuilder;
|
||||
import net.minecraft.client.renderer.RenderGlobal;
|
||||
import net.minecraft.client.renderer.chunk.ChunkCompileTaskGenerator;
|
||||
import net.minecraft.client.renderer.chunk.ChunkRenderDispatcher;
|
||||
import net.minecraft.client.renderer.chunk.ChunkRenderWorker;
|
||||
import net.minecraft.client.renderer.chunk.RenderChunk;
|
||||
@@ -12,6 +10,14 @@ import net.minecraft.client.renderer.chunk.RenderChunk;
|
||||
import java.lang.reflect.Field;
|
||||
import java.util.Iterator;
|
||||
|
||||
//#if MC>=11300
|
||||
import net.minecraft.client.renderer.WorldRenderer;
|
||||
import net.minecraft.client.renderer.chunk.ChunkRenderTask;
|
||||
//#else
|
||||
//$$ import net.minecraft.client.renderer.RenderGlobal;
|
||||
//$$ import net.minecraft.client.renderer.chunk.ChunkCompileTaskGenerator;
|
||||
//#endif
|
||||
|
||||
//#if MC>=10904
|
||||
import java.util.concurrent.PriorityBlockingQueue;
|
||||
//#else
|
||||
@@ -22,14 +28,28 @@ import static com.replaymod.core.versions.MCVer.*;
|
||||
|
||||
public class ChunkLoadingRenderGlobal {
|
||||
|
||||
private final RenderGlobal hooked;
|
||||
//#if MC>=11300
|
||||
private final WorldRenderer hooked;
|
||||
//#else
|
||||
//$$ private final RenderGlobal hooked;
|
||||
//#endif
|
||||
private ChunkRenderDispatcher renderDispatcher;
|
||||
private JailingQueue<ChunkCompileTaskGenerator> workerJailingQueue;
|
||||
//#if MC>=11300
|
||||
private JailingQueue<ChunkRenderTask> workerJailingQueue;
|
||||
//#else
|
||||
//$$ private JailingQueue<ChunkCompileTaskGenerator> workerJailingQueue;
|
||||
//#endif
|
||||
private CustomChunkRenderWorker renderWorker;
|
||||
private int frame;
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public ChunkLoadingRenderGlobal(RenderGlobal renderGlobal) {
|
||||
public ChunkLoadingRenderGlobal(
|
||||
//#if MC>=11300
|
||||
WorldRenderer renderGlobal
|
||||
//#else
|
||||
//$$ RenderGlobal renderGlobal
|
||||
//#endif
|
||||
) {
|
||||
this.hooked = renderGlobal;
|
||||
|
||||
setup(renderGlobal.renderDispatcher);
|
||||
@@ -51,14 +71,22 @@ public class ChunkLoadingRenderGlobal {
|
||||
|
||||
int workerThreads = renderDispatcher.listThreadedWorkers.size();
|
||||
//#if MC>=10904
|
||||
PriorityBlockingQueue<ChunkCompileTaskGenerator> queueChunkUpdates = renderDispatcher.queueChunkUpdates;
|
||||
//#if MC>=11300
|
||||
PriorityBlockingQueue<ChunkRenderTask> queueChunkUpdates = renderDispatcher.queueChunkUpdates;
|
||||
//#else
|
||||
//$$ PriorityBlockingQueue<ChunkCompileTaskGenerator> queueChunkUpdates = renderDispatcher.queueChunkUpdates;
|
||||
//#endif
|
||||
//#else
|
||||
//$$ BlockingQueue<ChunkCompileTaskGenerator> queueChunkUpdates = renderDispatcher.queueChunkUpdates;
|
||||
//#endif
|
||||
workerJailingQueue = new JailingQueue<>(queueChunkUpdates);
|
||||
renderDispatcher.queueChunkUpdates = workerJailingQueue;
|
||||
//#if MC>=10904
|
||||
ChunkCompileTaskGenerator element = new ChunkCompileTaskGenerator(null, null, 0);
|
||||
//#if MC>=11300
|
||||
ChunkRenderTask element = new ChunkRenderTask(null, null, 0);
|
||||
//#else
|
||||
//$$ ChunkCompileTaskGenerator element = new ChunkCompileTaskGenerator(null, null, 0);
|
||||
//#endif
|
||||
//#else
|
||||
//$$ ChunkCompileTaskGenerator element = new ChunkCompileTaskGenerator(null, null);
|
||||
//#endif
|
||||
@@ -75,7 +103,11 @@ public class ChunkLoadingRenderGlobal {
|
||||
renderDispatcher.queueChunkUpdates = queueChunkUpdates;
|
||||
|
||||
try {
|
||||
Field hookField = RenderGlobal.class.getField("replayModRender_hook");
|
||||
//#if MC>=11300
|
||||
Field hookField = WorldRenderer.class.getField("replayModRender_hook");
|
||||
//#else
|
||||
//$$ Field hookField = RenderGlobal.class.getField("replayModRender_hook");
|
||||
//#endif
|
||||
hookField.set(hooked, this);
|
||||
} catch (NoSuchFieldException | IllegalAccessException e) {
|
||||
throw new Error(e);
|
||||
@@ -119,7 +151,11 @@ public class ChunkLoadingRenderGlobal {
|
||||
workerJailingQueue.freeAll();
|
||||
|
||||
try {
|
||||
Field hookField = RenderGlobal.class.getField("replayModRender_hook");
|
||||
//#if MC>=11300
|
||||
Field hookField = WorldRenderer.class.getField("replayModRender_hook");
|
||||
//#else
|
||||
//$$ Field hookField = RenderGlobal.class.getField("replayModRender_hook");
|
||||
//#endif
|
||||
hookField.set(hooked, null);
|
||||
} catch (NoSuchFieldException | IllegalAccessException e) {
|
||||
throw new Error(e);
|
||||
@@ -139,7 +175,13 @@ public class ChunkLoadingRenderGlobal {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void processTask(ChunkCompileTaskGenerator p_178474_1_) throws InterruptedException {
|
||||
protected void processTask(
|
||||
//#if MC>=11300
|
||||
ChunkRenderTask p_178474_1_
|
||||
//#else
|
||||
//$$ ChunkCompileTaskGenerator p_178474_1_
|
||||
//#endif
|
||||
) throws InterruptedException {
|
||||
super.processTask(p_178474_1_);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package com.replaymod.render.hooks;
|
||||
|
||||
import com.replaymod.core.versions.MCVer;
|
||||
import com.replaymod.render.RenderSettings;
|
||||
import com.replaymod.render.capturer.CaptureData;
|
||||
import com.replaymod.render.capturer.RenderInfo;
|
||||
@@ -8,8 +9,12 @@ import lombok.Getter;
|
||||
import net.minecraft.client.Minecraft;
|
||||
|
||||
//#if MC>=10800
|
||||
import net.minecraft.client.renderer.GlStateManager;
|
||||
import net.minecraftforge.fml.common.FMLCommonHandler;
|
||||
//#if MC>=11300
|
||||
import net.minecraftforge.fml.hooks.BasicEventHooks;
|
||||
//#else
|
||||
//$$ import net.minecraft.client.renderer.GlStateManager;
|
||||
//$$ import net.minecraftforge.fml.common.FMLCommonHandler;
|
||||
//#endif
|
||||
//#else
|
||||
//$$ import com.replaymod.core.versions.MCVer.GlStateManager;
|
||||
//$$ import cpw.mods.fml.common.FMLCommonHandler;
|
||||
@@ -18,7 +23,7 @@ import net.minecraftforge.fml.common.FMLCommonHandler;
|
||||
import java.io.IOException;
|
||||
|
||||
public class EntityRendererHandler implements WorldRenderer {
|
||||
public final Minecraft mc = Minecraft.getMinecraft();
|
||||
public final Minecraft mc = MCVer.getMinecraft();
|
||||
|
||||
@Getter
|
||||
protected final RenderSettings settings;
|
||||
@@ -44,21 +49,33 @@ public class EntityRendererHandler implements WorldRenderer {
|
||||
}
|
||||
|
||||
public void renderWorld(float partialTicks, long finishTimeNano) {
|
||||
FMLCommonHandler.instance().onRenderTickStart(partialTicks);
|
||||
|
||||
mc.entityRenderer.updateLightmap(partialTicks);
|
||||
|
||||
GlStateManager.enableDepth();
|
||||
GlStateManager.enableAlpha();
|
||||
GlStateManager.alphaFunc(516, 0.5F);
|
||||
//#if MC>=11300
|
||||
BasicEventHooks.onRenderTickStart(partialTicks);
|
||||
//#else
|
||||
//$$ FMLCommonHandler.instance().onRenderTickStart(partialTicks);
|
||||
//#endif
|
||||
|
||||
//#if MC>=11300
|
||||
mc.entityRenderer.renderWorld(partialTicks, finishTimeNano);
|
||||
//#else
|
||||
//$$ mc.entityRenderer.updateLightmap(partialTicks);
|
||||
//$$
|
||||
//$$ GlStateManager.enableDepth();
|
||||
//$$ GlStateManager.enableAlpha();
|
||||
//$$ GlStateManager.alphaFunc(516, 0.5F);
|
||||
//$$
|
||||
//#if MC>=10800
|
||||
mc.entityRenderer.renderWorldPass(2, partialTicks, finishTimeNano);
|
||||
//$$ mc.entityRenderer.renderWorldPass(2, partialTicks, finishTimeNano);
|
||||
//#else
|
||||
//$$ mc.entityRenderer.renderWorld(partialTicks, finishTimeNano);
|
||||
//#endif
|
||||
//#endif
|
||||
|
||||
FMLCommonHandler.instance().onRenderTickEnd(partialTicks);
|
||||
//#if MC>=11300
|
||||
BasicEventHooks.onRenderTickEnd(partialTicks);
|
||||
//#else
|
||||
//$$ FMLCommonHandler.instance().onRenderTickEnd(partialTicks);
|
||||
//#endif
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -71,10 +88,6 @@ public class EntityRendererHandler implements WorldRenderer {
|
||||
this.omnidirectional = omnidirectional;
|
||||
}
|
||||
|
||||
public interface GluPerspective {
|
||||
void replayModRender_gluPerspective(float fovY, float aspect, float zNear, float zFar);
|
||||
}
|
||||
|
||||
public interface IEntityRenderer {
|
||||
void replayModRender_setHandler(EntityRendererHandler handler);
|
||||
EntityRendererHandler replayModRender_getHandler();
|
||||
|
||||
@@ -4,6 +4,8 @@ import com.coremedia.iso.IsoFile;
|
||||
import com.coremedia.iso.boxes.*;
|
||||
import com.google.common.primitives.Bytes;
|
||||
import com.googlecode.mp4parser.BasicContainer;
|
||||
import com.replaymod.render.RenderSettings;
|
||||
import de.johni0702.minecraft.gui.utils.lwjgl.Dimension;
|
||||
import org.apache.commons.io.FileUtils;
|
||||
import org.apache.commons.io.IOUtils;
|
||||
|
||||
@@ -30,12 +32,20 @@ public class MetadataInjector {
|
||||
"<GSpherical:Stitched>true</GSpherical:Stitched> " +
|
||||
"<GSpherical:StitchingSoftware>"+STITCHING_SOFTWARE+"</GSpherical:StitchingSoftware> " +
|
||||
"<GSpherical:ProjectionType>equirectangular</GSpherical:ProjectionType> ";
|
||||
private static final String SPHERICAL_CROP_XML =
|
||||
"<GSpherical:FullPanoWidthPixels>%d</GSpherical:FullPanoWidthPixels> " +
|
||||
"<GSpherical:FullPanoHeightPixels>%d</GSpherical:FullPanoHeightPixels> " +
|
||||
"<GSpherical:CroppedAreaImageWidthPixels>%d</GSpherical:CroppedAreaImageWidthPixels> " +
|
||||
"<GSpherical:CroppedAreaImageHeightPixels>%d</GSpherical:CroppedAreaImageHeightPixels> " +
|
||||
"<GSpherical:CroppedAreaLeftPixels>%d</GSpherical:CroppedAreaLeftPixels> " +
|
||||
"<GSpherical:CroppedAreaTopPixels>%d</GSpherical:CroppedAreaTopPixels> ";
|
||||
private static final String STEREO_XML_CONTENTS = "<GSpherical:StereoMode>top-bottom</GSpherical:StereoMode>";
|
||||
private static final String SPHERICAL_XML_FOOTER = "</rdf:SphericalVideo>";
|
||||
|
||||
private static final String XML_360_METADATA = SPHERICAL_XML_HEADER + SPHERICAL_XML_CONTENTS + SPHERICAL_XML_FOOTER;
|
||||
private static final String XML_ODS_METADATA = SPHERICAL_XML_HEADER + SPHERICAL_XML_CONTENTS
|
||||
+ STEREO_XML_CONTENTS + SPHERICAL_XML_FOOTER;
|
||||
private static final String XML_MONO_METADATA = SPHERICAL_XML_HEADER + SPHERICAL_XML_CONTENTS
|
||||
+ SPHERICAL_CROP_XML + SPHERICAL_XML_FOOTER;
|
||||
private static final String XML_STEREO_METADATA = SPHERICAL_XML_HEADER + SPHERICAL_XML_CONTENTS
|
||||
+ SPHERICAL_CROP_XML + STEREO_XML_CONTENTS + SPHERICAL_XML_FOOTER;
|
||||
|
||||
/**
|
||||
* These bytes are taken from the variable 'spherical_uuid_id'
|
||||
@@ -48,18 +58,43 @@ public class MetadataInjector {
|
||||
(byte)0x02, (byte)0x52, (byte)0x1f, (byte)0xdd
|
||||
};
|
||||
|
||||
private static final byte[] BYTES_360_METADATA = Bytes.concat(UUID_BYTES, XML_360_METADATA.getBytes());
|
||||
private static final byte[] BYTES_ODS_METADATA = Bytes.concat(UUID_BYTES, XML_ODS_METADATA.getBytes());
|
||||
public static void injectMetadata(RenderSettings.RenderMethod renderMethod, File videoFile,
|
||||
int videoWidth, int videoHeight,
|
||||
int sphericalFovX, int sphericalFovY) {
|
||||
String xmlString;
|
||||
switch (renderMethod) {
|
||||
case EQUIRECTANGULAR:
|
||||
xmlString = XML_MONO_METADATA;
|
||||
break;
|
||||
case ODS:
|
||||
xmlString = XML_STEREO_METADATA;
|
||||
break;
|
||||
default:
|
||||
throw new IllegalArgumentException("Invalid render method");
|
||||
}
|
||||
|
||||
public static void inject360Metadata(File videoFile) {
|
||||
writeMetadata(videoFile, BYTES_360_METADATA);
|
||||
Dimension original = getOriginalDimensions(videoWidth, videoHeight, sphericalFovX, sphericalFovY);
|
||||
writeMetadata(videoFile, String.format(xmlString,
|
||||
original.getWidth(), original.getHeight(), videoWidth, videoHeight,
|
||||
(original.getWidth() - videoWidth) / 2, (original.getHeight() - videoHeight) / 2));
|
||||
}
|
||||
|
||||
public static void injectODSMetadata(File videoFile) {
|
||||
writeMetadata(videoFile, BYTES_ODS_METADATA);
|
||||
private static Dimension getOriginalDimensions(int videoWidth, int videoHeight,
|
||||
int sphericalFovX, int sphericalFovY) {
|
||||
if (sphericalFovX < 360) {
|
||||
videoWidth = Math.round(videoWidth * 360 / (float) sphericalFovX);
|
||||
}
|
||||
|
||||
if (sphericalFovY < 180) {
|
||||
videoHeight = Math.round(videoHeight * 180 / (float) sphericalFovY);
|
||||
}
|
||||
|
||||
return new Dimension(videoWidth, videoHeight);
|
||||
}
|
||||
|
||||
private static void writeMetadata(File videoFile, byte[] metadata) {
|
||||
private static void writeMetadata(File videoFile, String metadata) {
|
||||
byte[] bytes = Bytes.concat(UUID_BYTES, metadata.getBytes());
|
||||
|
||||
File tempFile = null;
|
||||
FileOutputStream videoFileOutputStream = null;
|
||||
IsoFile tempIsoFile = null;
|
||||
@@ -80,7 +115,7 @@ public class MetadataInjector {
|
||||
|
||||
//create a new UserBox, which actually contains the Metadata bytes
|
||||
UserBox metadataBox = new UserBox(new byte[0]);
|
||||
metadataBox.setData(metadata);
|
||||
metadataBox.setData(bytes);
|
||||
|
||||
//add the Metadata UserBox to the Movie Track
|
||||
trackBox.addBox(metadataBox);
|
||||
@@ -97,7 +132,7 @@ public class MetadataInjector {
|
||||
videoFileOutputStream = new FileOutputStream(videoFile);
|
||||
tempIsoFile.getBox(videoFileOutputStream.getChannel());
|
||||
} catch(Exception e) {
|
||||
LOGGER.error("360 Degree Metadata couldn't be injected", e);
|
||||
LOGGER.error("Spherical Metadata couldn't be injected", e);
|
||||
} finally {
|
||||
IOUtils.closeQuietly(tempIsoFile);
|
||||
IOUtils.closeQuietly(videoFileOutputStream);
|
||||
|
||||
@@ -1,20 +1,16 @@
|
||||
package com.replaymod.render.mixin;
|
||||
|
||||
import com.replaymod.core.versions.MCVer;
|
||||
import com.replaymod.render.RenderSettings;
|
||||
import com.replaymod.render.capturer.CubicOpenGlFrameCapturer;
|
||||
import com.replaymod.render.capturer.StereoscopicOpenGlFrameCapturer;
|
||||
import com.replaymod.render.hooks.EntityRendererHandler;
|
||||
import com.replaymod.replay.camera.CameraEntity;
|
||||
import de.johni0702.minecraft.gui.utils.lwjgl.ReadableColor;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.renderer.EntityRenderer;
|
||||
import net.minecraft.client.renderer.RenderGlobal;
|
||||
import net.minecraft.client.settings.GameSettings;
|
||||
import net.minecraft.entity.Entity;
|
||||
import net.minecraft.entity.EntityLivingBase;
|
||||
import net.minecraft.entity.player.EntityPlayer;
|
||||
import org.lwjgl.opengl.GL11;
|
||||
import org.lwjgl.util.ReadableColor;
|
||||
import org.lwjgl.util.glu.Project;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.Shadow;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
@@ -22,6 +18,18 @@ import org.spongepowered.asm.mixin.injection.Inject;
|
||||
import org.spongepowered.asm.mixin.injection.Redirect;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||
|
||||
//#if MC>=11300
|
||||
import net.minecraft.client.GameSettings;
|
||||
import net.minecraft.client.renderer.GameRenderer;
|
||||
import net.minecraft.client.renderer.Matrix4f;
|
||||
import net.minecraft.client.renderer.WorldRenderer;
|
||||
//#else
|
||||
//$$ import net.minecraft.client.renderer.EntityRenderer;
|
||||
//$$ import net.minecraft.client.renderer.RenderGlobal;
|
||||
//$$ import net.minecraft.client.settings.GameSettings;
|
||||
//$$ import org.lwjgl.util.glu.Project;
|
||||
//#endif
|
||||
|
||||
//#if MC>=10904
|
||||
import net.minecraft.util.math.RayTraceResult;
|
||||
//#else
|
||||
@@ -31,13 +39,18 @@ import net.minecraft.util.math.RayTraceResult;
|
||||
//#if MC>=10800
|
||||
import net.minecraft.client.renderer.GlStateManager;
|
||||
//#else
|
||||
//$$ import net.minecraft.entity.EntityLivingBase;
|
||||
//$$ import com.replaymod.core.versions.MCVer.GlStateManager;
|
||||
//#endif
|
||||
|
||||
import static com.replaymod.core.versions.MCVer.*;
|
||||
|
||||
@Mixin(value = EntityRenderer.class)
|
||||
public abstract class MixinEntityRenderer implements EntityRendererHandler.IEntityRenderer, EntityRendererHandler.GluPerspective {
|
||||
//#if MC>=11300
|
||||
@Mixin(value = GameRenderer.class)
|
||||
//#else
|
||||
//$$ @Mixin(value = EntityRenderer.class)
|
||||
//#endif
|
||||
public abstract class MixinEntityRenderer implements EntityRendererHandler.IEntityRenderer {
|
||||
@Shadow
|
||||
public Minecraft mc;
|
||||
|
||||
@@ -64,18 +77,21 @@ public abstract class MixinEntityRenderer implements EntityRendererHandler.IEnti
|
||||
//$$ }
|
||||
//#endif
|
||||
|
||||
@Inject(method = "setupFog", at = @At("HEAD"), cancellable = true)
|
||||
private void replayModRender_onSetupFog(int fogDistanceFlag, float partialTicks, CallbackInfo ci) {
|
||||
if (replayModRender_handler == null) return;
|
||||
if (replayModRender_handler.getSettings().getChromaKeyingColor() != null) {
|
||||
ci.cancel();
|
||||
}
|
||||
}
|
||||
// Moved to MixinFogRenderer in 1.13
|
||||
//#if MC<11300
|
||||
//$$ @Inject(method = "setupFog", at = @At("HEAD"), cancellable = true)
|
||||
//$$ private void replayModRender_onSetupFog(int fogDistanceFlag, float partialTicks, CallbackInfo ci) {
|
||||
//$$ if (replayModRender_handler == null) return;
|
||||
//$$ if (replayModRender_handler.getSettings().getChromaKeyingColor() != null) {
|
||||
//$$ ci.cancel();
|
||||
//$$ }
|
||||
//$$ }
|
||||
//#endif
|
||||
|
||||
@Inject(method = "orientCamera", at = @At("HEAD"))
|
||||
private void replayModRender_resetRotationIfNeeded(float partialTicks, CallbackInfo ci) {
|
||||
if (replayModRender_handler != null) {
|
||||
Entity entity = getRenderViewEntity(Minecraft.getMinecraft());
|
||||
Entity entity = getRenderViewEntity(MCVer.getMinecraft());
|
||||
RenderSettings settings = replayModRender_handler.getSettings();
|
||||
if (settings.isStabilizeYaw()) {
|
||||
entity.prevRotationYaw = entity.rotationYaw = 0;
|
||||
@@ -96,9 +112,15 @@ public abstract class MixinEntityRenderer implements EntityRendererHandler.IEnti
|
||||
private float orgRoll;
|
||||
|
||||
@Inject(method = "setupCameraTransform", at = @At("HEAD"))
|
||||
private void replayModRender_beforeSetupCameraTransform(float partialTicks, int renderPass, CallbackInfo ci) {
|
||||
private void replayModRender_beforeSetupCameraTransform(
|
||||
float partialTicks,
|
||||
//#if MC<11300
|
||||
//$$ int renderPass,
|
||||
//#endif
|
||||
CallbackInfo ci
|
||||
) {
|
||||
if (replayModRender_handler != null) {
|
||||
Entity entity = getRenderViewEntity(Minecraft.getMinecraft());
|
||||
Entity entity = getRenderViewEntity(MCVer.getMinecraft());
|
||||
orgYaw = entity.rotationYaw;
|
||||
orgPitch = entity.rotationPitch;
|
||||
orgPrevYaw = entity.prevRotationYaw;
|
||||
@@ -108,9 +130,15 @@ public abstract class MixinEntityRenderer implements EntityRendererHandler.IEnti
|
||||
}
|
||||
|
||||
@Inject(method = "setupCameraTransform", at = @At("RETURN"))
|
||||
private void replayModRender_afterSetupCameraTransform(float partialTicks, int renderPass, CallbackInfo ci) {
|
||||
private void replayModRender_afterSetupCameraTransform(
|
||||
float partialTicks,
|
||||
//#if MC<11300
|
||||
//$$ int renderPass,
|
||||
//#endif
|
||||
CallbackInfo ci
|
||||
) {
|
||||
if (replayModRender_handler != null) {
|
||||
Entity entity = getRenderViewEntity(Minecraft.getMinecraft());
|
||||
Entity entity = getRenderViewEntity(MCVer.getMinecraft());
|
||||
entity.rotationYaw = orgYaw;
|
||||
entity.rotationPitch = orgPitch;
|
||||
entity.prevRotationYaw = orgPrevYaw;
|
||||
@@ -122,29 +150,46 @@ public abstract class MixinEntityRenderer implements EntityRendererHandler.IEnti
|
||||
}
|
||||
|
||||
@Inject(method = "renderHand", at = @At("HEAD"), cancellable = true)
|
||||
private void replayModRender_renderSpectatorHand(float partialTicks, int renderPass, CallbackInfo ci) {
|
||||
private void replayModRender_renderSpectatorHand(
|
||||
float partialTicks,
|
||||
//#if MC<11300
|
||||
//$$ int renderPass,
|
||||
//#endif
|
||||
CallbackInfo ci
|
||||
) {
|
||||
if (replayModRender_handler != null) {
|
||||
if (replayModRender_handler.omnidirectional) {
|
||||
// No spectator hands during 360° view, we wouldn't even know where to put it
|
||||
ci.cancel();
|
||||
return; // No spectator hands during 360° view, we wouldn't even know where to put it
|
||||
}
|
||||
Entity currentEntity = getRenderViewEntity(Minecraft.getMinecraft());
|
||||
if (currentEntity instanceof EntityPlayer && !(currentEntity instanceof CameraEntity)) {
|
||||
if (renderPass == 2) { // Need to update render pass
|
||||
renderPass = replayModRender_handler.data == StereoscopicOpenGlFrameCapturer.Data.LEFT_EYE ? 1 : 0;
|
||||
renderHand(partialTicks, renderPass);
|
||||
ci.cancel();
|
||||
} // else, render normally
|
||||
//#if MC>=11300
|
||||
}
|
||||
//#else
|
||||
//$$ } else {
|
||||
//$$ Entity currentEntity = getRenderViewEntity(MCVer.getMinecraft());
|
||||
//$$ if (currentEntity instanceof EntityPlayer && !(currentEntity instanceof CameraEntity)) {
|
||||
//$$ if (renderPass == 2) { // Need to update render pass
|
||||
//$$ renderPass = replayModRender_handler.data == StereoscopicOpenGlFrameCapturer.Data.LEFT_EYE ? 1 : 0;
|
||||
//$$ renderHand(partialTicks, renderPass);
|
||||
//$$ ci.cancel();
|
||||
//$$ } // else, render normally
|
||||
//$$ }
|
||||
//$$ }
|
||||
//#endif
|
||||
}
|
||||
}
|
||||
|
||||
@Shadow
|
||||
public abstract void renderHand(float partialTicks, int renderPass);
|
||||
//#if MC<11300
|
||||
//$$ @Shadow
|
||||
//$$ public abstract void renderHand(float partialTicks, int renderPass);
|
||||
//#endif
|
||||
|
||||
//#if MC>=11300
|
||||
@Redirect(method = "updateCameraAndRender(FJ)V", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/renderer/WorldRenderer;drawSelectionBox(Lnet/minecraft/entity/player/EntityPlayer;Lnet/minecraft/util/math/RayTraceResult;IF)V"))
|
||||
private void replayModRender_drawSelectionBox(WorldRenderer instance, EntityPlayer player, RayTraceResult rtr, int alwaysZero, float partialTicks) {
|
||||
//#else
|
||||
//#if MC>=10904
|
||||
@Redirect(method = "renderWorldPass", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/renderer/RenderGlobal;drawSelectionBox(Lnet/minecraft/entity/player/EntityPlayer;Lnet/minecraft/util/math/RayTraceResult;IF)V"))
|
||||
private void replayModRender_drawSelectionBox(RenderGlobal instance, EntityPlayer player, RayTraceResult rtr, int alwaysZero, float partialTicks) {
|
||||
//$$ @Redirect(method = "renderWorldPass", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/renderer/RenderGlobal;drawSelectionBox(Lnet/minecraft/entity/player/EntityPlayer;Lnet/minecraft/util/math/RayTraceResult;IF)V"))
|
||||
//$$ private void replayModRender_drawSelectionBox(RenderGlobal instance, EntityPlayer player, RayTraceResult rtr, int alwaysZero, float partialTicks) {
|
||||
//#else
|
||||
//#if MC>=10800
|
||||
//$$ @Redirect(method = "renderWorldPass", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/renderer/RenderGlobal;drawSelectionBox(Lnet/minecraft/entity/player/EntityPlayer;Lnet/minecraft/util/MovingObjectPosition;IF)V"))
|
||||
@@ -152,6 +197,7 @@ public abstract class MixinEntityRenderer implements EntityRendererHandler.IEnti
|
||||
//$$ @Redirect(method = "renderWorld", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/renderer/RenderGlobal;drawSelectionBox(Lnet/minecraft/entity/player/EntityPlayer;Lnet/minecraft/util/MovingObjectPosition;IF)V"))
|
||||
//#endif
|
||||
//$$ private void replayModRender_drawSelectionBox(RenderGlobal instance, EntityPlayer player, MovingObjectPosition rtr, int alwaysZero, float partialTicks) {
|
||||
//#endif
|
||||
//#endif
|
||||
if (replayModRender_handler == null) {
|
||||
instance.drawSelectionBox(player, rtr, alwaysZero, partialTicks);
|
||||
@@ -160,38 +206,51 @@ public abstract class MixinEntityRenderer implements EntityRendererHandler.IEnti
|
||||
|
||||
private int orgRenderDistanceChunks;
|
||||
|
||||
//#if MC>=11300
|
||||
@Inject(method = "updateCameraAndRender(FJ)V", at = @At(value = "JUMP", ordinal = 0))
|
||||
//#else
|
||||
//#if MC>=10800
|
||||
@Inject(method = "renderWorldPass", at = @At(value = "JUMP", ordinal = 0))
|
||||
//$$ @Inject(method = "renderWorldPass", at = @At(value = "JUMP", ordinal = 0))
|
||||
//#else
|
||||
//$$ @Inject(method = "renderWorld", at = @At(value = "INVOKE", ordinal = 0, shift = At.Shift.AFTER,
|
||||
//$$ target = "Lnet/minecraft/client/renderer/culling/ClippingHelperImpl;getInstance()Lnet/minecraft/client/renderer/culling/ClippingHelper;"))
|
||||
//#endif
|
||||
//#endif
|
||||
private void replayModRender_beforeRenderSky(CallbackInfo ci) {
|
||||
if (replayModRender_handler != null && replayModRender_handler.getSettings().getChromaKeyingColor() != null) {
|
||||
GameSettings settings = Minecraft.getMinecraft().gameSettings;
|
||||
GameSettings settings = MCVer.getMinecraft().gameSettings;
|
||||
orgRenderDistanceChunks = settings.renderDistanceChunks;
|
||||
settings.renderDistanceChunks = 5; // Set render distance to 5 so we're always rendering sky when chroma keying
|
||||
}
|
||||
}
|
||||
|
||||
//#if MC>=11300
|
||||
@Redirect(method = "updateCameraAndRender(FJ)V", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/renderer/WorldRenderer;renderSky(F)V"))
|
||||
private void replayModRender_renderSky(WorldRenderer instance, float partialTicks) {
|
||||
//#else
|
||||
//#if MC>=10800
|
||||
@Redirect(method = "renderWorldPass", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/renderer/RenderGlobal;renderSky(FI)V"))
|
||||
private void replayModRender_renderSky(RenderGlobal instance, float partialTicks, int renderPass) {
|
||||
//$$ @Redirect(method = "renderWorldPass", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/renderer/RenderGlobal;renderSky(FI)V"))
|
||||
//$$ private void replayModRender_renderSky(RenderGlobal instance, float partialTicks, int renderPass) {
|
||||
//#else
|
||||
//$$ @Redirect(method = "renderWorld", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/renderer/RenderGlobal;renderSky(F)V"))
|
||||
//$$ private void replayModRender_renderSky(RenderGlobal instance, float partialTicks) {
|
||||
//#endif
|
||||
//#endif
|
||||
if (replayModRender_handler != null && replayModRender_handler.getSettings().getChromaKeyingColor() != null) {
|
||||
Minecraft.getMinecraft().gameSettings.renderDistanceChunks = orgRenderDistanceChunks;
|
||||
MCVer.getMinecraft().gameSettings.renderDistanceChunks = orgRenderDistanceChunks;
|
||||
ReadableColor color = replayModRender_handler.getSettings().getChromaKeyingColor();
|
||||
GlStateManager.clearColor(color.getRed() / 255f, color.getGreen() / 255f, color.getBlue() / 255f, 1);
|
||||
GlStateManager.clear(GL11.GL_COLOR_BUFFER_BIT);
|
||||
} else {
|
||||
//#if MC>=11300
|
||||
instance.renderSky(partialTicks);
|
||||
//#else
|
||||
//#if MC>=10800
|
||||
instance.renderSky(partialTicks, renderPass);
|
||||
//$$ instance.renderSky(partialTicks, renderPass);
|
||||
//#else
|
||||
//$$ instance.renderSky(partialTicks);
|
||||
//#endif
|
||||
//#endif
|
||||
}
|
||||
}
|
||||
|
||||
@@ -204,12 +263,18 @@ public abstract class MixinEntityRenderer implements EntityRendererHandler.IEnti
|
||||
//#else
|
||||
//$$ @Inject(method = "setupCameraTransform", at = @At(value = "INVOKE", target = "Lorg/lwjgl/opengl/GL11;glLoadIdentity()V", shift = At.Shift.AFTER, ordinal = 0, remap = false))
|
||||
//#endif
|
||||
private void replayModRender_setupStereoscopicProjection(float partialTicks, int renderPass, CallbackInfo ci) {
|
||||
private void replayModRender_setupStereoscopicProjection(
|
||||
float partialTicks,
|
||||
//#if MC<11300
|
||||
//$$ int renderPass,
|
||||
//#endif
|
||||
CallbackInfo ci
|
||||
) {
|
||||
if (replayModRender_getHandler() != null) {
|
||||
if (replayModRender_getHandler().data == StereoscopicOpenGlFrameCapturer.Data.LEFT_EYE) {
|
||||
GlStateManager.translate(0.07, 0, 0);
|
||||
GL11.glTranslatef(0.07f, 0, 0);
|
||||
} else if (replayModRender_getHandler().data == StereoscopicOpenGlFrameCapturer.Data.RIGHT_EYE) {
|
||||
GlStateManager.translate(-0.07, 0, 0);
|
||||
GL11.glTranslatef(-0.07f, 0, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -219,12 +284,18 @@ public abstract class MixinEntityRenderer implements EntityRendererHandler.IEnti
|
||||
//#else
|
||||
//$$ @Inject(method = "setupCameraTransform", at = @At(value = "INVOKE", target = "Lorg/lwjgl/opengl/GL11;glLoadIdentity()V", shift = At.Shift.AFTER, ordinal = 1, remap = false))
|
||||
//#endif
|
||||
private void replayModRender_setupStereoscopicModelView(float partialTicks, int renderPass, CallbackInfo ci) {
|
||||
private void replayModRender_setupStereoscopicModelView(
|
||||
float partialTicks,
|
||||
//#if MC<11300
|
||||
//$$ int renderPass,
|
||||
//#endif
|
||||
CallbackInfo ci
|
||||
) {
|
||||
if (replayModRender_getHandler() != null) {
|
||||
if (replayModRender_getHandler().data == StereoscopicOpenGlFrameCapturer.Data.LEFT_EYE) {
|
||||
GlStateManager.translate(0.1, 0, 0);
|
||||
GL11.glTranslatef(0.1f, 0, 0);
|
||||
} else if (replayModRender_getHandler().data == StereoscopicOpenGlFrameCapturer.Data.RIGHT_EYE) {
|
||||
GlStateManager.translate(-0.1, 0, 0);
|
||||
GL11.glTranslatef(-0.1f, 0, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -233,63 +304,91 @@ public abstract class MixinEntityRenderer implements EntityRendererHandler.IEnti
|
||||
* Cubic Renderer
|
||||
*/
|
||||
|
||||
@Redirect(method = "setupCameraTransform", at = @At(value = "INVOKE", target = "Lorg/lwjgl/util/glu/Project;gluPerspective(FFFF)V", remap = false))
|
||||
private void replayModRender_gluPerspective$0(float fovY, float aspect, float zNear, float zFar) {
|
||||
replayModRender_gluPerspective(fovY, aspect, zNear, zFar);
|
||||
//#if MC>=11300
|
||||
@Redirect(method = "setupCameraTransform", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/renderer/Matrix4f;perspective(DFFF)Lnet/minecraft/client/renderer/Matrix4f;"))
|
||||
private Matrix4f replayModRender_perspective$0(double fovY, float aspect, float zNear, float zFar) {
|
||||
return replayModRender_perspective((float) fovY, aspect, zNear, zFar);
|
||||
}
|
||||
|
||||
//#if MC>=10800
|
||||
@Redirect(method = "renderWorldPass", at = @At(value = "INVOKE", target = "Lorg/lwjgl/util/glu/Project;gluPerspective(FFFF)V", remap = false))
|
||||
//#else
|
||||
//$$ @Redirect(method = "renderHand", at = @At(value = "INVOKE", target = "Lorg/lwjgl/util/glu/Project;gluPerspective(FFFF)V", remap = false))
|
||||
//#endif
|
||||
private void replayModRender_gluPerspective$1(float fovY, float aspect, float zNear, float zFar) {
|
||||
replayModRender_gluPerspective(fovY, aspect, zNear, zFar);
|
||||
@Redirect(method = "updateCameraAndRender(FJ)V", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/renderer/Matrix4f;perspective(DFFF)Lnet/minecraft/client/renderer/Matrix4f;"))
|
||||
private Matrix4f replayModRender_perspective$1(double fovY, float aspect, float zNear, float zFar) {
|
||||
return replayModRender_perspective((float) fovY, aspect, zNear, zFar);
|
||||
}
|
||||
|
||||
//#if MC>=10800
|
||||
@Redirect(method = "renderCloudsCheck", at = @At(value = "INVOKE", target = "Lorg/lwjgl/util/glu/Project;gluPerspective(FFFF)V", remap = false))
|
||||
private void replayModRender_gluPerspective$2(float fovY, float aspect, float zNear, float zFar) {
|
||||
replayModRender_gluPerspective(fovY, aspect, zNear, zFar);
|
||||
@Redirect(method = "renderCloudsCheck", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/renderer/Matrix4f;perspective(DFFF)Lnet/minecraft/client/renderer/Matrix4f;"))
|
||||
private Matrix4f replayModRender_perspective$2(double fovY, float aspect, float zNear, float zFar) {
|
||||
return replayModRender_perspective((float) fovY, aspect, zNear, zFar);
|
||||
}
|
||||
//#endif
|
||||
|
||||
@Override
|
||||
public void replayModRender_gluPerspective(float fovY, float aspect, float zNear, float zFar) {
|
||||
private Matrix4f replayModRender_perspective(float fovY, float aspect, float zNear, float zFar) {
|
||||
if (replayModRender_getHandler() != null && replayModRender_getHandler().omnidirectional) {
|
||||
fovY = 90;
|
||||
aspect = 1;
|
||||
}
|
||||
Project.gluPerspective(fovY, aspect, zNear, zFar);
|
||||
return Matrix4f.perspective(fovY, aspect, zNear, zFar);
|
||||
}
|
||||
//#else
|
||||
//$$ @Redirect(method = "setupCameraTransform", at = @At(value = "INVOKE", target = "Lorg/lwjgl/util/glu/Project;gluPerspective(FFFF)V", remap = false))
|
||||
//$$ private void replayModRender_gluPerspective$0(float fovY, float aspect, float zNear, float zFar) {
|
||||
//$$ replayModRender_gluPerspective(fovY, aspect, zNear, zFar);
|
||||
//$$ }
|
||||
//$$
|
||||
//#if MC>=10800
|
||||
//$$ @Redirect(method = "renderWorldPass", at = @At(value = "INVOKE", target = "Lorg/lwjgl/util/glu/Project;gluPerspective(FFFF)V", remap = false))
|
||||
//#else
|
||||
//$$ @Redirect(method = "renderHand", at = @At(value = "INVOKE", target = "Lorg/lwjgl/util/glu/Project;gluPerspective(FFFF)V", remap = false))
|
||||
//#endif
|
||||
//$$ private void replayModRender_gluPerspective$1(float fovY, float aspect, float zNear, float zFar) {
|
||||
//$$ replayModRender_gluPerspective(fovY, aspect, zNear, zFar);
|
||||
//$$ }
|
||||
//$$
|
||||
//#if MC>=10800
|
||||
//$$ @Redirect(method = "renderCloudsCheck", at = @At(value = "INVOKE", target = "Lorg/lwjgl/util/glu/Project;gluPerspective(FFFF)V", remap = false))
|
||||
//$$ private void replayModRender_gluPerspective$2(float fovY, float aspect, float zNear, float zFar) {
|
||||
//$$ replayModRender_gluPerspective(fovY, aspect, zNear, zFar);
|
||||
//$$ }
|
||||
//#endif
|
||||
//$$
|
||||
//$$ private void replayModRender_gluPerspective(float fovY, float aspect, float zNear, float zFar) {
|
||||
//$$ if (replayModRender_getHandler() != null && replayModRender_getHandler().omnidirectional) {
|
||||
//$$ fovY = 90;
|
||||
//$$ aspect = 1;
|
||||
//$$ }
|
||||
//$$ Project.gluPerspective(fovY, aspect, zNear, zFar);
|
||||
//$$ }
|
||||
//#endif
|
||||
|
||||
@Inject(method = "orientCamera", at = @At("HEAD"))
|
||||
private void replayModRender_setupCubicFrameRotation(float partialTicks, CallbackInfo ci) {
|
||||
if (replayModRender_getHandler() != null && replayModRender_getHandler().data instanceof CubicOpenGlFrameCapturer.Data) {
|
||||
switch ((CubicOpenGlFrameCapturer.Data) replayModRender_getHandler().data) {
|
||||
case FRONT:
|
||||
GlStateManager.rotate(0, 0.0F, 1.0F, 0.0F);
|
||||
GL11.glRotatef(0, 0.0F, 1.0F, 0.0F);
|
||||
break;
|
||||
case RIGHT:
|
||||
GlStateManager.rotate(90, 0.0F, 1.0F, 0.0F);
|
||||
GL11.glRotatef(90, 0.0F, 1.0F, 0.0F);
|
||||
break;
|
||||
case BACK:
|
||||
GlStateManager.rotate(180, 0.0F, 1.0F, 0.0F);
|
||||
GL11.glRotatef(180, 0.0F, 1.0F, 0.0F);
|
||||
break;
|
||||
case LEFT:
|
||||
GlStateManager.rotate(-90, 0.0F, 1.0F, 0.0F);
|
||||
GL11.glRotatef(-90, 0.0F, 1.0F, 0.0F);
|
||||
break;
|
||||
case BOTTOM:
|
||||
GlStateManager.rotate(90, 1.0F, 0.0F, 0.0F);
|
||||
GL11.glRotatef(90, 1.0F, 0.0F, 0.0F);
|
||||
break;
|
||||
case TOP:
|
||||
GlStateManager.rotate(-90, 1.0F, 0.0F, 0.0F);
|
||||
GL11.glRotatef(-90, 1.0F, 0.0F, 0.0F);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (replayModRender_getHandler() != null && replayModRender_getHandler().omnidirectional) {
|
||||
// Minecraft goes back a little so we have to revert that
|
||||
GlStateManager.translate(0.0F, 0.0F, 0.1F);
|
||||
//#if MC>=11300
|
||||
GL11.glTranslatef(0.0F, 0.0F, -0.05F);
|
||||
//#else
|
||||
//$$ GL11.glTranslatef(0.0F, 0.0F, 0.1F);
|
||||
//#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,24 @@
|
||||
//#if MC>=11300
|
||||
package com.replaymod.render.mixin;
|
||||
|
||||
import com.replaymod.core.versions.MCVer;
|
||||
import com.replaymod.render.hooks.EntityRendererHandler;
|
||||
import net.minecraft.client.renderer.FogRenderer;
|
||||
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;
|
||||
|
||||
@Mixin(FogRenderer.class)
|
||||
public abstract class MixinFogRenderer {
|
||||
@Inject(method = "setupFog", at = @At("HEAD"), cancellable = true)
|
||||
private void replayModRender_onSetupFog(int fogDistanceFlag, float partialTicks, CallbackInfo ci) {
|
||||
EntityRendererHandler handler =
|
||||
((EntityRendererHandler.IEntityRenderer) MCVer.getMinecraft().entityRenderer).replayModRender_getHandler();
|
||||
if (handler == null) return;
|
||||
if (handler.getSettings().getChromaKeyingColor() != null) {
|
||||
ci.cancel();
|
||||
}
|
||||
}
|
||||
}
|
||||
//#endif
|
||||
@@ -1,7 +1,7 @@
|
||||
package com.replaymod.render.mixin;
|
||||
|
||||
import com.replaymod.core.versions.MCVer;
|
||||
import com.replaymod.render.hooks.EntityRendererHandler;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
import org.spongepowered.asm.mixin.injection.Inject;
|
||||
@@ -21,7 +21,7 @@ import net.minecraft.client.renderer.culling.Frustum;
|
||||
public abstract class MixinFrustum {
|
||||
@Inject(method = "isBoxInFrustum", at = @At("HEAD"), cancellable = true)
|
||||
public void isBoxInFrustum(double minX, double minY, double minZ, double maxX, double maxY, double maxZ, CallbackInfoReturnable<Boolean> ci) {
|
||||
EntityRendererHandler handler = ((EntityRendererHandler.IEntityRenderer) Minecraft.getMinecraft().entityRenderer).replayModRender_getHandler();
|
||||
EntityRendererHandler handler = ((EntityRendererHandler.IEntityRenderer) MCVer.getMinecraft().entityRenderer).replayModRender_getHandler();
|
||||
if (handler != null && handler.omnidirectional && handler.data == null) {
|
||||
// Normally the camera is always facing the direction of the omnidirectional image face that is currently
|
||||
// getting rendered. With ODS however, the camera is always facing forwards and the turning happens in the
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
package com.replaymod.render.mixin;
|
||||
|
||||
//#if MC>=10904
|
||||
import com.replaymod.core.versions.MCVer;
|
||||
import com.replaymod.render.blend.BlendState;
|
||||
import com.replaymod.render.blend.exporters.ParticlesExporter;
|
||||
import com.replaymod.render.hooks.EntityRendererHandler;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.particle.Particle;
|
||||
import net.minecraft.client.particle.ParticleManager;
|
||||
import net.minecraft.entity.Entity;
|
||||
@@ -48,7 +48,7 @@ public abstract class MixinParticleManager {
|
||||
//$$ private void renderParticle(Particle particle, VertexBuffer vertexBuffer, Entity view, float partialTicks,
|
||||
//#endif
|
||||
float rotX, float rotXZ, float rotZ, float rotYZ, float rotXY) {
|
||||
EntityRendererHandler handler = ((EntityRendererHandler.IEntityRenderer) Minecraft.getMinecraft().entityRenderer).replayModRender_getHandler();
|
||||
EntityRendererHandler handler = ((EntityRendererHandler.IEntityRenderer) MCVer.getMinecraft().entityRenderer).replayModRender_getHandler();
|
||||
if (handler != null && handler.omnidirectional) {
|
||||
// Align all particles towards the camera
|
||||
double dx = particle.prevPosX + (particle.posX - particle.prevPosX) * partialTicks - view.posX;
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
package com.replaymod.render.mixin;
|
||||
|
||||
import com.replaymod.core.versions.MCVer;
|
||||
import com.replaymod.render.hooks.EntityRendererHandler;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.renderer.entity.Render;
|
||||
import net.minecraft.entity.Entity;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
@@ -13,7 +13,7 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||
public abstract class MixinRender {
|
||||
@Inject(method = "renderLivingLabel", at = @At("HEAD"), cancellable = true)
|
||||
private void replayModRender_areAllNamesHidden(Entity entityIn, String str, double x, double y, double z, int maxDistance, CallbackInfo ci) {
|
||||
EntityRendererHandler handler = ((EntityRendererHandler.IEntityRenderer) Minecraft.getMinecraft().entityRenderer).replayModRender_getHandler();
|
||||
EntityRendererHandler handler = ((EntityRendererHandler.IEntityRenderer) MCVer.getMinecraft().entityRenderer).replayModRender_getHandler();
|
||||
if (handler != null && !handler.getSettings().isRenderNameTags()) {
|
||||
ci.cancel();
|
||||
}
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
package com.replaymod.render.mixin;
|
||||
|
||||
import com.replaymod.render.hooks.ChunkLoadingRenderGlobal;
|
||||
import net.minecraft.client.renderer.RenderGlobal;
|
||||
import net.minecraft.client.renderer.chunk.ChunkRenderDispatcher;
|
||||
import net.minecraft.client.renderer.culling.ICamera;
|
||||
import net.minecraft.entity.Entity;
|
||||
@@ -10,16 +9,25 @@ import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.Shadow;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
import org.spongepowered.asm.mixin.injection.Inject;
|
||||
import org.spongepowered.asm.mixin.injection.Redirect;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||
|
||||
//#if MC>=11300
|
||||
import net.minecraft.client.renderer.WorldRenderer;
|
||||
//#else
|
||||
//$$ import net.minecraft.client.renderer.RenderGlobal;
|
||||
//#endif
|
||||
|
||||
//#if MC<10904
|
||||
//$$ import net.minecraft.client.renderer.chunk.RenderChunk;
|
||||
//$$ import net.minecraft.util.BlockPos;
|
||||
//$$ import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
|
||||
//#endif
|
||||
|
||||
@Mixin(RenderGlobal.class)
|
||||
//#if MC>=11300
|
||||
@Mixin(WorldRenderer.class)
|
||||
//#else
|
||||
//$$ @Mixin(RenderGlobal.class)
|
||||
//#endif
|
||||
public abstract class MixinRenderGlobal {
|
||||
public ChunkLoadingRenderGlobal replayModRender_hook;
|
||||
private boolean replayModRender_passThroughSetupTerrain;
|
||||
@@ -31,12 +39,31 @@ public abstract class MixinRenderGlobal {
|
||||
public ChunkRenderDispatcher renderDispatcher;
|
||||
|
||||
@Shadow
|
||||
public abstract void setupTerrain(Entity viewEntity, double partialTicks, ICamera camera,
|
||||
int frameCount, boolean playerSpectator);
|
||||
public abstract void setupTerrain(
|
||||
Entity viewEntity,
|
||||
//#if MC>=11300
|
||||
float partialTicks,
|
||||
//#else
|
||||
//$$ double partialTicks,
|
||||
//#endif
|
||||
ICamera camera,
|
||||
int frameCount,
|
||||
boolean playerSpectator
|
||||
);
|
||||
|
||||
@Inject(method = "setupTerrain", at = @At("HEAD"), cancellable = true)
|
||||
public void replayModRender_setupTerrain(Entity viewEntity, double partialTicks, ICamera camera,
|
||||
int frameCount, boolean playerSpectator, CallbackInfo ci) {
|
||||
private void replayModRender_setupTerrain(
|
||||
Entity viewEntity,
|
||||
//#if MC>=11300
|
||||
float partialTicks,
|
||||
//#else
|
||||
//$$ double partialTicks,
|
||||
//#endif
|
||||
ICamera camera,
|
||||
int frameCount,
|
||||
boolean playerSpectator,
|
||||
CallbackInfo ci
|
||||
) {
|
||||
if (replayModRender_hook != null && !replayModRender_passThroughSetupTerrain) {
|
||||
replayModRender_passThroughSetupTerrain = true;
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
package com.replaymod.render.mixin;
|
||||
|
||||
import com.replaymod.core.versions.MCVer;
|
||||
import com.replaymod.render.hooks.EntityRendererHandler;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.renderer.entity.RenderManager;
|
||||
import net.minecraft.entity.Entity;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
@@ -23,13 +23,17 @@ public abstract class MixinRenderManager {
|
||||
@Shadow
|
||||
private float playerViewY;
|
||||
|
||||
@Inject(method = "doRenderEntity", at = @At("HEAD"))
|
||||
//#if MC>=11300
|
||||
@Inject(method = "renderEntity", at = @At("HEAD"))
|
||||
//#else
|
||||
//$$ @Inject(method = "doRenderEntity", at = @At("HEAD"))
|
||||
//#endif
|
||||
//#if MC>=10904
|
||||
private void replayModRender_reorientForCubicRendering(Entity entity, double dx, double dy, double dz, float iDoNotKnow, float partialTicks, boolean iDoNotCare, CallbackInfo ci) {
|
||||
//#else
|
||||
//$$ private void replayModRender_reorientForCubicRendering(Entity entity, double dx, double dy, double dz, float iDoNotKnow, float partialTicks, boolean iDoNotCare, CallbackInfoReturnable<Boolean> ci) {
|
||||
//#endif
|
||||
EntityRendererHandler handler = ((EntityRendererHandler.IEntityRenderer) Minecraft.getMinecraft().entityRenderer).replayModRender_getHandler();
|
||||
EntityRendererHandler handler = ((EntityRendererHandler.IEntityRenderer) MCVer.getMinecraft().entityRenderer).replayModRender_getHandler();
|
||||
if (handler != null && handler.omnidirectional) {
|
||||
double pitch = -Math.atan2(dy, Math.sqrt(dx * dx + dz * dz));
|
||||
double yaw = -Math.atan2(dx, dz);
|
||||
|
||||
@@ -3,7 +3,7 @@ package com.replaymod.render.processor;
|
||||
import com.replaymod.render.frame.CubicOpenGlFrame;
|
||||
import com.replaymod.render.frame.RGBFrame;
|
||||
import com.replaymod.render.utils.ByteBufferPool;
|
||||
import org.lwjgl.util.Dimension;
|
||||
import de.johni0702.minecraft.gui.utils.lwjgl.Dimension;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
|
||||
@@ -15,7 +15,7 @@ public class CubicToRGBProcessor extends AbstractFrameProcessor<CubicOpenGlFrame
|
||||
int size = rawFrame.getLeft().getSize().getWidth();
|
||||
int width = size * 4;
|
||||
int height = size * 3;
|
||||
ByteBuffer result = ByteBufferPool.allocate(width * height * 3);
|
||||
ByteBuffer result = ByteBufferPool.allocate(width * height * 4);
|
||||
openGlBytesToRBG(rawFrame.getLeft().getByteBuffer(), size, 0, size, result, width);
|
||||
openGlBytesToRBG(rawFrame.getFront().getByteBuffer(), size, size, size, result, width);
|
||||
openGlBytesToRBG(rawFrame.getRight().getByteBuffer(), size, size * 2, size, result, width);
|
||||
|
||||
@@ -3,8 +3,9 @@ package com.replaymod.render.processor;
|
||||
import com.replaymod.render.frame.CubicOpenGlFrame;
|
||||
import com.replaymod.render.frame.RGBFrame;
|
||||
import com.replaymod.render.utils.ByteBufferPool;
|
||||
import de.johni0702.minecraft.gui.utils.lwjgl.Dimension;
|
||||
import lombok.Getter;
|
||||
import org.apache.commons.lang3.Validate;
|
||||
import org.lwjgl.util.Dimension;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
|
||||
@@ -18,6 +19,7 @@ public class EquirectangularToRGBProcessor extends AbstractFrameProcessor<CubicO
|
||||
private static final byte IMAGE_TOP = 4;
|
||||
private static final byte IMAGE_BOTTOM = 5;
|
||||
|
||||
@Getter
|
||||
private final int frameSize;
|
||||
private final int width;
|
||||
private final int height;
|
||||
@@ -26,18 +28,36 @@ public class EquirectangularToRGBProcessor extends AbstractFrameProcessor<CubicO
|
||||
private final int[][] imageX;
|
||||
private final int[][] imageY;
|
||||
|
||||
public EquirectangularToRGBProcessor(int outputWidth, int outputHeight, int sphericalFovX) {
|
||||
// calculate the dimensions of the original equirectangular projection
|
||||
// (before cropping according to FOV)
|
||||
width = outputWidth;
|
||||
height = outputHeight;
|
||||
|
||||
public EquirectangularToRGBProcessor(int frameSize) {
|
||||
this.frameSize = frameSize;
|
||||
int fullWidth;
|
||||
if (sphericalFovX < 360) {
|
||||
fullWidth = Math.round(width * 360 / (float) sphericalFovX);
|
||||
} else {
|
||||
fullWidth = width;
|
||||
}
|
||||
|
||||
int fullHeight = fullWidth / 2;
|
||||
|
||||
frameSize = fullWidth / 4;
|
||||
|
||||
width = frameSize * 4;
|
||||
height = frameSize * 2;
|
||||
image = new byte[height][width];
|
||||
imageX = new int[height][width];
|
||||
imageY = new int[height][width];
|
||||
for (int i = 0; i < width; i++) {
|
||||
double yaw = PI * 2 * i / width;
|
||||
int piQuarter = 8 * i / width - 4;
|
||||
|
||||
int xOffset = (fullWidth - width) / 2;
|
||||
int yOffset = (fullHeight - height) / 2;
|
||||
|
||||
for (int x = 0; x < width; x++) {
|
||||
// get x position relative to the full projection
|
||||
int i = xOffset + x;
|
||||
|
||||
double yaw = PI * 2 * i / fullWidth;
|
||||
int piQuarter = 8 * i / fullWidth - 4;
|
||||
byte target;
|
||||
if (piQuarter < -3) {
|
||||
target = IMAGE_BACK;
|
||||
@@ -50,13 +70,16 @@ public class EquirectangularToRGBProcessor extends AbstractFrameProcessor<CubicO
|
||||
} else {
|
||||
target = IMAGE_BACK;
|
||||
}
|
||||
double fYaw = (yaw + PI/4) % (PI / 2) - PI/4;
|
||||
double fYaw = (yaw + PI / 4) % (PI / 2) - PI / 4;
|
||||
double d = 1 / Math.cos(fYaw);
|
||||
double gcXN = (Math.tan(fYaw) + 1) / 2;
|
||||
for (int j = 0; j < height; j++) {
|
||||
for (int y = 0; y < height; y++) {
|
||||
// get y position relative to the full projection
|
||||
int j = yOffset + y;
|
||||
|
||||
double cXN = gcXN;
|
||||
byte pt = target;
|
||||
double pitch = PI * j / height - PI / 2;
|
||||
double pitch = PI * j / fullHeight - PI / 2;
|
||||
double cYN = (Math.tan(pitch) * d + 1) / 2;
|
||||
|
||||
if (cYN >= 1) {
|
||||
@@ -74,9 +97,9 @@ public class EquirectangularToRGBProcessor extends AbstractFrameProcessor<CubicO
|
||||
|
||||
int imgX = (int) Math.min(frameSize - 1, (cXN * frameSize));
|
||||
int imgY = (int) Math.min(frameSize - 1, (cYN * frameSize));
|
||||
image[j][i] = pt;
|
||||
imageX[j][i] = imgX;
|
||||
imageY[j][i] = frameSize - imgY - 1; // The OpenGl buffer contains data flipped vertically
|
||||
image[y][x] = pt;
|
||||
imageX[y][x] = imgX;
|
||||
imageY[y][x] = frameSize - imgY - 1; // The OpenGl buffer contains data flipped vertically
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -85,13 +108,13 @@ public class EquirectangularToRGBProcessor extends AbstractFrameProcessor<CubicO
|
||||
public RGBFrame process(CubicOpenGlFrame rawFrame) {
|
||||
Validate.isTrue(rawFrame.getLeft().getSize().getWidth() == frameSize, "Frame size must be %d but was %d",
|
||||
frameSize, rawFrame.getLeft().getSize().getWidth());
|
||||
ByteBuffer result = ByteBufferPool.allocate(width * height * 3);
|
||||
ByteBuffer result = ByteBufferPool.allocate(width * height * 4);
|
||||
ByteBuffer[] images = {
|
||||
rawFrame.getBack().getByteBuffer(), rawFrame.getFront().getByteBuffer(),
|
||||
rawFrame.getLeft().getByteBuffer(), rawFrame.getRight().getByteBuffer(),
|
||||
rawFrame.getTop().getByteBuffer(), rawFrame.getBottom().getByteBuffer()
|
||||
};
|
||||
byte[] pixel = new byte[3];
|
||||
byte[] pixel = new byte[4];
|
||||
byte[] image;
|
||||
int[] imageX, imageY;
|
||||
for (int y = 0; y < height; y++) {
|
||||
@@ -100,7 +123,7 @@ public class EquirectangularToRGBProcessor extends AbstractFrameProcessor<CubicO
|
||||
imageY = this.imageY[y];
|
||||
for (int x = 0; x < width; x++) {
|
||||
ByteBuffer source = images[image[x]];
|
||||
source.position((imageX[x] + imageY[x] * frameSize) * 3);
|
||||
source.position((imageX[x] + imageY[x] * frameSize) * 4);
|
||||
source.get(pixel);
|
||||
result.put(pixel);
|
||||
}
|
||||
|
||||
@@ -3,8 +3,8 @@ package com.replaymod.render.processor;
|
||||
import com.replaymod.render.frame.ODSOpenGlFrame;
|
||||
import com.replaymod.render.frame.RGBFrame;
|
||||
import com.replaymod.render.utils.ByteBufferPool;
|
||||
import org.lwjgl.util.Dimension;
|
||||
import org.lwjgl.util.ReadableDimension;
|
||||
import de.johni0702.minecraft.gui.utils.lwjgl.Dimension;
|
||||
import de.johni0702.minecraft.gui.utils.lwjgl.ReadableDimension;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.nio.ByteBuffer;
|
||||
@@ -12,8 +12,8 @@ import java.nio.ByteBuffer;
|
||||
public class ODSToRGBProcessor extends AbstractFrameProcessor<ODSOpenGlFrame, RGBFrame> {
|
||||
private final EquirectangularToRGBProcessor processor;
|
||||
|
||||
public ODSToRGBProcessor(int frameSize) {
|
||||
processor = new EquirectangularToRGBProcessor(frameSize);
|
||||
public ODSToRGBProcessor(int outputWidth, int outputHeight, int sphericalFovX) {
|
||||
processor = new EquirectangularToRGBProcessor(outputWidth, outputHeight / 2, sphericalFovX);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -21,7 +21,7 @@ public class ODSToRGBProcessor extends AbstractFrameProcessor<ODSOpenGlFrame, RG
|
||||
RGBFrame leftFrame = processor.process(rawFrame.getLeft());
|
||||
RGBFrame rightFrame = processor.process(rawFrame.getRight());
|
||||
ReadableDimension size = new Dimension(leftFrame.getSize().getWidth(), leftFrame.getSize().getHeight() * 2);
|
||||
ByteBuffer result = ByteBufferPool.allocate(size.getWidth() * size.getHeight() * 3);
|
||||
ByteBuffer result = ByteBufferPool.allocate(size.getWidth() * size.getHeight() * 4);
|
||||
result.put(leftFrame.getByteBuffer());
|
||||
result.put(rightFrame.getByteBuffer());
|
||||
result.rewind();
|
||||
@@ -34,4 +34,8 @@ public class ODSToRGBProcessor extends AbstractFrameProcessor<ODSOpenGlFrame, RG
|
||||
public void close() throws IOException {
|
||||
processor.close();
|
||||
}
|
||||
|
||||
public int getFrameSize() {
|
||||
return processor.getFrameSize();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,7 +2,7 @@ package com.replaymod.render.processor;
|
||||
|
||||
import com.replaymod.render.frame.OpenGlFrame;
|
||||
import com.replaymod.render.frame.RGBFrame;
|
||||
import org.lwjgl.util.ReadableDimension;
|
||||
import de.johni0702.minecraft.gui.utils.lwjgl.ReadableDimension;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
|
||||
@@ -15,7 +15,7 @@ public class OpenGlToRGBProcessor extends AbstractFrameProcessor<OpenGlFrame, RG
|
||||
// Flip whole image in place
|
||||
|
||||
ReadableDimension size = rawFrame.getSize();
|
||||
int rowSize = size.getWidth() * 3;
|
||||
int rowSize = size.getWidth() * 4;
|
||||
if (row == null || row.length < rowSize) {
|
||||
row = new byte[rowSize];
|
||||
rowSwap = new byte[rowSize];
|
||||
|
||||
@@ -3,8 +3,8 @@ package com.replaymod.render.processor;
|
||||
import com.replaymod.render.frame.RGBFrame;
|
||||
import com.replaymod.render.frame.StereoscopicOpenGlFrame;
|
||||
import com.replaymod.render.utils.ByteBufferPool;
|
||||
import org.lwjgl.util.Dimension;
|
||||
import org.lwjgl.util.ReadableDimension;
|
||||
import de.johni0702.minecraft.gui.utils.lwjgl.Dimension;
|
||||
import de.johni0702.minecraft.gui.utils.lwjgl.ReadableDimension;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
|
||||
@@ -17,7 +17,7 @@ public class StereoscopicToRGBProcessor extends AbstractFrameProcessor<Stereosco
|
||||
int width = size.getWidth();
|
||||
ByteBuffer leftBuffer = rawFrame.getLeft().getByteBuffer();
|
||||
ByteBuffer rightBuffer = rawFrame.getRight().getByteBuffer();
|
||||
ByteBuffer result = ByteBufferPool.allocate(width * 2 * size.getHeight() * 3);
|
||||
ByteBuffer result = ByteBufferPool.allocate(width * 2 * size.getHeight() * 4);
|
||||
openGlBytesToRBG(leftBuffer, width, 0, 0, result, width * 2);
|
||||
openGlBytesToRBG(rightBuffer, width, size.getWidth(), 0, result, width * 2);
|
||||
ByteBufferPool.release(leftBuffer);
|
||||
|
||||
@@ -1,16 +1,23 @@
|
||||
package com.replaymod.render.rendering;
|
||||
|
||||
import com.replaymod.core.versions.MCVer;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.crash.CrashReport;
|
||||
import net.minecraft.util.ReportedException;
|
||||
import org.lwjgl.opengl.Display;
|
||||
|
||||
//#if MC>=11300
|
||||
import org.lwjgl.glfw.GLFW;
|
||||
//#else
|
||||
//$$ import org.lwjgl.opengl.Display;
|
||||
//#endif
|
||||
|
||||
import java.util.concurrent.ArrayBlockingQueue;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.ThreadPoolExecutor;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import static com.replaymod.core.versions.MCVer.newReportedException;
|
||||
|
||||
public class Pipeline<R extends Frame, P extends Frame> implements Runnable {
|
||||
|
||||
private final FrameCapturer<R> capturer;
|
||||
@@ -48,9 +55,13 @@ public class Pipeline<R extends Frame, P extends Frame> implements Runnable {
|
||||
}
|
||||
}, new ThreadPoolExecutor.DiscardPolicy());
|
||||
|
||||
Minecraft mc = Minecraft.getMinecraft();
|
||||
Minecraft mc = MCVer.getMinecraft();
|
||||
while (!capturer.isDone() && !Thread.currentThread().isInterrupted()) {
|
||||
if (Display.isCloseRequested() || mc.hasCrashed) {
|
||||
//#if MC>=11300
|
||||
if (GLFW.glfwWindowShouldClose(mc.mainWindow.getHandle()) || mc.hasCrashed) {
|
||||
//#else
|
||||
//$$ if (Display.isCloseRequested() || mc.hasCrashed) {
|
||||
//#endif
|
||||
Thread.currentThread().interrupt();
|
||||
return;
|
||||
}
|
||||
@@ -73,7 +84,7 @@ public class Pipeline<R extends Frame, P extends Frame> implements Runnable {
|
||||
consumer.close();
|
||||
} catch (Throwable t) {
|
||||
CrashReport crashReport = CrashReport.makeCrashReport(t, "Cleaning up rendering pipeline");
|
||||
throw new ReportedException(crashReport);
|
||||
throw newReportedException(crashReport);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -105,7 +116,7 @@ public class Pipeline<R extends Frame, P extends Frame> implements Runnable {
|
||||
}
|
||||
} catch (Throwable t) {
|
||||
CrashReport crashReport = CrashReport.makeCrashReport(t, "Processing frame");
|
||||
Minecraft.getMinecraft().crashed(crashReport);
|
||||
MCVer.getMinecraft().crashed(crashReport);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -82,20 +82,28 @@ public class Pipelines {
|
||||
|
||||
public static Pipeline<CubicOpenGlFrame, RGBFrame> newEquirectangularPipeline(RenderInfo renderInfo, FrameConsumer<RGBFrame> consumer) {
|
||||
RenderSettings settings = renderInfo.getRenderSettings();
|
||||
|
||||
EquirectangularToRGBProcessor processor = new EquirectangularToRGBProcessor(settings.getVideoWidth(),
|
||||
settings.getVideoHeight(), settings.getSphericalFovX());
|
||||
|
||||
FrameCapturer<CubicOpenGlFrame> capturer;
|
||||
if (PixelBufferObject.SUPPORTED) {
|
||||
capturer = new CubicPboOpenGlFrameCapturer(new EntityRendererHandler(settings, renderInfo), renderInfo, settings.getVideoWidth() / 4);
|
||||
capturer = new CubicPboOpenGlFrameCapturer(new EntityRendererHandler(settings, renderInfo), renderInfo, processor.getFrameSize());
|
||||
} else {
|
||||
capturer = new CubicOpenGlFrameCapturer(new EntityRendererHandler(settings, renderInfo), renderInfo, settings.getVideoWidth() / 4);
|
||||
capturer = new CubicOpenGlFrameCapturer(new EntityRendererHandler(settings, renderInfo), renderInfo, processor.getFrameSize());
|
||||
}
|
||||
return new Pipeline<>(capturer, new EquirectangularToRGBProcessor(settings.getVideoWidth() / 4), consumer);
|
||||
return new Pipeline<>(capturer, processor, consumer);
|
||||
}
|
||||
|
||||
public static Pipeline<ODSOpenGlFrame, RGBFrame> newODSPipeline(RenderInfo renderInfo, FrameConsumer<RGBFrame> consumer) {
|
||||
RenderSettings settings = renderInfo.getRenderSettings();
|
||||
|
||||
ODSToRGBProcessor processor = new ODSToRGBProcessor(settings.getVideoWidth(),
|
||||
settings.getVideoHeight(), settings.getSphericalFovX());
|
||||
|
||||
FrameCapturer<ODSOpenGlFrame> capturer =
|
||||
new ODSFrameCapturer(new EntityRendererHandler(settings, renderInfo), renderInfo, settings.getVideoWidth() / 4);
|
||||
return new Pipeline<>(capturer, new ODSToRGBProcessor(settings.getVideoWidth() / 4), consumer);
|
||||
new ODSFrameCapturer(new EntityRendererHandler(settings, renderInfo), renderInfo, processor.getFrameSize());
|
||||
return new Pipeline<>(capturer, processor, consumer);
|
||||
}
|
||||
|
||||
public static Pipeline<RGBFrame, RGBFrame> newBlendPipeline(RenderInfo renderInfo) {
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package com.replaymod.render.rendering;
|
||||
|
||||
import com.replaymod.core.utils.WrappedTimer;
|
||||
import com.replaymod.core.versions.MCVer;
|
||||
import com.replaymod.pathing.player.AbstractTimelinePlayer;
|
||||
import com.replaymod.pathing.player.ReplayTimer;
|
||||
import com.replaymod.pathing.properties.TimestampProperty;
|
||||
@@ -19,15 +20,20 @@ import com.replaymod.replay.ReplayHandler;
|
||||
import com.replaymod.replaystudio.pathing.path.Keyframe;
|
||||
import com.replaymod.replaystudio.pathing.path.Path;
|
||||
import com.replaymod.replaystudio.pathing.path.Timeline;
|
||||
import de.johni0702.minecraft.gui.utils.lwjgl.Dimension;
|
||||
import de.johni0702.minecraft.gui.utils.lwjgl.ReadableDimension;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.gui.ScaledResolution;
|
||||
import net.minecraft.client.renderer.OpenGlHelper;
|
||||
import net.minecraft.client.shader.Framebuffer;
|
||||
import net.minecraft.util.Timer;
|
||||
import org.lwjgl.input.Mouse;
|
||||
import org.lwjgl.opengl.Display;
|
||||
import org.lwjgl.util.Dimension;
|
||||
import org.lwjgl.util.ReadableDimension;
|
||||
|
||||
//#if MC>=11300
|
||||
import org.lwjgl.glfw.GLFW;
|
||||
//#else
|
||||
//$$ import net.minecraft.client.gui.ScaledResolution;
|
||||
//$$ import org.lwjgl.input.Mouse;
|
||||
//$$ import org.lwjgl.opengl.Display;
|
||||
//#endif
|
||||
|
||||
//#if MC>=10904
|
||||
import net.minecraft.util.SoundCategory;
|
||||
@@ -57,7 +63,7 @@ import static org.lwjgl.opengl.GL11.GL_COLOR_BUFFER_BIT;
|
||||
import static org.lwjgl.opengl.GL11.GL_DEPTH_BUFFER_BIT;
|
||||
|
||||
public class VideoRenderer implements RenderInfo {
|
||||
private final Minecraft mc = Minecraft.getMinecraft();
|
||||
private final Minecraft mc = MCVer.getMinecraft();
|
||||
private final RenderSettings settings;
|
||||
private final ReplayHandler replayHandler;
|
||||
private final Timeline timeline;
|
||||
@@ -158,12 +164,14 @@ public class VideoRenderer implements RenderInfo {
|
||||
|
||||
renderingPipeline.run();
|
||||
|
||||
if (settings.isInject360Metadata()) {
|
||||
if (settings.getRenderMethod() == RenderSettings.RenderMethod.ODS) {
|
||||
MetadataInjector.injectODSMetadata(settings.getOutputFile());
|
||||
} else {
|
||||
MetadataInjector.inject360Metadata(settings.getOutputFile());
|
||||
}
|
||||
if (mc.hasCrashed) {
|
||||
throw newReportedException(mc.crashReporter);
|
||||
}
|
||||
|
||||
if (settings.isInjectSphericalMetadata()) {
|
||||
MetadataInjector.injectMetadata(settings.getRenderMethod(), settings.getOutputFile(),
|
||||
settings.getTargetVideoWidth(), settings.getTargetVideoHeight(),
|
||||
settings.getSphericalFovX(), settings.getSphericalFovY());
|
||||
}
|
||||
|
||||
finish();
|
||||
@@ -180,18 +188,28 @@ public class VideoRenderer implements RenderInfo {
|
||||
@Override
|
||||
public float updateForNextFrame() {
|
||||
// because the jGui lib uses Minecraft's displayWidth and displayHeight values, update these temporarily
|
||||
int displayWidthBefore = mc.displayWidth;
|
||||
int displayHeightBefore = mc.displayHeight;
|
||||
|
||||
mc.displayWidth = displayWidth;
|
||||
mc.displayHeight = displayHeight;
|
||||
//#if MC>=11300
|
||||
int displayWidthBefore = mc.mainWindow.framebufferWidth;
|
||||
int displayHeightBefore = mc.mainWindow.framebufferHeight;
|
||||
mc.mainWindow.framebufferWidth = displayWidth;
|
||||
mc.mainWindow.framebufferHeight = displayHeight;
|
||||
//#else
|
||||
//$$ int displayWidthBefore = mc.displayWidth;
|
||||
//$$ int displayHeightBefore = mc.displayHeight;
|
||||
//$$ mc.displayWidth = displayWidth;
|
||||
//$$ mc.displayHeight = displayHeight;
|
||||
//#endif
|
||||
|
||||
if (!settings.isHighPerformance() || framesDone % fps == 0) {
|
||||
drawGui();
|
||||
}
|
||||
|
||||
// Updating the timer will cause the timeline player to update the game state
|
||||
mc.timer.updateTimer();
|
||||
mc.timer.updateTimer(
|
||||
//#if MC>=11300
|
||||
MCVer.milliTime()
|
||||
//#endif
|
||||
);
|
||||
|
||||
int elapsedTicks = mc.timer.elapsedTicks;
|
||||
while (elapsedTicks-- > 0) {
|
||||
@@ -199,8 +217,13 @@ public class VideoRenderer implements RenderInfo {
|
||||
}
|
||||
|
||||
// change Minecraft's display size back
|
||||
mc.displayWidth = displayWidthBefore;
|
||||
mc.displayHeight = displayHeightBefore;
|
||||
//#if MC>=11300
|
||||
mc.mainWindow.framebufferWidth = displayWidthBefore;
|
||||
mc.mainWindow.framebufferHeight = displayHeightBefore;
|
||||
//#else
|
||||
//$$ mc.displayWidth = displayWidthBefore;
|
||||
//$$ mc.displayHeight = displayHeightBefore;
|
||||
//#endif
|
||||
|
||||
framesDone++;
|
||||
return mc.timer.renderPartialTicks;
|
||||
@@ -216,31 +239,52 @@ public class VideoRenderer implements RenderInfo {
|
||||
timelinePlayerFuture = timelinePlayer.start(timeline);
|
||||
|
||||
if (!OpenGlHelper.isFramebufferEnabled()) {
|
||||
Display.setResizable(false);
|
||||
//#if MC>=11300
|
||||
GLFW.glfwSetWindowAttrib(mc.mainWindow.getHandle(), GLFW.GLFW_RESIZABLE, 1);
|
||||
//#else
|
||||
//$$ Display.setResizable(false);
|
||||
//#endif
|
||||
}
|
||||
if (mc.gameSettings.showDebugInfo) {
|
||||
debugInfoWasShown = true;
|
||||
mc.gameSettings.showDebugInfo = false;
|
||||
}
|
||||
if (Mouse.isGrabbed()) {
|
||||
//#if MC>=11300
|
||||
if (mc.mouseHelper.isMouseGrabbed()) {
|
||||
mouseWasGrabbed = true;
|
||||
}
|
||||
Mouse.setGrabbed(false);
|
||||
mc.mouseHelper.ungrabMouse();
|
||||
//#else
|
||||
//$$ if (Mouse.isGrabbed()) {
|
||||
//$$ mouseWasGrabbed = true;
|
||||
//$$ }
|
||||
//$$ Mouse.setGrabbed(false);
|
||||
//#endif
|
||||
|
||||
// Mute all sounds except GUI sounds (buttons, etc.)
|
||||
Map<SoundCategory, Float> mutedSounds = new EnumMap<>(SoundCategory.class);
|
||||
//#if MC>=11300
|
||||
originalSoundLevels = new EnumMap<>(SoundCategory.class);
|
||||
for (SoundCategory category : SoundCategory.values()) {
|
||||
mutedSounds.put(category, 0f);
|
||||
if (category != SoundCategory.MASTER) {
|
||||
originalSoundLevels.put(category, mc.gameSettings.getSoundLevel(category));
|
||||
mc.gameSettings.setSoundLevel(category, 0);
|
||||
}
|
||||
}
|
||||
//#else
|
||||
//$$ Map<SoundCategory, Float> mutedSounds = new EnumMap<>(SoundCategory.class);
|
||||
//$$ for (SoundCategory category : SoundCategory.values()) {
|
||||
//$$ mutedSounds.put(category, 0f);
|
||||
//$$ }
|
||||
//#if MC>=10904
|
||||
originalSoundLevels = mc.gameSettings.soundLevels;
|
||||
mutedSounds.put(SoundCategory.MASTER, originalSoundLevels.get(SoundCategory.MASTER));
|
||||
mc.gameSettings.soundLevels = mutedSounds;
|
||||
//$$ originalSoundLevels = mc.gameSettings.soundLevels;
|
||||
//$$ mutedSounds.put(SoundCategory.MASTER, originalSoundLevels.get(SoundCategory.MASTER));
|
||||
//$$ mc.gameSettings.soundLevels = mutedSounds;
|
||||
//#else
|
||||
//$$ originalSoundLevels = mc.gameSettings.mapSoundLevels;
|
||||
//$$ mutedSounds.put(SoundCategory.MASTER, (Float) originalSoundLevels.get(SoundCategory.MASTER));
|
||||
//$$ mc.gameSettings.mapSoundLevels = mutedSounds;
|
||||
//#endif
|
||||
//#endif
|
||||
|
||||
fps = settings.getFramesPerSecond();
|
||||
|
||||
@@ -282,14 +326,28 @@ public class VideoRenderer implements RenderInfo {
|
||||
timelinePlayer.onTick(new ReplayTimer.UpdatedEvent());
|
||||
|
||||
if (!OpenGlHelper.isFramebufferEnabled()) {
|
||||
Display.setResizable(true);
|
||||
//#if MC>=11300
|
||||
GLFW.glfwSetWindowAttrib(mc.mainWindow.getHandle(), GLFW.GLFW_RESIZABLE, 0);
|
||||
//#else
|
||||
//$$ Display.setResizable(true);
|
||||
//#endif
|
||||
}
|
||||
mc.gameSettings.showDebugInfo = debugInfoWasShown;
|
||||
if (mouseWasGrabbed) {
|
||||
mc.mouseHelper.grabMouseCursor();
|
||||
//#if MC>=11300
|
||||
mc.mouseHelper.grabMouse();
|
||||
//#else
|
||||
//$$ mc.mouseHelper.grabMouseCursor();
|
||||
//#endif
|
||||
}
|
||||
//#if MC>=10904
|
||||
mc.gameSettings.soundLevels = originalSoundLevels;
|
||||
//#if MC>=11300
|
||||
for (Map.Entry<SoundCategory, Float> entry : originalSoundLevels.entrySet()) {
|
||||
mc.gameSettings.setSoundLevel(entry.getKey(), entry.getValue());
|
||||
}
|
||||
//#else
|
||||
//$$ mc.gameSettings.soundLevels = originalSoundLevels;
|
||||
//#endif
|
||||
//#else
|
||||
//$$ mc.gameSettings.mapSoundLevels = originalSoundLevels;
|
||||
//#endif
|
||||
@@ -311,7 +369,13 @@ public class VideoRenderer implements RenderInfo {
|
||||
}
|
||||
|
||||
// Finally, resize the Minecraft framebuffer to the actual width/height of the window
|
||||
mc.resize(displayWidth, displayHeight);
|
||||
//#if MC>=11300
|
||||
mc.getFramebuffer().createFramebuffer(displayWidth, displayHeight);
|
||||
mc.mainWindow.framebufferWidth = displayWidth;
|
||||
mc.mainWindow.framebufferHeight = displayHeight;
|
||||
//#else
|
||||
//$$ mc.resize(displayWidth, displayHeight);
|
||||
//#endif
|
||||
}
|
||||
|
||||
private void tick() {
|
||||
@@ -322,14 +386,14 @@ public class VideoRenderer implements RenderInfo {
|
||||
}
|
||||
|
||||
mc.currentScreen = gui.toMinecraft();
|
||||
//#if MC>=10800
|
||||
try {
|
||||
mc.runTick();
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
//#if MC>=10800 && MC<11300
|
||||
//$$ try {
|
||||
//$$ mc.runTick();
|
||||
//$$ } catch (IOException e) {
|
||||
//$$ throw new RuntimeException(e);
|
||||
//$$ }
|
||||
//#else
|
||||
//$$ mc.runTick();
|
||||
mc.runTick();
|
||||
//#endif
|
||||
}
|
||||
|
||||
@@ -338,7 +402,11 @@ public class VideoRenderer implements RenderInfo {
|
||||
// Resize the GUI framebuffer if the display size changed
|
||||
if (!settings.isHighPerformance() && displaySizeChanged()) {
|
||||
updateDisplaySize();
|
||||
guiFramebuffer.createBindFramebuffer(mc.displayWidth, mc.displayHeight);
|
||||
//#if MC>=11300
|
||||
guiFramebuffer.createBindFramebuffer(mc.mainWindow.getFramebufferWidth(), mc.mainWindow.getFramebufferHeight());
|
||||
//#else
|
||||
//$$ guiFramebuffer.createBindFramebuffer(mc.displayWidth, mc.displayHeight);
|
||||
//#endif
|
||||
}
|
||||
|
||||
pushMatrix();
|
||||
@@ -346,27 +414,47 @@ public class VideoRenderer implements RenderInfo {
|
||||
enableTexture2D();
|
||||
guiFramebuffer.bindFramebuffer(true);
|
||||
|
||||
mc.entityRenderer.setupOverlayRendering();
|
||||
//#if MC>=11300
|
||||
mc.mainWindow.setupOverlayRendering();
|
||||
//#else
|
||||
//$$ mc.entityRenderer.setupOverlayRendering();
|
||||
//#endif
|
||||
|
||||
ScaledResolution scaled = newScaledResolution(mc);
|
||||
gui.toMinecraft().setWorldAndResolution(mc, scaled.getScaledWidth(), scaled.getScaledHeight());
|
||||
//#if MC>=11300
|
||||
gui.toMinecraft().setWorldAndResolution(mc, mc.mainWindow.getScaledWidth(), mc.mainWindow.getScaledHeight());
|
||||
//#else
|
||||
//$$ ScaledResolution scaled = newScaledResolution(mc);
|
||||
//$$ gui.toMinecraft().setWorldAndResolution(mc, scaled.getScaledWidth(), scaled.getScaledHeight());
|
||||
//#endif
|
||||
|
||||
// Events are polled on 1.13+ in mainWindow.update which is called later
|
||||
//#if MC<11300
|
||||
//#if MC>=10800
|
||||
try {
|
||||
gui.toMinecraft().handleInput();
|
||||
} catch (IOException e) {
|
||||
// That's a strange exception from this kind of method O_o
|
||||
// It isn't actually thrown here, so we'll deal with it the easy way
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
//$$ try {
|
||||
//$$ gui.toMinecraft().handleInput();
|
||||
//$$ } catch (IOException e) {
|
||||
//$$ // That's a strange exception from this kind of method O_o
|
||||
//$$ // It isn't actually thrown here, so we'll deal with it the easy way
|
||||
//$$ throw new RuntimeException(e);
|
||||
//$$ }
|
||||
//#else
|
||||
//$$ gui.toMinecraft().handleInput();
|
||||
//#endif
|
||||
//#endif
|
||||
|
||||
int mouseX = Mouse.getX() * scaled.getScaledWidth() / mc.displayWidth;
|
||||
int mouseY = scaled.getScaledHeight() - Mouse.getY() * scaled.getScaledHeight() / mc.displayHeight - 1;
|
||||
//#if MC>=11300
|
||||
int mouseX = (int) mc.mouseHelper.getMouseX();
|
||||
int mouseY = (int) mc.mouseHelper.getMouseY();
|
||||
|
||||
gui.toMinecraft().drawScreen(mouseX, mouseY, 0);
|
||||
gui.toMinecraft().tick();
|
||||
gui.toMinecraft().render(mouseX, mouseY, 0);
|
||||
//#else
|
||||
//$$ int mouseX = Mouse.getX() * scaled.getScaledWidth() / mc.displayWidth;
|
||||
//$$ int mouseY = scaled.getScaledHeight() - Mouse.getY() * scaled.getScaledHeight() / mc.displayHeight - 1;
|
||||
//$$
|
||||
//$$ gui.toMinecraft().updateScreen();
|
||||
//$$ gui.toMinecraft().drawScreen(mouseX, mouseY, 0);
|
||||
//#endif
|
||||
|
||||
guiFramebuffer.unbindFramebuffer();
|
||||
popMatrix();
|
||||
@@ -374,20 +462,30 @@ public class VideoRenderer implements RenderInfo {
|
||||
guiFramebuffer.framebufferRender(displayWidth, displayHeight);
|
||||
popMatrix();
|
||||
|
||||
// if not in high performance mode, update the gui size if screen size changed
|
||||
// otherwise just swap the progress gui to screen
|
||||
if (settings.isHighPerformance()) {
|
||||
Display.update();
|
||||
} else {
|
||||
//#if MC>=11300
|
||||
mc.mainWindow.update(false);
|
||||
//#else
|
||||
//$$ // if not in high performance mode, update the gui size if screen size changed
|
||||
//$$ // otherwise just swap the progress gui to screen
|
||||
//$$ if (settings.isHighPerformance()) {
|
||||
//$$ Display.update();
|
||||
//$$ } else {
|
||||
//#if MC>=10800
|
||||
mc.updateDisplay();
|
||||
//$$ mc.updateDisplay();
|
||||
//#else
|
||||
//$$ mc.resetSize();
|
||||
//#endif
|
||||
//$$ }
|
||||
//#endif
|
||||
//#if MC>=11300
|
||||
if (mc.mouseHelper.isMouseGrabbed()) {
|
||||
mc.mouseHelper.ungrabMouse();
|
||||
}
|
||||
if (Mouse.isGrabbed()) {
|
||||
Mouse.setGrabbed(false);
|
||||
}
|
||||
//#else
|
||||
//$$ if (Mouse.isGrabbed()) {
|
||||
//$$ Mouse.setGrabbed(false);
|
||||
//$$ }
|
||||
//#endif
|
||||
if (paused) {
|
||||
try {
|
||||
Thread.sleep(50);
|
||||
@@ -400,12 +498,21 @@ public class VideoRenderer implements RenderInfo {
|
||||
}
|
||||
|
||||
private boolean displaySizeChanged() {
|
||||
return displayWidth != Display.getWidth() || displayHeight != Display.getHeight();
|
||||
//#if MC>=11300
|
||||
return displayWidth != mc.mainWindow.getWidth() || displayHeight != mc.mainWindow.getHeight();
|
||||
//#else
|
||||
//$$ return displayWidth != Display.getWidth() || displayHeight != Display.getHeight();
|
||||
//#endif
|
||||
}
|
||||
|
||||
private void updateDisplaySize() {
|
||||
displayWidth = Display.getWidth();
|
||||
displayHeight = Display.getHeight();
|
||||
//#if MC>=11300
|
||||
displayWidth = mc.mainWindow.getWidth();
|
||||
displayHeight = mc.mainWindow.getHeight();
|
||||
//#else
|
||||
//$$ displayWidth = Display.getWidth();
|
||||
//$$ displayHeight = Display.getHeight();
|
||||
//#endif
|
||||
}
|
||||
|
||||
public int getFramesDone() {
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
package com.replaymod.render.shader;
|
||||
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.resources.IResource;
|
||||
import com.replaymod.core.versions.MCVer;
|
||||
import net.minecraft.util.ResourceLocation;
|
||||
import org.apache.commons.io.IOUtils;
|
||||
import org.lwjgl.opengl.ARBFragmentShader;
|
||||
@@ -9,6 +8,12 @@ import org.lwjgl.opengl.ARBShaderObjects;
|
||||
import org.lwjgl.opengl.ARBVertexShader;
|
||||
import org.lwjgl.opengl.GL11;
|
||||
|
||||
//#if MC>=11300
|
||||
import net.minecraft.resources.IResource;
|
||||
//#else
|
||||
//$$ import net.minecraft.client.resources.IResource;
|
||||
//#endif
|
||||
|
||||
import java.io.InputStream;
|
||||
|
||||
import static org.lwjgl.opengl.ARBShaderObjects.*;
|
||||
@@ -47,7 +52,7 @@ public class Program {
|
||||
if(shader == 0)
|
||||
throw new Exception("glCreateShaderObjectARB failed");
|
||||
|
||||
IResource resource = Minecraft.getMinecraft().getResourceManager().getResource(resourceLocation);
|
||||
IResource resource = MCVer.getMinecraft().getResourceManager().getResource(resourceLocation);
|
||||
try (InputStream is = resource.getInputStream()) {
|
||||
glShaderSourceARB(shader, IOUtils.toString(is));
|
||||
}
|
||||
|
||||
@@ -1,12 +1,18 @@
|
||||
package com.replaymod.render.utils;
|
||||
|
||||
import com.google.common.base.Objects;
|
||||
import com.replaymod.core.versions.MCVer;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.lwjgl.opengl.ARBBufferObject;
|
||||
import org.lwjgl.opengl.GLContext;
|
||||
import org.lwjgl.opengl.Util;
|
||||
|
||||
//#if MC>=11300
|
||||
import org.lwjgl.opengl.ARBVertexBufferObject;
|
||||
import org.lwjgl.opengl.GL;
|
||||
//#else
|
||||
//$$ import org.lwjgl.opengl.ARBBufferObject;
|
||||
//$$ import org.lwjgl.opengl.GLContext;
|
||||
//$$ import org.lwjgl.opengl.Util;
|
||||
//#endif
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
|
||||
@@ -14,6 +20,10 @@ import static org.lwjgl.opengl.ARBPixelBufferObject.*;
|
||||
import static org.lwjgl.opengl.GL15.*;
|
||||
import static org.lwjgl.opengl.GL21.GL_PIXEL_PACK_BUFFER;
|
||||
|
||||
//#if MC>=11300
|
||||
import static org.lwjgl.opengl.ARBVertexBufferObject.*;
|
||||
//#endif
|
||||
|
||||
public class PixelBufferObject {
|
||||
@RequiredArgsConstructor
|
||||
public enum Usage {
|
||||
@@ -24,8 +34,13 @@ public class PixelBufferObject {
|
||||
private final int arb, gl15;
|
||||
}
|
||||
|
||||
public static final boolean SUPPORTED = GLContext.getCapabilities().GL_ARB_pixel_buffer_object || GLContext.getCapabilities().OpenGL15;
|
||||
private static final boolean arb = !GLContext.getCapabilities().OpenGL15;
|
||||
//#if MC>=11300
|
||||
public static final boolean SUPPORTED = GL.getCapabilities().GL_ARB_pixel_buffer_object || GL.getCapabilities().OpenGL15;
|
||||
private static final boolean arb = !GL.getCapabilities().OpenGL15;
|
||||
//#else
|
||||
//$$ public static final boolean SUPPORTED = GLContext.getCapabilities().GL_ARB_pixel_buffer_object || GLContext.getCapabilities().OpenGL15;
|
||||
//$$ private static final boolean arb = !GLContext.getCapabilities().OpenGL15;
|
||||
//#endif
|
||||
|
||||
private static ThreadLocal<Integer> bound = new ThreadLocal<>();
|
||||
private static ThreadLocal<Integer> mapped = new ThreadLocal<>();
|
||||
@@ -39,12 +54,20 @@ public class PixelBufferObject {
|
||||
}
|
||||
|
||||
this.size = size;
|
||||
this.handle = arb ? ARBBufferObject.glGenBuffersARB() : glGenBuffers();
|
||||
//#if MC>=11300
|
||||
this.handle = arb ? ARBVertexBufferObject.glGenBuffersARB() : glGenBuffers();
|
||||
//#else
|
||||
//$$ this.handle = arb ? ARBBufferObject.glGenBuffersARB() : glGenBuffers();
|
||||
//#endif
|
||||
|
||||
bind();
|
||||
|
||||
if (arb) {
|
||||
ARBBufferObject.glBufferDataARB(GL_PIXEL_PACK_BUFFER_ARB, size, usage.arb);
|
||||
//#if MC>=11300
|
||||
ARBVertexBufferObject.glBufferDataARB(GL_PIXEL_PACK_BUFFER_ARB, size, usage.arb);
|
||||
//#else
|
||||
//$$ ARBBufferObject.glBufferDataARB(GL_PIXEL_PACK_BUFFER_ARB, size, usage.arb);
|
||||
//#endif
|
||||
} else {
|
||||
glBufferData(GL_PIXEL_PACK_BUFFER, size, usage.gl15);
|
||||
}
|
||||
@@ -61,7 +84,11 @@ public class PixelBufferObject {
|
||||
|
||||
public void bind() {
|
||||
if (arb) {
|
||||
ARBBufferObject.glBindBufferARB(GL_PIXEL_PACK_BUFFER_ARB, getHandle());
|
||||
//#if MC>=11300
|
||||
ARBVertexBufferObject.glBindBufferARB(GL_PIXEL_PACK_BUFFER_ARB, getHandle());
|
||||
//#else
|
||||
//$$ ARBBufferObject.glBindBufferARB(GL_PIXEL_PACK_BUFFER_ARB, getHandle());
|
||||
//#endif
|
||||
} else {
|
||||
glBindBuffer(GL_PIXEL_PACK_BUFFER, getHandle());
|
||||
}
|
||||
@@ -71,7 +98,11 @@ public class PixelBufferObject {
|
||||
public void unbind() {
|
||||
checkBound();
|
||||
if (arb) {
|
||||
ARBBufferObject.glBindBufferARB(GL_PIXEL_PACK_BUFFER_ARB, 0);
|
||||
//#if MC>=11300
|
||||
ARBVertexBufferObject.glBindBufferARB(GL_PIXEL_PACK_BUFFER_ARB, 0);
|
||||
//#else
|
||||
//$$ ARBBufferObject.glBindBufferARB(GL_PIXEL_PACK_BUFFER_ARB, 0);
|
||||
//#endif
|
||||
} else {
|
||||
glBindBuffer(GL_PIXEL_PACK_BUFFER, 0);
|
||||
}
|
||||
@@ -95,13 +126,19 @@ public class PixelBufferObject {
|
||||
checkNotMapped();
|
||||
ByteBuffer buffer;
|
||||
if (arb) {
|
||||
buffer = ARBBufferObject.glMapBufferARB(GL_PIXEL_PACK_BUFFER_ARB, GL_READ_ONLY_ARB, size, null);
|
||||
//#if MC>=11300
|
||||
buffer = ARBVertexBufferObject.glMapBufferARB(GL_PIXEL_PACK_BUFFER_ARB, GL_READ_ONLY_ARB, size, null);
|
||||
//#else
|
||||
//$$ buffer = ARBBufferObject.glMapBufferARB(GL_PIXEL_PACK_BUFFER_ARB, GL_READ_ONLY_ARB, size, null);
|
||||
//#endif
|
||||
} else {
|
||||
buffer = glMapBuffer(GL_PIXEL_PACK_BUFFER, GL_READ_ONLY, size, null);
|
||||
}
|
||||
if (buffer == null) {
|
||||
Util.checkGLError();
|
||||
}
|
||||
//#if MC<11300
|
||||
//$$ if (buffer == null) {
|
||||
//$$ Util.checkGLError();
|
||||
//$$ }
|
||||
//#endif
|
||||
mapped.set(getHandle());
|
||||
return buffer;
|
||||
}
|
||||
@@ -111,13 +148,19 @@ public class PixelBufferObject {
|
||||
checkNotMapped();
|
||||
ByteBuffer buffer;
|
||||
if (arb) {
|
||||
buffer = ARBBufferObject.glMapBufferARB(GL_PIXEL_PACK_BUFFER_ARB, GL_WRITE_ONLY_ARB, size, null);
|
||||
//#if MC>=11300
|
||||
buffer = ARBVertexBufferObject.glMapBufferARB(GL_PIXEL_PACK_BUFFER_ARB, GL_WRITE_ONLY_ARB, size, null);
|
||||
//#else
|
||||
//$$ buffer = ARBBufferObject.glMapBufferARB(GL_PIXEL_PACK_BUFFER_ARB, GL_WRITE_ONLY_ARB, size, null);
|
||||
//#endif
|
||||
} else {
|
||||
buffer = glMapBuffer(GL_PIXEL_PACK_BUFFER, GL_WRITE_ONLY, size, null);
|
||||
}
|
||||
if (buffer == null) {
|
||||
Util.checkGLError();
|
||||
}
|
||||
//#if MC<11300
|
||||
//$$ if (buffer == null) {
|
||||
//$$ Util.checkGLError();
|
||||
//$$ }
|
||||
//#endif
|
||||
mapped.set(getHandle());
|
||||
return buffer;
|
||||
}
|
||||
@@ -127,13 +170,19 @@ public class PixelBufferObject {
|
||||
checkNotMapped();
|
||||
ByteBuffer buffer;
|
||||
if (arb) {
|
||||
buffer = ARBBufferObject.glMapBufferARB(GL_PIXEL_PACK_BUFFER_ARB, GL_READ_WRITE_ARB, size, null);
|
||||
//#if MC>=11300
|
||||
buffer = ARBVertexBufferObject.glMapBufferARB(GL_PIXEL_PACK_BUFFER_ARB, GL_READ_WRITE_ARB, size, null);
|
||||
//#else
|
||||
//$$ buffer = ARBBufferObject.glMapBufferARB(GL_PIXEL_PACK_BUFFER_ARB, GL_READ_WRITE_ARB, size, null);
|
||||
//#endif
|
||||
} else {
|
||||
buffer = glMapBuffer(GL_PIXEL_PACK_BUFFER, GL_READ_WRITE, size, null);
|
||||
}
|
||||
if (buffer == null) {
|
||||
Util.checkGLError();
|
||||
}
|
||||
//#if MC<11300
|
||||
//$$ if (buffer == null) {
|
||||
//$$ Util.checkGLError();
|
||||
//$$ }
|
||||
//#endif
|
||||
mapped.set(getHandle());
|
||||
return buffer;
|
||||
}
|
||||
@@ -144,7 +193,11 @@ public class PixelBufferObject {
|
||||
throw new IllegalStateException("Buffer not mapped.");
|
||||
}
|
||||
if (arb) {
|
||||
ARBBufferObject.glUnmapBufferARB(GL_PIXEL_PACK_BUFFER_ARB);
|
||||
//#if MC>=11300
|
||||
ARBVertexBufferObject.glUnmapBufferARB(GL_PIXEL_PACK_BUFFER_ARB);
|
||||
//#else
|
||||
//$$ ARBBufferObject.glUnmapBufferARB(GL_PIXEL_PACK_BUFFER_ARB);
|
||||
//#endif
|
||||
} else {
|
||||
glUnmapBuffer(GL_PIXEL_PACK_BUFFER);
|
||||
}
|
||||
@@ -154,7 +207,11 @@ public class PixelBufferObject {
|
||||
public void delete() {
|
||||
if (handle != -1) {
|
||||
if (arb) {
|
||||
ARBBufferObject.glDeleteBuffersARB(getHandle());
|
||||
//#if MC>=11300
|
||||
ARBVertexBufferObject.glDeleteBuffersARB(getHandle());
|
||||
//#else
|
||||
//$$ ARBBufferObject.glDeleteBuffersARB(getHandle());
|
||||
//#endif
|
||||
} else {
|
||||
glDeleteBuffers(getHandle());
|
||||
}
|
||||
@@ -167,12 +224,7 @@ public class PixelBufferObject {
|
||||
super.finalize();
|
||||
if (handle != -1) {
|
||||
LogManager.getLogger().warn("PBO garbage collected before deleted!");
|
||||
Minecraft.getMinecraft().addScheduledTask(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
delete();
|
||||
}
|
||||
});
|
||||
MCVer.getMinecraft().addScheduledTask(this::delete);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
package com.replaymod.render.utils;
|
||||
|
||||
import net.minecraft.client.Minecraft;
|
||||
import com.replaymod.core.versions.MCVer;
|
||||
import net.minecraft.util.ResourceLocation;
|
||||
import org.apache.commons.io.IOUtils;
|
||||
|
||||
@@ -24,7 +24,7 @@ public class SoundHandler {
|
||||
*/
|
||||
public void playSound(ResourceLocation loc) {
|
||||
try {
|
||||
InputStream is = Minecraft.getMinecraft().getResourceManager().getResource(loc).getInputStream();
|
||||
InputStream is = MCVer.getMinecraft().getResourceManager().getResource(loc).getInputStream();
|
||||
byte[] bytes = IOUtils.toByteArray(is);
|
||||
is.close();
|
||||
AudioInputStream ais = AudioSystem.getAudioInputStream(new ByteArrayInputStream(bytes));
|
||||
|
||||
@@ -13,12 +13,12 @@ public class Utils {
|
||||
* @param width Target image width
|
||||
*/
|
||||
public static void openGlBytesToRBG(ByteBuffer buffer, int bufferWidth, int xOffset, int yOffset, ByteBuffer to, int width) {
|
||||
byte[] rowBuf = new byte[bufferWidth * 3];
|
||||
byte[] rowBuf = new byte[bufferWidth * 4];
|
||||
// Copy image flipped vertically to target buffer
|
||||
int rows = buffer.remaining() / 3 / bufferWidth;
|
||||
int rows = buffer.remaining() / 4 / bufferWidth;
|
||||
for (int i = 0; i < rows; i++) {
|
||||
buffer.get(rowBuf);
|
||||
to.position(((yOffset + rows - i - 1) * width + xOffset) * 3);
|
||||
to.position(((yOffset + rows - i - 1) * width + xOffset) * 4);
|
||||
to.put(rowBuf);
|
||||
}
|
||||
to.rewind();
|
||||
|
||||
Reference in New Issue
Block a user