Add path preview to simplepathing

This commit is contained in:
johni0702
2016-08-03 11:48:46 +02:00
parent 36c973d13a
commit 90aaa4378e
7 changed files with 422 additions and 320 deletions

View File

@@ -16,7 +16,6 @@ import eu.crushedpixel.replaymod.registry.KeybindRegistry;
import eu.crushedpixel.replaymod.registry.ReplayFileAppender; import eu.crushedpixel.replaymod.registry.ReplayFileAppender;
import eu.crushedpixel.replaymod.registry.UploadedFileHandler; import eu.crushedpixel.replaymod.registry.UploadedFileHandler;
import eu.crushedpixel.replaymod.renderer.CustomObjectRenderer; import eu.crushedpixel.replaymod.renderer.CustomObjectRenderer;
import eu.crushedpixel.replaymod.renderer.PathPreviewRenderer;
import eu.crushedpixel.replaymod.renderer.SpectatorRenderer; import eu.crushedpixel.replaymod.renderer.SpectatorRenderer;
import eu.crushedpixel.replaymod.settings.ReplaySettings; import eu.crushedpixel.replaymod.settings.ReplaySettings;
import eu.crushedpixel.replaymod.sound.SoundHandler; import eu.crushedpixel.replaymod.sound.SoundHandler;
@@ -102,8 +101,6 @@ public class ReplayMod {
@Deprecated @Deprecated
public static TooltipRenderer tooltipRenderer; public static TooltipRenderer tooltipRenderer;
@Deprecated @Deprecated
public static PathPreviewRenderer pathPreviewRenderer;
@Deprecated
public static CustomObjectRenderer customObjectRenderer; public static CustomObjectRenderer customObjectRenderer;
@Deprecated @Deprecated
public static SoundHandler soundHandler = new SoundHandler(); public static SoundHandler soundHandler = new SoundHandler();
@@ -178,10 +175,6 @@ public class ReplayMod {
FMLCommonHandler.instance().bus().register(customObjectRenderer); FMLCommonHandler.instance().bus().register(customObjectRenderer);
MinecraftForge.EVENT_BUS.register(customObjectRenderer); MinecraftForge.EVENT_BUS.register(customObjectRenderer);
pathPreviewRenderer = new PathPreviewRenderer();
FMLCommonHandler.instance().bus().register(pathPreviewRenderer);
MinecraftForge.EVENT_BUS.register(pathPreviewRenderer);
crosshairRenderHandler = new CrosshairRenderHandler(); crosshairRenderHandler = new CrosshairRenderHandler();
FMLCommonHandler.instance().bus().register(crosshairRenderHandler); FMLCommonHandler.instance().bus().register(crosshairRenderHandler);
MinecraftForge.EVENT_BUS.register(crosshairRenderHandler); MinecraftForge.EVENT_BUS.register(crosshairRenderHandler);

View File

@@ -15,6 +15,7 @@ import com.replaymod.replaystudio.pathing.interpolation.LinearInterpolator;
import com.replaymod.replaystudio.pathing.path.Keyframe; import com.replaymod.replaystudio.pathing.path.Keyframe;
import com.replaymod.replaystudio.pathing.path.Timeline; import com.replaymod.replaystudio.pathing.path.Timeline;
import com.replaymod.simplepathing.gui.GuiPathing; import com.replaymod.simplepathing.gui.GuiPathing;
import com.replaymod.simplepathing.preview.PathPreview;
import net.minecraftforge.fml.common.FMLCommonHandler; import net.minecraftforge.fml.common.FMLCommonHandler;
import net.minecraftforge.fml.common.Mod; import net.minecraftforge.fml.common.Mod;
import net.minecraftforge.fml.common.event.FMLPreInitializationEvent; import net.minecraftforge.fml.common.event.FMLPreInitializationEvent;
@@ -32,6 +33,8 @@ public class ReplayModSimplePathing implements PathingRegistry {
private Logger logger; private Logger logger;
private GuiPathing guiPathing;
@Mod.EventHandler @Mod.EventHandler
public void preInit(FMLPreInitializationEvent event) { public void preInit(FMLPreInitializationEvent event) {
logger = event.getModLog(); logger = event.getModLog();
@@ -39,11 +42,14 @@ public class ReplayModSimplePathing implements PathingRegistry {
core.getSettingsRegistry().register(Setting.class); core.getSettingsRegistry().register(Setting.class);
FMLCommonHandler.instance().bus().register(this); FMLCommonHandler.instance().bus().register(this);
PathPreview pathPreview = new PathPreview(this);
pathPreview.register();
} }
@SubscribeEvent @SubscribeEvent
public void postReplayOpen(ReplayOpenEvent.Post event) { 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(); } private Timeline currentTimeline = createTimeline(); { currentTimeline.createPath(); currentTimeline.createPath(); }
@@ -113,4 +119,8 @@ public class ReplayModSimplePathing implements PathingRegistry {
public ReplayMod getCore() { public ReplayMod getCore() {
return core; return core;
} }
public GuiPathing getGuiPathing() {
return guiPathing;
}
} }

View File

@@ -3,9 +3,7 @@ package com.replaymod.simplepathing;
import com.replaymod.core.SettingsRegistry; import com.replaymod.core.SettingsRegistry;
public final class Setting<T> extends SettingsRegistry.SettingKeys<T> { public final class Setting<T> extends SettingsRegistry.SettingKeys<T> {
// public static final Setting<Boolean> RECORD_SINGLEPLAYER = make("recordSingleplayer", "recordsingleplayer", true); public static final Setting<Boolean> PATH_PREVIEW = make("pathpreview", "pathpreview", true);
// public static final Setting<Boolean> RECORD_SERVER = make("recordServer", "recordserver", true);
// public static final Setting<Boolean> INDICATOR = make("indicator", "indicator", true);
private static <T> Setting<T> make(String key, String displayName, T defaultValue) { private static <T> Setting<T> make(String key, String displayName, T defaultValue) {
return new Setting<>(key, displayName, defaultValue); return new Setting<>(key, displayName, defaultValue);

View File

@@ -480,6 +480,10 @@ public class GuiPathing {
return mod; return mod;
} }
public EntityPositionTracker getEntityTracker() {
return entityTracker;
}
private class LoadEntityTrackerPopup extends AbstractGuiPopup<LoadEntityTrackerPopup> { private class LoadEntityTrackerPopup extends AbstractGuiPopup<LoadEntityTrackerPopup> {
private final GuiProgressBar progressBar = new GuiProgressBar(popup).setSize(300, 20) private final GuiProgressBar progressBar = new GuiProgressBar(popup).setSize(300, 20)
.setI18nLabel("replaymod.gui.loadentitytracker"); .setI18nLabel("replaymod.gui.loadentitytracker");

View File

@@ -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;
}
}
}
}

View File

@@ -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<Double, Double, Double> 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<Double, Double, Double> prevPos = null;
for (int i = 0; i <= steps; i++) {
long time = start.getTime() + diff * i / steps;
if (spectator) {
Optional<Integer> entityId = path.getValue(SpectatorProperty.PROPERTY, time);
Optional<Integer> replayTime = timePath.getValue(TimestampProperty.PROPERTY, time);
if (entityId.isPresent() && replayTime.isPresent()) {
Location loc = entityTracker.getEntityPositionAtTimestamp(entityId.get(), replayTime.get());
if (loc != null) {
Triple<Double, Double, Double> pos = Triple.of(loc.getX(), loc.getY(), loc.getZ());
if (prevPos != null) {
drawConnection(viewPos, prevPos, pos, 0x0000ff, renderDistanceSquared);
}
prevPos = pos;
continue;
}
}
} else {
Optional<Triple<Double, Double, Double>> optPos = path.getValue(CameraProperties.POSITION, time);
if (optPos.isPresent()) {
Triple<Double, Double, Double> 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<Integer> entityId = path.getValue(SpectatorProperty.PROPERTY, time);
if (entityId.isPresent()) {
// Spectating an entity
if (entityTracker != null) {
Optional<Integer> 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<Triple<Double, Double, Double>> cameraPos = path.getValue(CameraProperties.POSITION, time);
Optional<Triple<Float, Float, Float>> 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<Double, Double, Double> p1, Triple<Double, Double, Double> 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<Double, Double, Double> view,
Triple<Double, Double, Double> pos1,
Triple<Double, Double, Double> 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<Double, Double, Double> view,
Triple<Double, Double, Double> 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<Double, Double, Double> view,
Triple<Double, Double, Double> pos,
Triple<Float, Float, Float> 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<Pair<Keyframe, Triple<Double, Double, Double>>> {
private final Triple<Double, Double, Double> viewPos;
public KeyframeComparator(Triple<Double, Double, Double> viewPos) {
this.viewPos = viewPos;
}
@Override
public int compare(Pair<Keyframe, Triple<Double, Double, Double>> o1,
Pair<Keyframe, Triple<Double, Double, Double>> o2) {
return -Double.compare(distanceSquared(o1.getRight(), viewPos), distanceSquared(o2.getRight(), viewPos));
}
}
}

View File

@@ -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<AdvancedPosition> 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<Keyframe<AdvancedPosition>> distanceSorted = new ArrayList<Keyframe<AdvancedPosition>>(keyframes);
// Collections.sort(distanceSorted, distanceComparator);
//
// GlStateManager.enableTexture2D();
// GlStateManager.blendFunc(GL11.GL_DST_COLOR, GL11.GL_SRC_COLOR);
//
// GlStateManager.disableDepth();
//
// for(Keyframe<AdvancedPosition> 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<Keyframe<AdvancedPosition>> {
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<AdvancedPosition> o1, Keyframe<AdvancedPosition> 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<AdvancedPosition> 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();
}
}