/* * 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.model.anim.Animation; import com.sqrt.liblab.entry.model.anim.AnimationNode; import com.sqrt.liblab.entry.model.anim.KeyFrame; import com.sqrt.liblab.entry.model.anim.Marker; import com.sqrt.liblab.io.DataSource; import com.sqrt.liblab.io.TextParser; import java.io.IOException; public class AnimationCodec extends EntryCodec<Animation> { protected Animation _read(DataSource source) throws IOException { if (source.getIntLE() == (('K' << 24) | ('E' << 16) | ('Y' << 8) | 'F')) return loadBinary(source); else { source.position(0); return loadText(source); } } private Animation loadText(DataSource data) throws IOException { // Todo: this has some major bugs, not sure what the issue is yet TextParser source = new TextParser(data); source.expectString("section: header"); Animation anim = new Animation(data.container, data.getName()); anim.flags = source.expectString("flags").readHex(); anim.type = source.expectString("type").readHex(); anim.numFrames = source.expectString("frames").readInt(); float fps = source.expectString("fps").readFloat(); int numJoints = source.expectString("joints").readInt(); if(source.currentLine().equalsIgnoreCase("section: markers")) { source.nextLine(); int numMarkers = source.expectString("markers").readInt(); for(int i = 0; i < numMarkers; i++) { Marker m = new Marker(); anim.markers.add(m); m.frame = source.readFloat(); m.val = source.readInt(); } } source.expectString("section: keyframe nodes"); int numNodes = source.expectString("nodes").readInt(); // allocate for(int i = 0; i < numJoints; i++) anim.nodes.add(null); for(int i = 0; i < numNodes; i++) { int idx = source.expectString("node").readInt(); AnimationNode an = new AnimationNode(); anim.nodes.set(idx, an); source.expectString("mesh name ").skipWhitespace(); an.meshName = source.read(source.remainingChars()); int numEntries = source.expectString("entries").readInt(); for(int j = 0; j < numEntries; j++) an.entries.add(null); for(int j = 0; j < numEntries; j++) { idx = source.readInt(); KeyFrame kf = new KeyFrame(); an.entries.set(idx, kf); source.expectString(":").skipWhitespace(); // Get to the data... kf.frame = source.readFloat(); kf.flags = source.readHex(); kf.pos = source.readVector3(); kf.pitch = source.readAngle(); kf.yaw = source.readAngle(); kf.roll = source.readAngle(); kf.dpos = source.readVector3(); kf.dpitch = source.readAngle(); kf.dyaw = source.readAngle(); kf.droll = source.readAngle(); } } return anim; } private Animation loadBinary(DataSource source) throws IOException { Animation anim = new Animation(source.container, source.getName()); source.position(40); anim.flags = source.getIntLE(); source.skip(4); anim.type = source.getIntLE(); source.position(56); anim.numFrames = source.getIntLE(); int numJoints = source.getIntLE(); source.skip(4); int numMarkers = source.getIntLE(); source.position(72); for(int i = 0; i < numMarkers; i++) { Marker m = new Marker(); m.frame = source.getFloatLE(); anim.markers.add(m); } source.position(104); for(int i = 0; i < numMarkers; i++) anim.markers.get(i).val = source.getIntLE(); source.position(136); // allocate for(int i = 0; i < numJoints; i++) anim.nodes.add(null); for(int i = 0; i < numJoints; i++) { String meshName = source.getString(32); if(meshName.isEmpty()) meshName = "(null)"; int nodeNum = source.getIntLE(); if(nodeNum >= numJoints) { System.err.println("Invalid node number (" + nodeNum + "/" + numJoints + ")"); continue; } if(anim.nodes.get(nodeNum) != null) { source.skip(8); continue; } AnimationNode node = new AnimationNode(); node.meshName = meshName; int count = source.getIntLE(); source.skip(4); for(int j = 0; j < count; j++) { KeyFrame kfe = new KeyFrame(); kfe.frame = source.getFloatLE(); kfe.flags = source.getIntLE(); kfe.pos = source.getVector3f(); kfe.pitch = source.getAngle(); kfe.yaw = source.getAngle(); kfe.roll = source.getAngle(); kfe.dpos = source.getVector3f(); kfe.dpitch = source.getAngle(); kfe.dyaw = source.getAngle(); kfe.droll = source.getAngle(); node.entries.add(kfe); } anim.nodes.set(nodeNum, node); } return anim; } public DataSource write(Animation source) throws IOException { throw new UnsupportedOperationException(); // Todo } public String[] getFileExtensions() { return new String[]{"key"}; } public Class<Animation> getEntryClass() { return Animation.class; } }