diff options
Diffstat (limited to 'src/javax/media/j3d/LinkRetained.java')
-rw-r--r-- | src/javax/media/j3d/LinkRetained.java | 353 |
1 files changed, 353 insertions, 0 deletions
diff --git a/src/javax/media/j3d/LinkRetained.java b/src/javax/media/j3d/LinkRetained.java new file mode 100644 index 0000000..4ad5ddf --- /dev/null +++ b/src/javax/media/j3d/LinkRetained.java @@ -0,0 +1,353 @@ +/* + * Copyright 1997-2008 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code 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 + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + * + */ + +package javax.media.j3d; +import java.util.ArrayList; + +/** + * A Link leaf node consisting of a reference to a SharedGroup node. + */ + +class LinkRetained extends LeafRetained { + /** + * The SharedGroup component of the link node. + */ + SharedGroupRetained sharedGroup; + + static String plus = "+"; + + // This is used when setLive to check for cycle scene graph + boolean visited = false; + + LinkRetained() { + this.nodeType = NodeRetained.LINK; + localBounds = new BoundingBox((Bounds)null); + } + + /** + * Sets the SharedGroup reference. + * @param sharedGroup the SharedGroup node + */ + void setSharedGroup(SharedGroup sharedGroup) { + // Note that it is possible that the sharedGroup pass + // in already link to another link and live. + HashKey newKeys[] = null; + boolean abort = false; + + if (source.isLive()) { + // bug 4370407: if sharedGroup is a parent, then don't do anything + if (sharedGroup != null) { + synchronized(universe.sceneGraphLock) { + NodeRetained pa; + for (pa = parent; pa != null; pa = pa.parent) { + if (pa == (NodeRetained)sharedGroup.retained) { + abort = true; + throw new SceneGraphCycleException(J3dI18N.getString("LinkRetained1")); + } + } + } + if (abort) + return; + } + + newKeys = getNewKeys(locale.nodeId, localToVworldKeys); + + if (this.sharedGroup != null) { + ((GroupRetained) parent).checkClearLive(this.sharedGroup, + newKeys, true, null, + 0, 0, this); + this.sharedGroup.parents.remove(this); + } + } + + if (sharedGroup != null) { + this.sharedGroup = + (SharedGroupRetained)sharedGroup.retained; + } else { + this.sharedGroup = null; + } + + if (source.isLive() && (sharedGroup != null)) { + + this.sharedGroup.parents.add(this); + visited = true; + try { + int ci = ((GroupRetained) parent).indexOfChild((Node)this.sharedGroup.source); + ((GroupRetained) parent).checkSetLive(this.sharedGroup, ci, + newKeys, true, null, + 0, this); + } catch (SceneGraphCycleException e) { + throw e; + } finally { + visited = false; + } + } + + } + + /** + * Retrieves the SharedGroup reference. + * @return the SharedGroup node + */ + SharedGroup getSharedGroup() { + return (sharedGroup != null ? + (SharedGroup)this.sharedGroup.source : null); + } + + @Override + void computeCombineBounds(Bounds bounds) { + + if (boundsAutoCompute) { + sharedGroup.computeCombineBounds(bounds); + } else { + // Should this be lock too ? ( MT safe ? ) + synchronized(localBounds) { + bounds.combine(localBounds); + } + } + } + + + /** + * Gets the bounding object of a node. + * @return the node's bounding object + */ + @Override + Bounds getBounds() { + return (boundsAutoCompute ? + (Bounds)sharedGroup.getBounds().clone() : + super.getBounds()); + } + + + /** + * assign a name to this node when it is made live. + */ + @Override + void setLive(SetLiveState s) { + + super.doSetLive(s); + + if (inBackgroundGroup) { + throw new + IllegalSceneGraphException(J3dI18N.getString("LinkRetained0")); + } + + if (nodeId == null) { + nodeId = universe.getNodeId(); + } + + if (sharedGroup != null) { + this.sharedGroup.parents.add(this); + HashKey newKeys[] = getNewKeys(s.locale.nodeId, s.keys); + HashKey oldKeys[] = s.keys; + s.keys = newKeys; + s.inSharedGroup = true; + if (visited) { + throw new SceneGraphCycleException(J3dI18N.getString("LinkRetained1")); + } + visited = true; + try { + this.sharedGroup.setLive(s); + } catch (SceneGraphCycleException e) { + throw e; + } finally { + visited = false; + } + + s.inSharedGroup = inSharedGroup; + s.keys = oldKeys; + + localBounds.setWithLock(this.sharedGroup.localBounds); + } + + super.markAsLive(); + } + + @Override + void setNodeData(SetLiveState s) { + + super.setNodeData(s); + + // add this node to parentTransformLink's childTransformLink + if (s.childTransformLinks != null) { + // do not duplicate shared nodes + synchronized(s.childTransformLinks) { + if(!inSharedGroup || !s.childTransformLinks.contains(this)) { + s.childTransformLinks.add(this); + } + } + } + + // add this node to parentSwitchLink's childSwitchLink + if (s.childSwitchLinks != null) { + if(!inSharedGroup || + // only add if not already added in sharedGroup + !s.childSwitchLinks.contains(this)) { + s.childSwitchLinks.add(this); + } + } + } + + + @Override + void recombineAbove() { + localBounds.setWithLock(sharedGroup.localBounds); + parent.recombineAbove(); + } + + /** + * assign a name to this node when it is made live. + */ + @Override + void clearLive(SetLiveState s) { + + if (sharedGroup != null) { + HashKey newKeys[] = getNewKeys(s.locale.nodeId, s.keys); + super.clearLive(s); + HashKey oldKeys[] = s.keys; + s.keys = newKeys; + s.inSharedGroup = true; + this.sharedGroup.parents.remove(this); + this.sharedGroup.clearLive(s); + s.inSharedGroup = inSharedGroup; + s.keys = oldKeys; + } else { + super.clearLive(s); + } + } + + @Override + void removeNodeData(SetLiveState s) { + if(refCount <= 0) { + // either not in sharedGroup or last instance in sharedGroup + // remove this node from parentTransformLink's childTransformLink + if (parentTransformLink != null) { + ArrayList<NodeRetained> obj; + if (parentTransformLink instanceof TransformGroupRetained) { + obj = ((TransformGroupRetained) + parentTransformLink).childTransformLinks; + } else { + obj = ((SharedGroupRetained) + parentTransformLink).childTransformLinks; + } + synchronized(obj) { + obj.remove(this); + } + } + + // remove this node from parentSwitchLink's childSwitchLink + if (parentSwitchLink != null) { + for(int i=0; i<parentSwitchLink.childrenSwitchLinks.size();i++){ + ArrayList<NodeRetained> switchLinks = parentSwitchLink.childrenSwitchLinks.get(i); + if (switchLinks.contains(this)) { + switchLinks.remove(this); + break; + } + } + } + } + super.removeNodeData(s); + } + + + @Override + void updatePickable(HashKey keys[], boolean pick[]) { + super.updatePickable(keys, pick); + + if (sharedGroup != null) { + HashKey newKeys[] = getNewKeys(locale.nodeId, keys); + sharedGroup.updatePickable(newKeys, pick); + } + } + + @Override + void updateCollidable(HashKey keys[], boolean collide[]) { + super.updateCollidable(keys, collide); + + if (sharedGroup != null) { + HashKey newKeys[] = getNewKeys(locale.nodeId, keys); + sharedGroup.updateCollidable(newKeys, collide); + } + } + + @Override + void setBoundsAutoCompute(boolean autoCompute) { + super.setBoundsAutoCompute(autoCompute); + if (!autoCompute) { + localBounds = getBounds(); + } + } + + @Override + void setCompiled() { + super.setCompiled(); + if (sharedGroup != null) { + sharedGroup.setCompiled(); + } + } + + @Override + void compile(CompileState compState) { + + super.compile(compState); + + // XXXX: for now keep the static transform in the parent tg + compState.keepTG = true; + + // don't remove this group node + mergeFlag = SceneGraphObjectRetained.DONT_MERGE; + + if (J3dDebug.devPhase && J3dDebug.debug) { + compState.numLinks++; + } + } + + HashKey[] getNewKeys(String localeNodeId, HashKey oldKeys[]) { + HashKey newKeys[]; + + if (!inSharedGroup) { + newKeys = new HashKey[1]; + newKeys[0] = new HashKey(localeNodeId); + newKeys[0].append(plus + nodeId); + } else { + // Need to append this link node id to all keys passed in. + newKeys = new HashKey[oldKeys.length]; + for (int i=oldKeys.length-1; i>=0; i--) { + newKeys[i] = new HashKey(oldKeys[i].toString() + + plus + nodeId); + } + } + return newKeys; + } + + @Override + void searchGeometryAtoms(UnorderList list) { + if (sharedGroup != null) { + sharedGroup.searchGeometryAtoms(list); + } + } +} |