diff --git a/src/java/com/threerings/jme/model/Translator.java b/src/java/com/threerings/jme/model/Translator.java new file mode 100644 index 00000000..94f22fb5 --- /dev/null +++ b/src/java/com/threerings/jme/model/Translator.java @@ -0,0 +1,134 @@ +// +// $Id: Rotator.java 132 2007-01-31 22:05:46Z andrzej $ +// +// Narya library - tools for developing networked games +// Copyright (C) 2002-2005 Three Rings Design, Inc., All Rights Reserved +// http://www.threerings.net/code/narya/ +// +// This library is free software; you can redistribute it and/or modify it +// under the terms of the GNU Lesser General Public License as published +// by the Free Software Foundation; either version 2.1 of the License, or +// (at your option) any later version. +// +// This library 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 +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +package com.threerings.jme.model; + +import java.io.IOException; + +import java.util.Properties; + +import com.jme.math.Quaternion; +import com.jme.math.Vector3f; +import com.jme.scene.Controller; +import com.jme.scene.Spatial; +import com.jme.util.export.JMEExporter; +import com.jme.util.export.JMEImporter; +import com.jme.util.export.InputCapsule; +import com.jme.util.export.OutputCapsule; + +import com.samskivert.util.StringUtil; + +import com.threerings.jme.Log; +import com.threerings.jme.util.JmeUtil; + +/** + * A procedural animation that moves a node along a straight line at a constant velocity (then + * either repeats or moves it in the other direction). + */ +public class Translator extends ModelController +{ + @Override // documentation inherited + public void configure (Properties props, Spatial target) + { + super.configure(props, target); + _from = JmeUtil.parseVector3f(props.getProperty("from", "0, 0, 0")); + _to = JmeUtil.parseVector3f(props.getProperty("to", "10, 0, 0")); + _duration = Float.parseFloat(props.getProperty("duration", "1")); + _repeatType = JmeUtil.parseRepeatType(props.getProperty("repeat_type"), + Controller.RT_WRAP); + } + + // documentation inherited + public void update (float time) + { + if (!isActive()) { + return; + } + _elapsed += (time / _duration); + float alpha; + if (_repeatType == Controller.RT_CLAMP) { + alpha = Math.min(_elapsed, 1f); + } else if (_repeatType == Controller.RT_WRAP) { + alpha = (_elapsed - (int)_elapsed); + } else { // _repeatType == Controller.RT_CYCLE + int ipart = (int)_elapsed; + float fpart = (_elapsed - ipart); + alpha = (ipart % 2 == 0) ? fpart : (1f - fpart); + } + _target.getLocalTranslation().interpolate(_from, _to, alpha); + } + + @Override // documentation inherited + public Controller putClone ( + Controller store, Model.CloneCreator properties) + { + Translator tstore; + if (store == null) { + tstore = new Translator(); + } else { + tstore = (Translator)store; + } + super.putClone(tstore, properties); + tstore._from = _from; + tstore._to = _to; + tstore._duration = _duration; + tstore._repeatType = _repeatType; + return tstore; + } + + @Override // documentation inherited + public void read (JMEImporter im) + throws IOException + { + super.read(im); + InputCapsule capsule = im.getCapsule(this); + _from = (Vector3f)capsule.readSavable("from", null); + _to = (Vector3f)capsule.readSavable("to", null); + _duration = capsule.readFloat("duration", 1f); + _repeatType = capsule.readInt("repeatType", Controller.RT_WRAP); + } + + @Override // documentation inherited + public void write (JMEExporter ex) + throws IOException + { + super.write(ex); + OutputCapsule capsule = ex.getCapsule(this); + capsule.write(_from, "from", null); + capsule.write(_to, "to", null); + capsule.write(_duration, "duration", 1f); + capsule.write(_repeatType, "repeatType", Controller.RT_WRAP); + } + + /** The beginning and end of the path. */ + protected Vector3f _from, _to; + + /** The duration of the path. */ + protected float _duration; + + /** What to do after reaching the destination. */ + protected int _repeatType; + + /** The accumulated amount of time elapsed. */ + protected transient float _elapsed; + + private static final long serialVersionUID = 1; +} diff --git a/src/java/com/threerings/jme/util/JmeUtil.java b/src/java/com/threerings/jme/util/JmeUtil.java index 51503f34..9dfdbc56 100644 --- a/src/java/com/threerings/jme/util/JmeUtil.java +++ b/src/java/com/threerings/jme/util/JmeUtil.java @@ -88,25 +88,38 @@ public class JmeUtil */ public static Vector3f parseAxis (String axis) { - if (axis == null) { - return null; - } - if (axis.equalsIgnoreCase("x")) { + if ("x".equalsIgnoreCase(axis)) { return Vector3f.UNIT_X; - } else if (axis.equalsIgnoreCase("y")) { + } else if ("y".equalsIgnoreCase(axis)) { return Vector3f.UNIT_Y; - } else if (axis.equalsIgnoreCase("z")) { + } else if ("z".equalsIgnoreCase(axis)) { return Vector3f.UNIT_Z; - } - float[] vals = StringUtil.parseFloatArray(axis); - if (vals != null && vals.length == 3) { - return new Vector3f(vals[0], vals[1], vals[2]).normalizeLocal(); } else { - Log.warning("Invalid axis [axis=" + axis + "]."); - return null; + Vector3f vector = parseVector3f(axis); + if (vector != null) { + vector.normalizeLocal(); + } + return vector; } } + /** + * Attempts to parse a string containing three comma-delimited values and return a + * {@link Vector3f}. + */ + public static Vector3f parseVector3f (String vector) + { + if (vector != null) { + float[] vals = StringUtil.parseFloatArray(vector); + if (vals != null && vals.length == 3) { + return new Vector3f(vals[0], vals[1], vals[2]); + } else { + Log.warning("Invalid vector [vector=" + vector + "]."); + } + } + return null; + } + /** * Attempts to parse a string describing one of the repeat types defined in {@link Controller}: * "clamp", "cycle", or "wrap". Will return the specified default if the type is