package NET.worlds.scape; import NET.worlds.console.Window; import java.io.IOException; import java.util.Enumeration; public class SmoothDriver extends SwitchableBehavior implements MouseDeltaHandler, KeyUpHandler, KeyDownHandler, FrameHandler, MouseDownHandler, MouseUpHandler, MomentumBehavior { protected float FB_force; protected boolean FB_forceFromMouse; protected float FB_vel; protected float LR_force; protected float LR_vel; protected int lastTime; protected float maxdvFB = 300.0F; protected float FB_damp = -2.5F; protected float minFB_vel = 4.0F; protected float minFB_pixDouble = 40.0F; protected float maxdvLR = 166.0F; protected float LR_damp = -5.0F; protected float minLR_vel = 3.0F; protected float minLR_pixDouble = 40.0F; protected float eyeHeight = 150.0F; private int appliedForceThisFrame = 0; private int forceDouble = 0; protected float FB_key = 1200.0F; protected float LR_key = 500.0F; private static Object classCookie = new Object(); @Override public boolean handle(MouseDeltaEvent e) { if (UniverseHandler.handle(e)) { return true; } else { if (e.dx != 0 || e.dy != 0) { this.applyFrameForce(e); float dx2 = e.dx * e.dx; float dy2 = e.dy * e.dy; double arrrr = Math.sqrt(dx2 + dy2); if (e.dy < 0) { dy2 = -dy2; } this.FB_vel -= (float)(1.1 * dy2 / arrrr); if (e.dx < 0) { dx2 = -dx2; } this.LR_vel -= (float)(0.5 * dx2 / arrrr); } return true; } } public void setVelocityDamping(float pDamp) { this.FB_damp = pDamp; } public float getVelocityDamping() { return this.FB_damp; } public void setEyeHeight(float newHeight) { this.eyeHeight = newHeight; } public float getEyeHeight() { return this.eyeHeight; } public void applyFrameForce(Event e) { if (e.receiver instanceof Pilot) { Pilot pilot = (Pilot)e.receiver; if (pilot.isActive()) { this.appliedForceThisFrame++; int now = e.time; float dt = (now - this.lastTime) / 1000.0F; if (!(dt <= 0.0F)) { if (dt > 0.33F) { dt = 0.33F; } this.lastTime = now; float dx = this.FB_vel * dt; float dv = 0.0F; if (this.FB_force != 0.0F) { dv += this.FB_force * dt; dv = this.maxdvFB * (float)Math.atan(dv / this.maxdvFB); this.FB_vel += dv; dx += dv * dt; } float dz = this.eyeHeight - pilot.getZ(); Room room = pilot.getRoom(); if (room != null) { dz += room.floorHeight(pilot.getX(), pilot.getY(), pilot.getZ()); } if (dx != 0.0F || dz != 0.0F) { this.moveLevel(pilot, dx, dz); } this.FB_vel = (float)(this.FB_vel * Math.exp(this.FB_damp * dt)); if (Math.abs(this.FB_vel) < this.minFB_vel) { this.FB_vel = 0.0F; } dv = this.LR_vel * dt; dz = 0.0F; if (this.LR_force != 0.0F) { dz += this.LR_force * dt; dz = this.maxdvLR * (float)Math.atan(dz / this.maxdvLR); this.LR_vel += dz; dv += dz * dt; } if (dv != 0.0F) { this.yawLevel(pilot, dv); } this.LR_vel = (float)(this.LR_vel * Math.exp(this.LR_damp * dt)); if (Math.abs(this.LR_vel) < this.minLR_vel) { this.LR_vel = 0.0F; } } } } } private void moveLevel(Pilot pilot, float dx, float dz) { float currentYaw = pilot.getYaw(); Point3Temp currentSpinAxis = Point3Temp.make(); float currentSpin = pilot.getSpin(currentSpinAxis); Point3Temp currentPosition = pilot.getPosition(); pilot.makeIdentity().moveTo(currentPosition).yaw(-currentYaw); pilot.premoveThrough(Point3Temp.make(0.0F, dx, dz)); pilot.yaw(currentYaw); pilot.spin(currentSpinAxis, currentSpin); } private void yawLevel(Pilot pilot, float dTheta) { float currentYaw = pilot.getYaw(); Point3Temp currentSpinAxis = Point3Temp.make(); float currentSpin = pilot.getSpin(currentSpinAxis); Point3Temp currentPosition = pilot.getPosition(); pilot.makeIdentity().moveTo(currentPosition).yaw(-currentYaw); pilot.yaw(dTheta); pilot.yaw(currentYaw); pilot.spin(currentSpinAxis, currentSpin); } @Override public boolean handle(FrameEvent e) { if (this.FB_forceFromMouse && !this.isDelta(e)) { this.applyFrameForce(e); this.FB_force = 0.0F; this.FB_forceFromMouse = false; } if (this.appliedForceThisFrame == 0) { this.applyFrameForce(e); } this.appliedForceThisFrame = 0; return true; } @Override public boolean handle(KeyDownEvent e) { if (UniverseHandler.handle(e)) { return true; } else { float FB; if (e.key == '\ue326') { FB = this.FB_key; } else { if (e.key != '\ue328') { float LR; if (e.key == '\ue325') { LR = this.LR_key; } else { if (e.key != '\ue327') { return true; } LR = -this.LR_key; } this.applyFrameForce(e); this.LR_force = LR; return true; } FB = -this.FB_key; } this.applyFrameForce(e); this.FB_force = FB; return true; } } @Override public boolean handle(KeyUpEvent e) { if (UniverseHandler.handle(e)) { return true; } else { if (e.key == '\ue326' || e.key == '\ue328') { this.applyFrameForce(e); this.FB_force = 0.0F; } else if (e.key == '\ue325' || e.key == '\ue327') { this.applyFrameForce(e); this.LR_force = 0.0F; } return true; } } private boolean isDelta(Event e) { if (e.receiver instanceof Pilot && ((Pilot)e.receiver).isActive()) { Window w = Window.getMainWindow(); return w != null && w.getDeltaMode(); } else { return false; } } @Override public boolean handle(MouseDownEvent e) { if (e.key == '\ue302' && this.isDelta(e)) { this.applyFrameForce(e); this.FB_force = this.FB_key; this.FB_forceFromMouse = true; } return true; } @Override public boolean handle(MouseUpEvent e) { if (e.key == '\ue302' && this.isDelta(e)) { this.applyFrameForce(e); this.FB_force = 0.0F; this.FB_forceFromMouse = false; } return true; } @Override public Object properties(int index, int offset, int mode, Object value) throws NoSuchPropertyException { Object ret = null; switch (index - offset) { case 0: if (mode == 0) { ret = FloatPropertyEditor.make(new Property(this, index, "Eye Height")); } else if (mode == 1) { ret = new Float(this.getEyeHeight()); } else if (mode == 2) { this.setEyeHeight((Float)value); } break; case 1: if (mode == 0) { ret = FloatPropertyEditor.make(new Property(this, index, "Fore/aft max acceleration")); } else if (mode == 1) { ret = new Float(this.maxdvFB); } else if (mode == 2) { this.maxdvFB = (Float)value; } break; case 2: if (mode == 0) { ret = FloatPropertyEditor.make(new Property(this, index, "Fore/aft velocity damping")); } else if (mode == 1) { ret = new Float(this.FB_damp); } else if (mode == 2) { this.FB_damp = (Float)value; } break; case 3: if (mode == 0) { ret = FloatPropertyEditor.make(new Property(this, index, "Fore/aft min velocity")); } else if (mode == 1) { ret = new Float(this.minFB_vel); } else if (mode == 2) { this.minFB_vel = (Float)value; } break; case 4: if (mode == 0) { ret = FloatPropertyEditor.make(new Property(this, index, "Fore/aft velocity threshold for pixel doubling")); } else if (mode == 1) { ret = new Float(this.minFB_pixDouble); } else if (mode == 2) { this.minFB_pixDouble = (Float)value; } break; case 5: if (mode == 0) { ret = FloatPropertyEditor.make(new Property(this, index, "Yaw max acceleration")); } else if (mode == 1) { ret = new Float(this.maxdvLR); } else if (mode == 2) { this.maxdvLR = (Float)value; } break; case 6: if (mode == 0) { ret = FloatPropertyEditor.make(new Property(this, index, "Yaw rate damping")); } else if (mode == 1) { ret = new Float(this.LR_damp); } else if (mode == 2) { this.LR_damp = (Float)value; } break; case 7: if (mode == 0) { ret = FloatPropertyEditor.make(new Property(this, index, "Yaw min rate")); } else if (mode == 1) { ret = new Float(this.minLR_vel); } else if (mode == 2) { this.minLR_vel = (Float)value; } break; case 8: if (mode == 0) { ret = FloatPropertyEditor.make(new Property(this, index, "Yaw rate threshold for pixel doubling")); } else if (mode == 1) { ret = new Float(this.minLR_pixDouble); } else if (mode == 2) { this.minLR_pixDouble = (Float)value; } break; case 9: if (mode == 0) { ret = FloatPropertyEditor.make(new Property(this, index, "Fore/aft velocity increment for up/down arrow keys")); } else if (mode == 1) { ret = new Float(this.FB_key); } else if (mode == 2) { this.FB_key = (Float)value; } break; case 10: if (mode == 0) { ret = FloatPropertyEditor.make(new Property(this, index, "Yaw rate increment for up/down arrow keys")); } else if (mode == 1) { ret = new Float(this.LR_key); } else if (mode == 2) { this.LR_key = (Float)value; } break; default: ret = super.properties(index, offset + 11, mode, value); } return ret; } @Override public void saveState(Saver s) throws IOException { s.saveVersion(3, classCookie); super.saveState(s); s.saveFloat(this.FB_vel); s.saveFloat(this.LR_vel); s.saveFloat(this.maxdvFB); s.saveFloat(this.FB_damp); s.saveFloat(this.minFB_vel); s.saveFloat(this.maxdvLR); s.saveFloat(this.LR_damp); s.saveFloat(this.minLR_vel); s.saveFloat(this.eyeHeight); s.saveFloat(this.FB_key); s.saveFloat(this.LR_key); s.saveInt(this.forceDouble); } @Override public void restoreState(Restorer r) throws IOException, TooNewException { switch (r.restoreVersion(classCookie)) { case 0: r.setOldFlag(); super.restoreState(r); r.restoreFloat(); this.FB_vel = r.restoreFloat(); r.restoreFloat(); this.LR_vel = r.restoreFloat(); break; case 1: r.setOldFlag(); super.restoreState(r); r.restoreFloat(); this.FB_vel = r.restoreFloat(); r.restoreFloat(); this.LR_vel = r.restoreFloat(); this.maxdvFB = r.restoreFloat(); this.FB_damp = r.restoreFloat(); this.minFB_vel = r.restoreFloat(); this.maxdvLR = r.restoreFloat(); this.LR_damp = r.restoreFloat(); this.minLR_vel = r.restoreFloat(); this.eyeHeight = r.restoreFloat(); this.FB_key = r.restoreFloat(); this.LR_key = r.restoreFloat(); break; case 2: r.setOldFlag(); super.restoreState(r); r.restoreFloat(); this.FB_vel = r.restoreFloat(); r.restoreFloat(); this.LR_vel = r.restoreFloat(); this.maxdvFB = r.restoreFloat(); this.FB_damp = r.restoreFloat(); this.minFB_vel = r.restoreFloat(); this.maxdvLR = r.restoreFloat(); this.LR_damp = r.restoreFloat(); this.minLR_vel = r.restoreFloat(); this.eyeHeight = r.restoreFloat(); this.FB_key = r.restoreFloat(); this.LR_key = r.restoreFloat(); this.forceDouble = r.restoreInt(); break; case 3: super.restoreState(r); this.FB_vel = r.restoreFloat(); this.LR_vel = r.restoreFloat(); this.maxdvFB = r.restoreFloat(); this.FB_damp = r.restoreFloat(); this.minFB_vel = r.restoreFloat(); this.maxdvLR = r.restoreFloat(); this.LR_damp = r.restoreFloat(); this.minLR_vel = r.restoreFloat(); this.eyeHeight = r.restoreFloat(); this.FB_key = r.restoreFloat(); this.LR_key = r.restoreFloat(); this.forceDouble = r.restoreInt(); break; default: throw new TooNewException(); } } @Override public void transferFrom(Enumeration oldMBs) { this.FB_force = 0.0F; this.LR_force = 0.0F; while (oldMBs.hasMoreElements()) { SuperRoot sr = (SuperRoot)oldMBs.nextElement(); if (sr instanceof SmoothDriver) { SmoothDriver sd = (SmoothDriver)sr; this.FB_vel = sd.FB_vel; this.LR_vel = sd.LR_vel; this.lastTime = sd.lastTime; return; } } this.FB_vel = 0.0F; this.LR_vel = 0.0F; this.lastTime = 0; } }