package NET.worlds.scape; import java.awt.Color; import java.io.IOException; public class RectPatch extends WObject implements FloorPatch { public float xDim; public float yDim; public float[] z = new float[]{0.0F, 0.0F, 0.0F, 0.0F}; public Material mat; public float xTile = 1.0F; public float xTileOffset = 0.0F; public float yTile = 1.0F; public float yTileOffset = 0.0F; public Polygon[] t = new Polygon[4]; private static Object classCookie = new Object(); public RectPatch(float x, float y) { this.setVisible(true); this.setBumpable(false); this.xDim = x; this.yDim = y; this.setMaterial(new Material(Color.gray)); } public RectPatch() { this.xDim = 1.0F; this.yDim = 1.0F; this.setMaterial(new Material(Color.gray)); } @Override protected void addRwChildren(WObject parent) { if (this.t[0] == null) { this.createAppearance(); } super.addRwChildren(parent); } @Override public void setVisible(boolean v) { super.setVisible(v); this.createAppearance(); } public void setMaterial(Material m) { if (this.mat != null) { this.mat.detach(); } this.add(m); this.mat = m; this.createAppearance(); } public Material getMaterial() { return this.mat; } @Override public boolean inPatch(float x, float y) { Transform inverse = this.getObjectToWorldMatrix().invert(); Point3Temp p = Point3Temp.make(x, y, 0.0F).times(inverse); inverse.recycle(); x = p.x; y = p.y; return !(x < 0.0F) && !(x > this.xDim) && !(y < 0.0F) && !(y > this.yDim); } @Override public float floorHeight(float x, float y) { Transform inverse = this.getObjectToWorldMatrix().invert(); Point3Temp p = Point3Temp.make(x, y, 0.0F).times(inverse); inverse.recycle(); x = p.x; y = p.y; float nx = x / this.xDim; float ny = y / this.yDim; float fx = 1.0F - nx; float fy = 1.0F - ny; return this.z[0] * fy * fx + this.z[1] * ny * fx + this.z[2] * ny * nx + this.z[3] * fy * nx; } @Override public Point3 surfaceNormal(float x, float y) { Point3 A = new Point3(this.xDim, 0.0F, this.z[1] - this.z[0]); Point3Temp B = Point3Temp.make(0.0F, this.yDim, this.z[3] - this.z[0]); A.cross(B); A.normalize(); A.times(this.getObjectToWorldMatrix()); return A; } private void removeAppearance() { for (int i = 0; i < 4; i++) { if (this.t[i] != null) { this.t[i].detach(); this.t[i] = null; } } } public void createAppearance() { this.removeAppearance(); if (this.getVisible()) { if (!(this.xDim <= 0.0F) && !(this.yDim <= 0.0F)) { if (this.xTile <= 0.0F) { this.xTile = 1.0F; } if (this.xTile > 31.0F) { this.xTile = 31.0F; } if (this.yTile <= 0.0F) { this.yTile = 1.0F; } if (this.yTile > 31.0F) { this.yTile = 31.0F; } if (this.xTileOffset < 0.0F) { this.xTileOffset = 1.0F - (float)Math.floor(this.xTileOffset) + this.xTileOffset; } if (this.yTileOffset < 0.0F) { this.yTileOffset = 1.0F - (float)Math.floor(this.yTileOffset) + this.yTileOffset; } float cx = this.xDim / 2.0F; float cy = this.yDim / 2.0F; float cz = (this.z[0] + this.z[1] + this.z[2] + this.z[3]) / 4.0F; float cU = this.xTileOffset + this.xTile / 2.0F; float cV = this.yTileOffset + this.yTile / 2.0F; this.t[0] = new Polygon(3, this.mat); this.t[0].setVertex(0, 0.0F, 0.0F, this.z[0], this.xTileOffset, this.yTileOffset); this.t[0].setVertex(1, cx, cy, cz, cU, cV); this.t[0].setVertex(2, 0.0F, this.yDim, this.z[1], this.xTileOffset, this.yTileOffset + this.yTile); this.add(this.t[0]); this.t[1] = new Polygon(3, this.mat); this.t[1].setVertex(0, 0.0F, this.yDim, this.z[1], this.xTileOffset, this.yTileOffset + this.yTile); this.t[1].setVertex(1, cx, cy, cz, cU, cV); this.t[1].setVertex(2, this.xDim, this.yDim, this.z[2], this.xTileOffset + this.xTile, this.yTileOffset + this.yTile); this.add(this.t[1]); this.t[2] = new Polygon(3, this.mat); this.t[2].setVertex(0, this.xDim, this.yDim, this.z[2], this.xTileOffset + this.xTile, this.yTileOffset + this.yTile); this.t[2].setVertex(1, cx, cy, cz, cU, cV); this.t[2].setVertex(2, this.xDim, 0.0F, this.z[3], this.xTileOffset + this.xTile, this.yTileOffset); this.add(this.t[2]); this.t[3] = new Polygon(3, this.mat); this.t[3].setVertex(0, this.xDim, 0.0F, this.z[3], this.xTileOffset + this.xTile, this.yTileOffset); this.t[3].setVertex(1, cx, cy, cz, cU, cV); this.t[3].setVertex(2, 0.0F, 0.0F, this.z[0], this.xTileOffset, this.yTileOffset); this.add(this.t[3]); } } } public void setCornerHeight(int corner, float height) { this.z[corner] = height; this.createAppearance(); } public void setWidth(float v) { this.xDim = v; this.createAppearance(); } public void setLength(float v) { this.yDim = v; this.createAppearance(); } @Override public Transform spin(float x, float y, float z, float a) { if (x == 0.0F && y == 0.0F) { return super.spin(x, y, z, a); } else { System.out.println("ERROR: cannot spin floor patch out of horizontal!"); return this; } } @Override public Transform postspin(float x, float y, float z, float a) { if (x == 0.0F && y == 0.0F) { return super.spin(x, y, z, a); } else { System.out.println("ERROR: cannot spin floor patch out of horizontal!"); return this; } } @Override public Transform worldSpin(float x, float y, float z, float a) { if (x == 0.0F && y == 0.0F) { return super.spin(x, y, z, a); } else { System.out.println("ERROR: cannot spin floor patch out of horizontal!"); return this; } } @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, "Length (y)")); } else if (mode == 1) { ret = new Float(this.yDim); } else if (mode == 2) { this.setLength((Float)value); } break; case 1: if (mode == 0) { ret = FloatPropertyEditor.make(new Property(this, index, "Width (x)")); } else if (mode == 1) { ret = new Float(this.xDim); } else if (mode == 2) { this.setWidth((Float)value); } break; case 2: if (mode == 0) { ret = FloatPropertyEditor.make(new Property(this, index, "0,0 corner")); } else if (mode == 1) { ret = new Float(this.z[0]); } else if (mode == 2) { this.setCornerHeight(0, (Float)value); } break; case 3: if (mode == 0) { ret = FloatPropertyEditor.make(new Property(this, index, "0,y corner")); } else if (mode == 1) { ret = new Float(this.z[1]); } else if (mode == 2) { this.setCornerHeight(1, (Float)value); } break; case 4: if (mode == 0) { ret = FloatPropertyEditor.make(new Property(this, index, "x,y corner")); } else if (mode == 1) { ret = new Float(this.z[2]); } else if (mode == 2) { this.setCornerHeight(2, (Float)value); } break; case 5: if (mode == 0) { ret = FloatPropertyEditor.make(new Property(this, index, "x,0 corner")); } else if (mode == 1) { ret = new Float(this.z[3]); } else if (mode == 2) { this.setCornerHeight(3, (Float)value); } break; case 6: if (mode == 0) { ret = FloatPropertyEditor.make(new Property(this, index, "# Tiles (x)")); } else if (mode == 1) { ret = new Float(this.xTile); } else if (mode == 2) { this.xTile = (Float)value; this.createAppearance(); } break; case 7: if (mode == 0) { ret = FloatPropertyEditor.make(new Property(this, index, "# Tiles (y)")); } else if (mode == 1) { ret = new Float(this.yTile); } else if (mode == 2) { this.yTile = (Float)value; this.createAppearance(); } break; case 8: if (mode == 0) { ret = FloatPropertyEditor.make(new Property(this, index, "Tile Offset (x)")); } else if (mode == 1) { ret = new Float(this.xTileOffset); } else if (mode == 2) { this.xTileOffset = (Float)value; this.createAppearance(); } break; case 9: if (mode == 0) { ret = FloatPropertyEditor.make(new Property(this, index, "Tile Offset (y)")); } else if (mode == 1) { ret = new Float(this.yTileOffset); } else if (mode == 2) { this.yTileOffset = (Float)value; this.createAppearance(); } break; case 10: if (mode == 0) { ret = new Property(this, index, "Material"); } else if (mode == 1) { ret = this.mat; } break; default: ret = super.properties(index, offset + 11, mode, value); } return ret; } @Override public void saveState(Saver s) throws IOException { s.saveVersion(2, classCookie); this.removeAppearance(); super.saveState(s); s.saveFloat(this.xDim); s.saveFloat(this.yDim); for (int i = 0; i < 4; i++) { s.saveFloat(this.z[i]); } s.saveFloat(this.xTile); s.saveFloat(this.xTileOffset); s.saveFloat(this.yTile); s.saveFloat(this.yTileOffset); s.saveMaybeNull(this.mat); this.createAppearance(); } @Override public void restoreState(Restorer r) throws IOException, TooNewException { this.restoreStateRectPatchHelper(r, classCookie); } public void restoreStateRectPatchHelper(Restorer r, Object cookie) throws IOException, TooNewException { switch (r.restoreVersion(cookie)) { case 0: r.setOldFlag(); super.restoreState(r); this.xDim = r.restoreFloat(); this.yDim = r.restoreFloat(); for (int i = 0; i < 4; i++) { this.z[i] = r.restoreFloat(); } this.setVisible(false); break; case 1: r.setOldFlag(); super.restoreState(r); this.xDim = r.restoreFloat(); this.yDim = r.restoreFloat(); for (int i = 0; i < 4; i++) { this.z[i] = r.restoreFloat(); } this.xTile = r.restoreFloat(); this.xTileOffset = r.restoreFloat(); this.yTile = r.restoreFloat(); this.yTileOffset = r.restoreFloat(); this.setMaterial(Material.restore(r)); r.restoreMaybeNull(); r.restoreMaybeNull(); r.restoreMaybeNull(); r.restoreMaybeNull(); break; case 2: super.restoreState(r); this.xDim = r.restoreFloat(); this.yDim = r.restoreFloat(); for (int i = 0; i < 4; i++) { this.z[i] = r.restoreFloat(); } this.xTile = r.restoreFloat(); this.xTileOffset = r.restoreFloat(); this.yTile = r.restoreFloat(); this.yTileOffset = r.restoreFloat(); this.setMaterial(Material.restore(r)); break; default: throw new TooNewException(); } } @Override public String toString() { return super.toString() + "[" + this.xDim + "," + this.yDim + "]"; } }