diff options
| author | Fuwn <[email protected]> | 2026-02-12 22:33:32 -0800 |
|---|---|---|
| committer | Fuwn <[email protected]> | 2026-02-12 22:33:32 -0800 |
| commit | c7a9d4a6bd53ed7d61731770f2f10e8b9fd435f9 (patch) | |
| tree | df9f48bf128a6c0186a8e91857d6ff30fe0e9f18 /NET/worlds/scape/Hologram.java | |
| download | worldsplayer-c7a9d4a6bd53ed7d61731770f2f10e8b9fd435f9.tar.xz worldsplayer-c7a9d4a6bd53ed7d61731770f2f10e8b9fd435f9.zip | |
Initial commit
Diffstat (limited to 'NET/worlds/scape/Hologram.java')
| -rw-r--r-- | NET/worlds/scape/Hologram.java | 568 |
1 files changed, 568 insertions, 0 deletions
diff --git a/NET/worlds/scape/Hologram.java b/NET/worlds/scape/Hologram.java new file mode 100644 index 0000000..b138ac2 --- /dev/null +++ b/NET/worlds/scape/Hologram.java @@ -0,0 +1,568 @@ +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; + } +} |