diff --git a/src/main/java/com/replaymod/core/ReplayMod.java b/src/main/java/com/replaymod/core/ReplayMod.java index 11e84591..43cca831 100755 --- a/src/main/java/com/replaymod/core/ReplayMod.java +++ b/src/main/java/com/replaymod/core/ReplayMod.java @@ -16,7 +16,6 @@ import eu.crushedpixel.replaymod.registry.KeybindRegistry; import eu.crushedpixel.replaymod.registry.ReplayFileAppender; import eu.crushedpixel.replaymod.registry.UploadedFileHandler; import eu.crushedpixel.replaymod.renderer.CustomObjectRenderer; -import eu.crushedpixel.replaymod.renderer.PathPreviewRenderer; import eu.crushedpixel.replaymod.renderer.SpectatorRenderer; import eu.crushedpixel.replaymod.settings.ReplaySettings; import eu.crushedpixel.replaymod.sound.SoundHandler; @@ -102,8 +101,6 @@ public class ReplayMod { @Deprecated public static TooltipRenderer tooltipRenderer; @Deprecated - public static PathPreviewRenderer pathPreviewRenderer; - @Deprecated public static CustomObjectRenderer customObjectRenderer; @Deprecated public static SoundHandler soundHandler = new SoundHandler(); @@ -178,10 +175,6 @@ public class ReplayMod { FMLCommonHandler.instance().bus().register(customObjectRenderer); MinecraftForge.EVENT_BUS.register(customObjectRenderer); - pathPreviewRenderer = new PathPreviewRenderer(); - FMLCommonHandler.instance().bus().register(pathPreviewRenderer); - MinecraftForge.EVENT_BUS.register(pathPreviewRenderer); - crosshairRenderHandler = new CrosshairRenderHandler(); FMLCommonHandler.instance().bus().register(crosshairRenderHandler); MinecraftForge.EVENT_BUS.register(crosshairRenderHandler); diff --git a/src/main/java/com/replaymod/simplepathing/ReplayModSimplePathing.java b/src/main/java/com/replaymod/simplepathing/ReplayModSimplePathing.java index 65f0896a..064bfb4f 100644 --- a/src/main/java/com/replaymod/simplepathing/ReplayModSimplePathing.java +++ b/src/main/java/com/replaymod/simplepathing/ReplayModSimplePathing.java @@ -15,6 +15,7 @@ import com.replaymod.replaystudio.pathing.interpolation.LinearInterpolator; import com.replaymod.replaystudio.pathing.path.Keyframe; import com.replaymod.replaystudio.pathing.path.Timeline; import com.replaymod.simplepathing.gui.GuiPathing; +import com.replaymod.simplepathing.preview.PathPreview; import net.minecraftforge.fml.common.FMLCommonHandler; import net.minecraftforge.fml.common.Mod; import net.minecraftforge.fml.common.event.FMLPreInitializationEvent; @@ -32,6 +33,8 @@ public class ReplayModSimplePathing implements PathingRegistry { private Logger logger; + private GuiPathing guiPathing; + @Mod.EventHandler public void preInit(FMLPreInitializationEvent event) { logger = event.getModLog(); @@ -39,11 +42,14 @@ public class ReplayModSimplePathing implements PathingRegistry { core.getSettingsRegistry().register(Setting.class); FMLCommonHandler.instance().bus().register(this); + + PathPreview pathPreview = new PathPreview(this); + pathPreview.register(); } @SubscribeEvent public void postReplayOpen(ReplayOpenEvent.Post event) { - new GuiPathing(core, this, event.getReplayHandler()); + guiPathing = new GuiPathing(core, this, event.getReplayHandler()); } private Timeline currentTimeline = createTimeline(); { currentTimeline.createPath(); currentTimeline.createPath(); } @@ -113,4 +119,8 @@ public class ReplayModSimplePathing implements PathingRegistry { public ReplayMod getCore() { return core; } + + public GuiPathing getGuiPathing() { + return guiPathing; + } } diff --git a/src/main/java/com/replaymod/simplepathing/Setting.java b/src/main/java/com/replaymod/simplepathing/Setting.java index 720331a3..3c30c2ed 100644 --- a/src/main/java/com/replaymod/simplepathing/Setting.java +++ b/src/main/java/com/replaymod/simplepathing/Setting.java @@ -3,9 +3,7 @@ package com.replaymod.simplepathing; import com.replaymod.core.SettingsRegistry; public final class Setting extends SettingsRegistry.SettingKeys { -// public static final Setting RECORD_SINGLEPLAYER = make("recordSingleplayer", "recordsingleplayer", true); -// public static final Setting RECORD_SERVER = make("recordServer", "recordserver", true); -// public static final Setting INDICATOR = make("indicator", "indicator", true); + public static final Setting PATH_PREVIEW = make("pathpreview", "pathpreview", true); private static Setting make(String key, String displayName, T defaultValue) { return new Setting<>(key, displayName, defaultValue); diff --git a/src/main/java/com/replaymod/simplepathing/gui/GuiPathing.java b/src/main/java/com/replaymod/simplepathing/gui/GuiPathing.java index 688bc21a..db7af2b0 100644 --- a/src/main/java/com/replaymod/simplepathing/gui/GuiPathing.java +++ b/src/main/java/com/replaymod/simplepathing/gui/GuiPathing.java @@ -480,6 +480,10 @@ public class GuiPathing { return mod; } + public EntityPositionTracker getEntityTracker() { + return entityTracker; + } + private class LoadEntityTrackerPopup extends AbstractGuiPopup { private final GuiProgressBar progressBar = new GuiProgressBar(popup).setSize(300, 20) .setI18nLabel("replaymod.gui.loadentitytracker"); diff --git a/src/main/java/com/replaymod/simplepathing/preview/PathPreview.java b/src/main/java/com/replaymod/simplepathing/preview/PathPreview.java new file mode 100644 index 00000000..0fad42f5 --- /dev/null +++ b/src/main/java/com/replaymod/simplepathing/preview/PathPreview.java @@ -0,0 +1,58 @@ +package com.replaymod.simplepathing.preview; + +import com.replaymod.core.events.SettingsChangedEvent; +import com.replaymod.replay.ReplayHandler; +import com.replaymod.replay.events.ReplayCloseEvent; +import com.replaymod.replay.events.ReplayOpenEvent; +import com.replaymod.simplepathing.ReplayModSimplePathing; +import com.replaymod.simplepathing.Setting; +import net.minecraftforge.fml.common.FMLCommonHandler; +import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; + +public class PathPreview { + private final ReplayModSimplePathing mod; + + private ReplayHandler replayHandler; + private PathPreviewRenderer renderer; + + public PathPreview(ReplayModSimplePathing mod) { + this.mod = mod; + } + + public void register() { + FMLCommonHandler.instance().bus().register(this); + } + + @SubscribeEvent + public void onReplayOpen(ReplayOpenEvent.Post event) { + replayHandler = event.getReplayHandler(); + update(); + } + + @SubscribeEvent + public void onReplayClose(ReplayCloseEvent.Pre event) { + replayHandler = null; + update(); + } + + @SubscribeEvent + public void onSettingsChanged(SettingsChangedEvent event) { + if (event.getKey() == Setting.PATH_PREVIEW) { + update(); + } + } + + private void update() { + if (mod.getCore().getSettingsRegistry().get(Setting.PATH_PREVIEW) && replayHandler != null) { + if (renderer == null) { + renderer = new PathPreviewRenderer(mod, replayHandler); + renderer.register(); + } + } else { + if (renderer != null) { + renderer.unregister(); + renderer = null; + } + } + } +} diff --git a/src/main/java/com/replaymod/simplepathing/preview/PathPreviewRenderer.java b/src/main/java/com/replaymod/simplepathing/preview/PathPreviewRenderer.java new file mode 100644 index 00000000..129cccec --- /dev/null +++ b/src/main/java/com/replaymod/simplepathing/preview/PathPreviewRenderer.java @@ -0,0 +1,348 @@ +package com.replaymod.simplepathing.preview; + +import com.replaymod.core.ReplayMod; +import com.replaymod.pathing.properties.CameraProperties; +import com.replaymod.pathing.properties.SpectatorProperty; +import com.replaymod.pathing.properties.TimestampProperty; +import com.replaymod.replay.ReplayHandler; +import com.replaymod.replaystudio.pathing.interpolation.Interpolator; +import com.replaymod.replaystudio.pathing.path.Keyframe; +import com.replaymod.replaystudio.pathing.path.Path; +import com.replaymod.replaystudio.pathing.path.PathSegment; +import com.replaymod.replaystudio.pathing.path.Timeline; +import com.replaymod.replaystudio.util.EntityPositionTracker; +import com.replaymod.replaystudio.util.Location; +import com.replaymod.simplepathing.ReplayModSimplePathing; +import com.replaymod.simplepathing.gui.GuiPathing; +import net.minecraft.client.Minecraft; +import net.minecraft.client.renderer.GlStateManager; +import net.minecraft.client.renderer.Tessellator; +import net.minecraft.client.renderer.WorldRenderer; +import net.minecraft.entity.Entity; +import net.minecraft.util.ResourceLocation; +import net.minecraftforge.client.event.RenderWorldLastEvent; +import net.minecraftforge.common.MinecraftForge; +import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; +import org.apache.commons.lang3.tuple.Pair; +import org.apache.commons.lang3.tuple.Triple; +import org.lwjgl.opengl.GL11; + +import java.util.Comparator; +import java.util.Optional; + +import static com.replaymod.core.ReplayMod.TEXTURE; + +public class PathPreviewRenderer { + private static final ResourceLocation CAMERA_HEAD = new ResourceLocation("replaymod", "camera_head.png"); + private static final Minecraft mc = Minecraft.getMinecraft(); + + private final ReplayModSimplePathing mod; + private final ReplayHandler replayHandler; + + public PathPreviewRenderer(ReplayModSimplePathing mod, ReplayHandler replayHandler) { + this.mod = mod; + this.replayHandler = replayHandler; + } + + public void register() { + MinecraftForge.EVENT_BUS.register(this); + } + + public void unregister() { + MinecraftForge.EVENT_BUS.unregister(this); + } + + @SubscribeEvent + public void renderCameraPath(RenderWorldLastEvent event) { + if (!replayHandler.getReplaySender().isAsyncMode() || mc.gameSettings.hideGUI) return; + + Entity view = mc.getRenderViewEntity(); + if (view == null) return; + + GuiPathing guiPathing = mod.getGuiPathing(); + if (guiPathing == null) return; + EntityPositionTracker entityTracker = guiPathing.getEntityTracker(); + + Timeline timeline = mod.getCurrentTimeline(); + if (timeline == null) return; + Path path = timeline.getPaths().get(GuiPathing.POSITION_PATH); + if (path.getKeyframes().isEmpty()) return; + Path timePath = timeline.getPaths().get(GuiPathing.TIME_PATH); + + path.update(); + + int renderDistance = mc.gameSettings.renderDistanceChunks * 16; + int renderDistanceSquared = renderDistance * renderDistance; + + // Eye height is subtracted to make path appear higher (at eye height) than it actually is (at foot height) + Triple viewPos = Triple.of(view.posX, view.posY - view.getEyeHeight(), view.posZ); + + GL11.glPushAttrib(GL11.GL_ALL_ATTRIB_BITS); + try { + GL11.glDisable(GL11.GL_LIGHTING); + GL11.glDisable(GL11.GL_TEXTURE_2D); + GL11.glEnable(GL11.GL_BLEND); + + for (PathSegment segment : path.getSegments()) { + Interpolator interpolator = segment.getInterpolator(); + Keyframe start = segment.getStartKeyframe(); + Keyframe end = segment.getEndKeyframe(); + long diff = (int) (end.getTime() - start.getTime()); + + boolean spectator = interpolator.getKeyframeProperties().contains(SpectatorProperty.PROPERTY); + if (spectator && entityTracker == null) { + continue; // Cannot render spectator positions when entity tracker is not yet loaded + } + // Spectator segments have 20 lines per second whereas normal segments have a fixed 100 + long steps = spectator ? diff / 50 : 100; + Triple prevPos = null; + for (int i = 0; i <= steps; i++) { + long time = start.getTime() + diff * i / steps; + if (spectator) { + Optional entityId = path.getValue(SpectatorProperty.PROPERTY, time); + Optional replayTime = timePath.getValue(TimestampProperty.PROPERTY, time); + if (entityId.isPresent() && replayTime.isPresent()) { + Location loc = entityTracker.getEntityPositionAtTimestamp(entityId.get(), replayTime.get()); + if (loc != null) { + Triple pos = Triple.of(loc.getX(), loc.getY(), loc.getZ()); + if (prevPos != null) { + drawConnection(viewPos, prevPos, pos, 0x0000ff, renderDistanceSquared); + } + prevPos = pos; + continue; + } + } + } else { + Optional> optPos = path.getValue(CameraProperties.POSITION, time); + if (optPos.isPresent()) { + Triple pos = optPos.get(); + if (prevPos != null) { + drawConnection(viewPos, prevPos, pos, 0xff0000, renderDistanceSquared); + } + prevPos = pos; + continue; + } + } + prevPos = null; + } + } + + GL11.glEnable(GL11.GL_TEXTURE_2D); + GL11.glBlendFunc(GL11.GL_DST_COLOR, GL11.GL_SRC_COLOR); + GL11.glDisable(GL11.GL_DEPTH_TEST); + + path.getKeyframes().stream() + .map(k -> Pair.of(k, k.getValue(CameraProperties.POSITION))) + .filter(p -> p.getRight().isPresent()) + .map(p -> Pair.of(p.getLeft(), p.getRight().get())) + .filter(p -> distanceSquared(p.getRight(), viewPos) < renderDistanceSquared) + .sorted(new KeyframeComparator(viewPos)) // Need to render the furthest first + .forEachOrdered(p -> drawPoint(viewPos, p.getRight(), p.getLeft())); + + GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA); + GL11.glEnable(GL11.GL_DEPTH_TEST); + + int time = guiPathing.timeline.getCursorPosition(); + Optional entityId = path.getValue(SpectatorProperty.PROPERTY, time); + if (entityId.isPresent()) { + // Spectating an entity + if (entityTracker != null) { + Optional replayTime = timePath.getValue(TimestampProperty.PROPERTY, time); + if (replayTime.isPresent()) { + Location loc = entityTracker.getEntityPositionAtTimestamp(entityId.get(), replayTime.get()); + if (loc != null) { + drawCamera(viewPos, + Triple.of(loc.getX(), loc.getY(), loc.getZ()), + Triple.of(loc.getYaw(), loc.getPitch(), 0f)); + } + } + } + } else { + // Normal camera path + Optional> cameraPos = path.getValue(CameraProperties.POSITION, time); + Optional> cameraRot = path.getValue(CameraProperties.ROTATION, time); + if (cameraPos.isPresent() && cameraRot.isPresent()) { + drawCamera(viewPos, cameraPos.get(), cameraRot.get()); + } + } + } finally { + GlStateManager.popAttrib(); + } + } + + private static double distanceSquared(Triple p1, Triple p2) { + double dx = p1.getLeft() - p2.getLeft(); + double dy = p1.getMiddle() - p2.getMiddle(); + double dz = p1.getRight() - p2.getRight(); + return dx * dx + dy * dy + dz * dz; + } + + private void drawConnection(Triple view, + Triple pos1, + Triple pos2, + int color, int renderDistanceSquared) { + if (distanceSquared(view, pos1) > renderDistanceSquared) return; + if (distanceSquared(view, pos2) > renderDistanceSquared) return; + + Tessellator tessellator = Tessellator.getInstance(); + WorldRenderer renderer = tessellator.getWorldRenderer(); + renderer.setTranslation(-view.getLeft(), -view.getMiddle(), -view.getRight()); + + renderer.startDrawing(GL11.GL_LINES); + renderer.setColorRGBA_I(color, 255); + + renderer.addVertex(pos1.getLeft(), pos1.getMiddle(), pos1.getRight()); + renderer.addVertex(pos2.getLeft(), pos2.getMiddle(), pos2.getRight()); + + GL11.glLineWidth(3); + tessellator.draw(); + renderer.setTranslation(0, 0, 0); + } + + private void drawPoint(Triple view, + Triple pos, + Keyframe keyframe) { + Tessellator tessellator = Tessellator.getInstance(); + WorldRenderer renderer = tessellator.getWorldRenderer(); + renderer.setTranslation(0, 0, 0); + + mc.renderEngine.bindTexture(TEXTURE); + + float posX = 80f / ReplayMod.TEXTURE_SIZE; + float posY = 0f; + float size = 10f / ReplayMod.TEXTURE_SIZE; + + if (keyframe == mod.getSelectedPositionKeyframe()) { + posY += size; + } + + if (keyframe.getValue(SpectatorProperty.PROPERTY).isPresent()) { + posX += size; + } + + float minX = -0.5f; + float minY = -0.5f; + float maxX = 0.5f; + float maxY = 0.5f; + + renderer.startDrawingQuads(); + + renderer.addVertexWithUV(minX, minY, 0, posX + size, posY + size); + renderer.addVertexWithUV(minX, maxY, 0, posX + size, posY); + renderer.addVertexWithUV(maxX, maxY, 0, posX, posY); + renderer.addVertexWithUV(maxX, minY, 0, posX, posY + size); + + GL11.glPushMatrix(); + + GL11.glTranslated( + pos.getLeft() - view.getLeft(), + pos.getMiddle() - view.getMiddle(), + pos.getRight() - view.getRight() + ); + GL11.glNormal3f(0, 1, 0); + GL11.glRotatef(-mc.getRenderManager().playerViewY, 0, 1, 0); + GL11.glRotatef(mc.getRenderManager().playerViewX, 1, 0, 0); + + tessellator.draw(); + + GL11.glPopMatrix(); + } + + private void drawCamera(Triple view, + Triple pos, + Triple rot) { + Tessellator tessellator = Tessellator.getInstance(); + WorldRenderer renderer = tessellator.getWorldRenderer(); + renderer.setTranslation(0, 0, 0); + + mc.renderEngine.bindTexture(CAMERA_HEAD); + + GL11.glPushMatrix(); + + GL11.glTranslated( + pos.getLeft() - view.getLeft(), + pos.getMiddle() - view.getMiddle(), + pos.getRight() - view.getRight() + ); + GL11.glRotated(-rot.getLeft(), 0, 1, 0); // Yaw + GL11.glRotated(rot.getMiddle(), 1, 0, 0); // Pitch + GL11.glRotated(rot.getRight(), 0, 0, 1); // Roll + GL11.glNormal3f(0, 1, 0); + + //draw the position line + GL11.glDisable(GL11.GL_TEXTURE_2D); + renderer.startDrawing(GL11.GL_LINES); + + renderer.setColorRGBA_I(0x00ff00, 170); + + renderer.addVertex(0, 0, 0); + renderer.addVertex(0, 0, 2); + + tessellator.draw(); + + // draw camera cube + GL11.glEnable(GL11.GL_TEXTURE_2D); + + float cubeSize = 0.5f; + + double r = -cubeSize/2; + + renderer.startDrawingQuads(); + + renderer.setColorRGBA_I(0xffffff, 200); + + //back + renderer.addVertexWithUV(r, r + cubeSize, r, 3 * 8 / 64f, 8 / 64f); + renderer.addVertexWithUV(r + cubeSize, r + cubeSize, r, 4*8/64f, 8/64f); + renderer.addVertexWithUV(r + cubeSize, r, r, 4*8/64f, 2*8/64f); + renderer.addVertexWithUV(r, r, r, 3*8/64f, 2*8/64f); + + //front + renderer.addVertexWithUV(r + cubeSize, r, r + cubeSize, 2 * 8 / 64f, 2*8/64f); + renderer.addVertexWithUV(r + cubeSize, r + cubeSize, r + cubeSize, 2 * 8 / 64f, 8/64f); + renderer.addVertexWithUV(r, r + cubeSize, r + cubeSize, 8 / 64f, 8 / 64f); + renderer.addVertexWithUV(r, r, r + cubeSize, 8 / 64f, 2*8/64f); + + //left + renderer.addVertexWithUV(r + cubeSize, r + cubeSize, r, 0, 8/64f); + renderer.addVertexWithUV(r + cubeSize, r + cubeSize, r + cubeSize, 8/64f, 8/64f); + renderer.addVertexWithUV(r + cubeSize, r, r + cubeSize, 8/64f, 2*8/64f); + renderer.addVertexWithUV(r+cubeSize, r, r, 0, 2*8/64f); + + //right + renderer.addVertexWithUV(r, r + cubeSize, r + cubeSize, 2*8/64f, 8/64f); + renderer.addVertexWithUV(r, r + cubeSize, r, 3*8/64f, 8/64f); + renderer.addVertexWithUV(r, r, r, 3*8/64f, 2*8/64f); + renderer.addVertexWithUV(r, r, r + cubeSize, 2 * 8 / 64f, 2 * 8 / 64f); + + //bottom + renderer.addVertexWithUV(r + cubeSize, r, r, 3*8/64f, 0); + renderer.addVertexWithUV(r + cubeSize, r, r + cubeSize, 3*8/64f, 8/64f); + renderer.addVertexWithUV(r, r, r + cubeSize, 2*8/64f, 8/64f); + renderer.addVertexWithUV(r, r, r, 2 * 8 / 64f, 0); + + //top + renderer.addVertexWithUV(r, r + cubeSize, r, 8/64f, 0); + renderer.addVertexWithUV(r, r + cubeSize, r + cubeSize, 8/64f, 8/64f); + renderer.addVertexWithUV(r + cubeSize, r + cubeSize, r + cubeSize, 2*8/64f, 8/64f); + renderer.addVertexWithUV(r + cubeSize, r + cubeSize, r, 2 * 8 / 64f, 0); + + tessellator.draw(); + + GL11.glPopMatrix(); + } + + private class KeyframeComparator implements Comparator>> { + private final Triple viewPos; + + public KeyframeComparator(Triple viewPos) { + this.viewPos = viewPos; + } + + @Override + public int compare(Pair> o1, + Pair> o2) { + return -Double.compare(distanceSquared(o1.getRight(), viewPos), distanceSquared(o2.getRight(), viewPos)); + } + } +} diff --git a/src/main/java/eu/crushedpixel/replaymod/renderer/PathPreviewRenderer.java b/src/main/java/eu/crushedpixel/replaymod/renderer/PathPreviewRenderer.java deleted file mode 100644 index 7dce53f3..00000000 --- a/src/main/java/eu/crushedpixel/replaymod/renderer/PathPreviewRenderer.java +++ /dev/null @@ -1,309 +0,0 @@ -package eu.crushedpixel.replaymod.renderer; - -import eu.crushedpixel.replaymod.events.KeyframesModifyEvent; -import eu.crushedpixel.replaymod.holders.AdvancedPosition; -import eu.crushedpixel.replaymod.holders.Keyframe; -import eu.crushedpixel.replaymod.holders.SpectatorData; -import eu.crushedpixel.replaymod.interpolation.AdvancedPositionKeyframeList; -import net.minecraft.client.Minecraft; -import net.minecraft.client.renderer.GlStateManager; -import net.minecraft.client.renderer.Tessellator; -import net.minecraft.client.renderer.WorldRenderer; -import net.minecraft.util.ResourceLocation; -import net.minecraftforge.client.event.RenderWorldLastEvent; -import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; -import org.lwjgl.opengl.GL11; - -import java.awt.*; -import java.util.Comparator; - -import static com.replaymod.core.ReplayMod.TEXTURE; - -public class PathPreviewRenderer { - - private static final Minecraft mc = Minecraft.getMinecraft(); - private static final int DEFAULT_PATH_COLOR = Color.RED.getRGB(); - private static final int SPECTATOR_PATH_COLOR = Color.BLUE.getRGB(); - - private DistanceComparator distanceComparator = new DistanceComparator(); - - private AdvancedPositionKeyframeList keyframes; - - private final ResourceLocation cameraHeadResource = new ResourceLocation("replaymod", "camera_head.png"); - - @SubscribeEvent - public void renderCameraPath(RenderWorldLastEvent event) { - // TODO -// if(!ReplayHandler.isInReplay() || ReplayHandler.isInPath() || !ReplayMod.replaySettings.showPathPreview() || mc.gameSettings.hideGUI) return; -// -// GlStateManager.pushAttrib(); -// -// int renderDistanceSquared = mc.gameSettings.renderDistanceChunks*16 * mc.gameSettings.renderDistanceChunks*16; -// -// Entity entity = ReplayHandler.getCameraEntity(); -// if(entity == null) return; -// -// double doubleX = entity.posX; -// double doubleY = entity.posY; -// double doubleZ = entity.posZ; -// -// GlStateManager.disableLighting(); -// GlStateManager.disableTexture2D(); -// GlStateManager.enableBlend(); -// -// if(keyframes.size() > 1) { -// AdvancedPosition previousPosition = null; -// -// int i = 0; -// for(Keyframe property : keyframes) { -// int timestamp = property.getRealTimestamp(); -// int nextTimestamp = timestamp; -// -// if(i+1 < keyframes.size()) { -// nextTimestamp = keyframes.get(i+1).getRealTimestamp(); -// } -// -// int diff = nextTimestamp-timestamp; -// int step = diff/100; -// -// for(int currentTimestamp = timestamp; currentTimestamp < nextTimestamp; currentTimestamp += step) { -// AdvancedPosition position = keyframes.getInterpolatedValueForTimestamp(currentTimestamp, ReplayMod.replaySettings.isLinearMovement()); -// if(previousPosition != null) { -// drawConnection(doubleX, doubleY, doubleZ, previousPosition, position, DEFAULT_PATH_COLOR, renderDistanceSquared); -// } -// previousPosition = position; -// } -// -// i++; -// } -// } -// -// distanceComparator.setPlayerPos(doubleX, doubleY + 1.4, doubleZ); -// -// List> distanceSorted = new ArrayList>(keyframes); -// Collections.sort(distanceSorted, distanceComparator); -// -// GlStateManager.enableTexture2D(); -// GlStateManager.blendFunc(GL11.GL_DST_COLOR, GL11.GL_SRC_COLOR); -// -// GlStateManager.disableDepth(); -// -// for(Keyframe kf : distanceSorted) { -// if(kf.getValue().distanceSquared(entity.posX, entity.posY, entity.posZ) < renderDistanceSquared) { -// drawPoint(doubleX, doubleY, doubleZ, kf); -// } -// } -// -// if(ReplayHandler.getPositionKeyframes().size() > 1) { -// AdvancedPosition cameraPosition = ReplayHandler.getPositionKeyframes().getInterpolatedValueForTimestamp(ReplayHandler.getRealTimelineCursor(), -// ReplayMod.replaySettings.isLinearMovement()); -// if(cameraPosition != null) { -// GlStateManager.blendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA); -// drawCamera(doubleX, doubleY, doubleZ, cameraPosition); -// } -// } -// -// GlStateManager.disableBlend(); -// -// GlStateManager.popAttrib(); - } - - @SubscribeEvent - public void recalcSpline(KeyframesModifyEvent event) { - // TODO -// keyframes = ReplayHandler.getPositionKeyframes(); - } - - private class DistanceComparator implements Comparator> { - - private double playerX, playerY, playerZ; - - public void setPlayerPos(double playerX, double playerY, double playerZ) { - this.playerX = playerX; - this.playerY = playerY; - this.playerZ = playerZ; - } - - @Override - public int compare(Keyframe o1, Keyframe o2) { - return -(new Double(o1.getValue().distanceSquared(playerX, playerY, playerZ)).compareTo(o2.getValue().distanceSquared(playerX, playerY, playerZ))); - } - - @Override - public boolean equals(Object obj) { - return false; - } - } - - private void drawConnection(double playerX, double playerY, double playerZ, AdvancedPosition pos1, AdvancedPosition pos2, int color, int renderDistanceSquared) { - if(pos2.distanceSquared(playerX, playerY, playerZ) > renderDistanceSquared) return; - GlStateManager.pushMatrix(); - - Tessellator tessellator = Tessellator.getInstance(); - WorldRenderer renderer = tessellator.getWorldRenderer(); - - GL11.glLineWidth(3.0F); - - double x = pos1.getX() - playerX; - double y = pos1.getY() - playerY; - double z = pos1.getZ() - playerZ; - - renderer.setTranslation(x, y+1.4, z); - - renderer.startDrawing(1); - - renderer.setColorRGBA_I(color, 255); - - renderer.addVertex(pos2.getX() - pos1.getX(), pos2.getY() - pos1.getY(), pos2.getZ() - pos1.getZ()); - renderer.addVertex(0, 0, 0); - - tessellator.draw(); - renderer.setTranslation(0, 0, 0); - - GlStateManager.popMatrix(); - } - - private void drawPoint(double playerX, double playerY, double playerZ, Keyframe kf) { - GlStateManager.pushMatrix(); - - Tessellator tessellator = Tessellator.getInstance(); - WorldRenderer renderer = tessellator.getWorldRenderer(); - - mc.renderEngine.bindTexture(TEXTURE); - - AdvancedPosition pos1 = kf.getValue(); - - double x = pos1.getX() - playerX; - double y = pos1.getY() - playerY; - double z = pos1.getZ() - playerZ; - - GlStateManager.translate(x, y+1.4, z); - - float pitch = mc.getRenderManager().playerViewX; - float yaw = mc.getRenderManager().playerViewY; - - GL11.glNormal3f(0, 1, 0); - - GlStateManager.rotate(-yaw, 0, 1, 0); - GlStateManager.rotate(pitch, 1, 0, 0); - - renderer.startDrawingQuads(); - - float posX = 80/128f; - float posY = 0; - float size = 10/128f; - - - // TODO -// if(kf.equals(ReplayHandler.getSelectedKeyframe())) { -// posY += size; -// } - - if(pos1 instanceof SpectatorData) { - posX += size; - } - - float minX = -0.5f; - float minY = -0.5f; - float maxX = 0.5f; - float maxY = 0.5f; - - renderer.addVertexWithUV(minX, minY, 0, posX + size, posY + size); - renderer.addVertexWithUV(minX, maxY, 0, posX + size, posY); - renderer.addVertexWithUV(maxX, maxY, 0, posX, posY); - renderer.addVertexWithUV(maxX, minY, 0, posX, posY + size); - - tessellator.draw(); - renderer.setTranslation(0, 0, 0); - - GlStateManager.popMatrix(); - } - - private void drawCamera(double playerX, double playerY, double playerZ, AdvancedPosition pos) { - GlStateManager.pushMatrix(); - - Tessellator tessellator = Tessellator.getInstance(); - WorldRenderer renderer = tessellator.getWorldRenderer(); - - mc.renderEngine.bindTexture(cameraHeadResource); - - double x = pos.getX() - playerX; - double y = pos.getY() - playerY; - double z = pos.getZ() - playerZ; - - GlStateManager.translate(x, y + 1.4, z); - - GL11.glNormal3f(0, 1, 0); - - //draw the position line - AdvancedPosition pos2 = pos.getDestination(2); - - GlStateManager.enableDepth(); - GlStateManager.disableLighting(); - GlStateManager.disableTexture2D(); - GlStateManager.enableBlend(); - renderer.startDrawing(1); - - renderer.setColorRGBA_I(Color.GREEN.getRGB(), 170); - - renderer.addVertex(pos2.getX() - pos.getX(), pos2.getY() - pos.getY(), pos2.getZ() - pos.getZ()); - renderer.addVertex(0, 0, 0); - - Tessellator.getInstance().draw(); - - GlStateManager.enableTexture2D(); - - GlStateManager.rotate((float) -pos.getYaw(), 0, 1, 0); - GlStateManager.rotate((float) pos.getPitch(), 1, 0, 0); - GlStateManager.rotate((float) pos.getRoll(), 0, 0, 1); - - float cubeSize = 0.5f; - - x = y = z = -cubeSize/2; - - renderer.startDrawingQuads(); - - renderer.setColorRGBA_I(Color.WHITE.getRGB(), 200); - - //back - renderer.addVertexWithUV(x, y + cubeSize, z, 3 * 8 / 64f, 8 / 64f); - renderer.addVertexWithUV(x + cubeSize, y + cubeSize, z, 4*8/64f, 8/64f); - renderer.addVertexWithUV(x + cubeSize, y, z, 4*8/64f, 2*8/64f); - renderer.addVertexWithUV(x, y, z, 3*8/64f, 2*8/64f); - - //front - renderer.addVertexWithUV(x + cubeSize, y, z + cubeSize, 2 * 8 / 64f, 2*8/64f); - renderer.addVertexWithUV(x + cubeSize, y + cubeSize, z + cubeSize, 2 * 8 / 64f, 8/64f); - renderer.addVertexWithUV(x, y + cubeSize, z + cubeSize, 8 / 64f, 8 / 64f); - renderer.addVertexWithUV(x, y, z + cubeSize, 8 / 64f, 2*8/64f); - - //left - renderer.addVertexWithUV(x + cubeSize, y + cubeSize, z, 0, 8/64f); - renderer.addVertexWithUV(x + cubeSize, y + cubeSize, z + cubeSize, 8/64f, 8/64f); - renderer.addVertexWithUV(x + cubeSize, y, z + cubeSize, 8/64f, 2*8/64f); - renderer.addVertexWithUV(x+cubeSize,y,z, 0, 2*8/64f); - - //right - renderer.addVertexWithUV(x, y + cubeSize, z + cubeSize, 2*8/64f, 8/64f); - renderer.addVertexWithUV(x, y + cubeSize, z, 3*8/64f, 8/64f); - renderer.addVertexWithUV(x, y, z, 3*8/64f, 2*8/64f); - renderer.addVertexWithUV(x, y, z + cubeSize, 2 * 8 / 64f, 2 * 8 / 64f); - - //bottom - renderer.addVertexWithUV(x + cubeSize, y, z, 3*8/64f, 0); - renderer.addVertexWithUV(x + cubeSize, y, z + cubeSize, 3*8/64f, 8/64f); - renderer.addVertexWithUV(x, y, z + cubeSize, 2*8/64f, 8/64f); - renderer.addVertexWithUV(x, y, z, 2 * 8 / 64f, 0); - - //top - renderer.addVertexWithUV(x, y + cubeSize, z, 8/64f, 0); - renderer.addVertexWithUV(x, y + cubeSize, z + cubeSize, 8/64f, 8/64f); - renderer.addVertexWithUV(x + cubeSize, y + cubeSize, z + cubeSize, 2*8/64f, 8/64f); - renderer.addVertexWithUV(x + cubeSize, y + cubeSize, z, 2 * 8 / 64f, 0); - - Tessellator.getInstance().draw(); - renderer.setTranslation(0, 0, 0); - - GlStateManager.popMatrix(); - } -}