Source Code Cross Referenced for GroupRetained.java in  » 6.0-JDK-Modules » java-3d » javax » media » j3d » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Java Source Code / Java Documentation
1. 6.0 JDK Core
2. 6.0 JDK Modules
3. 6.0 JDK Modules com.sun
4. 6.0 JDK Modules com.sun.java
5. 6.0 JDK Modules sun
6. 6.0 JDK Platform
7. Ajax
8. Apache Harmony Java SE
9. Aspect oriented
10. Authentication Authorization
11. Blogger System
12. Build
13. Byte Code
14. Cache
15. Chart
16. Chat
17. Code Analyzer
18. Collaboration
19. Content Management System
20. Database Client
21. Database DBMS
22. Database JDBC Connection Pool
23. Database ORM
24. Development
25. EJB Server geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » 6.0 JDK Modules » java 3d » javax.media.j3d 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


0001:        /*
0002:         * $RCSfile: GroupRetained.java,v $
0003:         *
0004:         * Copyright 1996-2008 Sun Microsystems, Inc.  All Rights Reserved.
0005:         * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
0006:         *
0007:         * This code is free software; you can redistribute it and/or modify it
0008:         * under the terms of the GNU General Public License version 2 only, as
0009:         * published by the Free Software Foundation.  Sun designates this
0010:         * particular file as subject to the "Classpath" exception as provided
0011:         * by Sun in the LICENSE file that accompanied this code.
0012:         *
0013:         * This code is distributed in the hope that it will be useful, but WITHOUT
0014:         * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
0015:         * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
0016:         * version 2 for more details (a copy is included in the LICENSE file that
0017:         * accompanied this code).
0018:         *
0019:         * You should have received a copy of the GNU General Public License version
0020:         * 2 along with this work; if not, write to the Free Software Foundation,
0021:         * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
0022:         *
0023:         * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
0024:         * CA 95054 USA or visit www.sun.com if you need additional information or
0025:         * have any questions.
0026:         *
0027:         * $Revision: 1.16 $
0028:         * $Date: 2008/02/28 20:17:23 $
0029:         * $State: Exp $
0030:         */
0031:
0032:        package javax.media.j3d;
0033:
0034:        import java.util.Vector;
0035:        import java.util.Enumeration;
0036:        import java.util.ArrayList;
0037:
0038:        /**
0039:         * Group node.
0040:         */
0041:
0042:        class GroupRetained extends NodeRetained implements  BHLeafInterface {
0043:            /**
0044:             * The Group Node's children vector.
0045:             */
0046:            ArrayList children = new ArrayList(1);
0047:
0048:            /**
0049:             * The Group node's collision bounds in local coordinates.
0050:             */
0051:            Bounds collisionBound = null;
0052:
0053:            // The locale that this node is decended from
0054:            Locale locale = null;
0055:
0056:            // The list of lights that are scoped to this node
0057:            // One such arraylist per path. If not in sharedGroup
0058:            // then only index 0 is valid
0059:            ArrayList lights = null;
0060:
0061:            // The list of fogs that are scoped to this node
0062:            // One such arraylist per path. If not in sharedGroup
0063:            // then only index 0 is valid
0064:            ArrayList fogs = null;
0065:
0066:            // The list of model clips that are scoped to this node
0067:            // One such arraylist per path. If not in sharedGroup
0068:            // then only index 0 is valid
0069:            ArrayList modelClips = null;
0070:
0071:            // The list of alternateappearance that are scoped to this node
0072:            // One such arraylist per path. If not in sharedGroup
0073:            // then only index 0 is valid
0074:            ArrayList altAppearances = null;
0075:
0076:            // indicates whether this Group node can be the target of a collision
0077:            boolean collisionTarget = false;
0078:
0079:            // per child switchLinks
0080:            ArrayList childrenSwitchLinks = null;
0081:
0082:            // the immediate childIndex of a parentSwitchLink
0083:            int parentSwitchLinkChildIndex = -1;
0084:
0085:            // per shared path ordered path data
0086:            ArrayList orderedPaths = null;
0087:
0088:            /**
0089:             * If collisionBound is set, this is equal to the
0090:             * transformed collisionBounds, otherwise it is equal
0091:             * to the transformed localBounds.
0092:             * This variable is set to null unless collisionTarget = true.
0093:             * This bound is only used by mirror Group.
0094:             */
0095:            BoundingBox collisionVwcBounds;
0096:
0097:            /**
0098:             * Mirror group of this node, it is only used when
0099:             * collisionTarget = true. Otherwise it is set to null.
0100:             * If not in shared group,
0101:             * only entry 0 is used.
0102:             *
0103:             */
0104:            ArrayList mirrorGroup;
0105:
0106:            /**
0107:             * key of mirror GroupRetained.
0108:             */
0109:            HashKey key;
0110:
0111:            /**
0112:             * sourceNode of this mirror Group 
0113:             */
0114:            GroupRetained sourceNode;
0115:
0116:            /**
0117:             * The BHLeafNode for this GeometryAtom.
0118:             */
0119:            BHLeafNode bhLeafNode = null;
0120:
0121:            //
0122:            // The following variables are used during compile
0123:            //
0124:
0125:            // true if this is the root of the scenegraph tree
0126:            boolean isRoot = false;
0127:
0128:            boolean allocatedLights = false;
0129:
0130:            boolean allocatedFogs = false;
0131:
0132:            boolean allocatedMclips = false;
0133:
0134:            boolean allocatedAltApps = false;
0135:
0136:            // > 0 if this group is being used in scoping
0137:            int scopingRefCount = 0;
0138:
0139:            ArrayList compiledChildrenList = null;
0140:
0141:            boolean isInClearLive = false;
0142:
0143:            // List of viewes scoped to this Group, for all subclasses
0144:            // of group, except ViewSpecificGroup its a pointer to closest
0145:            // ViewSpecificGroup parent
0146:            // viewList for this node, if inSharedGroup is
0147:            // false then only viewList(0) is valid
0148:            // For VSGs, this list is an intersection of
0149:            // higher level VSGs
0150:            ArrayList viewLists = null;
0151:
0152:            // True if this Node is descendent of ViewSpecificGroup;
0153:            boolean inViewSpecificGroup = false;
0154:
0155:            GroupRetained() {
0156:                this .nodeType = NodeRetained.GROUP;
0157:                // issue 544
0158:                if (VirtualUniverse.mc.useBoxForGroupBounds) {
0159:                    localBounds = new BoundingBox((Bounds) null);
0160:                } else {
0161:                    localBounds = new BoundingSphere();
0162:                    ((BoundingSphere) localBounds).setRadius(-1.0);
0163:                }
0164:            }
0165:
0166:            /**
0167:             * Sets the collision bounds of a node.
0168:             * @param bounds the bounding object for the node
0169:             */
0170:            void setCollisionBounds(Bounds bounds) {
0171:                if (bounds == null) {
0172:                    this .collisionBound = null;
0173:                } else {
0174:                    this .collisionBound = (Bounds) bounds.clone();
0175:                }
0176:
0177:                if (source.isLive()) {
0178:                    J3dMessage message = new J3dMessage();
0179:                    message.type = J3dMessage.COLLISION_BOUND_CHANGED;
0180:                    message.threads = J3dThread.UPDATE_TRANSFORM
0181:                            | J3dThread.UPDATE_GEOMETRY;
0182:                    message.universe = universe;
0183:                    message.args[0] = this ;
0184:                    VirtualUniverse.mc.processMessage(message);
0185:                }
0186:
0187:            }
0188:
0189:            /**
0190:             * Gets the collision bounds of a node.
0191:             * @return the node's bounding object
0192:             */
0193:            Bounds getCollisionBounds() {
0194:                return (collisionBound == null ? null : (Bounds) collisionBound
0195:                        .clone());
0196:            }
0197:
0198:            /**
0199:             * Replaces the specified child with the child provided.
0200:             * @param child the new child
0201:             * @param index which child to replace
0202:             */
0203:            void setChild(Node child, int index) {
0204:
0205:                checkValidChild(child, "GroupRetained0");
0206:                if (this .source.isLive()) {
0207:                    universe.resetWaitMCFlag();
0208:                    synchronized (universe.sceneGraphLock) {
0209:                        doSetChild(child, index);
0210:                        universe.setLiveState.clear();
0211:                    }
0212:                    universe.waitForMC();
0213:
0214:                } else {
0215:                    doSetChild(child, index);
0216:                    if (universe != null) {
0217:                        synchronized (universe.sceneGraphLock) {
0218:                            universe.setLiveState.clear();
0219:                        }
0220:                    }
0221:                }
0222:                dirtyBoundsCache();
0223:            }
0224:
0225:            // The method that does the work once the lock is acquired.
0226:            void doSetChild(Node child, int index) {
0227:                NodeRetained oldchildr;
0228:                J3dMessage[] messages = null;
0229:                int numMessages = 0;
0230:                int attachStartIndex = 0;
0231:
0232:                // since we want to make sure the replacement of the child
0233:                // including removal of the oldChild and insertion of the newChild
0234:                // all happen in the same frame, we'll send all the necessary
0235:                // messages to masterControl for processing in one call.
0236:                // So let's first find out how many messages will be sent
0237:
0238:                oldchildr = (NodeRetained) children.get(index);
0239:
0240:                if (this .source.isLive()) {
0241:                    if (oldchildr != null) {
0242:                        numMessages += 3; // REMOVE_NODES, ORDERED_GROUP_REMOVED
0243:                        // VIEWSPECIFICGROUP_CLEAR
0244:                        attachStartIndex = 3;
0245:                    }
0246:
0247:                    if (child != null) {
0248:                        numMessages += 4; // INSERT_NODES,BEHAVIOR_ACTIVATE,ORDERED_GROUP_INSERTED,
0249:                        // VIEWSPECIFICGROUP_INIT
0250:                    }
0251:
0252:                    messages = new J3dMessage[numMessages];
0253:                    for (int i = 0; i < numMessages; i++) {
0254:                        messages[i] = new J3dMessage();
0255:                    }
0256:                }
0257:
0258:                if (oldchildr != null) {
0259:                    oldchildr.setParent(null);
0260:                    checkClearLive(oldchildr, messages, 0, index, null);
0261:                    if (this .source.isLive()) {
0262:                        universe.notifyStructureChangeListeners(false,
0263:                                this .source, (BranchGroup) oldchildr.source);
0264:                    }
0265:                }
0266:                removeChildrenData(index);
0267:
0268:                if (child == null) {
0269:                    children.set(index, null);
0270:                    if (messages != null) {
0271:                        VirtualUniverse.mc.processMessage(messages);
0272:                    }
0273:                    return;
0274:                }
0275:
0276:                if (this .source.isLive()) {
0277:                    universe.notifyStructureChangeListeners(true, this .source,
0278:                            (BranchGroup) child);
0279:                }
0280:                NodeRetained childr = (NodeRetained) child.retained;
0281:                childr.setParent(this );
0282:                children.set(index, childr);
0283:
0284:                insertChildrenData(index);
0285:                checkSetLive(childr, index, messages, attachStartIndex, null);
0286:                if (this .source.isLive()) {
0287:                    ((BranchGroupRetained) childr).isNew = true;
0288:                }
0289:
0290:                if (messages != null) {
0291:                    VirtualUniverse.mc.processMessage(messages);
0292:                }
0293:            }
0294:
0295:            /**
0296:             * Inserts the specified child at specified index.
0297:             * @param child the new child
0298:             * @param index position to insert new child at
0299:             */
0300:            void insertChild(Node child, int index) {
0301:
0302:                checkValidChild(child, "GroupRetained1");
0303:                if (this .source.isLive()) {
0304:                    universe.resetWaitMCFlag();
0305:                    synchronized (universe.sceneGraphLock) {
0306:                        universe.notifyStructureChangeListeners(true,
0307:                                this .source, (BranchGroup) child);
0308:                        doInsertChild(child, index);
0309:                        universe.setLiveState.clear();
0310:                    }
0311:                    universe.waitForMC();
0312:                } else {
0313:                    doInsertChild(child, index);
0314:                    if (universe != null) {
0315:                        synchronized (universe.sceneGraphLock) {
0316:                            universe.setLiveState.clear();
0317:                        }
0318:                    }
0319:                }
0320:                dirtyBoundsCache();
0321:            }
0322:
0323:            // The method that does the work once the lock is acquired.
0324:            void doInsertChild(Node child, int index) {
0325:                int i;
0326:                NodeRetained childi;
0327:
0328:                insertChildrenData(index);
0329:                for (i = index; i < children.size(); i++) {
0330:                    childi = (NodeRetained) children.get(i);
0331:                    if (childi != null)
0332:                        childi.childIndex++;
0333:                }
0334:                if (child == null) {
0335:                    children.add(index, null);
0336:                    return;
0337:                }
0338:
0339:                NodeRetained childr = (NodeRetained) child.retained;
0340:                childr.setParent(this );
0341:                children.add(index, childr);
0342:                checkSetLive(childr, index, null, 0, null);
0343:                if (this .source.isLive()) {
0344:                    ((BranchGroupRetained) childr).isNew = true;
0345:                }
0346:            }
0347:
0348:            /**
0349:             * Removes the child at specified index.
0350:             * @param index which child to remove
0351:             */
0352:            void removeChild(int index) {
0353:
0354:                if (this .source.isLive()) {
0355:                    universe.resetWaitMCFlag();
0356:                    synchronized (universe.sceneGraphLock) {
0357:                        NodeRetained childr = (NodeRetained) children
0358:                                .get(index);
0359:                        doRemoveChild(index, null, 0);
0360:                        universe.setLiveState.clear();
0361:                        universe.notifyStructureChangeListeners(false,
0362:                                this .source, (BranchGroup) childr.source);
0363:                    }
0364:                    universe.waitForMC();
0365:                } else {
0366:                    doRemoveChild(index, null, 0);
0367:                    if (universe != null) {
0368:                        synchronized (universe.sceneGraphLock) {
0369:                            universe.setLiveState.clear();
0370:                        }
0371:                    }
0372:                }
0373:                dirtyBoundsCache();
0374:            }
0375:
0376:            /** 
0377:             * Returns the index of the specified Node in this Group's list of Nodes
0378:             * @param Node whose index is desired
0379:             * @return index of the Node
0380:             */
0381:            int indexOfChild(Node child) {
0382:                if (child != null)
0383:                    return children.indexOf((NodeRetained) child.retained);
0384:                else
0385:                    return children.indexOf(null);
0386:            }
0387:
0388:            /**
0389:             * Removes the specified child from this Group's list of
0390:             * children. If the specified child is not found, the method returns
0391:             * quietly
0392:             *
0393:             * @param child to be removed
0394:             */
0395:            void removeChild(Node child) {
0396:                int i = indexOfChild(child);
0397:                if (i >= 0)
0398:                    removeChild(i);
0399:            }
0400:
0401:            void removeAllChildren() {
0402:                int n = children.size();
0403:                for (int i = n - 1; i >= 0; i--) {
0404:                    removeChild(i);
0405:                }
0406:            }
0407:
0408:            // The method that does the work once the lock is acquired.
0409:            void doRemoveChild(int index, J3dMessage messages[],
0410:                    int messageIndex) {
0411:                NodeRetained oldchildr, child;
0412:                int i;
0413:
0414:                oldchildr = (NodeRetained) children.get(index);
0415:
0416:                int size = children.size();
0417:                for (i = index; i < size; i++) {
0418:                    child = (NodeRetained) children.get(i);
0419:                    if (child != null)
0420:                        child.childIndex--;
0421:                }
0422:
0423:                if (oldchildr != null) {
0424:                    oldchildr.setParent(null);
0425:                    checkClearLive(oldchildr, messages, messageIndex, index,
0426:                            null);
0427:                }
0428:
0429:                children.remove(index);
0430:                removeChildrenData(index);
0431:
0432:                if (nodeType == NodeRetained.SWITCH) {
0433:                    // force reEvaluation of switch children
0434:                    SwitchRetained sg = (SwitchRetained) this ;
0435:                    sg.setWhichChild(sg.whichChild, true);
0436:                }
0437:
0438:            }
0439:
0440:            /**
0441:             * Returns the child specified by the index.
0442:             * @param index which child to return
0443:             * @return the children at location index
0444:             */
0445:            Node getChild(int index) {
0446:
0447:                SceneGraphObjectRetained sgo = (SceneGraphObjectRetained) children
0448:                        .get(index);
0449:                if (sgo == null)
0450:                    return null;
0451:                else
0452:                    return (Node) sgo.source;
0453:            }
0454:
0455:            /**
0456:             * Returns an enumeration object of the children.
0457:             * @return an enumeration object of the children
0458:             */
0459:            Enumeration getAllChildren() {
0460:                Vector userChildren = new Vector(children.size());
0461:                SceneGraphObjectRetained sgo;
0462:
0463:                for (int i = 0; i < children.size(); i++) {
0464:                    sgo = (SceneGraphObjectRetained) children.get(i);
0465:                    if (sgo != null)
0466:                        userChildren.add(sgo.source);
0467:                    else
0468:                        userChildren.add(null);
0469:                }
0470:
0471:                return userChildren.elements();
0472:            }
0473:
0474:            void checkValidChild(Node child, String s) {
0475:
0476:                if ((child != null)
0477:                        && (((child instanceof  BranchGroup) && (((BranchGroupRetained) child.retained).attachedToLocale)) || (((NodeRetained) child.retained).parent != null))) {
0478:                    throw new MultipleParentException(J3dI18N.getString(s));
0479:                }
0480:            }
0481:
0482:            /**
0483:             * Appends the specified child to this node's list of children.
0484:             * @param child the child to add to this node's list of children
0485:             */
0486:            void addChild(Node child) {
0487:                checkValidChild(child, "GroupRetained2");
0488:
0489:                if (this .source.isLive()) {
0490:                    universe.resetWaitMCFlag();
0491:                    synchronized (universe.sceneGraphLock) {
0492:                        universe.notifyStructureChangeListeners(true,
0493:                                this .source, (BranchGroup) child);
0494:                        doAddChild(child, null, 0);
0495:                        universe.setLiveState.clear();
0496:                    }
0497:                    universe.waitForMC();
0498:                } else {
0499:                    doAddChild(child, null, 0);
0500:                    if (universe != null) {
0501:                        synchronized (universe.sceneGraphLock) {
0502:                            universe.setLiveState.clear();
0503:                        }
0504:                    }
0505:                }
0506:                dirtyBoundsCache();
0507:            }
0508:
0509:            // The method that does the work once the lock is acquired.
0510:            void doAddChild(Node child, J3dMessage messages[], int messageIndex) {
0511:
0512:                appendChildrenData();
0513:
0514:                if (child == null) {
0515:                    children.add(null);
0516:                    return;
0517:                }
0518:
0519:                NodeRetained childr = (NodeRetained) child.retained;
0520:                childr.setParent(this );
0521:                children.add(childr);
0522:                checkSetLive(childr, children.size() - 1, messages,
0523:                        messageIndex, null);
0524:                if (this .source.isLive()) {
0525:                    ((BranchGroupRetained) childr).isNew = true;
0526:                }
0527:
0528:            }
0529:
0530:            void moveTo(BranchGroup bg) {
0531:                if (bg != null) {
0532:                    ((GroupRetained) bg.retained).dirtyBoundsCache();
0533:                }
0534:                if (this .source.isLive()) {
0535:                    universe.resetWaitMCFlag();
0536:                    synchronized (universe.sceneGraphLock) {
0537:                        GroupRetained oldParent = (GroupRetained) ((BranchGroupRetained) bg.retained).parent;
0538:                        doMoveTo(bg);
0539:                        universe.setLiveState.clear();
0540:                        if (oldParent == null)
0541:                            universe.notifyStructureChangeListeners(
0542:                                    ((BranchGroupRetained) bg.retained).locale,
0543:                                    this .source, bg);
0544:                        else
0545:                            universe.notifyStructureChangeListeners(
0546:                                    oldParent.source, this .source, bg);
0547:                    }
0548:                    universe.waitForMC();
0549:                } else {
0550:                    doMoveTo(bg);
0551:                    if (universe != null) {
0552:                        synchronized (universe.sceneGraphLock) {
0553:                            universe.setLiveState.clear();
0554:                        }
0555:                    }
0556:                }
0557:                dirtyBoundsCache();
0558:            }
0559:
0560:            // The method that does the work once the lock is acquired.
0561:            void doMoveTo(BranchGroup branchGroup) {
0562:                J3dMessage messages[] = null;
0563:                int numMessages = 0;
0564:                int detachStartIndex = 0;
0565:                int attachStartIndex = 0;
0566:                if (branchGroup != null) {
0567:                    BranchGroupRetained bg = (BranchGroupRetained) branchGroup.retained;
0568:                    GroupRetained g = (GroupRetained) bg.parent;
0569:
0570:                    // Find out how many messages to be created
0571:                    // Note that g can be NULL if branchGroup parent is
0572:                    // a Locale, in this case the following condition 
0573:                    // will fail.
0574:                    // Figure out the number of messages based on whether the group
0575:                    // from which its moving from is live and group to which its
0576:                    // moving to is live
0577:                    if (g != null) {
0578:                        if (g.source.isLive()) {
0579:                            numMessages = 3; // REMOVE_NODES, ORDERED_GROUP_REMOVED,VIEWSPECIFICGROUP_CLEAR
0580:                            attachStartIndex = 3;
0581:                        } else {
0582:                            numMessages = 0;
0583:                            attachStartIndex = 0;
0584:                        }
0585:
0586:                    } else { // Attached to locale
0587:                        numMessages = 3; // REMOVE_NODES, ORDERED_GROUP_REMOVED, VIEWSPECIFICGROUP_CLEAR
0588:                        attachStartIndex = 3;
0589:                    }
0590:                    // Now, do the evaluation for the group that its going to be
0591:                    // attached to ..
0592:                    if (this .source.isLive()) {
0593:                        numMessages += 4; // INSERT_NODES, BEHAVIOR_ACTIVATE
0594:                        // ORDERED_GROUP_INSERTED, VIEWSPECIFICGROUP_INIT
0595:
0596:                    }
0597:                    messages = new J3dMessage[numMessages];
0598:                    for (int i = 0; i < numMessages; i++) {
0599:                        messages[i] = new J3dMessage();
0600:                        messages[i].type = J3dMessage.INVALID_TYPE;
0601:                    }
0602:
0603:                    // Remove it from it's parents state
0604:                    if (g == null) {
0605:                        if (bg.locale != null) {
0606:                            bg.locale.doRemoveBranchGraph(branchGroup,
0607:                                    messages, detachStartIndex);
0608:                        }
0609:                    } else {
0610:                        g.doRemoveChild(g.children.indexOf(bg), messages,
0611:                                detachStartIndex);
0612:                    }
0613:                }
0614:
0615:                // Add it to it's new parent
0616:                doAddChild(branchGroup, messages, attachStartIndex);
0617:
0618:                if (numMessages > 0) {
0619:                    int count = 0;
0620:                    for (int i = 0; i < numMessages; i++) {
0621:                        if (messages[i].type != J3dMessage.INVALID_TYPE) {
0622:                            count++;
0623:                        }
0624:                    }
0625:                    if (count == numMessages) {
0626:                        // in most cases
0627:                        VirtualUniverse.mc.processMessage(messages);
0628:                    } else {
0629:                        J3dMessage ms[] = null;
0630:
0631:                        if (count > 0) {
0632:                            ms = new J3dMessage[count];
0633:                        }
0634:
0635:                        int k = 0;
0636:                        for (int i = 0; i < numMessages; i++) {
0637:                            if (messages[i].type != J3dMessage.INVALID_TYPE) {
0638:                                ms[k++] = messages[i];
0639:                            }
0640:                        }
0641:                        if (ms != null) {
0642:                            VirtualUniverse.mc.processMessage(ms);
0643:                        }
0644:                    }
0645:                }
0646:            }
0647:
0648:            /**
0649:             * Returns a count of this nodes' children.
0650:             * @return the number of children descendant from this node
0651:             */
0652:            int numChildren() {
0653:                return children.size();
0654:            }
0655:
0656:            // Remove a light from the list of lights
0657:            void removeLight(int numLgt, LightRetained[] removelight,
0658:                    HashKey key) {
0659:                ArrayList l;
0660:                int index;
0661:                if (inSharedGroup) {
0662:                    int hkIndex = key.equals(localToVworldKeys, 0,
0663:                            localToVworldKeys.length);
0664:                    l = (ArrayList) lights.get(hkIndex);
0665:                    if (l != null) {
0666:                        for (int i = 0; i < numLgt; i++) {
0667:                            index = l.indexOf(removelight[i]);
0668:                            l.remove(index);
0669:                        }
0670:                    }
0671:                } else {
0672:                    l = (ArrayList) lights.get(0);
0673:                    for (int i = 0; i < numLgt; i++) {
0674:                        index = l.indexOf(removelight[i]);
0675:                        l.remove(index);
0676:                    }
0677:                }
0678:
0679:                /*
0680:                // XXXX: lights may remove twice or more during clearLive(),
0681:                // one from itself and one call from every LightRetained
0682:                // reference this.  So there is case that this procedure get
0683:                // called when light already removed.
0684:                if (i >= 0) 
0685:                    lights.remove(i);
0686:                 */
0687:            }
0688:
0689:            void addAllNodesForScopedLight(int numLgts, LightRetained[] ml,
0690:                    ArrayList list, HashKey k) {
0691:                if (inSharedGroup) {
0692:                    for (int i = 0; i < localToVworldKeys.length; i++) {
0693:                        k.set(localToVworldKeys[i]);
0694:                        processAllNodesForScopedLight(numLgts, ml, list, k);
0695:                    }
0696:                } else {
0697:                    processAllNodesForScopedLight(numLgts, ml, list, k);
0698:                }
0699:            }
0700:
0701:            void processAllNodesForScopedLight(int numLgts, LightRetained[] ml,
0702:                    ArrayList list, HashKey k) {
0703:                if (allocatedLights) {
0704:                    addLight(ml, numLgts, k);
0705:                }
0706:                if (this .source.isLive() || this .isInSetLive()) {
0707:                    for (int i = children.size() - 1; i >= 0; i--) {
0708:                        NodeRetained child = (NodeRetained) children.get(i);
0709:                        if (child != null) {
0710:                            if (child instanceof  GroupRetained
0711:                                    && (child.source.isLive() || child
0712:                                            .isInSetLive()))
0713:                                ((GroupRetained) child)
0714:                                        .processAllNodesForScopedLight(numLgts,
0715:                                                ml, list, k);
0716:                            else if (child instanceof  LinkRetained
0717:                                    && (child.source.isLive() || child
0718:                                            .isInSetLive())) {
0719:                                int lastCount = k.count;
0720:                                LinkRetained ln = (LinkRetained) child;
0721:                                if (k.count == 0) {
0722:                                    k.append(locale.nodeId);
0723:                                }
0724:                                ((GroupRetained) (ln.sharedGroup))
0725:                                        .processAllNodesForScopedLight(numLgts,
0726:                                                ml, list, k.append("+").append(
0727:                                                        ln.nodeId));
0728:                                k.count = lastCount;
0729:                            } else if (child instanceof  Shape3DRetained
0730:                                    && child.source.isLive()) {
0731:                                ((Shape3DRetained) child).getMirrorObjects(
0732:                                        list, k);
0733:                            } else if (child instanceof  MorphRetained
0734:                                    && child.source.isLive()) {
0735:                                ((MorphRetained) child).getMirrorObjects(list,
0736:                                        k);
0737:                            }
0738:                        }
0739:                    }
0740:                }
0741:            }
0742:
0743:            // If its a group, then add the scope to the group, if
0744:            // its a shape, then keep a list to be added during
0745:            // updateMirrorObject
0746:            void removeAllNodesForScopedLight(int numLgts, LightRetained[] ml,
0747:                    ArrayList list, HashKey k) {
0748:                if (inSharedGroup) {
0749:                    for (int i = 0; i < localToVworldKeys.length; i++) {
0750:                        k.set(localToVworldKeys[i]);
0751:                        processRemoveAllNodesForScopedLight(numLgts, ml, list,
0752:                                k);
0753:                    }
0754:                } else {
0755:                    processRemoveAllNodesForScopedLight(numLgts, ml, list, k);
0756:                }
0757:            }
0758:
0759:            void processRemoveAllNodesForScopedLight(int numLgts,
0760:                    LightRetained[] ml, ArrayList list, HashKey k) {
0761:                if (allocatedLights) {
0762:                    removeLight(numLgts, ml, k);
0763:                }
0764:                // If the source is live, then notify the children
0765:                if (this .source.isLive() && !isInClearLive) {
0766:                    for (int i = children.size() - 1; i >= 0; i--) {
0767:                        NodeRetained child = (NodeRetained) children.get(i);
0768:                        if (child != null) {
0769:                            if (child instanceof  GroupRetained
0770:                                    && (child.source.isLive() && !((GroupRetained) child).isInClearLive))
0771:                                ((GroupRetained) child)
0772:                                        .processRemoveAllNodesForScopedLight(
0773:                                                numLgts, ml, list, k);
0774:                            else if (child instanceof  LinkRetained
0775:                                    && child.source.isLive()) {
0776:                                int lastCount = k.count;
0777:                                LinkRetained ln = (LinkRetained) child;
0778:                                if (k.count == 0) {
0779:                                    k.append(locale.nodeId);
0780:                                }
0781:                                ((GroupRetained) (ln.sharedGroup))
0782:                                        .processRemoveAllNodesForScopedLight(
0783:                                                numLgts, ml, list, k
0784:                                                        .append("+").append(
0785:                                                                ln.nodeId));
0786:                                k.count = lastCount;
0787:                            } else if (child instanceof  Shape3DRetained
0788:                                    && child.source.isLive()) {
0789:                                ((Shape3DRetained) child).getMirrorObjects(
0790:                                        list, k);
0791:                            } else if (child instanceof  MorphRetained
0792:                                    && child.source.isLive()) {
0793:                                ((MorphRetained) child).getMirrorObjects(list,
0794:                                        k);
0795:                            }
0796:                        }
0797:                    }
0798:                }
0799:            }
0800:
0801:            void addAllNodesForScopedFog(FogRetained mfog, ArrayList list,
0802:                    HashKey k) {
0803:                if (inSharedGroup) {
0804:                    for (int i = 0; i < localToVworldKeys.length; i++) {
0805:                        k.set(localToVworldKeys[i]);
0806:                        processAddNodesForScopedFog(mfog, list, k);
0807:                    }
0808:                } else {
0809:                    processAddNodesForScopedFog(mfog, list, k);
0810:                }
0811:            }
0812:
0813:            void processAddNodesForScopedFog(FogRetained mfog, ArrayList list,
0814:                    HashKey k) {
0815:                // If this group has it own scoping list then add .. 
0816:                if (allocatedFogs)
0817:                    addFog(mfog, k);
0818:                // If the source is live, then notify the children
0819:                if (this .source.isLive() || this .isInSetLive()) {
0820:                    for (int i = children.size() - 1; i >= 0; i--) {
0821:                        NodeRetained child = (NodeRetained) children.get(i);
0822:                        if (child != null) {
0823:                            if (child instanceof  GroupRetained
0824:                                    && (child.source.isLive() || child
0825:                                            .isInSetLive()))
0826:                                ((GroupRetained) child)
0827:                                        .processAddNodesForScopedFog(mfog,
0828:                                                list, k);
0829:                            else if (child instanceof  LinkRetained
0830:                                    && (child.source.isLive() || child
0831:                                            .isInSetLive())) {
0832:                                int lastCount = k.count;
0833:                                LinkRetained ln = (LinkRetained) child;
0834:                                if (k.count == 0) {
0835:                                    k.append(locale.nodeId);
0836:                                }
0837:                                ((GroupRetained) (ln.sharedGroup))
0838:                                        .processAddNodesForScopedFog(mfog,
0839:                                                list, k.append("+").append(
0840:                                                        ln.nodeId));
0841:                                k.count = lastCount;
0842:                            } else if (child instanceof  Shape3DRetained
0843:                                    && child.source.isLive()) {
0844:                                ((Shape3DRetained) child).getMirrorObjects(
0845:                                        list, k);
0846:                            } else if (child instanceof  MorphRetained
0847:                                    && child.source.isLive()) {
0848:                                ((MorphRetained) child).getMirrorObjects(list,
0849:                                        k);
0850:                            }
0851:                        }
0852:                    }
0853:                }
0854:            }
0855:
0856:            // If its a group, then add the scope to the group, if
0857:            // its a shape, then keep a list to be added during
0858:            // updateMirrorObject
0859:            void removeAllNodesForScopedFog(FogRetained mfog, ArrayList list,
0860:                    HashKey k) {
0861:                if (inSharedGroup) {
0862:                    for (int i = 0; i < localToVworldKeys.length; i++) {
0863:                        k.set(localToVworldKeys[i]);
0864:                        processRemoveAllNodesForScopedFog(mfog, list, k);
0865:                    }
0866:                } else {
0867:                    processRemoveAllNodesForScopedFog(mfog, list, k);
0868:                }
0869:            }
0870:
0871:            void processRemoveAllNodesForScopedFog(FogRetained mfog,
0872:                    ArrayList list, HashKey k) {
0873:                // If the source is live, then notify the children
0874:                if (allocatedFogs)
0875:                    removeFog(mfog, k);
0876:                if (this .source.isLive() && !isInClearLive) {
0877:                    for (int i = children.size() - 1; i >= 0; i--) {
0878:                        NodeRetained child = (NodeRetained) children.get(i);
0879:                        if (child != null) {
0880:                            if (child instanceof  GroupRetained
0881:                                    && (child.source.isLive() && !((GroupRetained) child).isInClearLive))
0882:                                ((GroupRetained) child)
0883:                                        .processRemoveAllNodesForScopedFog(
0884:                                                mfog, list, k);
0885:                            else if (child instanceof  LinkRetained
0886:                                    && child.source.isLive()) {
0887:                                int lastCount = k.count;
0888:                                LinkRetained ln = (LinkRetained) child;
0889:                                if (k.count == 0) {
0890:                                    k.append(locale.nodeId);
0891:                                }
0892:                                ((GroupRetained) (ln.sharedGroup))
0893:                                        .processRemoveAllNodesForScopedFog(
0894:                                                mfog, list, k.append("+")
0895:                                                        .append(ln.nodeId));
0896:                                k.count = lastCount;
0897:                            } else if (child instanceof  Shape3DRetained
0898:                                    && child.source.isLive()) {
0899:                                ((Shape3DRetained) child).getMirrorObjects(
0900:                                        list, k);
0901:                            } else if (child instanceof  MorphRetained
0902:                                    && child.source.isLive()) {
0903:                                ((MorphRetained) child).getMirrorObjects(list,
0904:                                        k);
0905:                            }
0906:                        }
0907:                    }
0908:                }
0909:            }
0910:
0911:            void addAllNodesForScopedModelClip(ModelClipRetained mModelClip,
0912:                    ArrayList list, HashKey k) {
0913:                if (inSharedGroup) {
0914:                    for (int i = 0; i < localToVworldKeys.length; i++) {
0915:                        k.set(localToVworldKeys[i]);
0916:                        processAddNodesForScopedModelClip(mModelClip, list, k);
0917:                    }
0918:                } else {
0919:                    processAddNodesForScopedModelClip(mModelClip, list, k);
0920:                }
0921:            }
0922:
0923:            void processAddNodesForScopedModelClip(
0924:                    ModelClipRetained mModelClip, ArrayList list, HashKey k) {
0925:                if (allocatedMclips)
0926:                    addModelClip(mModelClip, k);
0927:                // If the source is live, then notify the children
0928:                if (this .source.isLive() || this .isInSetLive()) {
0929:                    for (int i = children.size() - 1; i >= 0; i--) {
0930:                        NodeRetained child = (NodeRetained) children.get(i);
0931:                        if (child != null) {
0932:                            if (child instanceof  GroupRetained
0933:                                    && (child.source.isLive() || child
0934:                                            .isInSetLive()))
0935:                                ((GroupRetained) child)
0936:                                        .processAddNodesForScopedModelClip(
0937:                                                mModelClip, list, k);
0938:                            else if (child instanceof  LinkRetained
0939:                                    && (child.source.isLive() || child
0940:                                            .isInSetLive())) {
0941:                                int lastCount = k.count;
0942:                                LinkRetained ln = (LinkRetained) child;
0943:                                if (k.count == 0) {
0944:                                    k.append(locale.nodeId);
0945:                                }
0946:                                ((GroupRetained) (ln.sharedGroup))
0947:                                        .processAddNodesForScopedModelClip(
0948:                                                mModelClip, list, k.append("+")
0949:                                                        .append(ln.nodeId));
0950:                                k.count = lastCount;
0951:                            } else if (child instanceof  Shape3DRetained
0952:                                    && child.source.isLive()) {
0953:                                ((Shape3DRetained) child).getMirrorObjects(
0954:                                        list, k);
0955:                            } else if (child instanceof  MorphRetained
0956:                                    && child.source.isLive()) {
0957:                                ((MorphRetained) child).getMirrorObjects(list,
0958:                                        k);
0959:                            }
0960:                        }
0961:                    }
0962:                }
0963:            }
0964:
0965:            void removeAllNodesForScopedModelClip(ModelClipRetained mModelClip,
0966:                    ArrayList list, HashKey k) {
0967:                if (inSharedGroup) {
0968:                    for (int i = 0; i < localToVworldKeys.length; i++) {
0969:                        k.set(localToVworldKeys[i]);
0970:                        processRemoveAllNodesForScopedModelClip(mModelClip,
0971:                                list, k);
0972:                    }
0973:                } else {
0974:                    processRemoveAllNodesForScopedModelClip(mModelClip, list, k);
0975:                }
0976:
0977:            }
0978:
0979:            // If its a group, then add the scope to the group, if
0980:            // its a shape, then keep a list to be added during
0981:            // updateMirrorObject
0982:            void processRemoveAllNodesForScopedModelClip(
0983:                    ModelClipRetained mModelClip, ArrayList list, HashKey k) {
0984:                // If the source is live, then notify the children
0985:                if (allocatedMclips)
0986:                    removeModelClip(mModelClip, k);
0987:                if (this .source.isLive() && !isInClearLive) {
0988:                    for (int i = children.size() - 1; i >= 0; i--) {
0989:                        NodeRetained child = (NodeRetained) children.get(i);
0990:                        if (child != null) {
0991:                            if (child instanceof  GroupRetained
0992:                                    && (child.source.isLive() && !((GroupRetained) child).isInClearLive))
0993:                                ((GroupRetained) child)
0994:                                        .processRemoveAllNodesForScopedModelClip(
0995:                                                mModelClip, list, k);
0996:                            else if (child instanceof  LinkRetained
0997:                                    && child.source.isLive()) {
0998:                                int lastCount = k.count;
0999:                                LinkRetained ln = (LinkRetained) child;
1000:                                if (k.count == 0) {
1001:                                    k.append(locale.nodeId);
1002:                                }
1003:                                ((GroupRetained) (ln.sharedGroup))
1004:                                        .processRemoveAllNodesForScopedModelClip(
1005:                                                mModelClip, list, k.append("+")
1006:                                                        .append(ln.nodeId));
1007:                                k.count = lastCount;
1008:                            } else if (child instanceof  Shape3DRetained
1009:                                    && child.source.isLive()) {
1010:                                ((Shape3DRetained) child).getMirrorObjects(
1011:                                        list, k);
1012:                            } else if (child instanceof  MorphRetained
1013:                                    && child.source.isLive()) {
1014:                                ((MorphRetained) child).getMirrorObjects(list,
1015:                                        k);
1016:                            }
1017:                        }
1018:                    }
1019:                }
1020:            }
1021:
1022:            void addAllNodesForScopedAltApp(
1023:                    AlternateAppearanceRetained mAltApp, ArrayList list,
1024:                    HashKey k) {
1025:                if (inSharedGroup) {
1026:                    for (int i = 0; i < localToVworldKeys.length; i++) {
1027:                        k.set(localToVworldKeys[i]);
1028:                        processAddNodesForScopedAltApp(mAltApp, list, k);
1029:                    }
1030:                } else {
1031:                    processAddNodesForScopedAltApp(mAltApp, list, k);
1032:                }
1033:            }
1034:
1035:            // If its a group, then add the scope to the group, if
1036:            // its a shape, then keep a list to be added during
1037:            // updateMirrorObject
1038:            void processAddNodesForScopedAltApp(
1039:                    AlternateAppearanceRetained mAltApp, ArrayList list,
1040:                    HashKey k) {
1041:                // If the source is live, then notify the children
1042:                if (allocatedAltApps)
1043:                    addAltApp(mAltApp, k);
1044:                if (this .source.isLive() || this .isInSetLive()) {
1045:                    for (int i = children.size() - 1; i >= 0; i--) {
1046:                        NodeRetained child = (NodeRetained) children.get(i);
1047:                        if (child != null) {
1048:                            if (child instanceof  GroupRetained
1049:                                    && (child.source.isLive() || child
1050:                                            .isInSetLive()))
1051:                                ((GroupRetained) child)
1052:                                        .processAddNodesForScopedAltApp(
1053:                                                mAltApp, list, k);
1054:                            else if (child instanceof  LinkRetained
1055:                                    && child.source.isLive()) {
1056:                                int lastCount = k.count;
1057:                                LinkRetained ln = (LinkRetained) child;
1058:                                if (k.count == 0) {
1059:                                    k.append(locale.nodeId);
1060:                                }
1061:                                ((GroupRetained) (ln.sharedGroup))
1062:                                        .processAddNodesForScopedAltApp(
1063:                                                mAltApp, list, k.append("+")
1064:                                                        .append(ln.nodeId));
1065:                                k.count = lastCount;
1066:                            } else if (child instanceof  Shape3DRetained
1067:                                    && child.source.isLive()) {
1068:                                ((Shape3DRetained) child).getMirrorObjects(
1069:                                        list, k);
1070:                            } else if (child instanceof  MorphRetained
1071:                                    && child.source.isLive()) {
1072:                                ((MorphRetained) child).getMirrorObjects(list,
1073:                                        k);
1074:                            }
1075:                        }
1076:                    }
1077:                }
1078:            }
1079:
1080:            void removeAllNodesForScopedAltApp(
1081:                    AlternateAppearanceRetained mAltApp, ArrayList list,
1082:                    HashKey k) {
1083:                if (inSharedGroup) {
1084:                    for (int i = 0; i < localToVworldKeys.length; i++) {
1085:                        k.set(localToVworldKeys[i]);
1086:                        processRemoveNodesForScopedAltApp(mAltApp, list, k);
1087:                    }
1088:                } else {
1089:                    processAddNodesForScopedAltApp(mAltApp, list, k);
1090:                }
1091:            }
1092:
1093:            // If its a group, then add the scope to the group, if
1094:            // its a shape, then keep a list to be added during
1095:            // updateMirrorObject
1096:            void processRemoveNodesForScopedAltApp(
1097:                    AlternateAppearanceRetained mAltApp, ArrayList list,
1098:                    HashKey k) {
1099:                // If the source is live, then notify the children
1100:                if (allocatedAltApps)
1101:                    removeAltApp(mAltApp, k);
1102:                if (this .source.isLive() && !isInClearLive) {
1103:                    for (int i = children.size() - 1; i >= 0; i--) {
1104:                        NodeRetained child = (NodeRetained) children.get(i);
1105:                        if (child != null) {
1106:                            if (child instanceof  GroupRetained
1107:                                    && (child.source.isLive() && !((GroupRetained) child).isInClearLive))
1108:                                ((GroupRetained) child)
1109:                                        .processRemoveNodesForScopedAltApp(
1110:                                                mAltApp, list, k);
1111:                            else if (child instanceof  LinkRetained
1112:                                    && child.source.isLive()) {
1113:                                int lastCount = k.count;
1114:                                LinkRetained ln = (LinkRetained) child;
1115:                                if (k.count == 0) {
1116:                                    k.append(locale.nodeId);
1117:                                }
1118:                                ((GroupRetained) (ln.sharedGroup))
1119:                                        .processRemoveNodesForScopedAltApp(
1120:                                                mAltApp, list, k.append("+")
1121:                                                        .append(ln.nodeId));
1122:                                k.count = lastCount;
1123:                            } else if (child instanceof  Shape3DRetained
1124:                                    && child.source.isLive()) {
1125:                                ((Shape3DRetained) child).getMirrorObjects(
1126:                                        list, k);
1127:                            } else if (child instanceof  MorphRetained
1128:                                    && child.source.isLive()) {
1129:                                ((MorphRetained) child).getMirrorObjects(list,
1130:                                        k);
1131:                            }
1132:                        }
1133:                    }
1134:                }
1135:            }
1136:
1137:            synchronized void setLightScope() {
1138:                // Make group's own copy
1139:                ArrayList newLights;
1140:                if (!allocatedLights) {
1141:                    allocatedLights = true;
1142:                    if (lights != null) {
1143:                        newLights = new ArrayList(lights.size());
1144:                        int size = lights.size();
1145:                        for (int i = 0; i < size; i++) {
1146:                            ArrayList l = (ArrayList) lights.get(i);
1147:                            if (l != null) {
1148:                                newLights.add(l.clone());
1149:                            } else {
1150:                                newLights.add(null);
1151:                            }
1152:                        }
1153:                    } else {
1154:                        if (inSharedGroup) {
1155:                            newLights = new ArrayList();
1156:                            for (int i = 0; i < localToVworldKeys.length; i++) {
1157:                                newLights.add(new ArrayList());
1158:                            }
1159:                        } else {
1160:                            newLights = new ArrayList();
1161:                            newLights.add(new ArrayList());
1162:                        }
1163:                    }
1164:                    lights = newLights;
1165:
1166:                }
1167:                scopingRefCount++;
1168:            }
1169:
1170:            synchronized void removeLightScope() {
1171:                scopingRefCount--;
1172:            }
1173:
1174:            synchronized void setFogScope() {
1175:                // Make group's own copy
1176:                ArrayList newFogs;
1177:                if (!allocatedFogs) {
1178:                    allocatedFogs = true;
1179:                    if (fogs != null) {
1180:                        newFogs = new ArrayList(fogs.size());
1181:                        int size = fogs.size();
1182:                        for (int i = 0; i < size; i++) {
1183:                            ArrayList l = (ArrayList) fogs.get(i);
1184:                            if (l != null) {
1185:                                newFogs.add(l.clone());
1186:                            } else {
1187:                                newFogs.add(null);
1188:                            }
1189:                        }
1190:                    } else {
1191:                        if (inSharedGroup) {
1192:                            newFogs = new ArrayList();
1193:                            for (int i = 0; i < localToVworldKeys.length; i++) {
1194:                                newFogs.add(new ArrayList());
1195:                            }
1196:                        } else {
1197:                            newFogs = new ArrayList();
1198:                            newFogs.add(new ArrayList());
1199:                        }
1200:                    }
1201:                    fogs = newFogs;
1202:
1203:                }
1204:                scopingRefCount++;
1205:            }
1206:
1207:            synchronized void removeFogScope() {
1208:                scopingRefCount--;
1209:            }
1210:
1211:            synchronized void setMclipScope() {
1212:                // Make group's own copy
1213:                ArrayList newMclips;
1214:                if (!allocatedMclips) {
1215:                    allocatedMclips = true;
1216:                    if (modelClips != null) {
1217:                        newMclips = new ArrayList(modelClips.size());
1218:                        int size = modelClips.size();
1219:                        for (int i = 0; i < size; i++) {
1220:                            ArrayList l = (ArrayList) modelClips.get(i);
1221:                            if (l != null) {
1222:                                newMclips.add(l.clone());
1223:                            } else {
1224:                                newMclips.add(null);
1225:                            }
1226:                        }
1227:                    } else {
1228:                        if (inSharedGroup) {
1229:                            newMclips = new ArrayList();
1230:                            for (int i = 0; i < localToVworldKeys.length; i++) {
1231:                                newMclips.add(new ArrayList());
1232:                            }
1233:                        } else {
1234:                            newMclips = new ArrayList();
1235:                            newMclips.add(new ArrayList());
1236:                        }
1237:                    }
1238:                    modelClips = newMclips;
1239:
1240:                }
1241:                scopingRefCount++;
1242:            }
1243:
1244:            synchronized void removeMclipScope() {
1245:                scopingRefCount--;
1246:            }
1247:
1248:            synchronized void setAltAppScope() {
1249:                // Make group's own copy
1250:                ArrayList newAltApps;
1251:                if (!allocatedAltApps) {
1252:                    allocatedAltApps = true;
1253:                    if (altAppearances != null) {
1254:                        newAltApps = new ArrayList(altAppearances.size());
1255:                        int size = altAppearances.size();
1256:                        for (int i = 0; i < size; i++) {
1257:                            ArrayList l = (ArrayList) altAppearances.get(i);
1258:                            if (l != null) {
1259:                                newAltApps.add(l.clone());
1260:                            } else {
1261:                                newAltApps.add(null);
1262:                            }
1263:                        }
1264:                    } else {
1265:                        if (inSharedGroup) {
1266:                            newAltApps = new ArrayList();
1267:                            for (int i = 0; i < localToVworldKeys.length; i++) {
1268:                                newAltApps.add(new ArrayList());
1269:                            }
1270:                        } else {
1271:                            newAltApps = new ArrayList();
1272:                            newAltApps.add(new ArrayList());
1273:                        }
1274:                    }
1275:                    altAppearances = newAltApps;
1276:
1277:                }
1278:                scopingRefCount++;
1279:            }
1280:
1281:            synchronized void removeAltAppScope() {
1282:                scopingRefCount--;
1283:            }
1284:
1285:            synchronized boolean usedInScoping() {
1286:                return (scopingRefCount > 0);
1287:            }
1288:
1289:            // Add a light to the list of lights
1290:            void addLight(LightRetained[] addlight, int numLgts, HashKey key) {
1291:                ArrayList l;
1292:                if (inSharedGroup) {
1293:                    int hkIndex = key.equals(localToVworldKeys, 0,
1294:                            localToVworldKeys.length);
1295:                    l = (ArrayList) lights.get(hkIndex);
1296:                    if (l != null) {
1297:                        for (int i = 0; i < numLgts; i++) {
1298:                            l.add(addlight[i]);
1299:                        }
1300:                    }
1301:                } else {
1302:                    l = (ArrayList) lights.get(0);
1303:                    for (int i = 0; i < numLgts; i++) {
1304:                        l.add(addlight[i]);
1305:                    }
1306:                }
1307:
1308:            }
1309:
1310:            // Add a fog to the list of fogs
1311:            void addFog(FogRetained fog, HashKey key) {
1312:                ArrayList l;
1313:                if (inSharedGroup) {
1314:                    int hkIndex = key.equals(localToVworldKeys, 0,
1315:                            localToVworldKeys.length);
1316:                    l = (ArrayList) fogs.get(hkIndex);
1317:                    if (l != null) {
1318:                        l.add(fog);
1319:                    }
1320:                } else {
1321:                    l = (ArrayList) fogs.get(0);
1322:                    l.add(fog);
1323:                }
1324:
1325:            }
1326:
1327:            // Add a ModelClip to the list of ModelClip
1328:            void addModelClip(ModelClipRetained modelClip, HashKey key) {
1329:                ArrayList l;
1330:                if (inSharedGroup) {
1331:                    int hkIndex = key.equals(localToVworldKeys, 0,
1332:                            localToVworldKeys.length);
1333:                    l = (ArrayList) modelClips.get(hkIndex);
1334:                    if (l != null) {
1335:                        l.add(modelClip);
1336:                    }
1337:                } else {
1338:                    l = (ArrayList) modelClips.get(0);
1339:                    l.add(modelClip);
1340:                }
1341:
1342:            }
1343:
1344:            // Add a alt appearance to the list of alt appearance
1345:            void addAltApp(AlternateAppearanceRetained altApp, HashKey key) {
1346:                ArrayList l;
1347:                if (inSharedGroup) {
1348:                    int hkIndex = key.equals(localToVworldKeys, 0,
1349:                            localToVworldKeys.length);
1350:                    l = (ArrayList) altAppearances.get(hkIndex);
1351:                    if (l != null) {
1352:                        l.add(altApp);
1353:                    }
1354:                } else {
1355:                    l = (ArrayList) altAppearances.get(0);
1356:                    l.add(altApp);
1357:                }
1358:
1359:            }
1360:
1361:            // Remove a fog from the list of fogs
1362:            void removeFog(FogRetained fog, HashKey key) {
1363:                ArrayList l;
1364:                int index;
1365:                if (inSharedGroup) {
1366:                    int hkIndex = key.equals(localToVworldKeys, 0,
1367:                            localToVworldKeys.length);
1368:                    l = (ArrayList) fogs.get(hkIndex);
1369:                    if (l != null) {
1370:                        index = l.indexOf(fog);
1371:                        l.remove(index);
1372:                    }
1373:                } else {
1374:                    l = (ArrayList) fogs.get(0);
1375:                    index = l.indexOf(fog);
1376:                    l.remove(index);
1377:                }
1378:
1379:            }
1380:
1381:            // Remove a ModelClip from the list of ModelClip
1382:            void removeModelClip(ModelClipRetained modelClip, HashKey key) {
1383:                ArrayList l;
1384:                int index;
1385:                if (inSharedGroup) {
1386:                    int hkIndex = key.equals(localToVworldKeys, 0,
1387:                            localToVworldKeys.length);
1388:                    l = (ArrayList) modelClips.get(hkIndex);
1389:                    if (l != null) {
1390:                        index = l.indexOf(modelClip);
1391:                        l.remove(index);
1392:                    }
1393:                } else {
1394:                    l = (ArrayList) modelClips.get(0);
1395:                    index = l.indexOf(modelClip);
1396:                    l.remove(index);
1397:                }
1398:            }
1399:
1400:            // Remove a fog from the list of alt appearance
1401:            void removeAltApp(AlternateAppearanceRetained altApp, HashKey key) {
1402:                ArrayList l;
1403:                int index;
1404:                if (inSharedGroup) {
1405:                    int hkIndex = key.equals(localToVworldKeys, 0,
1406:                            localToVworldKeys.length);
1407:                    l = (ArrayList) altAppearances.get(hkIndex);
1408:                    if (l != null) {
1409:                        index = l.indexOf(altApp);
1410:                        l.remove(index);
1411:                    }
1412:                } else {
1413:                    l = (ArrayList) altAppearances.get(0);
1414:                    index = l.indexOf(altApp);
1415:                    l.remove(index);
1416:                }
1417:
1418:            }
1419:
1420:            void updatePickable(HashKey keys[], boolean pick[]) {
1421:                int numChildLessOne = children.size() - 1;
1422:                super .updatePickable(keys, pick);
1423:                int i = 0;
1424:                NodeRetained child;
1425:
1426:                // Fix for issue 540
1427:                if (numChildLessOne < 0) {
1428:                    return;
1429:                }
1430:                // End fix for issue 540
1431:
1432:                for (i = 0; i < numChildLessOne; i++) {
1433:                    child = (NodeRetained) children.get(i);
1434:                    if (child != null)
1435:                        child.updatePickable(keys, (boolean[]) pick.clone());
1436:                }
1437:                // No need to clone for the last value
1438:
1439:                child = (NodeRetained) children.get(i);
1440:                if (child != null)
1441:                    child.updatePickable(keys, pick);
1442:
1443:            }
1444:
1445:            void updateCollidable(HashKey keys[], boolean collide[]) {
1446:                int numChildLessOne = children.size() - 1;
1447:                super .updateCollidable(keys, collide);
1448:                int i = 0;
1449:                NodeRetained child;
1450:
1451:                // Fix for issue 540
1452:                if (numChildLessOne < 0) {
1453:                    return;
1454:                }
1455:                // End fix for issue 540
1456:
1457:                for (i = 0; i < numChildLessOne; i++) {
1458:                    child = (NodeRetained) children.get(i);
1459:                    if (child != null)
1460:                        child.updateCollidable(keys, (boolean[]) collide
1461:                                .clone());
1462:                }
1463:                // No need to clone for the last value
1464:                child = (NodeRetained) children.get(i);
1465:                if (child != null)
1466:                    child.updateCollidable(keys, collide);
1467:            }
1468:
1469:            void setAlternateCollisionTarget(boolean target) {
1470:                if (collisionTarget == target)
1471:                    return;
1472:
1473:                collisionTarget = target;
1474:
1475:                if (source.isLive()) {
1476:                    // Notify parent TransformGroup to add itself
1477:                    // Since we want to update collisionVwcBounds when
1478:                    // transform change in TransformStructure.
1479:                    TransformGroupRetained tg;
1480:                    J3dMessage message = new J3dMessage();
1481:                    message.threads = J3dThread.UPDATE_GEOMETRY;
1482:                    message.universe = universe;
1483:                    // send message to GeometryStructure to add/remove this
1484:                    // group node in BHTree as AlternateCollisionTarget
1485:
1486:                    int numPath;
1487:                    CachedTargets newCtArr[] = null;
1488:
1489:                    if (target) {
1490:                        createMirrorGroup();
1491:
1492:                        TargetsInterface ti = getClosestTargetsInterface(TargetsInterface.TRANSFORM_TARGETS);
1493:                        if (ti != null) {
1494:
1495:                            // update targets
1496:                            CachedTargets ct;
1497:                            Targets targets = new Targets();
1498:                            numPath = mirrorGroup.size();
1499:                            newCtArr = new CachedTargets[numPath];
1500:                            for (int i = 0; i < numPath; i++) {
1501:                                ct = ti.getCachedTargets(
1502:                                        TargetsInterface.TRANSFORM_TARGETS, i,
1503:                                        -1);
1504:                                if (ct != null) {
1505:                                    targets.addNode((NnuId) mirrorGroup.get(i),
1506:                                            Targets.GRP_TARGETS);
1507:                                    newCtArr[i] = targets.snapShotAdd(ct);
1508:                                } else {
1509:                                    newCtArr[i] = null;
1510:                                }
1511:                            }
1512:
1513:                            // update target threads and propagate change to above
1514:                            // nodes in scene graph
1515:                            ti.updateTargetThreads(
1516:                                    TargetsInterface.TRANSFORM_TARGETS,
1517:                                    newCtArr);
1518:                            ti.resetCachedTargets(
1519:                                    TargetsInterface.TRANSFORM_TARGETS,
1520:                                    newCtArr, -1);
1521:                        }
1522:
1523:                        message.type = J3dMessage.INSERT_NODES;
1524:                        message.args[0] = mirrorGroup.toArray();
1525:                        message.args[1] = ti;
1526:                        message.args[2] = newCtArr;
1527:
1528:                    } else {
1529:                        TargetsInterface ti = getClosestTargetsInterface(TargetsInterface.TRANSFORM_TARGETS);
1530:                        if (ti != null) {
1531:
1532:                            // update targets
1533:                            Targets targets = new Targets();
1534:                            CachedTargets ct;
1535:                            numPath = mirrorGroup.size();
1536:                            newCtArr = new CachedTargets[numPath];
1537:                            for (int i = 0; i < numPath; i++) {
1538:                                ct = ti.getCachedTargets(
1539:                                        TargetsInterface.TRANSFORM_TARGETS, i,
1540:                                        -1);
1541:                                if (ct != null) {
1542:                                    targets.addNode((NnuId) mirrorGroup.get(i),
1543:                                            Targets.GRP_TARGETS);
1544:                                    //Note snapShotRemove calls targets.clearNode()
1545:                                    newCtArr[i] = targets.snapShotRemove(ct);
1546:                                } else {
1547:                                    newCtArr[i] = null;
1548:                                }
1549:                            }
1550:                            // update target threads and propagate change to above
1551:                            // nodes in scene graph
1552:                            ti.updateTargetThreads(
1553:                                    TargetsInterface.TRANSFORM_TARGETS,
1554:                                    newCtArr);
1555:                            ti.resetCachedTargets(
1556:                                    TargetsInterface.TRANSFORM_TARGETS,
1557:                                    newCtArr, -1);
1558:                        }
1559:
1560:                        message.type = J3dMessage.REMOVE_NODES;
1561:                        message.args[0] = mirrorGroup.toArray();
1562:                        message.args[1] = ti;
1563:                        message.args[2] = newCtArr;
1564:                        mirrorGroup = null; // for gc
1565:                    }
1566:                    VirtualUniverse.mc.processMessage(message);
1567:                }
1568:            }
1569:
1570:            boolean getAlternateCollisionTarget() {
1571:                return collisionTarget;
1572:            }
1573:
1574:            /**
1575:             * This checks is setLive needs to be called.  If it does, it gets the
1576:             * needed info and calls it.
1577:             */
1578:            void checkSetLive(NodeRetained child, int childIndex,
1579:                    J3dMessage messages[], int messageIndex,
1580:                    NodeRetained linkNode) {
1581:                checkSetLive(child, childIndex, localToVworldKeys,
1582:                        inSharedGroup, messages, messageIndex, linkNode);
1583:            }
1584:
1585:            /**
1586:             * This checks is setLive needs to be called.  If it does, it gets the
1587:             * needed info and calls it.
1588:             */
1589:            void checkSetLive(NodeRetained child, int childIndex,
1590:                    HashKey keys[], boolean isShared, J3dMessage messages[],
1591:                    int messageIndex, NodeRetained linkNode) {
1592:
1593:                SceneGraphObject me = this .source;
1594:                SetLiveState s;
1595:                J3dMessage createMessage;
1596:                boolean sendMessages = false;
1597:                boolean sendOGMessage = true;
1598:                boolean sendVSGMessage = true;
1599:
1600:                if (me.isLive()) {
1601:
1602:                    s = universe.setLiveState;
1603:                    s.reset(locale);
1604:                    s.refCount = refCount;
1605:                    s.inSharedGroup = isShared;
1606:                    s.inBackgroundGroup = inBackgroundGroup;
1607:                    s.inViewSpecificGroup = inViewSpecificGroup;
1608:                    s.geometryBackground = geometryBackground;
1609:                    s.keys = keys;
1610:                    s.viewLists = viewLists;
1611:                    s.parentBranchGroupPaths = branchGroupPaths;
1612:                    // Note that there is no need to clone individual
1613:                    // branchGroupArray since they will get replace (not append)
1614:                    // by creating a new reference in child's group.
1615:                    s.branchGroupPaths = (ArrayList) branchGroupPaths.clone();
1616:                    s.orderedPaths = orderedPaths;
1617:
1618:                    // Make the scoped fogs and lights of the child to include, the
1619:                    // the scoped fog of this group
1620:                    s.lights = lights;
1621:                    s.altAppearances = altAppearances;
1622:                    s.fogs = fogs;
1623:                    s.modelClips = modelClips;
1624:
1625:                    boolean pick[];
1626:                    boolean collide[];
1627:
1628:                    if (!inSharedGroup) {
1629:                        pick = new boolean[1];
1630:                        collide = new boolean[1];
1631:                    } else {
1632:                        pick = new boolean[localToVworldKeys.length];
1633:                        collide = new boolean[localToVworldKeys.length];
1634:                    }
1635:                    findPickableFlags(pick);
1636:                    super .updatePickable(null, pick);
1637:                    s.pickable = pick;
1638:
1639:                    findCollidableFlags(collide);
1640:                    super .updateCollidable(null, collide);
1641:                    s.collidable = collide;
1642:
1643:                    TargetsInterface transformInterface, switchInterface;
1644:                    transformInterface = initTransformStates(s, true);
1645:                    switchInterface = initSwitchStates(s, this , child,
1646:                            linkNode, true);
1647:
1648:                    if (s.inViewSpecificGroup && (s.changedViewGroup == null)) {
1649:                        s.changedViewGroup = new ArrayList();
1650:                        s.changedViewList = new ArrayList();
1651:                        s.keyList = new int[10];
1652:                        s.viewScopedNodeList = new ArrayList();
1653:                        s.scopedNodesViewList = new ArrayList();
1654:                    }
1655:
1656:                    childCheckSetLive(child, childIndex, s, linkNode);
1657:
1658:                    CachedTargets[] newCtArr = null;
1659:                    newCtArr = updateTransformStates(s, transformInterface,
1660:                            true);
1661:                    updateSwitchStates(s, switchInterface, true);
1662:
1663:                    // We're sending multiple messages in the call, inorder to
1664:                    // have all these messages to be process as an atomic operation.
1665:                    // We need to create an array of messages to MasterControl, this
1666:                    // will ensure that all these messages will get the same time stamp.
1667:
1668:                    // If it is called from "moveTo",  messages is not null. 
1669:                    if (messages == null) {
1670:                        int numMessages = 2;
1671:                        if (s.ogList.size() > 0) {
1672:                            numMessages++;
1673:                        } else {
1674:                            sendOGMessage = false;
1675:                        }
1676:                        if (s.changedViewGroup != null) {
1677:                            numMessages++;
1678:                        } else {
1679:                            sendVSGMessage = false;
1680:                        }
1681:
1682:                        messages = new J3dMessage[numMessages];
1683:                        messageIndex = 0;
1684:                        for (int mIndex = 0; mIndex < numMessages; mIndex++) {
1685:                            messages[mIndex] = new J3dMessage();
1686:                        }
1687:                        sendMessages = true;
1688:                    }
1689:
1690:                    if (sendOGMessage) {
1691:                        createMessage = messages[messageIndex++];
1692:                        createMessage.threads = J3dThread.UPDATE_RENDER
1693:                                | J3dThread.UPDATE_RENDERING_ENVIRONMENT;
1694:                        createMessage.type = J3dMessage.ORDERED_GROUP_INSERTED;
1695:                        createMessage.universe = universe;
1696:                        createMessage.args[0] = s.ogList.toArray();
1697:                        createMessage.args[1] = s.ogChildIdList.toArray();
1698:                        createMessage.args[2] = s.ogOrderedIdList.toArray();
1699:                        createMessage.args[3] = s.ogCIOList.toArray();
1700:                        createMessage.args[4] = s.ogCIOTableList.toArray();
1701:                    }
1702:
1703:                    if (sendVSGMessage) {
1704:                        createMessage = messages[messageIndex++];
1705:                        createMessage.threads = J3dThread.UPDATE_RENDERING_ENVIRONMENT;
1706:                        createMessage.type = J3dMessage.VIEWSPECIFICGROUP_INIT;
1707:                        createMessage.universe = universe;
1708:                        createMessage.args[0] = s.changedViewGroup;
1709:                        createMessage.args[1] = s.changedViewList;
1710:                        createMessage.args[2] = s.keyList;
1711:                    }
1712:
1713:                    createMessage = messages[messageIndex++];
1714:                    createMessage.threads = s.notifyThreads;
1715:                    createMessage.type = J3dMessage.INSERT_NODES;
1716:                    createMessage.universe = universe;
1717:                    createMessage.args[0] = s.nodeList.toArray();
1718:                    if (newCtArr != null) {
1719:                        createMessage.args[1] = transformInterface;
1720:                        createMessage.args[2] = newCtArr;
1721:                    } else {
1722:                        createMessage.args[1] = null;
1723:                        createMessage.args[2] = null;
1724:                    }
1725:
1726:                    if (s.viewScopedNodeList != null) {
1727:                        createMessage.args[3] = s.viewScopedNodeList;
1728:                        createMessage.args[4] = s.scopedNodesViewList;
1729:                    }
1730:
1731:                    // execute user behavior's initialize methods
1732:                    int sz = s.behaviorNodes.size();
1733:
1734:                    for (int i = 0; i < sz; i++) {
1735:                        BehaviorRetained b;
1736:                        b = (BehaviorRetained) s.behaviorNodes.get(i);
1737:                        b.executeInitialize();
1738:                    }
1739:
1740:                    s.behaviorNodes.clear();
1741:
1742:                    createMessage = messages[messageIndex++];
1743:
1744:                    createMessage.threads = J3dThread.UPDATE_BEHAVIOR;
1745:                    createMessage.type = J3dMessage.BEHAVIOR_ACTIVATE;
1746:                    createMessage.universe = universe;
1747:
1748:                    if (sendMessages == true) {
1749:                        VirtualUniverse.mc.processMessage(messages);
1750:                    }
1751:
1752:                    if (nodeType == NodeRetained.SWITCH) {
1753:                        // force reEvaluation of switch children
1754:                        SwitchRetained sw = (SwitchRetained) this ;
1755:                        sw.setWhichChild(sw.whichChild, true);
1756:                    }
1757:
1758:                    //Reset SetLiveState to free up memory.
1759:                    s.reset(null);
1760:                }
1761:            }
1762:
1763:            void checkClearLive(NodeRetained child, J3dMessage messages[],
1764:                    int messageIndex, int childIndex, NodeRetained linkNode) {
1765:                checkClearLive(child, localToVworldKeys, inSharedGroup,
1766:                        messages, messageIndex, childIndex, linkNode);
1767:            }
1768:
1769:            /**
1770:             * This checks if clearLive needs to be called.  If it does, it gets the
1771:             * needed info and calls it.
1772:             */
1773:            void checkClearLive(NodeRetained child, HashKey keys[],
1774:                    boolean isShared, J3dMessage messages[], int messageIndex,
1775:                    int childIndex, NodeRetained linkNode) {
1776:
1777:                SceneGraphObject me = this .source;
1778:                J3dMessage destroyMessage;
1779:                boolean sendMessages = false;
1780:                boolean sendOGMessage = true;
1781:                boolean sendVSGMessage = true;
1782:
1783:                int i, j;
1784:                TransformGroupRetained tg;
1785:
1786:                if (me.isLive()) {
1787:                    SetLiveState s = universe.setLiveState;
1788:
1789:                    s.reset(locale);
1790:                    s.refCount = refCount;
1791:                    s.inSharedGroup = isShared;
1792:                    s.inBackgroundGroup = inBackgroundGroup;
1793:                    s.inViewSpecificGroup = inViewSpecificGroup;
1794:                    s.keys = keys;
1795:                    s.fogs = fogs;
1796:                    s.lights = lights;
1797:                    s.altAppearances = altAppearances;
1798:                    s.modelClips = modelClips;
1799:
1800:                    // Issue 312: Allocate data structures if we are in a ViewSpecificGroup
1801:                    if (s.inViewSpecificGroup && (s.changedViewGroup == null)) {
1802:                        s.changedViewGroup = new ArrayList();
1803:                        s.changedViewList = new ArrayList();
1804:                        s.keyList = new int[10];
1805:                        s.viewScopedNodeList = new ArrayList();
1806:                        s.scopedNodesViewList = new ArrayList();
1807:                    }
1808:
1809:                    if (this  instanceof  OrderedGroupRetained
1810:                            && linkNode == null) {
1811:                        // set this regardless of refCount
1812:                        s.ogList.add(this );
1813:                        s.ogChildIdList.add(new Integer(childIndex));
1814:                        s.ogCIOList.add(this );
1815:                        int[] newArr = null;
1816:                        OrderedGroupRetained og = (OrderedGroupRetained) this ;
1817:                        if (og.userChildIndexOrder != null) {
1818:                            newArr = new int[og.userChildIndexOrder.length];
1819:                            System.arraycopy(og.userChildIndexOrder, 0, newArr,
1820:                                    0, og.userChildIndexOrder.length);
1821:                        }
1822:                        s.ogCIOTableList.add(newArr);
1823:
1824:                    }
1825:
1826:                    // Issue 312: always initialize s.viewLists
1827:                    s.viewLists = viewLists;
1828:
1829:                    TargetsInterface transformInterface, switchInterface;
1830:                    transformInterface = initTransformStates(s, false);
1831:                    switchInterface = initSwitchStates(s, this , child,
1832:                            linkNode, false);
1833:
1834:                    child.clearLive(s);
1835:
1836:                    CachedTargets[] newCtArr = null;
1837:                    newCtArr = updateTransformStates(s, transformInterface,
1838:                            false);
1839:                    updateSwitchStates(s, switchInterface, false);
1840:
1841:                    // We're sending multiple messages in the call, inorder to
1842:                    // have all these messages to be process as an atomic operation.
1843:                    // We need to create an array of messages to MasterControl, this
1844:                    // will ensure that all these messages will get the same time stamp.
1845:
1846:                    // If it is called from "moveTo",  messages is not null.
1847:                    if (messages == null) {
1848:                        int numMessages = 1;
1849:                        if (s.ogList.size() > 0) {
1850:                            numMessages++;
1851:                        } else {
1852:                            sendOGMessage = false;
1853:                        }
1854:
1855:                        if (s.changedViewGroup != null) {
1856:                            numMessages++;
1857:                        } else {
1858:                            sendVSGMessage = false;
1859:                        }
1860:
1861:                        messages = new J3dMessage[numMessages];
1862:                        messageIndex = 0;
1863:                        for (int mIndex = 0; mIndex < numMessages; mIndex++) {
1864:                            messages[mIndex] = new J3dMessage();
1865:                        }
1866:                        sendMessages = true;
1867:                    }
1868:
1869:                    if (sendOGMessage) {
1870:                        destroyMessage = messages[messageIndex++];
1871:                        destroyMessage.threads = J3dThread.UPDATE_RENDER
1872:                                | J3dThread.UPDATE_RENDERING_ENVIRONMENT;
1873:                        destroyMessage.type = J3dMessage.ORDERED_GROUP_REMOVED;
1874:                        destroyMessage.universe = universe;
1875:                        destroyMessage.args[0] = s.ogList.toArray();
1876:                        destroyMessage.args[1] = s.ogChildIdList.toArray();
1877:                        destroyMessage.args[3] = s.ogCIOList.toArray();
1878:                        destroyMessage.args[4] = s.ogCIOTableList.toArray();
1879:                    }
1880:
1881:                    // Issue 312: We need to send the REMOVE_NODES message to the
1882:                    // RenderingEnvironmentStructure before we send VIEWSPECIFICGROUP_CLEAR,
1883:                    // since the latter clears the list of views that is referred to by
1884:                    // scopedNodesViewList and used by removeNodes.
1885:                    destroyMessage = messages[messageIndex++];
1886:                    destroyMessage.threads = s.notifyThreads;
1887:                    destroyMessage.type = J3dMessage.REMOVE_NODES;
1888:                    destroyMessage.universe = universe;
1889:                    destroyMessage.args[0] = s.nodeList.toArray();
1890:
1891:                    if (newCtArr != null) {
1892:                        destroyMessage.args[1] = transformInterface;
1893:                        destroyMessage.args[2] = newCtArr;
1894:                    } else {
1895:                        destroyMessage.args[1] = null;
1896:                        destroyMessage.args[2] = null;
1897:                    }
1898:                    if (s.viewScopedNodeList != null) {
1899:                        destroyMessage.args[3] = s.viewScopedNodeList;
1900:                        destroyMessage.args[4] = s.scopedNodesViewList;
1901:                    }
1902:
1903:                    if (sendVSGMessage) {
1904:                        destroyMessage = messages[messageIndex++];
1905:                        destroyMessage.threads = J3dThread.UPDATE_RENDERING_ENVIRONMENT;
1906:                        destroyMessage.type = J3dMessage.VIEWSPECIFICGROUP_CLEAR;
1907:                        destroyMessage.universe = universe;
1908:                        destroyMessage.args[0] = s.changedViewGroup;
1909:                        destroyMessage.args[1] = s.keyList;
1910:                    }
1911:
1912:                    if (sendMessages == true) {
1913:                        VirtualUniverse.mc.processMessage(messages);
1914:                    }
1915:
1916:                    s.reset(null); // for GC
1917:                }
1918:            }
1919:
1920:            TargetsInterface initTransformStates(SetLiveState s,
1921:                    boolean isSetLive) {
1922:
1923:                int numPaths = (inSharedGroup) ? s.keys.length : 1;
1924:                TargetsInterface ti = getClosestTargetsInterface(TargetsInterface.TRANSFORM_TARGETS);
1925:
1926:                if (isSetLive) {
1927:                    s.currentTransforms = localToVworld;
1928:                    s.currentTransformsIndex = localToVworldIndex;
1929:                    s.localToVworldKeys = localToVworldKeys;
1930:                    s.localToVworld = s.currentTransforms;
1931:                    s.localToVworldIndex = s.currentTransformsIndex;
1932:
1933:                    s.parentTransformLink = parentTransformLink;
1934:                    if (parentTransformLink != null) {
1935:                        if (parentTransformLink instanceof  TransformGroupRetained) {
1936:                            TransformGroupRetained tg;
1937:                            tg = (TransformGroupRetained) parentTransformLink;
1938:                            s.childTransformLinks = tg.childTransformLinks;
1939:                        } else {
1940:                            SharedGroupRetained sg;
1941:                            sg = (SharedGroupRetained) parentTransformLink;
1942:                            s.childTransformLinks = sg.childTransformLinks;
1943:                        }
1944:                    }
1945:                }
1946:
1947:                int transformLevels[] = new int[numPaths];
1948:                findTransformLevels(transformLevels);
1949:                s.transformLevels = transformLevels;
1950:
1951:                if (ti != null) {
1952:                    Targets[] newTargets = new Targets[numPaths];
1953:                    for (int i = 0; i < numPaths; i++) {
1954:                        if (s.transformLevels[i] >= 0) {
1955:                            newTargets[i] = new Targets();
1956:                        } else {
1957:                            newTargets[i] = null;
1958:                        }
1959:                    }
1960:                    s.transformTargets = newTargets;
1961:
1962:                    // XXXX: optimization for targetThreads computation, require
1963:                    // cleanup in GroupRetained.doSetLive()
1964:                    //s.transformTargetThreads = 0;
1965:                }
1966:
1967:                return ti;
1968:            }
1969:
1970:            CachedTargets[] updateTransformStates(SetLiveState s,
1971:                    TargetsInterface ti, boolean isSetLive) {
1972:                CachedTargets[] newCtArr = null;
1973:
1974:                if (ti != null) {
1975:                    if (isSetLive) {
1976:                        CachedTargets ct;
1977:                        int newTargetThreads = 0;
1978:                        int hkIndex;
1979:
1980:                        newCtArr = new CachedTargets[localToVworld.length];
1981:
1982:                        // update targets
1983:                        if (!inSharedGroup) {
1984:                            if (s.transformTargets[0] != null) {
1985:                                ct = ti.getCachedTargets(
1986:                                        TargetsInterface.TRANSFORM_TARGETS, 0,
1987:                                        -1);
1988:                                if (ct != null) {
1989:                                    newCtArr[0] = s.transformTargets[0]
1990:                                            .snapShotAdd(ct);
1991:                                }
1992:                            } else {
1993:                                newCtArr[0] = null;
1994:                            }
1995:                        } else {
1996:                            for (int i = 0; i < s.keys.length; i++) {
1997:
1998:                                if (s.transformTargets[i] != null) {
1999:                                    ct = ti.getCachedTargets(
2000:                                            TargetsInterface.TRANSFORM_TARGETS,
2001:                                            i, -1);
2002:                                    if (ct != null) {
2003:                                        newCtArr[i] = s.transformTargets[i]
2004:                                                .snapShotAdd(ct);
2005:                                    }
2006:                                } else {
2007:                                    newCtArr[i] = null;
2008:                                }
2009:                            }
2010:                        }
2011:                    } else {
2012:
2013:                        CachedTargets ct;
2014:                        int hkIndex;
2015:
2016:                        newCtArr = new CachedTargets[localToVworld.length];
2017:
2018:                        if (!inSharedGroup) {
2019:                            if (s.transformTargets[0] != null) {
2020:                                ct = ti.getCachedTargets(
2021:                                        TargetsInterface.TRANSFORM_TARGETS, 0,
2022:                                        -1);
2023:                                if (ct != null) {
2024:                                    newCtArr[0] = s.transformTargets[0]
2025:                                            .snapShotRemove(ct);
2026:                                }
2027:                            } else {
2028:                                newCtArr[0] = null;
2029:                            }
2030:                        } else {
2031:                            for (int i = 0; i < s.keys.length; i++) {
2032:                                if (s.transformTargets[i] != null) {
2033:                                    ct = ti.getCachedTargets(
2034:                                            TargetsInterface.TRANSFORM_TARGETS,
2035:                                            i, -1);
2036:                                    if (ct != null) {
2037:                                        newCtArr[i] = s.transformTargets[i]
2038:                                                .snapShotRemove(ct);
2039:                                    }
2040:                                } else {
2041:                                    newCtArr[i] = null;
2042:                                }
2043:                            }
2044:                        }
2045:                    }
2046:                    // update target threads and propagate change to above
2047:                    // nodes in scene graph
2048:
2049:                    ti.updateTargetThreads(TargetsInterface.TRANSFORM_TARGETS,
2050:                            newCtArr);
2051:                    ti.resetCachedTargets(TargetsInterface.TRANSFORM_TARGETS,
2052:                            newCtArr, -1);
2053:
2054:                }
2055:                return newCtArr;
2056:            }
2057:
2058:            TargetsInterface initSwitchStates(SetLiveState s,
2059:                    NodeRetained parentNode, NodeRetained childNode,
2060:                    NodeRetained linkNode, boolean isSetLive) {
2061:                NodeRetained child;
2062:                NodeRetained parent;
2063:                int i, j;
2064:
2065:                findSwitchInfo(s, parentNode, childNode, linkNode);
2066:                TargetsInterface ti = getClosestTargetsInterface(TargetsInterface.SWITCH_TARGETS);
2067:                if (ti != null) {
2068:                    Targets[] newTargets = null;
2069:                    int numPaths = (inSharedGroup) ? s.keys.length : 1;
2070:                    newTargets = new Targets[numPaths];
2071:                    for (i = 0; i < numPaths; i++) {
2072:                        if (s.switchLevels[i] >= 0) {
2073:                            newTargets[i] = new Targets();
2074:                        } else {
2075:                            newTargets[i] = null;
2076:                        }
2077:                    }
2078:                    s.switchTargets = newTargets;
2079:                }
2080:
2081:                if (isSetLive) {
2082:                    // set switch states
2083:                    if (nodeType == NodeRetained.SWITCH) {
2084:                        i = parentSwitchLinkChildIndex;
2085:                        s.childSwitchLinks = (ArrayList) childrenSwitchLinks
2086:                                .get(i);
2087:                        s.parentSwitchLink = this ;
2088:
2089:                    } else {
2090:                        if (nodeType == NodeRetained.SHAREDGROUP) {
2091:                            i = parentSwitchLinkChildIndex;
2092:                            s.childSwitchLinks = (ArrayList) childrenSwitchLinks
2093:                                    .get(i);
2094:                            s.parentSwitchLink = this ;
2095:
2096:                        } else {
2097:                            s.parentSwitchLink = parentSwitchLink;
2098:                            if (parentSwitchLink != null) {
2099:                                i = parentSwitchLinkChildIndex;
2100:                                s.childSwitchLinks = (ArrayList) parentSwitchLink.childrenSwitchLinks
2101:                                        .get(i);
2102:                            }
2103:                        }
2104:                    }
2105:                    if (ti != null) {
2106:                        s.switchStates = ti.getTargetsData(
2107:                                TargetsInterface.SWITCH_TARGETS,
2108:                                parentSwitchLinkChildIndex);
2109:                    } else {
2110:                        s.switchStates = new ArrayList(1);
2111:                        s.switchStates.add(new SwitchState(false));
2112:                    }
2113:                }
2114:                return ti;
2115:            }
2116:
2117:            void updateSwitchStates(SetLiveState s, TargetsInterface ti,
2118:                    boolean isSetLive) {
2119:
2120:                // update switch leaves's compositeSwitchMask for ancestors
2121:                // and update switch leaves' switchOn flag if at top level switch
2122:
2123:                if (ti != null) {
2124:                    if (isSetLive) {
2125:                        CachedTargets[] newCtArr = null;
2126:                        CachedTargets ct;
2127:
2128:                        newCtArr = new CachedTargets[localToVworld.length];
2129:
2130:                        // update targets
2131:                        if (!inSharedGroup) {
2132:
2133:                            if (s.switchTargets[0] != null) {
2134:                                ct = ti.getCachedTargets(
2135:                                        TargetsInterface.SWITCH_TARGETS, 0,
2136:                                        parentSwitchLinkChildIndex);
2137:                                if (ct != null) {
2138:                                    newCtArr[0] = s.switchTargets[0]
2139:                                            .snapShotAdd(ct);
2140:                                } else {
2141:                                    newCtArr[0] = s.switchTargets[0]
2142:                                            .snapShotInit();
2143:                                }
2144:                            } else {
2145:                                newCtArr[0] = null;
2146:                            }
2147:                        } else {
2148:                            for (int i = 0; i < s.keys.length; i++) {
2149:                                if (s.switchTargets[i] != null) {
2150:                                    ct = ti.getCachedTargets(
2151:                                            TargetsInterface.SWITCH_TARGETS, i,
2152:                                            parentSwitchLinkChildIndex);
2153:                                    if (ct != null) {
2154:                                        newCtArr[i] = s.switchTargets[i]
2155:                                                .snapShotAdd(ct);
2156:                                    } else {
2157:                                        newCtArr[i] = s.switchTargets[i]
2158:                                                .snapShotInit();
2159:                                    }
2160:                                } else {
2161:                                    newCtArr[i] = null;
2162:                                }
2163:                            }
2164:                        }
2165:                        ti.resetCachedTargets(TargetsInterface.SWITCH_TARGETS,
2166:                                newCtArr, parentSwitchLinkChildIndex);
2167:                        if (ti instanceof  SwitchRetained) {
2168:                            ((SwitchRetained) ti).traverseSwitchParent();
2169:                        } else if (ti instanceof  SharedGroupRetained) {
2170:                            ((SharedGroupRetained) ti).traverseSwitchParent();
2171:                        }
2172:                    } else {
2173:                        CachedTargets ct;
2174:
2175:                        CachedTargets[] newCtArr = new CachedTargets[localToVworld.length];
2176:
2177:                        if (!inSharedGroup) {
2178:                            if (s.switchTargets[0] != null) {
2179:                                ct = ti.getCachedTargets(
2180:                                        TargetsInterface.SWITCH_TARGETS, 0,
2181:                                        parentSwitchLinkChildIndex);
2182:                                if (ct != null) {
2183:                                    newCtArr[0] = s.switchTargets[0]
2184:                                            .snapShotRemove(ct);
2185:                                }
2186:                            } else {
2187:                                newCtArr[0] = null;
2188:                            }
2189:                        } else {
2190:                            for (int i = 0; i < s.keys.length; i++) {
2191:                                if (s.switchTargets[i] != null) {
2192:                                    ct = ti.getCachedTargets(
2193:                                            TargetsInterface.SWITCH_TARGETS, i,
2194:                                            parentSwitchLinkChildIndex);
2195:
2196:                                    if (ct != null) {
2197:                                        newCtArr[i] = s.switchTargets[i]
2198:                                                .snapShotRemove(ct);
2199:                                    }
2200:                                } else {
2201:                                    newCtArr[i] = null;
2202:                                }
2203:                            }
2204:                        }
2205:                        ti.resetCachedTargets(TargetsInterface.SWITCH_TARGETS,
2206:                                newCtArr, parentSwitchLinkChildIndex);
2207:                    }
2208:                }
2209:            }
2210:
2211:            void appendChildrenData() {
2212:            }
2213:
2214:            void insertChildrenData(int index) {
2215:            }
2216:
2217:            void removeChildrenData(int index) {
2218:            }
2219:
2220:            TargetsInterface getClosestTargetsInterface(int type) {
2221:                return (type == TargetsInterface.TRANSFORM_TARGETS) ? (TargetsInterface) parentTransformLink
2222:                        : (TargetsInterface) parentSwitchLink;
2223:            }
2224:
2225:            synchronized void updateLocalToVworld() {
2226:                NodeRetained child;
2227:
2228:                // For each children call .....
2229:                for (int i = children.size() - 1; i >= 0; i--) {
2230:                    child = (NodeRetained) children.get(i);
2231:                    if (child != null)
2232:                        child.updateLocalToVworld();
2233:                }
2234:            }
2235:
2236:            void setNodeData(SetLiveState s) {
2237:                super .setNodeData(s);
2238:                orderedPaths = s.orderedPaths;
2239:            }
2240:
2241:            void removeNodeData(SetLiveState s) {
2242:
2243:                if ((!inSharedGroup) || (s.keys.length == localToVworld.length)) {
2244:                    orderedPaths = null;
2245:                } else {
2246:                    // Set it back to its parent localToVworld data. This is b/c the
2247:                    // parent has changed it localToVworld data arrays.
2248:                    orderedPaths = s.orderedPaths;
2249:                }
2250:                super .removeNodeData(s);
2251:            }
2252:
2253:            void setLive(SetLiveState s) {
2254:                doSetLive(s);
2255:                super .markAsLive();
2256:            }
2257:
2258:            // Note that SwitchRetained, OrderedGroupRetained and SharedGroupRetained
2259:            // override this method
2260:            void childDoSetLive(NodeRetained child, int childIndex,
2261:                    SetLiveState s) {
2262:                if (child != null)
2263:                    child.setLive(s);
2264:            }
2265:
2266:            // Note that BranchRetained, OrderedGroupRetained and SharedGroupRetained
2267:            // TransformGroupRetained override this method
2268:            void childCheckSetLive(NodeRetained child, int childIndex,
2269:                    SetLiveState s, NodeRetained linkNode) {
2270:                child.setLive(s);
2271:            }
2272:
2273:            /**
2274:             * This version of setLive calls setLive on all of its chidren.
2275:             */
2276:            void doSetLive(SetLiveState s) {
2277:                int i, nchildren;
2278:                NodeRetained child;
2279:                super .doSetLive(s);
2280:                locale = s.locale;
2281:
2282:                inViewSpecificGroup = s.inViewSpecificGroup;
2283:                nchildren = children.size();
2284:                ArrayList savedScopedLights = s.lights;
2285:                ArrayList savedScopedFogs = s.fogs;
2286:                ArrayList savedScopedAltApps = s.altAppearances;
2287:                ArrayList savedScopedMclips = s.modelClips;
2288:
2289:                boolean oldpickableArray[] = (boolean[]) s.pickable.clone();
2290:                boolean oldcollidableArray[] = (boolean[]) s.collidable.clone();
2291:                boolean workingpickableArray[] = new boolean[oldpickableArray.length];
2292:                boolean workingcollidableArray[] = new boolean[oldcollidableArray.length];
2293:                ArrayList oldBranchGroupPaths = s.branchGroupPaths;
2294:                setScopingInfo(s);
2295:
2296:                if (!(this  instanceof  ViewSpecificGroupRetained)) {
2297:                    viewLists = s.viewLists;
2298:                }
2299:
2300:                for (i = 0; i < nchildren; i++) {
2301:                    child = (NodeRetained) children.get(i);
2302:
2303:                    // Restore old values before child.setLive(s)
2304:                    System.arraycopy(oldpickableArray, 0, workingpickableArray,
2305:                            0, oldpickableArray.length);
2306:                    System.arraycopy(oldcollidableArray, 0,
2307:                            workingcollidableArray, 0,
2308:                            oldcollidableArray.length);
2309:                    s.pickable = workingpickableArray;
2310:                    s.collidable = workingcollidableArray;
2311:                    // s.branchGroupPaths will be modified by child setLive()
2312:                    // so we have to restore it every time.
2313:                    s.parentBranchGroupPaths = branchGroupPaths;
2314:                    s.branchGroupPaths = (ArrayList) oldBranchGroupPaths
2315:                            .clone();
2316:                    s.inViewSpecificGroup = inViewSpecificGroup;
2317:                    childDoSetLive(child, i, s);
2318:                }
2319:
2320:                if (collisionTarget) {
2321:                    processCollisionTarget(s);
2322:                }
2323:
2324:                s.lights = savedScopedLights;
2325:                s.fogs = savedScopedFogs;
2326:                s.altAppearances = savedScopedAltApps;
2327:                s.modelClips = savedScopedMclips;
2328:            }
2329:
2330:            void setScopingInfo(SetLiveState s) {
2331:
2332:                int i, k, hkIndex;
2333:                // If this is a scoped group , then copy the parent's
2334:                // scoping info
2335:                if (allocatedLights) {
2336:                    if (s.lights != null) {
2337:                        // Add the parent's scoping info to this group
2338:                        if (inSharedGroup) {
2339:                            for (i = 0; i < s.keys.length; i++) {
2340:                                hkIndex = s.keys[i].equals(localToVworldKeys,
2341:                                        0, localToVworldKeys.length);
2342:                                ArrayList l = (ArrayList) lights.get(hkIndex);
2343:                                ArrayList src = (ArrayList) s.lights.get(i);
2344:                                if (src != null) {
2345:                                    int size = src.size();
2346:                                    for (k = 0; k < size; k++) {
2347:                                        l.add(src.get(k));
2348:                                    }
2349:                                }
2350:
2351:                            }
2352:                        } else {
2353:                            ArrayList l = (ArrayList) lights.get(0);
2354:                            ArrayList src = (ArrayList) s.lights.get(0);
2355:                            int size = src.size();
2356:                            for (i = 0; i < size; i++) {
2357:                                l.add(src.get(i));
2358:                            }
2359:                        }
2360:                    }
2361:                    s.lights = lights;
2362:                } else {
2363:                    lights = s.lights;
2364:                }
2365:
2366:                if (allocatedFogs) {
2367:                    if (s.fogs != null) {
2368:                        // Add the parent's scoping info to this group
2369:                        if (inSharedGroup) {
2370:                            for (i = 0; i < s.keys.length; i++) {
2371:                                hkIndex = s.keys[i].equals(localToVworldKeys,
2372:                                        0, localToVworldKeys.length);
2373:                                ArrayList l = (ArrayList) fogs.get(hkIndex);
2374:                                ArrayList src = (ArrayList) s.fogs.get(i);
2375:                                if (src != null) {
2376:                                    int size = src.size();
2377:                                    for (k = 0; k < size; k++) {
2378:                                        l.add(src.get(k));
2379:                                    }
2380:                                }
2381:
2382:                            }
2383:                        } else {
2384:                            ArrayList l = (ArrayList) fogs.get(0);
2385:                            ArrayList src = (ArrayList) s.fogs.get(0);
2386:                            int size = src.size();
2387:                            for (i = 0; i < size; i++) {
2388:                                l.add(src.get(i));
2389:                            }
2390:                        }
2391:                    }
2392:                    s.fogs = fogs;
2393:                } else {
2394:                    fogs = s.fogs;
2395:                }
2396:
2397:                if (allocatedMclips) {
2398:                    if (s.modelClips != null) {
2399:                        // Add the parent's scoping info to this group
2400:                        if (inSharedGroup) {
2401:                            for (i = 0; i < s.keys.length; i++) {
2402:                                hkIndex = s.keys[i].equals(localToVworldKeys,
2403:                                        0, localToVworldKeys.length);
2404:                                ArrayList l = (ArrayList) modelClips
2405:                                        .get(hkIndex);
2406:                                ArrayList src = (ArrayList) s.modelClips.get(i);
2407:                                if (src != null) {
2408:                                    int size = src.size();
2409:                                    for (k = 0; k < size; k++) {
2410:                                        l.add(src.get(k));
2411:                                    }
2412:                                }
2413:
2414:                            }
2415:                        } else {
2416:                            ArrayList l = (ArrayList) modelClips.get(0);
2417:                            ArrayList src = (ArrayList) s.modelClips.get(0);
2418:                            int size = src.size();
2419:                            for (i = 0; i < size; i++) {
2420:                                l.add(src.get(i));
2421:                            }
2422:                        }
2423:                    }
2424:                    s.modelClips = modelClips;
2425:                } else {
2426:                    modelClips = s.modelClips;
2427:                }
2428:
2429:                if (allocatedAltApps) {
2430:                    if (s.altAppearances != null) {
2431:                        // Add the parent's scoping info to this group
2432:                        if (inSharedGroup) {
2433:                            for (i = 0; i < s.keys.length; i++) {
2434:                                hkIndex = s.keys[i].equals(localToVworldKeys,
2435:                                        0, localToVworldKeys.length);
2436:                                ArrayList l = (ArrayList) altAppearances
2437:                                        .get(hkIndex);
2438:                                ArrayList src = (ArrayList) s.altAppearances
2439:                                        .get(i);
2440:                                if (src != null) {
2441:                                    int size = src.size();
2442:                                    for (k = 0; k < size; k++) {
2443:                                        l.add(src.get(k));
2444:                                    }
2445:                                }
2446:
2447:                            }
2448:                        } else {
2449:                            ArrayList l = (ArrayList) altAppearances.get(0);
2450:                            ArrayList src = (ArrayList) s.altAppearances.get(0);
2451:                            int size = src.size();
2452:                            for (i = 0; i < size; i++) {
2453:                                l.add(src.get(i));
2454:                            }
2455:                        }
2456:                    }
2457:                    s.altAppearances = altAppearances;
2458:                } else {
2459:                    altAppearances = s.altAppearances;
2460:                }
2461:            }
2462:
2463:            void processCollisionTarget(SetLiveState s) {
2464:
2465:                GroupRetained g;
2466:                if (mirrorGroup == null) {
2467:                    mirrorGroup = new ArrayList();
2468:                }
2469:                Bounds bound = (collisionBound != null ? collisionBound
2470:                        : getEffectiveBounds());
2471:                if (inSharedGroup) {
2472:                    for (int i = 0; i < s.keys.length; i++) {
2473:                        int j;
2474:                        g = new GroupRetained();
2475:                        g.key = s.keys[i];
2476:                        g.localToVworld = new Transform3D[1][];
2477:                        g.localToVworldIndex = new int[1][];
2478:
2479:                        j = s.keys[i].equals(localToVworldKeys, 0,
2480:                                localToVworldKeys.length);
2481:                        if (j < 0) {
2482:                            System.err
2483:                                    .println("GroupRetained : Can't find hashKey");
2484:                        }
2485:
2486:                        g.localToVworld[0] = localToVworld[j];
2487:                        g.localToVworldIndex[0] = localToVworldIndex[j];
2488:                        g.collisionVwcBounds = new BoundingBox();
2489:                        g.collisionVwcBounds.transform(bound, g
2490:                                .getCurrentLocalToVworld(0));
2491:                        g.sourceNode = this ;
2492:                        g.locale = locale; // need by getVisibleGeometryAtom()
2493:                        mirrorGroup.add(g);
2494:                        /*
2495:                          System.err.println("processCollisionTarget mirrorGroup.add() : " +
2496:                          g.getId() + " mirrorGroup.size() "
2497:                          + mirrorGroup.size());
2498:                         */
2499:                        if (s.transformTargets != null
2500:                                && s.transformTargets[i] != null) {
2501:                            s.transformTargets[i].addNode(g,
2502:                                    Targets.GRP_TARGETS);
2503:                        }
2504:                        s.nodeList.add(g);
2505:                    }
2506:                } else {
2507:                    g = new GroupRetained();
2508:                    g.localToVworld = new Transform3D[1][];
2509:                    g.localToVworldIndex = new int[1][];
2510:                    g.localToVworld[0] = localToVworld[0];
2511:                    g.localToVworldIndex[0] = localToVworldIndex[0];
2512:                    g.collisionVwcBounds = new BoundingBox();
2513:                    g.collisionVwcBounds.transform(bound, g
2514:                            .getCurrentLocalToVworld(0));
2515:                    g.sourceNode = this ;
2516:                    g.locale = locale; // need by getVisibleGeometryAtom()
2517:                    mirrorGroup.add(g);
2518:                    if (s.transformTargets != null
2519:                            && s.transformTargets[0] != null) {
2520:                        s.transformTargets[0].addNode(g, Targets.GRP_TARGETS);
2521:                    }
2522:                    s.nodeList.add(g);
2523:                }
2524:            }
2525:
2526:            void computeCombineBounds(Bounds bounds) {
2527:                if (!VirtualUniverse.mc.cacheAutoComputedBounds) {
2528:                    if (boundsAutoCompute) {
2529:                        for (int i = children.size() - 1; i >= 0; i--) {
2530:                            NodeRetained child = (NodeRetained) children.get(i);
2531:                            if (child != null)
2532:                                child.computeCombineBounds(bounds);
2533:                        }
2534:                    } else {
2535:                        // Should this be lock too ? ( MT safe  ? )
2536:                        synchronized (localBounds) {
2537:                            bounds.combine(localBounds);
2538:                        }
2539:                    }
2540:                } else {
2541:                    // Issue 514 : NPE in Wonderland : triggered in cached bounds computation
2542:                    if (validCachedBounds && boundsAutoCompute) {
2543:                        bounds.combine(cachedBounds);
2544:                        return;
2545:                    }
2546:
2547:                    if (boundsAutoCompute) {
2548:                        // issue 544
2549:                        if (VirtualUniverse.mc.useBoxForGroupBounds) {
2550:                            cachedBounds = new BoundingBox((Bounds) null);
2551:                        } else {
2552:                            cachedBounds = new BoundingSphere();
2553:                            ((BoundingSphere) cachedBounds).setRadius(-1);
2554:                        }
2555:                        for (int i = children.size() - 1; i >= 0; i--) {
2556:                            NodeRetained child = (NodeRetained) children.get(i);
2557:                            if (child != null) {
2558:                                child.computeCombineBounds(cachedBounds);
2559:                            }
2560:                        }
2561:                        bounds.combine(cachedBounds);
2562:                    } else {
2563:                        // Should this be lock too ? ( MT safe  ? )
2564:                        synchronized (localBounds) {
2565:                            bounds.combine(localBounds);
2566:                        }
2567:                    }
2568:                }
2569:
2570:            }
2571:
2572:            /**
2573:             * Gets the bounding object of a node.
2574:             * @return the node's bounding object
2575:             */
2576:            Bounds getBounds() {
2577:
2578:                if (boundsAutoCompute) {
2579:                    // Issue 514 : NPE in Wonderland : triggered in cached bounds computation
2580:                    if (validCachedBounds) {
2581:                        return (Bounds) cachedBounds.clone();
2582:                    }
2583:                    // issue 544
2584:                    Bounds boundingObject = null;
2585:                    if (VirtualUniverse.mc.useBoxForGroupBounds) {
2586:                        boundingObject = new BoundingBox((Bounds) null);
2587:                    } else {
2588:                        boundingObject = new BoundingSphere();
2589:                        ((BoundingSphere) boundingObject).setRadius(-1.0);
2590:                    }
2591:                    for (int i = children.size() - 1; i >= 0; i--) {
2592:                        NodeRetained child = (NodeRetained) children.get(i);
2593:                        if (child != null) {
2594:                            child.computeCombineBounds((Bounds) boundingObject);
2595:                        }
2596:                    }
2597:
2598:                    return (Bounds) boundingObject;
2599:                }
2600:                return super .getBounds();
2601:            }
2602:
2603:            /**
2604:             * Gets the bounding object of a node.
2605:             * @return the node's bounding object
2606:             */
2607:            Bounds getEffectiveBounds() {
2608:                if (boundsAutoCompute) {
2609:                    return getBounds();
2610:                }
2611:                return super .getEffectiveBounds();
2612:            }
2613:
2614:            // returns true if children cannot be read/written and none of the
2615:            // children can read their parent (i.e., "this") group node
2616:            boolean isStaticChildren() {
2617:                if (source.getCapability(Group.ALLOW_CHILDREN_READ)
2618:                        || source.getCapability(Group.ALLOW_CHILDREN_WRITE)) {
2619:                    return false;
2620:                }
2621:
2622:                for (int i = children.size() - 1; i >= 0; i--) {
2623:                    SceneGraphObjectRetained nodeR = (SceneGraphObjectRetained) children
2624:                            .get(i);
2625:                    if (nodeR != null
2626:                            && nodeR.source
2627:                                    .getCapability(Node.ALLOW_PARENT_READ)) {
2628:                        return false;
2629:                    }
2630:                }
2631:
2632:                return true;
2633:            }
2634:
2635:            boolean isStatic() {
2636:                return (super .isStatic() && isStaticChildren());
2637:            }
2638:
2639:            /**
2640:             * This compiles() a group
2641:             */
2642:            void setCompiled() {
2643:                super .setCompiled();
2644:                for (int i = children.size() - 1; i >= 0; i--) {
2645:                    SceneGraphObjectRetained node = (SceneGraphObjectRetained) children
2646:                            .get(i);
2647:                    if (node != null)
2648:                        node.setCompiled();
2649:                }
2650:            }
2651:
2652:            void traverse(boolean sameLevel, int level) {
2653:                SceneGraphObjectRetained node;
2654:
2655:                if (!sameLevel) {
2656:                    super .traverse(true, level);
2657:
2658:                    if (source.getCapability(Group.ALLOW_CHILDREN_READ)) {
2659:                        System.err.print(" (r)");
2660:                    } else if (isStatic()) {
2661:                        System.err.print(" (s)");
2662:                    } else if (source.getCapability(Group.ALLOW_CHILDREN_WRITE)) {
2663:                        System.err.print(" (w)");
2664:                    }
2665:                }
2666:
2667:                level++;
2668:                for (int i = 0; i < children.size(); i++) {
2669:                    node = (SceneGraphObjectRetained) children.get(i);
2670:                    if (node != null) {
2671:                        node.traverse(false, level);
2672:                    }
2673:                }
2674:            }
2675:
2676:            void compile(CompileState compState) {
2677:
2678:                SceneGraphObjectRetained node;
2679:
2680:                super .compile(compState);
2681:
2682:                mergeFlag = SceneGraphObjectRetained.MERGE;
2683:
2684:                if (!isStatic()) {
2685:                    compState.keepTG = true;
2686:                    mergeFlag = SceneGraphObjectRetained.DONT_MERGE;
2687:                }
2688:
2689:                if (isRoot || this .usedInScoping()
2690:                        || (parent instanceof  SwitchRetained)) {
2691:                    mergeFlag = SceneGraphObjectRetained.DONT_MERGE;
2692:                }
2693:
2694:                compiledChildrenList = new ArrayList(5);
2695:
2696:                for (int i = 0; i < children.size(); i++) {
2697:                    node = (SceneGraphObjectRetained) children.get(i);
2698:                    if (node != null) {
2699:                        node.compile(compState);
2700:                    }
2701:                }
2702:
2703:                if (J3dDebug.devPhase && J3dDebug.debug) {
2704:                    compState.numGroups++;
2705:                }
2706:            }
2707:
2708:            void merge(CompileState compState) {
2709:
2710:                GroupRetained saveParentGroup = null;
2711:                SceneGraphObjectRetained node;
2712:
2713:                if (mergeFlag != SceneGraphObjectRetained.MERGE_DONE) {
2714:                    if (mergeFlag == SceneGraphObjectRetained.DONT_MERGE) {
2715:
2716:                        // don't merge/eliminate this node
2717:                        super .merge(compState);
2718:
2719:                        saveParentGroup = compState.parentGroup;
2720:                        compState.parentGroup = this ;
2721:                    }
2722:
2723:                    for (int i = 0; i < children.size(); i++) {
2724:                        node = (SceneGraphObjectRetained) children.get(i);
2725:                        if (node != null) {
2726:                            node.merge(compState);
2727:                        }
2728:                    }
2729:
2730:                    if (compState.parentGroup == this ) {
2731:                        this .children = compiledChildrenList;
2732:                        compState.doShapeMerge();
2733:                        compiledChildrenList = null;
2734:                        compState.parentGroup = saveParentGroup;
2735:                    } else {
2736:                        // this group node can be eliminated
2737:                        this .children.clear();
2738:
2739:                        if (J3dDebug.devPhase && J3dDebug.debug) {
2740:                            compState.numMergedGroups++;
2741:                        }
2742:                    }
2743:
2744:                    mergeFlag = SceneGraphObjectRetained.MERGE_DONE;
2745:
2746:                } else {
2747:                    if (compState.parentGroup != null) {
2748:                        compState.parentGroup.compiledChildrenList.add(this );
2749:                        parent = compState.parentGroup;
2750:                    }
2751:                }
2752:            }
2753:
2754:            /**
2755:             * This version of clearLive calls clearLive on all of its chidren.
2756:             */
2757:            void clearLive(SetLiveState s) {
2758:                int i, k, hkIndex, nchildren;
2759:                NodeRetained child;
2760:                int parentScopedLtSize = 0;
2761:                int parentScopedFogSize = 0;
2762:                int parentScopedMcSize = 0;
2763:                int parentScopedAltAppSize = 0;
2764:                int groupScopedLtSize = 0;
2765:                int groupScopedFogSize = 0;
2766:                int groupScopedMcSize = 0;
2767:                int groupScopedAltAppSize = 0;
2768:                int size;
2769:
2770:                isInClearLive = true;
2771:
2772:                // Save this for later use in this method. Temporary. to be removed when OG cleanup. 
2773:                HashKey[] savedLocalToVworldKeys = localToVworldKeys;
2774:
2775:                super .clearLive(s);
2776:
2777:                nchildren = this .children.size();
2778:
2779:                if (!(this  instanceof  ViewSpecificGroupRetained)) {
2780:                    viewLists = s.viewLists;
2781:                }
2782:
2783:                ArrayList savedParentLights = s.lights;
2784:                if (allocatedLights) {
2785:                    s.lights = lights;
2786:                }
2787:
2788:                ArrayList savedParentFogs = s.fogs;
2789:                if (allocatedFogs) {
2790:                    s.fogs = fogs;
2791:                }
2792:
2793:                ArrayList savedParentMclips = s.modelClips;
2794:                if (allocatedMclips) {
2795:                    s.modelClips = modelClips;
2796:                }
2797:
2798:                ArrayList savedParentAltApps = s.altAppearances;
2799:                if (allocatedAltApps) {
2800:                    s.altAppearances = altAppearances;
2801:                }
2802:
2803:                for (i = nchildren - 1; i >= 0; i--) {
2804:                    child = (NodeRetained) children.get(i);
2805:                    if (this  instanceof  OrderedGroupRetained) {
2806:                        OrderedGroupRetained og = (OrderedGroupRetained) this ;
2807:
2808:                        // adjust refCount, which has been decremented 
2809:                        //in super.clearLive
2810:                        if ((refCount + 1) == s.refCount) {
2811:                            //only need to do it once if in shared group. Add
2812:                            //all the children to the list of OG_REMOVED message
2813:                            s.ogList.add(this );
2814:                            s.ogChildIdList.add(new Integer(i));
2815:                        }
2816:                        s.orderedPaths = (ArrayList) og.childrenOrderedPaths
2817:                                .get(i);
2818:                    }
2819:
2820:                    if (child != null) {
2821:                        child.clearLive(s);
2822:                    }
2823:                }
2824:                // Has its own copy
2825:                // XXXX: Handle the case of
2826:                // was non-zero, gone to zero?
2827:                if (savedParentLights != null) {
2828:                    if (allocatedLights) {
2829:                        if (inSharedGroup) {
2830:
2831:                            for (i = 0; i < s.keys.length; i++) {
2832:                                hkIndex = s.keys[i].equals(localToVworldKeys,
2833:                                        0, localToVworldKeys.length);
2834:                                ArrayList l = (ArrayList) savedParentLights
2835:                                        .get(hkIndex);
2836:                                ArrayList gl = (ArrayList) lights.get(hkIndex);
2837:                                if (l != null) {
2838:                                    size = l.size();
2839:                                    for (k = 0; k < size; k++) {
2840:                                        gl.remove(l.get(k));
2841:                                    }
2842:                                }
2843:
2844:                            }
2845:                        } else {
2846:                            ArrayList l = (ArrayList) savedParentLights.get(0);
2847:                            ArrayList gl = (ArrayList) lights.get(0);
2848:                            size = l.size();
2849:                            for (int m = 0; m < size; m++) {
2850:                                gl.remove(l.get(m));
2851:                            }
2852:                        }
2853:                    }
2854:                }
2855:
2856:                if (savedParentFogs != null) {
2857:                    if (allocatedFogs) {
2858:                        if (inSharedGroup) {
2859:                            for (i = 0; i < s.keys.length; i++) {
2860:                                hkIndex = s.keys[i].equals(localToVworldKeys,
2861:                                        0, localToVworldKeys.length);
2862:                                ArrayList l = (ArrayList) savedParentFogs
2863:                                        .get(hkIndex);
2864:                                ArrayList gl = (ArrayList) fogs.get(hkIndex);
2865:                                if (l != null) {
2866:                                    size = l.size();
2867:                                    for (k = 0; k < size; k++) {
2868:                                        gl.remove(l.get(k));
2869:                                    }
2870:                                }
2871:
2872:                            }
2873:                        } else {
2874:                            ArrayList l = (ArrayList) savedParentFogs.get(0);
2875:                            size = l.size();
2876:                            for (int m = 0; m < size; m++) {
2877:                                fogs.remove(l.get(m));
2878:                            }
2879:                        }
2880:                    }
2881:                }
2882:
2883:                if (savedParentMclips != null) {
2884:                    if (allocatedMclips) {
2885:                        if (inSharedGroup) {
2886:                            for (i = 0; i < s.keys.length; i++) {
2887:                                hkIndex = s.keys[i].equals(localToVworldKeys,
2888:                                        0, localToVworldKeys.length);
2889:                                ArrayList l = (ArrayList) savedParentMclips
2890:                                        .get(hkIndex);
2891:                                ArrayList gl = (ArrayList) modelClips
2892:                                        .get(hkIndex);
2893:                                if (l != null) {
2894:                                    size = l.size();
2895:                                    for (k = 0; k < size; k++) {
2896:                                        gl.remove(l.get(k));
2897:                                    }
2898:                                }
2899:
2900:                            }
2901:                        } else {
2902:                            ArrayList l = (ArrayList) savedParentMclips.get(0);
2903:                            size = l.size();
2904:                            for (int m = 0; m < size; m++) {
2905:                                modelClips.remove(l.get(m));
2906:                            }
2907:                        }
2908:                    }
2909:                }
2910:
2911:                if (savedParentAltApps != null) {
2912:                    if (allocatedAltApps) {
2913:                        if (inSharedGroup) {
2914:                            for (i = 0; i < s.keys.length; i++) {
2915:                                hkIndex = s.keys[i].equals(localToVworldKeys,
2916:                                        0, localToVworldKeys.length);
2917:                                ArrayList l = (ArrayList) savedParentAltApps
2918:                                        .get(hkIndex);
2919:                                ArrayList gl = (ArrayList) altAppearances
2920:                                        .get(hkIndex);
2921:                                if (l != null) {
2922:                                    size = l.size();
2923:                                    for (k = 0; k < size; k++) {
2924:                                        gl.remove(l.get(k));
2925:                                    }
2926:                                }
2927:
2928:                            }
2929:                        } else {
2930:                            ArrayList l = (ArrayList) savedParentAltApps.get(0);
2931:                            size = l.size();
2932:                            for (int m = 0; m < size; m++) {
2933:                                altAppearances.remove(l.get(m));
2934:                            }
2935:                        }
2936:                    }
2937:                }
2938:
2939:                if (collisionTarget) {
2940:                    GroupRetained g;
2941:                    if (inSharedGroup) {
2942:                        for (i = s.keys.length - 1; i >= 0; i--) {
2943:                            HashKey hkey = s.keys[i];
2944:                            for (int j = mirrorGroup.size() - 1; j >= 0; j--) {
2945:                                g = (GroupRetained) mirrorGroup.get(j);
2946:                                if (g.key.equals(hkey)) {
2947:                                    s.nodeList.add(mirrorGroup.remove(j));
2948:                                    if (s.transformTargets != null
2949:                                            && s.transformTargets[j] != null) {
2950:                                        s.transformTargets[j].addNode(g,
2951:                                                Targets.GRP_TARGETS);
2952:                                    }
2953:                                    break;
2954:                                }
2955:
2956:                            }
2957:                        }
2958:                    } else {
2959:                        g = (GroupRetained) mirrorGroup.get(0);
2960:                        if (s.transformTargets != null
2961:                                && s.transformTargets[0] != null) {
2962:                            s.transformTargets[0].addNode(g,
2963:                                    Targets.GRP_TARGETS);
2964:                        }
2965:                        s.nodeList.add(mirrorGroup.remove(0));
2966:                    }
2967:                }
2968:                s.lights = savedParentLights;
2969:                s.modelClips = savedParentMclips;
2970:                s.fogs = savedParentFogs;
2971:                s.altAppearances = savedParentAltApps;
2972:                isInClearLive = false;
2973:            }
2974:
2975:            // This is only used by alternateCollisionTarget
2976:            public BoundingBox computeBoundingHull() {
2977:                return collisionVwcBounds;
2978:            }
2979:
2980:            // If isSwitchOn cached here, we don't need to traverse up the tree
2981:            public boolean isEnable() {
2982:                return isNodeSwitchOn(this .sourceNode, key);
2983:            }
2984:
2985:            // If isSwitchOn cached here, we don't need to traverse up the tree
2986:            // This method does nothing with vis.
2987:            public boolean isEnable(int vis) {
2988:                return isNodeSwitchOn(this .sourceNode, key);
2989:            }
2990:
2991:            // Can't use getLocale, it is used by BranchGroupRetained
2992:            public Locale getLocale2() {
2993:                return locale;
2994:            }
2995:
2996:            /**
2997:             * Return true of nodeR is not under a switch group or
2998:             * nodeR is enable under a switch group.
2999:             */
3000:            static boolean isNodeSwitchOn(NodeRetained node, HashKey key) {
3001:                NodeRetained prevNode = null;
3002:                if (key != null) {
3003:                    key = new HashKey(key);
3004:                }
3005:
3006:                synchronized (node.universe.sceneGraphLock) {
3007:                    do {
3008:                        if ((node instanceof  SwitchRetained)
3009:                                && (prevNode != null)
3010:                                && !validSwitchChild((SwitchRetained) node,
3011:                                        prevNode)) {
3012:                            return false;
3013:                        }
3014:                        prevNode = node;
3015:                        if (node instanceof  SharedGroupRetained) {
3016:                            // retrieve the last node ID
3017:                            String nodeId = key.getLastNodeId();
3018:                            Vector parents = ((SharedGroupRetained) node).parents;
3019:                            // find the matching link
3020:                            for (int i = parents.size() - 1; i >= 0; i--) {
3021:                                NodeRetained link = (NodeRetained) parents
3022:                                        .get(i);
3023:                                if (link.nodeId.equals(nodeId)) {
3024:                                    node = link;
3025:                                    break;
3026:                                }
3027:                            }
3028:                            if (node == prevNode) {
3029:                                // Fail to found a matching link, this is
3030:                                // probably cause by BHTree not yet updated 
3031:                                // because message not yet arrive
3032:                                // when collision so it return current node as target.
3033:                                return false;
3034:                            }
3035:                        } else {
3036:                            node = node.parent;
3037:                        }
3038:                    } while (node != null);
3039:                    // reach locale
3040:                }
3041:                return true;
3042:            }
3043:
3044:            /** 
3045:             * Determinte if nodeR is a valid child to render for
3046:             * Switch Node swR.
3047:             */
3048:            static boolean validSwitchChild(SwitchRetained sw, NodeRetained node) {
3049:
3050:                int whichChild = sw.whichChild;
3051:
3052:                if (whichChild == Switch.CHILD_NONE) {
3053:                    return false;
3054:                }
3055:
3056:                if (whichChild == Switch.CHILD_ALL) {
3057:                    return true;
3058:                }
3059:
3060:                ArrayList children = sw.children;
3061:
3062:                if (whichChild >= 0) { // most common case
3063:                    return (children.get(whichChild) == node);
3064:                }
3065:
3066:                // Switch.CHILD_MASK
3067:                for (int i = children.size() - 1; i >= 0; i--) {
3068:                    if (sw.childMask.get(i) && (children.get(i) == node)) {
3069:                        return true;
3070:                    }
3071:                }
3072:                return false;
3073:            }
3074:
3075:            /**
3076:             * Create mirror group when this Group AlternateCollisionTarget
3077:             * is set to true while live.
3078:             */
3079:            void createMirrorGroup() {
3080:                GroupRetained g;
3081:
3082:                mirrorGroup = new ArrayList();
3083:
3084:                Bounds bound = (collisionBound != null ? collisionBound
3085:                        : getEffectiveBounds());
3086:
3087:                if (inSharedGroup) {
3088:                    for (int i = 0; i < localToVworldKeys.length; i++) {
3089:                        g = new GroupRetained();
3090:                        g.key = localToVworldKeys[i];
3091:                        g.localToVworld = new Transform3D[1][];
3092:                        g.localToVworldIndex = new int[1][];
3093:                        g.localToVworld[0] = localToVworld[i];
3094:                        g.localToVworldIndex[0] = localToVworldIndex[i];
3095:                        g.collisionVwcBounds = new BoundingBox();
3096:                        g.collisionVwcBounds.transform(bound, g
3097:                                .getCurrentLocalToVworld());
3098:                        g.sourceNode = this ;
3099:                        g.locale = locale; // need by getVisibleGeometryAtom()
3100:                        mirrorGroup.add(g);
3101:                    }
3102:                } else {
3103:                    g = new GroupRetained();
3104:                    g.localToVworld = new Transform3D[1][];
3105:                    g.localToVworldIndex = new int[1][];
3106:                    g.localToVworld[0] = localToVworld[0];
3107:                    g.localToVworldIndex[0] = localToVworldIndex[0];
3108:                    g.collisionVwcBounds = new BoundingBox();
3109:                    g.collisionVwcBounds.transform(bound, g
3110:                            .getCurrentLocalToVworld());
3111:                    g.sourceNode = this ;
3112:                    g.locale = locale; // need by getVisibleGeometryAtom()
3113:                    mirrorGroup.add(g);
3114:                }
3115:            }
3116:
3117:            void setBoundsAutoCompute(boolean autoCompute) {
3118:                if (autoCompute != boundsAutoCompute) {
3119:                    super .setBoundsAutoCompute(autoCompute);
3120:                    if (!autoCompute) {
3121:                        localBounds = getEffectiveBounds();
3122:                    }
3123:                    if (source.isLive() && collisionBound == null
3124:                            && autoCompute && mirrorGroup != null) {
3125:
3126:                        J3dMessage message = new J3dMessage();
3127:                        message.type = J3dMessage.COLLISION_BOUND_CHANGED;
3128:                        message.threads = J3dThread.UPDATE_TRANSFORM
3129:                                | J3dThread.UPDATE_GEOMETRY;
3130:                        message.universe = universe;
3131:                        message.args[0] = this ;
3132:                        VirtualUniverse.mc.processMessage(message);
3133:                    }
3134:                }
3135:            }
3136:
3137:            void setBounds(Bounds bounds) {
3138:                super .setBounds(bounds);
3139:                if (source.isLive() && !boundsAutoCompute
3140:                        && collisionBound == null && mirrorGroup != null) {
3141:
3142:                    J3dMessage message = new J3dMessage();
3143:                    message.type = J3dMessage.COLLISION_BOUND_CHANGED;
3144:                    message.threads = J3dThread.UPDATE_TRANSFORM
3145:                            | J3dThread.UPDATE_GEOMETRY;
3146:                    message.universe = universe;
3147:                    message.args[0] = this ;
3148:                    VirtualUniverse.mc.processMessage(message);
3149:                }
3150:            }
3151:
3152:            int[] processViewSpecificInfo(int mode, HashKey k, View v,
3153:                    ArrayList vsgList, int[] keyList, ArrayList leafList) {
3154:                int nchildren = children.size();
3155:                if (source.isLive()) {
3156:                    for (int i = 0; i < nchildren; i++) {
3157:                        NodeRetained child = (NodeRetained) children.get(i);
3158:                        if (child instanceof  LeafRetained) {
3159:                            if (child instanceof  LinkRetained) {
3160:                                int lastCount = k.count;
3161:                                LinkRetained ln = (LinkRetained) child;
3162:                                if (k.count == 0) {
3163:                                    k.append(locale.nodeId);
3164:                                }
3165:                                keyList = ((GroupRetained) (ln.sharedGroup))
3166:                                        .processViewSpecificInfo(mode, k
3167:                                                .append("+").append(ln.nodeId),
3168:                                                v, vsgList, keyList, leafList);
3169:                                k.count = lastCount;
3170:                            } else {
3171:                                ((LeafRetained) child).getMirrorObjects(
3172:                                        leafList, k);
3173:                            }
3174:                        } else {
3175:                            keyList = child.processViewSpecificInfo(mode, k, v,
3176:                                    vsgList, keyList, leafList);
3177:                        }
3178:                    }
3179:                }
3180:                return keyList;
3181:            }
3182:
3183:            void findSwitchInfo(SetLiveState s, NodeRetained parentNode,
3184:                    NodeRetained childNode, NodeRetained linkNode) {
3185:
3186:                NodeRetained child;
3187:                NodeRetained parent;
3188:
3189:                parentSwitchLinkChildIndex = -1;
3190:
3191:                // traverse up scene graph to find switch parent information
3192:                if (!inSharedGroup) {
3193:                    child = (linkNode == null) ? childNode : linkNode;
3194:                    parent = parentNode;
3195:                    while (parent != null) {
3196:                        if (parent instanceof  SwitchRetained) {
3197:                            s.switchLevels[0]++;
3198:                            if (s.closestSwitchParents[0] == null) {
3199:                                s.closestSwitchParents[0] = (SwitchRetained) parent;
3200:                                s.closestSwitchIndices[0] = ((SwitchRetained) parent).switchIndexCount++;
3201:                            }
3202:                            if (parentSwitchLinkChildIndex == -1) {
3203:                                parentSwitchLinkChildIndex = ((GroupRetained) parent).children
3204:                                        .indexOf(child);
3205:                            }
3206:                        } else if (parent instanceof  SharedGroupRetained) {
3207:                            if (parentSwitchLinkChildIndex == -1) {
3208:                                parentSwitchLinkChildIndex = ((GroupRetained) parent).children
3209:                                        .indexOf(child);
3210:                            }
3211:                        }
3212:                        child = parent;
3213:                        parent = child.parent;
3214:                    }
3215:                } else {
3216:                    HashKey key;
3217:                    int i, j;
3218:
3219:                    s.switchLevels = new int[localToVworldKeys.length];
3220:                    s.closestSwitchParents = new SwitchRetained[localToVworldKeys.length];
3221:                    s.closestSwitchIndices = new int[localToVworldKeys.length];
3222:                    for (i = 0; i < localToVworldKeys.length; i++) {
3223:                        s.switchLevels[i] = -1;
3224:                        s.closestSwitchParents[i] = null;
3225:                        s.closestSwitchIndices[i] = -1;
3226:                    }
3227:
3228:                    for (i = 0; i < localToVworldKeys.length; i++) {
3229:                        child = (linkNode == null) ? childNode : linkNode;
3230:                        parent = parentNode;
3231:                        key = new HashKey(localToVworldKeys[i]);
3232:
3233:                        while (parent != null) {
3234:
3235:                            if (parent instanceof  SwitchRetained) {
3236:                                s.switchLevels[i]++;
3237:                                if (s.closestSwitchParents[i] == null) {
3238:                                    s.closestSwitchParents[i] = (SwitchRetained) parent;
3239:                                    s.closestSwitchIndices[i] = ((SwitchRetained) parent).switchIndexCount++;
3240:
3241:                                }
3242:                                if (parentSwitchLinkChildIndex == -1) {
3243:                                    parentSwitchLinkChildIndex = ((GroupRetained) parent).children
3244:                                            .indexOf(child);
3245:                                }
3246:                            } else if (parent instanceof  SharedGroupRetained) {
3247:                                String nodeId = key.getLastNodeId();
3248:                                Vector parents = ((SharedGroupRetained) parent).parents;
3249:                                NodeRetained ln;
3250:
3251:                                if (parentSwitchLinkChildIndex == -1) {
3252:                                    parentSwitchLinkChildIndex = ((GroupRetained) parent).children
3253:                                            .indexOf(child);
3254:                                }
3255:
3256:                                for (j = 0; j < parents.size(); j++) {
3257:                                    ln = (NodeRetained) parents.get(j);
3258:                                    if (ln.nodeId.equals(nodeId)) {
3259:                                        parent = ln;
3260:                                        break;
3261:                                    }
3262:                                }
3263:                            }
3264:                            child = parent;
3265:                            parent = child.parent;
3266:                        }
3267:                    }
3268:                }
3269:            }
3270:
3271:            static void gatherBlUsers(ArrayList blUsers, Object[] blArr) {
3272:                ArrayList users;
3273:
3274:                for (int i = 0; i < blArr.length; i++) {
3275:                    users = ((BoundingLeafRetained) blArr[i]).users;
3276:                    synchronized (users) {
3277:                        blUsers.addAll(users);
3278:                    }
3279:                }
3280:            }
3281:
3282:            // recursively found all geometryAtoms under this Group
3283:            void searchGeometryAtoms(UnorderList list) {
3284:                for (int i = children.size() - 1; i >= 0; i--) {
3285:                    NodeRetained child = (NodeRetained) children.get(i);
3286:                    child.searchGeometryAtoms(list);
3287:                }
3288:            }
3289:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.