📄 groupretained.java
字号:
/* * $RCSfile: GroupRetained.java,v $ * * Copyright (c) 2007 Sun Microsystems, Inc. All rights reserved. * * Use is subject to license terms. * * $Revision: 1.11 $ * $Date: 2007/06/05 00:11:37 $ * $State: Exp $ */package javax.media.j3d;import java.util.Vector;import java.util.Enumeration;import java.util.ArrayList;import java.util.Hashtable;/** * Group node. */class GroupRetained extends NodeRetained implements BHLeafInterface { /** * The Group Node's children vector. */ ArrayList children = new ArrayList(1); /** * The Group node's collision bounds in local coordinates. */ Bounds collisionBound = null; // The locale that this node is decended from Locale locale = null; // The list of lights that are scoped to this node // One such arraylist per path. If not in sharedGroup // then only index 0 is valid ArrayList lights = null; // The list of fogs that are scoped to this node // One such arraylist per path. If not in sharedGroup // then only index 0 is valid ArrayList fogs = null; // The list of model clips that are scoped to this node // One such arraylist per path. If not in sharedGroup // then only index 0 is valid ArrayList modelClips = null; // The list of alternateappearance that are scoped to this node // One such arraylist per path. If not in sharedGroup // then only index 0 is valid ArrayList altAppearances = null; // indicates whether this Group node can be the target of a collision boolean collisionTarget = false; // per child switchLinks ArrayList childrenSwitchLinks = null; // the immediate childIndex of a parentSwitchLink int parentSwitchLinkChildIndex = -1; // per shared path ordered path data ArrayList orderedPaths = null; /** * If collisionBound is set, this is equal to the * transformed collisionBounds, otherwise it is equal * to the transformed localBounds. * This variable is set to null unless collisionTarget = true. * This bound is only used by mirror Group. */ BoundingBox collisionVwcBounds; /** * Mirror group of this node, it is only used when * collisionTarget = true. Otherwise it is set to null. * If not in shared group, * only entry 0 is used. * */ ArrayList mirrorGroup; /** * key of mirror GroupRetained. */ HashKey key; /** * sourceNode of this mirror Group */ GroupRetained sourceNode; /** * The BHLeafNode for this GeometryAtom. */ BHLeafNode bhLeafNode = null; // // The following variables are used during compile // // true if this is the root of the scenegraph tree boolean isRoot = false; boolean allocatedLights = false; boolean allocatedFogs = false; boolean allocatedMclips = false; boolean allocatedAltApps = false; // > 0 if this group is being used in scoping int scopingRefCount = 0; ArrayList compiledChildrenList = null; boolean isInClearLive = false; // List of viewes scoped to this Group, for all subclasses // of group, except ViewSpecificGroup its a pointer to closest // ViewSpecificGroup parent // viewList for this node, if inSharedGroup is // false then only viewList(0) is valid // For VSGs, this list is an intersection of // higher level VSGs ArrayList viewLists = null; // True if this Node is descendent of ViewSpecificGroup; boolean inViewSpecificGroup = false; GroupRetained() { this.nodeType = NodeRetained.GROUP; localBounds = new BoundingSphere(); ((BoundingSphere)localBounds).setRadius( -1.0 ); } /** * Sets the collision bounds of a node. * @param bounds the bounding object for the node */ void setCollisionBounds(Bounds bounds) { if (bounds == null) { this.collisionBound = null; } else { this.collisionBound = (Bounds)bounds.clone(); } if (source.isLive()) { J3dMessage message = new J3dMessage(); message.type = J3dMessage.COLLISION_BOUND_CHANGED; message.threads = J3dThread.UPDATE_TRANSFORM | J3dThread.UPDATE_GEOMETRY; message.universe = universe; message.args[0] = this; VirtualUniverse.mc.processMessage(message); } } /** * Gets the collision bounds of a node. * @return the node's bounding object */ Bounds getCollisionBounds() { return (collisionBound == null ? null : (Bounds)collisionBound.clone()); } /** * Replaces the specified child with the child provided. * @param child the new child * @param index which child to replace */ void setChild(Node child, int index) { checkValidChild(child, "GroupRetained0"); if (this.source.isLive()) { universe.resetWaitMCFlag(); synchronized (universe.sceneGraphLock) { doSetChild(child, index); universe.setLiveState.clear(); } universe.waitForMC(); } else { doSetChild(child, index); if (universe != null) { synchronized (universe.sceneGraphLock) { universe.setLiveState.clear(); } } } dirtyBoundsCache(); } // The method that does the work once the lock is acquired. void doSetChild(Node child, int index) { NodeRetained oldchildr; J3dMessage[] messages = null; int numMessages = 0; int attachStartIndex = 0; // since we want to make sure the replacement of the child // including removal of the oldChild and insertion of the newChild // all happen in the same frame, we'll send all the necessary // messages to masterControl for processing in one call. // So let's first find out how many messages will be sent oldchildr = (NodeRetained) children.get(index); if (this.source.isLive()) { if (oldchildr != null) { numMessages+=3; // REMOVE_NODES, ORDERED_GROUP_REMOVED // VIEWSPECIFICGROUP_CLEAR attachStartIndex = 3; } if (child != null) { numMessages+=4; // INSERT_NODES,BEHAVIOR_ACTIVATE,ORDERED_GROUP_INSERTED, // VIEWSPECIFICGROUP_INIT } messages = new J3dMessage[numMessages]; for (int i = 0; i < numMessages; i++) { messages[i] = new J3dMessage(); } } if(oldchildr != null) { oldchildr.setParent(null); checkClearLive(oldchildr, messages, 0, index, null); if (this.source.isLive()) { universe.notifyStructureChangeListeners(false, this.source, (BranchGroup)oldchildr.source); } } removeChildrenData(index); if(child == null) { children.set(index, null); if (messages != null) { VirtualUniverse.mc.processMessage(messages); } return; } if (this.source.isLive()) { universe.notifyStructureChangeListeners(true, this.source, (BranchGroup)child); } NodeRetained childr = (NodeRetained) child.retained; childr.setParent(this); children.set(index, childr); insertChildrenData(index); checkSetLive(childr, index, messages, attachStartIndex, null); if (this.source.isLive()) { ((BranchGroupRetained)childr).isNew = true; } if (messages != null) { VirtualUniverse.mc.processMessage(messages); } } /** * Inserts the specified child at specified index. * @param child the new child * @param index position to insert new child at */ void insertChild(Node child, int index) { checkValidChild(child, "GroupRetained1"); if (this.source.isLive()) { universe.resetWaitMCFlag(); synchronized (universe.sceneGraphLock) { universe.notifyStructureChangeListeners(true, this.source, (BranchGroup)child); doInsertChild(child, index); universe.setLiveState.clear(); } universe.waitForMC(); } else { doInsertChild(child, index); if (universe != null) { synchronized (universe.sceneGraphLock) { universe.setLiveState.clear(); } } } dirtyBoundsCache(); } // The method that does the work once the lock is acquired. void doInsertChild(Node child, int index) { int i; NodeRetained childi; insertChildrenData(index); for (i=index; i<children.size(); i++) { childi = (NodeRetained) children.get(i); if(childi != null) childi.childIndex++; } if(child==null) { children.add(index, null); return; } NodeRetained childr = (NodeRetained) child.retained; childr.setParent(this); children.add(index, childr); checkSetLive(childr, index, null, 0, null); if (this.source.isLive()) { ((BranchGroupRetained)childr).isNew = true; } } /** * Removes the child at specified index. * @param index which child to remove */ void removeChild(int index) { if (this.source.isLive()) { universe.resetWaitMCFlag(); synchronized (universe.sceneGraphLock) { NodeRetained childr = (NodeRetained)children.get(index); doRemoveChild(index, null, 0); universe.setLiveState.clear(); universe.notifyStructureChangeListeners(false, this.source, (BranchGroup)childr.source); } universe.waitForMC(); } else { doRemoveChild(index, null, 0); if (universe != null) { synchronized (universe.sceneGraphLock) { universe.setLiveState.clear(); } } } dirtyBoundsCache(); } /** * Returns the index of the specified Node in this Group's list of Nodes * @param Node whose index is desired * @return index of the Node */ int indexOfChild(Node child) { if(child != null) return children.indexOf((NodeRetained)child.retained); else return children.indexOf(null); } /** * Removes the specified child from this Group's list of * children. If the specified child is not found, the method returns * quietly * * @param child to be removed */ void removeChild(Node child) { int i = indexOfChild(child); if(i >= 0) removeChild(i); } void removeAllChildren() { int n = children.size(); for(int i = n-1; i >= 0; i--) { removeChild(i); } } // The method that does the work once the lock is acquired. void doRemoveChild(int index, J3dMessage messages[], int messageIndex) { NodeRetained oldchildr, child; int i; oldchildr = (NodeRetained) children.get(index); int size = children.size(); for (i=index; i<size; i++) { child = (NodeRetained) children.get(i); if(child != null) child.childIndex--; } if(oldchildr != null) { oldchildr.setParent(null); checkClearLive(oldchildr, messages, messageIndex, index, null); } children.remove(index); removeChildrenData(index); if (nodeType == NodeRetained.SWITCH) { // force reEvaluation of switch children SwitchRetained sg = (SwitchRetained)this; sg.setWhichChild(sg.whichChild, true); } } /** * Returns the child specified by the index. * @param index which child to return * @return the children at location index */ Node getChild(int index) { SceneGraphObjectRetained sgo = (SceneGraphObjectRetained) children.get(index); if(sgo == null) return null; else return (Node) sgo.source;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -