package NET.worlds.scape; import NET.worlds.console.Console; import NET.worlds.console.Main; import NET.worlds.console.MainCallback; import NET.worlds.network.URL; import java.io.IOException; public class Hologram extends Surface implements Prerenderable, BGLoaded, Postrenderable, MainCallback { private int isLoading; ScapePicMovie fromMovie; URL movieName; protected Texture[] images; protected Material[] materials; private static Object classCookie = new Object(); private int origTransformID = 0; private HoloCallback callback; private float scaleDist; static { nativeInit(); } public Hologram(float w, float h, Texture[] texs) { super(null); this.scale(w, 1.0F, h); this.images = texs; } public Hologram() { super(null); } public Hologram(Texture[] texs) { this(texs[0].getW(), texs[0].getH(), texs); } public Hologram(ScapePicMovie texs) { this(texs.getW(), texs.getH(), texs.getTextures()); this.fromMovie = texs; } public Hologram(float w, float h, ScapePicMovie texs) { this(w, h, texs.getTextures()); this.fromMovie = texs; } public Hologram(URL movieName, HoloCallback cb) { super(null); this.setAutosize(true); this.scale(100.0F, 1.0F, 100.0F); this.load(movieName, cb); } public Hologram(URL movieName) { this(movieName, null); } public Hologram(float w, float h, URL movieName, HoloCallback cb) { super(null); this.scale(w, 1.0F, h); this.load(movieName, cb); } public Hologram(float w, float h, URL movieName) { this(w, h, movieName, null); } public static native void nativeInit(); private void load(URL movieName, HoloCallback cb) { assert this.getMaterial() != null; this.callback = cb; this.movieName = movieName; if (this.callback != null || this.hasClump()) { this.forceLoad(); } } private void lockMaterials(boolean val) { if (this.materials != null) { for (int i = 0; i < this.materials.length; i++) { this.materials[i].setKeepLoaded(val); } } } private void releaseMaterials() { this.lockMaterials(false); this.materials = null; } private void loadMultipart(URL url, String base, int numParts, String end) { this.images = null; this.releaseMaterials(); this.materials = new Material[numParts]; while (--numParts >= 0) { this.materials[numParts] = new Material(URL.make(url, base + (numParts + 1) + end)); } this.setMaterial(this.materials[0]); if (this.callback != null) { this.callback.holoCallback(this, true); this.callback = null; } } private void forceLoad() { URL url = HoloDrone.permission(this.movieName); String name = (url == null ? this.movieName : url).getBase(); int len = name.length(); boolean isMov = len > 5 && name.regionMatches(true, len - 5, "*.mov", 0, 5); int h = 1; int v = 1; int s = 1; int num; for (int nextStarIndex = len - 5; nextStarIndex > 2 && name.charAt(nextStarIndex) == '*' && (num = name.charAt(nextStarIndex - 2) - '0') > 0 && num <= 9; nextStarIndex -= 3 ) { char control = Character.toLowerCase(name.charAt(nextStarIndex - 1)); if (control == 'h') { h = num; } else if (control == 'v') { v = num; } else if (control == 's') { if (this.getAutosize()) { this.scale(h * 160.0F / v / this.getScaleX(), 1.0F, 160.0F / this.getScaleZ()); } if (isMov) { this.loadMultipart(this.movieName, name.substring(0, nextStarIndex - 2), num, "s*" + h + "h*" + v + "v*.mov"); } else { this.loadMultipart(this.movieName, name.substring(0, nextStarIndex - 2), num, name.substring(nextStarIndex + 1)); } return; } } this.isLoading++; BackgroundLoader.get(this, this.movieName); } @Override public Object asyncBackgroundLoad(String localName, URL remoteName) { if (localName != null) { if (localName.toLowerCase().endsWith(".mov")) { return new ScapePicMovie(localName, remoteName).getTextures(); } Texture[] texs = new Texture[]{TextureDecoder.decode(remoteName, localName)}; if (texs[0] != null && texs[0].textureID != 0) { return texs; } } return null; } @Override public boolean syncBackgroundLoad(Object obj, URL remoteURL) { this.releaseMaterials(); if (obj != null) { this.images = (Texture[])obj; if (this.getAutosize()) { this.scale(this.images[0].getW() / this.getScaleX(), 1.0F, this.images[0].getH() / this.getScaleZ()); } } else { if (this.movieName != null) { Console.println(Console.message("No-load-hologram") + this.movieName); } this.images = null; this.setMaterial(null); } if (this.callback != null) { this.callback.holoCallback(this, this.images != null || this.materials != null); this.callback = null; } this.isLoading--; return false; } @Override public Room getBackgroundLoadRoom() { return this.getRoom(); } @Override public BoundBoxTemp getBoundBox() { Point3Temp center = this.getWorldPosition(); Point3Temp jog = Point3Temp.make(this.getW() / 2.0F, this.getW() / 2.0F, this.getH() / 2.0F); return BoundBoxTemp.make(Point3Temp.make(center).minus(jog), Point3Temp.make(center).plus(jog)); } @Override public float getMinXYExtent() { return this.getW(); } public float getW() { return this.getScaleX(); } public float getH() { return this.getScaleZ(); } public int getNumSides() { if (this.images == null) { return this.materials == null ? 1 : this.materials.length; } else { return this.images.length; } } void setActiveSide(int side) { if (side >= this.getNumSides()) { System.out.println("Error at NET.worlds.Hologram.setActiveSide side " + side + " of " + this.getNumSides()); side = 0; } if (this.materials == null) { Texture t = this.images == null ? null : (side < this.images.length ? this.images[side] : null); if (t != null) { t.incRef(); } this.material.setTexture(t); } else if (this.materials[side] != this.material) { this.setMaterial(this.materials[side]); } } public URL getMovieName() { return this.movieName == null && this.fromMovie != null ? this.fromMovie.getURL() : this.movieName; } @Override protected void addRwChildren(WObject container) { this.addNewRwChild(container); if (this.images == null && this.materials == null && this.movieName != null && this.isLoading == 0) { this.forceLoad(); } this.addVertex(0.5F, 0.0F, -0.5F, 0.0F, 1.0F); this.addVertex(-0.5F, 0.0F, -0.5F, 1.0F, 1.0F); this.addVertex(-0.5F, 0.0F, 0.5F, 1.0F, 0.0F); this.addVertex(0.5F, 0.0F, 0.5F, 0.0F, 0.0F); this.doneWithEditing(); if (!this.isReclumping()) { this.lockMaterials(true); this.getRoom().addPrerenderHandler(this); this.getRoom().addPostrenderHandler(this); } if (this.images == null && this.materials == null && this.isLoading > 0) { this.makeTemporarilyInvisible(); } } public native void makeTemporarilyInvisible(); @Override protected void markVoid() { if (!this.isReclumping()) { this.lockMaterials(false); this.getRoom().removePrerenderHandler(this); this.getRoom().removePostrenderHandler(this); } if (this.movieName != null && this.fromMovie == null && this.isLoading == 0) { Main.register(this); } super.markVoid(); } @Override public void mainCallback() { if (!this.hasClump()) { if (this.images != null) { int i = this.images.length; while (--i >= 0) { if (this.images[i] != null) { this.images[i].decRef(); } } this.images = null; } this.releaseMaterials(); } Main.unregister(this); } @Override public native void prerender(Camera var1); @Override public native void postrender(Camera var1); @Override public void saveState(Saver s) throws IOException { s.saveVersion(6, classCookie); s.saveFloat(this.scaleDist); Material origMaterial = this.getMaterial(); URL name = this.getMovieName(); if (name != null) { this.setMaterial(null); } super.saveState(s); this.setMaterial(origMaterial); URL.save(s, name); if (name == null) { if (this.fromMovie != null) { s.saveBoolean(true); s.save(this.fromMovie); } else { s.saveBoolean(false); if (this.images != null) { s.saveBoolean(true); s.saveArray(this.images); } else { assert this.materials == null; s.saveBoolean(false); } } } } private static Texture[] extractTextureArray(Material[] mats) { Texture[] texs = new Texture[mats.length]; for (int i = 0; i < mats.length; i++) { texs[i] = mats[i].extractTexture(0); } return texs; } @Override public void restoreState(Restorer r) throws IOException, TooNewException { int vers = r.restoreVersion(classCookie); switch (vers) { case 0: super.restoreState(r); float w = r.restoreFloat(); if (w == 0.0F) { w = 100.0F; } float h = r.restoreFloat(); if (h == 0.0F) { h = 100.0F; } this.scale(w, 1.0F, h); if (r.restoreBoolean()) { this.fromMovie = (ScapePicMovie)r.restore(); this.images = this.fromMovie.getTextures(); } else { this.setAutosize(true); } break; case 1: super.restoreState(r); float wx = r.restoreFloat(); if (wx == 0.0F) { wx = 100.0F; } float hx = r.restoreFloat(); if (hx == 0.0F) { hx = 100.0F; } this.scale(wx, 1.0F, hx); if ((this.movieName = URL.restore(r)) != null) { this.load(this.movieName, null); } else if (r.restoreBoolean()) { this.fromMovie = (ScapePicMovie)r.restore(); this.images = this.fromMovie.getTextures(); } else { this.setAutosize(true); } break; case 2: super.restoreState(r); if ((this.movieName = URL.restore(r)) != null) { this.load(this.movieName, null); } else if (r.restoreBoolean()) { this.fromMovie = (ScapePicMovie)r.restore(); this.images = this.fromMovie.getTextures(); } else { this.setAutosize(true); } break; case 3: super.restoreState(r); if ((this.movieName = URL.restore(r)) != null) { this.load(this.movieName, null); } else if (r.restoreBoolean()) { this.fromMovie = (ScapePicMovie)r.restore(); this.images = this.fromMovie.getTextures(); } else { this.setAutosize(true); if (r.restoreBoolean()) { this.images = extractTextureArray((Material[])r.restoreArray()); } } break; case 5: case 6: this.scaleDist = r.restoreFloat(); case 4: super.restoreState(r); if ((this.movieName = URL.restore(r)) != null) { this.load(this.movieName, null); } else if (r.restoreBoolean()) { this.fromMovie = (ScapePicMovie)r.restore(); this.images = this.fromMovie.getTextures(); } else { if (vers < 6) { this.setAutosize(true); } if (r.restoreBoolean()) { this.images = (Texture[])r.restoreArray(); } } break; default: throw new TooNewException(); } } public Hologram setRoughCut(boolean b) { if (b) { this.flags |= 4; } else { this.flags &= -5; } return this; } public final boolean getRoughCut() { return (this.flags & 4) != 0; } public void setAutosize(boolean b) { if (b) { this.flags |= 4194304; } else { this.flags &= -4194305; } } public final boolean getAutosize() { return (this.flags & 4194304) != 0; } public Hologram setViewplaneAligned(boolean b) { if (b) { this.flags |= 262144; } else { this.flags &= -262145; } return this; } public final boolean getViewplaneAligned() { return (this.flags & 262144) != 0; } @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 = URLPropertyEditor.make(new Property(this, index, "File"), TextureDecoder.getAllExts()); } else if (mode == 1) { ret = this.getMovieName(); } else if (mode == 2) { this.load((URL)value, null); } break; case 1: if (mode == 0) { ret = BooleanPropertyEditor.make(new Property(this, index, "Viewplane Aligned"), "No", "Yes"); } else if (mode == 1) { ret = new Boolean(this.getViewplaneAligned()); } else if (mode == 2) { this.setViewplaneAligned((Boolean)value); } break; case 2: if (mode == 0) { ret = BooleanPropertyEditor.make(new Property(this, index, "Rough Cut Alignment"), "No", "Yes"); } else if (mode == 1) { ret = new Boolean(this.getRoughCut()); } else if (mode == 2) { this.setRoughCut((Boolean)value); } break; case 3: if (mode == 0) { ret = FloatPropertyEditor.make(new Property(this, index, "Scale Distance")); } else if (mode == 1) { ret = new Float(this.getScaleDist()); } else if (mode == 2) { this.setScaleDist((Float)value); } break; case 4: if (mode == 0) { ret = Point2PropertyEditor.make(new Property(this, index, "Extent")); } else if (mode == 1) { ret = new Point2(this.getScaleX(), this.getScaleZ()); } else if (mode == 2) { this.setAutosize(false); this.scale(((Point2)value).x / this.getScaleX(), 1.0F, ((Point2)value).y / this.getScaleZ()); } break; case 5: if (mode == 0) { ret = BooleanPropertyEditor.make(new Property(this, index, "Autosize"), "No", "Yes"); } else if (mode == 1) { ret = new Boolean(this.getAutosize()); } else if (mode == 2) { this.setAutosize((Boolean)value); } break; default: ret = super.properties(index, offset + 6, mode, value); } return ret; } @Override public String toString() { URL name = this.getMovieName(); return super.toString() + "[" + (name != null ? name.toString() : "") + "]"; } public void setScaleDist(float dist) { this.scaleDist = dist; } public final float getScaleDist() { return this.scaleDist; } }