/* * Copyright (C) 2014 James Lawrence. * * This file is part of LibLab. * * LibLab is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. */ package com.sqrt.liblab.codec; import com.sqrt.liblab.entry.graphics.GrimBitmap; import com.sqrt.liblab.entry.model.ColorMap; import com.sqrt.liblab.entry.model.set.Light; import com.sqrt.liblab.entry.model.set.Sector; import com.sqrt.liblab.entry.model.set.Set; import com.sqrt.liblab.entry.model.set.Setup; import com.sqrt.liblab.io.DataSource; import com.sqrt.liblab.io.TextParser; import com.sqrt.liblab.threed.Vector3f; import java.awt.*; import java.io.IOException; import java.util.ArrayList; import java.util.List; /** * Created by James on 30/09/2014. */ public class SetCodec extends EntryCodec<Set>{ @Override protected Set _read(DataSource source) throws IOException { String s = source.getString(7); source.position(0); if(s.equalsIgnoreCase("section")) return loadText(source); return loadBinary(source); } private Set loadBinary(DataSource source) { // This doesn't seem to be in my version of GRIM so I can't test or develop System.err.println("Todo: binary loading of SETS"); return null; } private Set loadText(DataSource source) throws IOException { Set set = new Set(source.container, source.getName()); TextParser t = new TextParser(source); t.expectString("section: colormaps"); t.skipWhitespace(); t.expectString("numcolormaps"); int n = t.readInt(); set.colorMaps = new ColorMap[n]; for(int i = 0; i < n; i++) { t.skipWhitespace(); t.expectString("colormap"); String name = t.readString(); set.colorMaps[i] = (ColorMap) source.container.container.findByName(name); } if(t.checkString("section: objectstates") || t.checkString("section: object_states")) { t.nextLine(); t.skipWhitespace(); t.expectString("tot_objects"); n = t.readInt(); for(int i = 0; i < n; i++) { t.skipWhitespace(); t.expectString("object"); String name = t.readString(); System.out.println("Object: " + name); } } t.skipWhitespace(); t.expectString("section: setups"); t.skipWhitespace(); t.expectString("numsetups"); n = t.readInt(); set.setups = new Setup[n]; for(int i = 0; i < n; i++) { Setup s = set.setups[i] = new Setup(); t.skipWhitespace(); t.expectString("setup"); s.name = t.readString(); t.skipWhitespace(); t.expectString("background"); s.background = (GrimBitmap) source.container.container.findByName(t.readString()); if(t.checkString("zbuffer")) { t.skipWhitespace(); t.expectString("zbuffer"); s.zBackground = (GrimBitmap) source.container.container.findByName(t.readString()); } t.skipWhitespace(); t.expectString("position"); s.position = t.readVector3(); t.skipWhitespace(); t.expectString("interest"); s.interest = t.readVector3(); t.skipWhitespace(); t.expectString("roll"); s.roll = t.readAngle(); t.skipWhitespace(); t.expectString("fov"); s.fov = t.readAngle(); t.skipWhitespace(); t.expectString("nclip"); s.nclip = t.readFloat(); t.skipWhitespace(); t.expectString("fclip"); s.fclip = t.readFloat(); while(true) { if(!t.checkString("object_art")) break; t.skipWhitespace(); t.expectString("object_art"); t.skipWhitespace(); String objName = t.readString(); String bm = t.readString(); System.out.println("Obj: " + objName + ", " + bm); if(t.checkString("object_z")) { t.skipWhitespace(); t.expectString("object_z"); String zObjName = t.readString(); String zBm = t.readString(); System.out.println("ZObj: " + zObjName + ", " + zBm); } // Todo: add object state (as in https://github.com/residualvm/residualvm/blob/e6aae9206f5bef6d7f49d3f28c2bb5e0886947b5/engines/grim/set.cpp#L364) } } if(!t.checkString("section: lights")) return set; t.skipWhitespace(); t.expectString("section: lights"); t.skipWhitespace(); t.expectString("numlights"); n = t.readInt(); set.lights = new Light[n]; for(int i = 0; i < n; i++) { Light l = set.lights[i] = new Light(); t.skipWhitespace(); t.expectString("light"); if(!t.checkString("light")) l.name = ""; else l.name = t.readString(); t.skipWhitespace(); t.expectString("type"); l.type = t.readString(); t.skipWhitespace(); t.expectString("position"); l.position = t.readVector3(); t.skipWhitespace(); t.expectString("direction"); l.direction = t.readVector3(); t.skipWhitespace(); t.expectString("intensity"); l.intensity = t.readFloat(); t.skipWhitespace(); t.expectString("umbraangle"); l.umbra = t.readAngle(); t.skipWhitespace(); t.expectString("penumbraangle"); l.penumbra = t.readAngle(); t.skipWhitespace(); t.expectString("color"); Vector3f cv = t.readVector3(); l.color = new Color((int) cv.x, (int) cv.y, (int) cv.z); } // Todo: sectors t.skipWhitespace(); t.expectString("section: sectors"); if(t.eof()) return set; t.skipWhitespace(); if(t.checkString("numsectors")) // inv_naut.set in DATA003.LAB seems to have this t.nextLine(); List<Sector> sectors = new ArrayList<>(); while(!t.eof()) { Sector sector = new Sector(); sectors.add(sector); t.skipWhitespace(); t.expectString("sector"); if(!t.checkString("sector")) sector.name = ""; else sector.name = t.readString(); t.skipWhitespace(); t.expectString("id"); sector.id = t.readInt(); t.skipWhitespace(); t.expectString("type"); sector.type = t.readString(); t.skipWhitespace(); t.expectString("default visibility"); sector.defaultVisibility = t.readString().equals("visible"); t.skipWhitespace(); if(!t.checkString("numvertices")) { // inv_naut.set in DATA003.LAB seems to have this t.expectString("height"); sector.height = t.readFloat(); } t.skipWhitespace(); t.expectString("numvertices"); n = t.readInt(); t.skipWhitespace(); t.expectString("vertices:"); t.skipWhitespace(); Vector3f[] vertices = sector.vertices = new Vector3f[n+1]; for(int i = 0; i < n; i++) vertices[i] = t.readVector3(); // Residual repeats the last vertex so it loops vertices[n] = vertices[0]; sector.normal = vertices[1].sub(vertices[0]).cross(vertices[n-1].sub(vertices[0])); float length = sector.normal.length(); if(length > 0) sector.normal = sector.normal.div(length); if(t.checkString("numgates")) { // inv_naut.set in DATA003.LAB seems to have this t.skipWhitespace(); t.expectString("numgates"); n = t.readInt(); t.expectString("gates:"); } } set.sectors = sectors.toArray(new Sector[sectors.size()]); return set; } @Override public DataSource write(Set source) throws IOException { return null; // Todo: } @Override public String[] getFileExtensions() { return new String[] {"set"}; } @Override public Class<Set> getEntryClass() { return Set.class; } }