/* ========================
* JSynoptic : a free Synoptic editor
* ========================
*
* Project Info: http://jsynoptic.sourceforge.net/index.html
*
* This program 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 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 Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License along with this
* program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330,
* Boston, MA 02111-1307, USA.
*
* (C) Copyright 2001-2007, by :
* Corporate:
* EADS Astrium
* Individual:
* Claude Cazenave
*
* $Id: Animator.java,v 1.8 2008/11/14 17:03:14 cazenave Exp $
*
* Changes
* -------
* 19 janv. 08 : Initial public release
*
*/
package jsynoptic.plugins.java3d;
import java.io.DataInput;
import java.io.DataOutput;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import javax.media.j3d.Group;
import javax.media.j3d.Node;
import javax.media.j3d.RestrictedAccessException;
import javax.media.j3d.SceneGraphObject;
import com.sun.j3d.utils.scenegraph.io.SceneGraphStateProvider;
import com.sun.j3d.utils.scenegraph.io.retained.Controller;
import com.sun.j3d.utils.scenegraph.io.retained.SymbolTableData;
import com.sun.j3d.utils.scenegraph.io.state.javax.media.j3d.SceneGraphObjectState;
/**
*
*/
public abstract class Animator extends Group implements
SceneGraphStateProvider {
protected ArrayList<GraphObjectReference> _references;
protected HashMap<SceneGraphObject, ArrayList<Integer>> _oldCapabilities;
public Animator() {
super();
_references = new ArrayList<GraphObjectReference>();
_oldCapabilities = new HashMap<SceneGraphObject, ArrayList<Integer>>();
}
@Override
public void addChild(Node child) {
throw new RestrictedAccessException("Can not add a node to an animator (but a reference to a node)");
}
@Override
public Node cloneNode(boolean forceDuplicate) {
throw new RestrictedAccessException("Can not clone animator");
}
public boolean isCompatibleWith(Animator an){
return an.getClass().equals(getClass());
}
public SceneGraphObject getCapableObject(SceneGraphObject o){
return o;
}
@Override
public Class<? extends SceneGraphObjectState> getStateClass() {
return State.class;
}
public static class State extends SceneGraphObjectState {
int[][] _caps;
GraphObjectReference.State[] _states; // to read reference states and
// then use build the graph
public State(SymbolTableData symbol, Controller control) {
super(symbol, control);
}
public void writeObject(DataOutput out) throws IOException {
super.writeObject(out);
Animator an = (Animator) node;
out.writeInt(an._references.size());
for (GraphObjectReference gor : an._references) {
control.writeObject(out, control.createState(gor));
ArrayList<Integer> caps = an._oldCapabilities.get(gor
.getObject());
int ncap = (caps == null) ? 0 : caps.size();
out.writeInt(ncap);
for (int i = 0; i < ncap; i++) {
out.writeInt(caps.get(i));
}
}
}
public void readObject(DataInput in) throws IOException {
super.readObject(in);
Animator an = (Animator) node;
int nref = in.readInt();
_caps = new int[nref][];
_states = new GraphObjectReference.State[nref];
for (int i = 0; i < nref; i++) {
_states[i] = (GraphObjectReference.State) control
.readObject(in);
GraphObjectReference gor = (GraphObjectReference) _states[i]
.getNode();
an._references.add(gor);
int ncap = in.readInt();
_caps[i] = new int[ncap];
for (int j = 0; j < ncap; j++) {
_caps[i][j] = in.readInt();
}
}
}
/*
* (non-Javadoc)
*
* @see com.sun.j3d.utils.scenegraph.io.state.javax.media.j3d.SceneGraphObjectState#buildGraph()
*/
@Override
public void buildGraph() {
Animator an = (Animator) node;
for (GraphObjectReference.State gors : _states) {
gors.buildGraph();
}
for (int i = 0; i < _caps.length; i++) {
int[] caps = _caps[i];
ArrayList<Integer> al = new ArrayList<Integer>();
for (int j = 0; j < caps.length; j++)
al.add(caps[j]);
an._oldCapabilities.put(an._references.get(i).getObject(), al);
}
super.buildGraph(); // Must be last call in method
}
@Override
public void cleanup() {
for (int i = 0; i < _states.length; i++) {
_states[i].cleanup();
_states[i] = null;
}
_states = null;
for (int i = 0; i < _caps.length; i++) {
_caps[i] = null;
}
_caps = null;
}
}
/**
* Add a graph object to apply these data changes on
*/
public void addGraphObject(SceneGraphObject obj, Node owner, AttachDetach ad) {
int[] cap = getCapabilities();
boolean capChange = false;
ArrayList<Integer> olds = new ArrayList<Integer>();
SceneGraphObject co=getCapableObject(obj);
for (int i : cap) {
if (!co.getCapability(i)) {
// there is need to change
capChange = true;
olds.add(new Integer(i));
}
}
if (capChange) {
boolean detached=false;
if (ad != null && ad.getNode().isLive()) {
ad.detach();
detached=true;
}
for (int i : cap) {
co.setCapability(i);
}
if (detached) {
ad.attach();
}
_oldCapabilities.put(co, olds);
}
GraphObjectReference gn = new GraphObjectReference(owner, obj);
_references.add(gn);
}
/**
* Remove a graph object to stop applying these data changes on
*/
public void removeGraphObject(GraphObjectReference gnr, AttachDetach ad) {
_references.remove(gnr);
SceneGraphObject co=getCapableObject(gnr.getObject());
ArrayList<Integer> olds = _oldCapabilities.get(co);
if (olds != null) {
boolean detached=false;
if (ad != null && ad.getNode().isLive()) {
ad.detach();
detached=true;
}
for (Integer i : olds) {
co.clearCapability(i);
}
if (detached) {
ad.attach();
}
_oldCapabilities.put(co, olds);
}
}
public GraphObjectReference get(SceneGraphObject o) {
for (GraphObjectReference gn : _references) {
if (gn.getObject() == o) {
return gn;
}
}
return null;
}
public ArrayList<GraphObjectReference> getGraphObjects() {
return _references;
}
protected abstract int[] getCapabilities();
}