Added Spectator Keyframes and handles them properly in both normal and rendered Replay Paths

This commit is contained in:
CrushedPixel
2015-05-31 13:54:22 +02:00
parent 431a36c9d9
commit fe036d72d8
8 changed files with 143 additions and 71 deletions

View File

@@ -214,7 +214,9 @@ public class GuiReplayOverlay extends Gui {
if(cam != null) { if(cam != null) {
Position position = new Position(cam.posX, cam.posY, cam.posZ, cam.rotationPitch, Position position = new Position(cam.posX, cam.posY, cam.posZ, cam.rotationPitch,
cam.rotationYaw % 360, ReplayHandler.getCameraTilt()); cam.rotationYaw % 360, ReplayHandler.getCameraTilt());
ReplayHandler.addKeyframe(new PositionKeyframe(ReplayHandler.getRealTimelineCursor(), position));
if(ReplayHandler.isCamera()) ReplayHandler.addKeyframe(new PositionKeyframe(ReplayHandler.getRealTimelineCursor(), position));
else ReplayHandler.addKeyframe(new PositionKeyframe(ReplayHandler.getRealTimelineCursor(), cam.getEntityId()));
} }
} }
} }

View File

@@ -1,5 +1,6 @@
package eu.crushedpixel.replaymod.holders; package eu.crushedpixel.replaymod.holders;
import net.minecraft.client.Minecraft;
import net.minecraft.entity.Entity; import net.minecraft.entity.Entity;
import org.apache.commons.lang3.builder.HashCodeBuilder; import org.apache.commons.lang3.builder.HashCodeBuilder;
@@ -8,6 +9,10 @@ public class Position {
private double x, y, z; private double x, y, z;
private float pitch, yaw, roll; private float pitch, yaw, roll;
public Position(int entityID) {
this(Minecraft.getMinecraft().theWorld.getEntityByID(entityID));
}
public Position(Entity e) { public Position(Entity e) {
this.x = e.posX; this.x = e.posX;
this.y = e.posY; this.y = e.posY;

View File

@@ -5,10 +5,11 @@ import org.apache.commons.lang3.builder.HashCodeBuilder;
public class PositionKeyframe extends Keyframe { public class PositionKeyframe extends Keyframe {
private Position position; private Position position;
private Integer spectatedEntityID = null;
@Override @Override
public Object clone() { public Object clone() {
return new PositionKeyframe(this.getRealTimestamp(), this.getPosition()); return new PositionKeyframe(this.getRealTimestamp(), this.getPosition(), this.getSpectatedEntityID());
} }
public PositionKeyframe(int realTime, Position position) { public PositionKeyframe(int realTime, Position position) {
@@ -16,12 +17,24 @@ public class PositionKeyframe extends Keyframe {
this.position = position; this.position = position;
} }
public PositionKeyframe(int realTime, Position position, int spectatedEntityID) {
super(realTime);
this.position = position;
this.spectatedEntityID = spectatedEntityID;
}
public PositionKeyframe(int realTime, int spectatedEntityID) {
this(realTime, new Position(spectatedEntityID), spectatedEntityID);
}
public Position getPosition() { public Position getPosition() {
return position; return position;
} }
public void setPosition(Position position) { this.position = position; } public void setPosition(Position position) { this.position = position; }
public Integer getSpectatedEntityID() { return spectatedEntityID; }
@Override @Override
public boolean equals(Object o2) { public boolean equals(Object o2) {
if(o2 == null) return false; if(o2 == null) return false;
@@ -35,6 +48,7 @@ public class PositionKeyframe extends Keyframe {
return new HashCodeBuilder(17, 37) return new HashCodeBuilder(17, 37)
.append(getPosition()) .append(getPosition())
.append(getRealTimestamp()) .append(getRealTimestamp())
.append(getSpectatedEntityID())
.toHashCode(); .toHashCode();
} }
} }

View File

@@ -36,6 +36,55 @@ public class SpectatorRenderer {
return (EntityPlayer)current; return (EntityPlayer)current;
} }
public void renderSpectatorHand(EntityPlayer entityPlayer, float partialTicks, int renderPass) {
GlStateManager.matrixMode(GL11.GL_PROJECTION);
GlStateManager.loadIdentity();
float f1 = 0.07F;
if(this.mc.gameSettings.anaglyph) {
GlStateManager.translate((float)(-(renderPass * 2 - 1)) * f1, 0.0F, 0.0F);
}
Project.gluPerspective(mc.entityRenderer.getFOVModifier(partialTicks, false),
(float) this.mc.displayWidth / (float) this.mc.displayHeight, 0.05F, mc.entityRenderer.farPlaneDistance * 2.0F);
GlStateManager.matrixMode(GL11.GL_MODELVIEW);
GlStateManager.loadIdentity();
if(this.mc.gameSettings.anaglyph) {
GlStateManager.translate((float)(renderPass * 2 - 1) * 0.1F, 0.0F, 0.0F);
}
GlStateManager.pushMatrix();
mc.entityRenderer.hurtCameraEffect(partialTicks);
if(this.mc.gameSettings.viewBobbing) {
mc.entityRenderer.setupViewBobbing(partialTicks);
}
boolean sleeping = this.mc.getRenderViewEntity() instanceof EntityLivingBase &&
((EntityLivingBase)this.mc.getRenderViewEntity()).isPlayerSleeping();
if(this.mc.gameSettings.thirdPersonView == 0 && !sleeping && !this.mc.gameSettings.hideGUI) {
mc.entityRenderer.enableLightmap();
renderItemInFirstPerson(partialTicks);
mc.entityRenderer.disableLightmap();
}
GlStateManager.popMatrix();
if(this.mc.gameSettings.thirdPersonView == 0 && !sleeping) {
renderOverlays(partialTicks, entityPlayer);
mc.entityRenderer.hurtCameraEffect(partialTicks);
}
if(this.mc.gameSettings.viewBobbing) {
mc.entityRenderer.setupViewBobbing(partialTicks);
}
}
@SubscribeEvent @SubscribeEvent
public void renderHandEvent(RenderHandEvent event) { public void renderHandEvent(RenderHandEvent event) {
if(!ReplayHandler.isInReplay() || ReplayHandler.isCamera()) { if(!ReplayHandler.isInReplay() || ReplayHandler.isCamera()) {
@@ -45,54 +94,8 @@ public class SpectatorRenderer {
EntityPlayer entityPlayer = getSpectatedPlayer(); EntityPlayer entityPlayer = getSpectatedPlayer();
if(entityPlayer == null) return; if(entityPlayer == null) return;
renderSpectatorHand(entityPlayer, event.partialTicks, event.renderPass);
event.setCanceled(true); event.setCanceled(true);
GlStateManager.matrixMode(GL11.GL_PROJECTION);
GlStateManager.loadIdentity();
float f1 = 0.07F;
if(this.mc.gameSettings.anaglyph) {
GlStateManager.translate((float)(-(event.renderPass * 2 - 1)) * f1, 0.0F, 0.0F);
}
Project.gluPerspective(mc.entityRenderer.getFOVModifier(event.partialTicks, false),
(float)this.mc.displayWidth / (float) this.mc.displayHeight, 0.05F, mc.entityRenderer.farPlaneDistance * 2.0F);
GlStateManager.matrixMode(GL11.GL_MODELVIEW);
GlStateManager.loadIdentity();
if(this.mc.gameSettings.anaglyph) {
GlStateManager.translate((float)(event.renderPass * 2 - 1) * 0.1F, 0.0F, 0.0F);
}
GlStateManager.pushMatrix();
mc.entityRenderer.hurtCameraEffect(event.partialTicks);
if(this.mc.gameSettings.viewBobbing) {
mc.entityRenderer.setupViewBobbing(event.partialTicks);
}
boolean sleeping = this.mc.getRenderViewEntity() instanceof EntityLivingBase &&
((EntityLivingBase)this.mc.getRenderViewEntity()).isPlayerSleeping();
if(this.mc.gameSettings.thirdPersonView == 0 && !sleeping && !this.mc.gameSettings.hideGUI) {
mc.entityRenderer.enableLightmap();
renderItemInFirstPerson(event.partialTicks);
mc.entityRenderer.disableLightmap();
}
GlStateManager.popMatrix();
if(this.mc.gameSettings.thirdPersonView == 0 && !sleeping) {
renderOverlays(event.partialTicks, entityPlayer);
mc.entityRenderer.hurtCameraEffect(event.partialTicks);
}
if(this.mc.gameSettings.viewBobbing) {
mc.entityRenderer.setupViewBobbing(event.partialTicks);
}
} }
public void renderItemInFirstPerson(float partialTicks) { public void renderItemInFirstPerson(float partialTicks) {

View File

@@ -71,9 +71,14 @@ public class ReplayHandler {
} }
public static void spectateEntity(Entity e) { public static void spectateEntity(Entity e) {
if(e == null) {
spectateCamera();
}
else {
currentEntity = e; currentEntity = e;
mc.setRenderViewEntity(currentEntity); mc.setRenderViewEntity(currentEntity);
} }
}
public static void spectateCamera() { public static void spectateCamera() {
if(currentEntity != null) { if(currentEntity != null) {

View File

@@ -221,6 +221,18 @@ public class ReplayProcess {
PositionKeyframe lastPos = ReplayHandler.getPreviousPositionKeyframe(curRealReplayTime); PositionKeyframe lastPos = ReplayHandler.getPreviousPositionKeyframe(curRealReplayTime);
PositionKeyframe nextPos = ReplayHandler.getNextPositionKeyframe(curRealReplayTime); PositionKeyframe nextPos = ReplayHandler.getNextPositionKeyframe(curRealReplayTime);
boolean spectating = false;
//if it's between two spectator keyframes sharing the same entity, spectate this entity
if(lastPos != null && nextPos != null) {
if(lastPos.getSpectatedEntityID() != null && nextPos.getSpectatedEntityID() != null) {
if(lastPos.getSpectatedEntityID().equals(nextPos.getSpectatedEntityID())) {
spectating = true;
}
}
}
ReplayHandler.setRealTimelineCursor(curRealReplayTime); ReplayHandler.setRealTimelineCursor(curRealReplayTime);
int lastPosStamp = 0; int lastPosStamp = 0;
@@ -292,6 +304,8 @@ public class ReplayProcess {
float splinePos = ((float) ReplayHandler.getKeyframeIndex(lastPos) + currentPosStepPerc) / (float) (posCount - 1); float splinePos = ((float) ReplayHandler.getKeyframeIndex(lastPos) + currentPosStepPerc) / (float) (posCount - 1);
float timePos = ((float) ReplayHandler.getKeyframeIndex(lastTime) + currentTimeStepPerc) / (float) (timeCount - 1); float timePos = ((float) ReplayHandler.getKeyframeIndex(lastTime) + currentTimeStepPerc) / (float) (timeCount - 1);
if(!spectating) {
ReplayHandler.spectateCamera();
Position pos = null; Position pos = null;
if(posCount > 1) { if(posCount > 1) {
if(!linear) { if(!linear) {
@@ -305,15 +319,18 @@ public class ReplayProcess {
} }
} }
Integer curTimestamp = null;
if(timeLinear != null && timeCount > 1) {
curTimestamp = timeLinear.getPoint(Math.max(0, Math.min(1, timePos)));
}
if(pos != null) { if(pos != null) {
ReplayHandler.setCameraTilt(pos.getRoll()); ReplayHandler.setCameraTilt(pos.getRoll());
ReplayHandler.getCameraEntity().movePath(pos); ReplayHandler.getCameraEntity().movePath(pos);
} }
} else {
ReplayHandler.spectateEntity(mc.theWorld.getEntityByID(lastPos.getSpectatedEntityID()));
}
Integer curTimestamp = null;
if(timeLinear != null && timeCount > 1) {
curTimestamp = timeLinear.getPoint(Math.max(0, Math.min(1, timePos)));
}
if(!isVideoRecording()) ReplayMod.replaySender.setReplaySpeed(curSpeed); if(!isVideoRecording()) ReplayMod.replaySender.setReplaySpeed(curSpeed);
//if(curSpeed > 0) //if(curSpeed > 0)

View File

@@ -198,12 +198,13 @@ public class VideoRenderer {
Position pos; Position pos;
PositionKeyframe lastPos = ReplayHandler.getPreviousPositionKeyframe(videoTime); PositionKeyframe lastPos = ReplayHandler.getPreviousPositionKeyframe(videoTime);
PositionKeyframe nextPos = null;
if (movement == null || lastPos == null) { if (movement == null || lastPos == null) {
// Stay at one position, no movement // Stay at one position, no movement
pos = ReplayHandler.getNextPositionKeyframe(-1).getPosition(); pos = ReplayHandler.getNextPositionKeyframe(-1).getPosition();
} else { } else {
// Position interpolation // Position interpolation
PositionKeyframe nextPos = ReplayHandler.getNextPositionKeyframe(videoTime); nextPos = ReplayHandler.getNextPositionKeyframe(videoTime);
int lastPosStamp = lastPos.getRealTimestamp(); int lastPosStamp = lastPos.getRealTimestamp();
int nextPosStamp = (nextPos == null ? lastPos : nextPos).getRealTimestamp(); int nextPosStamp = (nextPos == null ? lastPos : nextPos).getRealTimestamp();
@@ -215,13 +216,32 @@ public class VideoRenderer {
float totalPct = (ReplayHandler.getKeyframeIndex(lastPos) + diffPct) / (posCount-1); float totalPct = (ReplayHandler.getKeyframeIndex(lastPos) + diffPct) / (posCount-1);
pos = movement.getPoint(Math.max(0, Math.min(1, totalPct))); pos = movement.getPoint(Math.max(0, Math.min(1, totalPct)));
} }
ReplayHandler.setCameraTilt(pos.getRoll());
ReplayHandler.getCameraEntity().movePath(pos);
boolean spectating = false;
//if it's between two spectator keyframes sharing the same entity, spectate this entity
if(lastPos != null && nextPos != null) {
if(lastPos.getSpectatedEntityID() != null && nextPos.getSpectatedEntityID() != null) {
if(lastPos.getSpectatedEntityID().equals(nextPos.getSpectatedEntityID())) {
spectating = true;
}
}
}
if(!spectating) {
// Make sure we're spectating the camera entity // Make sure we're spectating the camera entity
// We do not use .spectateCamera() as that method sets the position of the camera to the previous // We do not use .spectateCamera() as that method sets the position of the camera to the previous
// entity, overriding our calculations // entity, overriding our calculations
ReplayHandler.spectateEntity(ReplayHandler.getCameraEntity()); ReplayHandler.spectateEntity(ReplayHandler.getCameraEntity());
if(pos != null) {
ReplayHandler.setCameraTilt(pos.getRoll());
ReplayHandler.getCameraEntity().movePath(pos);
}
} else {
ReplayHandler.spectateEntity(mc.theWorld.getEntityByID(lastPos.getSpectatedEntityID()));
}
} }
private void updateTime(Timer timer, int framesDone) { private void updateTime(Timer timer, int framesDone) {

View File

@@ -1,5 +1,7 @@
package eu.crushedpixel.replaymod.video.entity; package eu.crushedpixel.replaymod.video.entity;
import eu.crushedpixel.replaymod.ReplayMod;
import eu.crushedpixel.replaymod.replay.ReplayHandler;
import net.minecraft.client.Minecraft; import net.minecraft.client.Minecraft;
import net.minecraft.client.particle.EffectRenderer; import net.minecraft.client.particle.EffectRenderer;
import net.minecraft.client.renderer.*; import net.minecraft.client.renderer.*;
@@ -7,6 +9,7 @@ import net.minecraft.client.renderer.culling.ClippingHelperImpl;
import net.minecraft.client.renderer.culling.ICamera; import net.minecraft.client.renderer.culling.ICamera;
import net.minecraft.client.renderer.texture.TextureMap; import net.minecraft.client.renderer.texture.TextureMap;
import net.minecraft.entity.Entity; import net.minecraft.entity.Entity;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.util.AxisAlignedBB; import net.minecraft.util.AxisAlignedBB;
import net.minecraft.util.EnumWorldBlockLayer; import net.minecraft.util.EnumWorldBlockLayer;
import net.minecraft.util.MathHelper; import net.minecraft.util.MathHelper;
@@ -172,6 +175,9 @@ public abstract class CustomEntityRenderer {
} }
net.minecraftforge.client.ForgeHooksClient.dispatchRenderLast(renderglobal, partialTicks); net.minecraftforge.client.ForgeHooksClient.dispatchRenderLast(renderglobal, partialTicks);
if(!ReplayHandler.isCamera() && ReplayHandler.getCurrentEntity() instanceof EntityPlayer)
ReplayMod.spectatorRenderer.renderSpectatorHand((EntityPlayer)ReplayHandler.getCurrentEntity(), partialTicks, renderPass);
} }
protected void setupCameraTransform(float partialTicks) { protected void setupCameraTransform(float partialTicks) {