001: /*
002: * $RCSfile: AlternateAppearanceRetained.java,v $
003: *
004: * Copyright 1999-2008 Sun Microsystems, Inc. All Rights Reserved.
005: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
006: *
007: * This code is free software; you can redistribute it and/or modify it
008: * under the terms of the GNU General Public License version 2 only, as
009: * published by the Free Software Foundation. Sun designates this
010: * particular file as subject to the "Classpath" exception as provided
011: * by Sun in the LICENSE file that accompanied this code.
012: *
013: * This code is distributed in the hope that it will be useful, but WITHOUT
014: * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
015: * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
016: * version 2 for more details (a copy is included in the LICENSE file that
017: * accompanied this code).
018: *
019: * You should have received a copy of the GNU General Public License version
020: * 2 along with this work; if not, write to the Free Software Foundation,
021: * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
022: *
023: * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
024: * CA 95054 USA or visit www.sun.com if you need additional information or
025: * have any questions.
026: *
027: * $Revision: 1.7 $
028: * $Date: 2008/02/28 20:17:19 $
029: * $State: Exp $
030: */
031:
032: package javax.media.j3d;
033:
034: import javax.vecmath.*;
035: import java.util.Enumeration;
036: import java.util.Vector;
037: import java.util.ArrayList;
038:
039: class AlternateAppearanceRetained extends LeafRetained {
040:
041: // Statics used when something in the alternate app changes
042: static final int APPEARANCE_CHANGED = 0x0001;
043: static final int SCOPE_CHANGED = 0x0002;
044: static final int BOUNDS_CHANGED = 0x0004;
045: static final int BOUNDINGLEAF_CHANGED = 0x0008;
046: static final int INIT_MIRROR = 0x0010; // setLive
047: static final int CLEAR_MIRROR = 0x0020; // clearLive
048:
049: /**
050: * The Boundary object defining the lights's region of influence.
051: */
052: Bounds regionOfInfluence = null;
053:
054: /**
055: * The bounding leaf reference
056: */
057: BoundingLeafRetained boundingLeaf = null;
058:
059: /**
060: * Vector of GroupRetained nodes that scopes this alternate app .
061: */
062: Vector scopes = new Vector();
063:
064: // This is true when this alternate app is referenced in an immediate mode context
065: boolean inImmCtx = false;
066:
067: // Target threads to be notified when light changes
068: static final int targetThreads = J3dThread.UPDATE_RENDERING_ENVIRONMENT
069: | J3dThread.UPDATE_RENDER;
070:
071: // Boolean to indicate if this object is scoped (only used for mirror objects
072: boolean isScoped = false;
073:
074: // The object that contains the dynamic HashKey - a string type object
075: // Used in scoping
076: HashKey tempKey = new HashKey(250);
077:
078: /**
079: * The transformed value of the applicationRegion.
080: */
081: Bounds region = null;
082:
083: /**
084: * mirror Alternate appearance
085: */
086: AlternateAppearanceRetained mirrorAltApp = null;
087:
088: /**
089: * Appearance for this object
090: */
091: AppearanceRetained appearance;
092:
093: /**
094: * A reference to the scene graph alternateApp
095: */
096: AlternateAppearanceRetained sgAltApp = null;
097:
098: /**
099: * Is true, if the mirror altapp is viewScoped
100: */
101: boolean isViewScoped = false;
102:
103: AlternateAppearanceRetained() {
104: this .nodeType = NodeRetained.ALTERNATEAPPEARANCE;
105: localBounds = new BoundingBox();
106: ((BoundingBox) localBounds).setLower(1.0, 1.0, 1.0);
107: ((BoundingBox) localBounds).setUpper(-1.0, -1.0, -1.0);
108: }
109:
110: /**
111: * Initializes the appearance
112: */
113: void initAppearance(Appearance app) {
114: if (app != null)
115: appearance = (AppearanceRetained) app.retained;
116: else
117: appearance = null;
118: }
119:
120: /**
121: * sets the appearance and send a message
122: */
123: void setAppearance(Appearance app) {
124: if (appearance != null)
125: synchronized (appearance.liveStateLock) {
126: appearance.clearLive(refCount);
127: }
128: initAppearance(app);
129: if (appearance != null) {
130: synchronized (appearance.liveStateLock) {
131: appearance.setLive(inBackgroundGroup, refCount);
132: }
133: }
134: // There is no need to clone the appearance's mirror
135: sendMessage(APPEARANCE_CHANGED,
136: (appearance != null ? appearance.mirror : null));
137: }
138:
139: Appearance getAppearance() {
140: return (appearance == null ? null
141: : (Appearance) appearance.source);
142: }
143:
144: /**
145: * Set the alternate's region of influence.
146: */
147: void initInfluencingBounds(Bounds region) {
148: if (region != null) {
149: this .regionOfInfluence = (Bounds) region.clone();
150: } else {
151: this .regionOfInfluence = null;
152: }
153: }
154:
155: /**
156: * Set the alternate's region of influence and send message
157: */
158: void setInfluencingBounds(Bounds region) {
159: initInfluencingBounds(region);
160: sendMessage(BOUNDS_CHANGED, (region != null ? region.clone()
161: : null));
162: }
163:
164: /**
165: * Get the alternate's region of Influence.
166: */
167: Bounds getInfluencingBounds() {
168: return (regionOfInfluence != null ? (Bounds) regionOfInfluence
169: .clone() : null);
170: }
171:
172: /**
173: * Set the alternate's region of influence to the specified Leaf node.
174: */
175: void initInfluencingBoundingLeaf(BoundingLeaf region) {
176: if (region != null) {
177: boundingLeaf = (BoundingLeafRetained) region.retained;
178: } else {
179: boundingLeaf = null;
180: }
181: }
182:
183: /**
184: * Set the alternate's region of influence to the specified Leaf node.
185: */
186: void setInfluencingBoundingLeaf(BoundingLeaf region) {
187: if (boundingLeaf != null)
188: boundingLeaf.mirrorBoundingLeaf.removeUser(mirrorAltApp);
189: if (region != null) {
190: boundingLeaf = (BoundingLeafRetained) region.retained;
191: boundingLeaf.mirrorBoundingLeaf.addUser(mirrorAltApp);
192: } else {
193: boundingLeaf = null;
194: }
195: sendMessage(BOUNDINGLEAF_CHANGED,
196: (boundingLeaf != null ? boundingLeaf.mirrorBoundingLeaf
197: : null));
198: }
199:
200: /**
201: * Get the alternate's region of influence.
202: */
203: BoundingLeaf getInfluencingBoundingLeaf() {
204: return (boundingLeaf != null ? (BoundingLeaf) boundingLeaf.source
205: : null);
206: }
207:
208: /**
209: * Replaces the specified scope with the scope provided.
210: * @param scope the new scope
211: * @param index which scope to replace
212: */
213: void initScope(Group scope, int index) {
214: scopes.setElementAt((GroupRetained) (scope.retained), index);
215:
216: }
217:
218: /**
219: * Replaces the specified scope with the scope provided.
220: * @param scope the new scope
221: * @param index which scope to replace
222: */
223: void setScope(Group scope, int index) {
224:
225: ArrayList removeScopeList = new ArrayList();
226: GroupRetained group;
227: ArrayList addScopeList = new ArrayList();
228: Object[] scopeInfo = new Object[3];
229:
230: group = (GroupRetained) scopes.get(index);
231: tempKey.reset();
232: group.removeAllNodesForScopedAltApp(mirrorAltApp,
233: removeScopeList, tempKey);
234:
235: group = (GroupRetained) scope.retained;
236: initScope(scope, index);
237: tempKey.reset();
238:
239: // If its a group, then add the scope to the group, if
240: // its a shape, then keep a list to be added during
241: // updateMirrorObject
242: group.addAllNodesForScopedAltApp(mirrorAltApp, addScopeList,
243: tempKey);
244: scopeInfo[0] = addScopeList;
245: scopeInfo[1] = removeScopeList;
246: scopeInfo[2] = (scopes.size() > 0 ? Boolean.TRUE
247: : Boolean.FALSE);
248: sendMessage(SCOPE_CHANGED, scopeInfo);
249: }
250:
251: Group getScope(int index) {
252: return (Group) (((GroupRetained) (scopes.elementAt(index))).source);
253: }
254:
255: /**
256: * Inserts the specified scope at specified index.before the
257: * alt app is live
258: * @param scope the new scope
259: * @param index position to insert new scope at
260: */
261: void initInsertScope(Node scope, int index) {
262: GroupRetained group = (GroupRetained) scope.retained;
263: scopes.insertElementAt((GroupRetained) (scope.retained), index);
264: group.setAltAppScope();
265: }
266:
267: /**
268: * Inserts the specified scope at specified index and sends
269: * a message
270: * @param scope the new scope
271: * @param index position to insert new scope at
272: */
273: void insertScope(Node scope, int index) {
274: Object[] scopeInfo = new Object[3];
275: ArrayList addScopeList = new ArrayList();
276: GroupRetained group = (GroupRetained) scope.retained;
277:
278: initInsertScope(scope, index);
279: group = (GroupRetained) scope.retained;
280: tempKey.reset();
281: group.addAllNodesForScopedAltApp(mirrorAltApp, addScopeList,
282: tempKey);
283:
284: scopeInfo[0] = addScopeList;
285: scopeInfo[1] = null;
286: scopeInfo[2] = (scopes.size() > 0 ? Boolean.TRUE
287: : Boolean.FALSE);
288: sendMessage(SCOPE_CHANGED, scopeInfo);
289: }
290:
291: void initRemoveScope(int index) {
292: GroupRetained group = (GroupRetained) scopes.elementAt(index);
293: scopes.removeElementAt(index);
294: group.removeAltAppScope();
295:
296: }
297:
298: void removeScope(int index) {
299:
300: Object[] scopeInfo = new Object[3];
301: ArrayList removeScopeList = new ArrayList();
302: GroupRetained group = (GroupRetained) scopes.elementAt(index);
303:
304: tempKey.reset();
305: group.removeAllNodesForScopedAltApp(mirrorAltApp,
306: removeScopeList, tempKey);
307:
308: initRemoveScope(index);
309: scopeInfo[0] = null;
310: scopeInfo[1] = removeScopeList;
311: scopeInfo[2] = (scopes.size() > 0 ? Boolean.TRUE
312: : Boolean.FALSE);
313: sendMessage(SCOPE_CHANGED, scopeInfo);
314: }
315:
316: /**
317: * Removes the specified Group node from this node's list of scopes.
318: * Method is a no-op if the
319: * specified node is not found
320: * @param The Group node to be removed
321: */
322: void removeScope(Group scope) {
323: int ind = indexOfScope(scope);
324: if (ind >= 0)
325: removeScope(ind);
326: }
327:
328: void initRemoveScope(Group scope) {
329: int ind = indexOfScope(scope);
330: if (ind >= 0)
331: initRemoveScope(ind);
332: }
333:
334: void removeAllScopes() {
335: GroupRetained group;
336: ArrayList removeScopeList = new ArrayList();
337: int n = scopes.size();
338: for (int index = n - 1; index >= 0; index--) {
339: group = (GroupRetained) scopes.elementAt(index);
340: tempKey.reset();
341: group.removeAllNodesForScopedAltApp(mirrorAltApp,
342: removeScopeList, tempKey);
343: initRemoveScope(index);
344: }
345: Object[] scopeInfo = new Object[3];
346: scopeInfo[0] = null;
347: scopeInfo[1] = removeScopeList;
348: scopeInfo[2] = (Boolean.FALSE);
349: sendMessage(SCOPE_CHANGED, scopeInfo);
350: }
351:
352: void initRemoveAllScopes() {
353: int n = scopes.size();
354: for (int i = n - 1; i >= 0; i--)
355: initRemoveScope(i);
356: }
357:
358: /**
359: * Returns an enumeration object of the scoperen.
360: * @return an enumeration object of the scoperen
361: */
362: Enumeration getAllScopes() {
363: Enumeration elm = scopes.elements();
364: Vector v = new Vector(scopes.size());
365: while (elm.hasMoreElements()) {
366: v.add(((GroupRetained) elm.nextElement()).source);
367: }
368: return v.elements();
369: }
370:
371: /**
372: * Returns the index of the specified Group node in this node's list of scopes.
373: * @param scope the Group node whose index is needed
374: */
375: int indexOfScope(Group scope) {
376: if (scope != null)
377: return scopes.indexOf((GroupRetained) scope.retained);
378: else
379: return scopes.indexOf(null);
380: }
381:
382: /**
383: * Appends the specified scope to this node's list of scopes before
384: * the alt app is alive
385: * @param scope the scope to add to this node's list of scopes
386: */
387: void initAddScope(Group scope) {
388: GroupRetained group = (GroupRetained) scope.retained;
389: scopes.addElement((GroupRetained) (scope.retained));
390: group.setAltAppScope();
391: }
392:
393: /**
394: * Appends the specified scope to this node's list of scopes.
395: * @param scope the scope to add to this node's list of scopes
396: */
397: void addScope(Group scope) {
398:
399: Object[] scopeInfo = new Object[3];
400: ArrayList addScopeList = new ArrayList();
401: GroupRetained group = (GroupRetained) scope.retained;
402:
403: initAddScope(scope);
404: tempKey.reset();
405: group.addAllNodesForScopedAltApp(mirrorAltApp, addScopeList,
406: tempKey);
407: scopeInfo[0] = addScopeList;
408: scopeInfo[1] = null;
409: scopeInfo[2] = (scopes.size() > 0 ? Boolean.TRUE
410: : Boolean.FALSE);
411: sendMessage(SCOPE_CHANGED, scopeInfo);
412: }
413:
414: /**
415: * Returns a count of this nodes' scopes.
416: * @return the number of scopes descendant from this node
417: */
418: int numScopes() {
419: return scopes.size();
420: }
421:
422: /**
423: * This sets the immedate mode context flag
424: */
425: void setInImmCtx(boolean inCtx) {
426: inImmCtx = inCtx;
427: }
428:
429: /**
430: * This gets the immedate mode context flag
431: */
432: boolean getInImmCtx() {
433: return (inImmCtx);
434: }
435:
436: boolean isScoped() {
437: return (scopes != null);
438: }
439:
440: void updateImmediateMirrorObject(Object[] objs) {
441: GroupRetained group;
442: Vector currentScopes;
443: int i, nscopes;
444: Transform3D trans;
445:
446: int component = ((Integer) objs[1]).intValue();
447: if ((component & APPEARANCE_CHANGED) != 0) {
448: mirrorAltApp.appearance = (AppearanceRetained) objs[2];
449: }
450: if ((component & BOUNDS_CHANGED) != 0) {
451: mirrorAltApp.regionOfInfluence = (Bounds) objs[2];
452: if (mirrorAltApp.boundingLeaf == null) {
453: if (objs[2] != null) {
454: mirrorAltApp.region = (Bounds) mirrorAltApp.regionOfInfluence
455: .copy(mirrorAltApp.region);
456: mirrorAltApp.region.transform(
457: mirrorAltApp.regionOfInfluence,
458: getCurrentLocalToVworld());
459: } else {
460: mirrorAltApp.region = null;
461: }
462: }
463: } else if ((component & BOUNDINGLEAF_CHANGED) != 0) {
464: mirrorAltApp.boundingLeaf = (BoundingLeafRetained) objs[2];
465: if (objs[2] != null) {
466: mirrorAltApp.region = (Bounds) mirrorAltApp.boundingLeaf.transformedRegion;
467: } else {
468: if (mirrorAltApp.regionOfInfluence != null) {
469: mirrorAltApp.region = mirrorAltApp.regionOfInfluence
470: .copy(mirrorAltApp.region);
471: mirrorAltApp.region.transform(
472: mirrorAltApp.regionOfInfluence,
473: getCurrentLocalToVworld());
474: } else {
475: mirrorAltApp.region = null;
476: }
477:
478: }
479: } else if ((component & SCOPE_CHANGED) != 0) {
480: Object[] scopeList = (Object[]) objs[2];
481: ArrayList addList = (ArrayList) scopeList[0];
482: ArrayList removeList = (ArrayList) scopeList[1];
483: boolean isScoped = ((Boolean) scopeList[2]).booleanValue();
484:
485: if (addList != null) {
486: mirrorAltApp.isScoped = isScoped;
487: for (i = 0; i < addList.size(); i++) {
488: Shape3DRetained obj = ((GeometryAtom) addList
489: .get(i)).source;
490: obj.addAltApp(mirrorAltApp);
491: }
492: }
493:
494: if (removeList != null) {
495: mirrorAltApp.isScoped = isScoped;
496: for (i = 0; i < removeList.size(); i++) {
497: Shape3DRetained obj = ((GeometryAtom) removeList
498: .get(i)).source;
499: obj.removeAltApp(mirrorAltApp);
500: }
501: }
502: }
503:
504: }
505:
506: /** Note: This routine will only be called on
507: * the mirror object - will update the object's
508: * cached region and transformed region
509: */
510:
511: void updateBoundingLeaf() {
512: if (boundingLeaf != null
513: && boundingLeaf.switchState.currentSwitchOn) {
514: region = boundingLeaf.transformedRegion;
515: } else {
516: if (regionOfInfluence != null) {
517: region = regionOfInfluence.copy(region);
518: region.transform(regionOfInfluence,
519: getCurrentLocalToVworld());
520: } else {
521: region = null;
522: }
523: }
524: }
525:
526: void setLive(SetLiveState s) {
527: GroupRetained group;
528: Vector currentScopes;
529: int i, nscopes;
530: TransformGroupRetained[] tlist;
531:
532: if (inImmCtx) {
533: throw new IllegalSharingException(J3dI18N
534: .getString("AlternateAppearanceRetained13"));
535: }
536:
537: if (inSharedGroup) {
538: throw new IllegalSharingException(J3dI18N
539: .getString("AlternateAppearanceRetained15"));
540: }
541:
542: if (inBackgroundGroup) {
543: throw new IllegalSceneGraphException(J3dI18N
544: .getString("AlternateAppearanceRetained16"));
545: }
546:
547: super .doSetLive(s);
548:
549: if (appearance != null) {
550: if (appearance.getInImmCtx()) {
551: throw new IllegalSharingException(J3dI18N
552: .getString("AlternateAppearanceRetained14"));
553: }
554: synchronized (appearance.liveStateLock) {
555: appearance.setLive(inBackgroundGroup, s.refCount);
556: }
557: }
558:
559: // Create the mirror object
560: // Initialization of the mirror object during the INSERT_NODE
561: // message (in updateMirrorObject)
562: if (mirrorAltApp == null) {
563: mirrorAltApp = (AlternateAppearanceRetained) this .clone();
564: // Assign the bounding leaf of this mirror object as null
565: // it will later be assigned to be the mirror of the alternate app
566: // bounding leaf object
567: mirrorAltApp.boundingLeaf = null;
568: mirrorAltApp.sgAltApp = this ;
569: }
570: // If bounding leaf is not null, add the mirror object as a user
571: // so that any changes to the bounding leaf will be received
572: if (boundingLeaf != null) {
573: boundingLeaf.mirrorBoundingLeaf.addUser(mirrorAltApp);
574: }
575:
576: if ((s.viewScopedNodeList != null) && (s.viewLists != null)) {
577: s.viewScopedNodeList.add(mirrorAltApp);
578: s.scopedNodesViewList.add(s.viewLists.get(0));
579: } else {
580: s.nodeList.add(mirrorAltApp);
581: }
582:
583: if (s.transformTargets != null && s.transformTargets[0] != null) {
584: s.transformTargets[0].addNode(mirrorAltApp,
585: Targets.ENV_TARGETS);
586: s.notifyThreads |= J3dThread.UPDATE_TRANSFORM;
587: }
588:
589: // process switch leaf
590: if (s.switchTargets != null && s.switchTargets[0] != null) {
591: s.switchTargets[0].addNode(mirrorAltApp,
592: Targets.ENV_TARGETS);
593: }
594: mirrorAltApp.switchState = (SwitchState) s.switchStates.get(0);
595:
596: s.notifyThreads |= J3dThread.UPDATE_RENDERING_ENVIRONMENT
597: | J3dThread.UPDATE_RENDER;
598:
599: // At the end make it live
600: super .markAsLive();
601:
602: // Initialize the mirror object, this needs to be done, when
603: // renderBin is not accessing any of the fields
604: J3dMessage createMessage = new J3dMessage();
605: createMessage.threads = J3dThread.UPDATE_RENDERING_ENVIRONMENT;
606: createMessage.universe = universe;
607: createMessage.type = J3dMessage.ALTERNATEAPPEARANCE_CHANGED;
608: createMessage.args[0] = this ;
609: // a snapshot of all attributes that needs to be initialized
610: // in the mirror object
611: createMessage.args[1] = new Integer(INIT_MIRROR);
612: ArrayList addScopeList = new ArrayList();
613: for (i = 0; i < scopes.size(); i++) {
614: group = (GroupRetained) scopes.get(i);
615: tempKey.reset();
616: group.addAllNodesForScopedAltApp(mirrorAltApp,
617: addScopeList, tempKey);
618: }
619: Object[] scopeInfo = new Object[2];
620: scopeInfo[0] = ((scopes.size() > 0) ? Boolean.TRUE
621: : Boolean.FALSE);
622: scopeInfo[1] = addScopeList;
623: createMessage.args[2] = scopeInfo;
624: if (appearance != null) {
625: createMessage.args[3] = appearance.mirror;
626: } else {
627: createMessage.args[3] = null;
628: }
629: Object[] obj = new Object[2];
630: obj[0] = boundingLeaf;
631: obj[1] = (regionOfInfluence != null ? regionOfInfluence.clone()
632: : null);
633: createMessage.args[4] = obj;
634: VirtualUniverse.mc.processMessage(createMessage);
635:
636: }
637:
638: /**
639: * This is called on the parent object
640: */
641: void initMirrorObject(Object[] args) {
642: Shape3DRetained shape;
643: Object[] scopeInfo = (Object[]) args[2];
644: Boolean scoped = (Boolean) scopeInfo[0];
645: ArrayList shapeList = (ArrayList) scopeInfo[1];
646: AppearanceRetained app = (AppearanceRetained) args[3];
647: BoundingLeafRetained bl = (BoundingLeafRetained) ((Object[]) args[4])[0];
648: Bounds bnds = (Bounds) ((Object[]) args[4])[1];
649:
650: for (int i = 0; i < shapeList.size(); i++) {
651: shape = ((GeometryAtom) shapeList.get(i)).source;
652: shape.addAltApp(mirrorAltApp);
653: }
654: mirrorAltApp.isScoped = scoped.booleanValue();
655:
656: if (app != null)
657: mirrorAltApp.appearance = app;
658:
659: if (bl != null) {
660: mirrorAltApp.boundingLeaf = bl.mirrorBoundingLeaf;
661: mirrorAltApp.region = boundingLeaf.transformedRegion;
662: } else {
663: mirrorAltApp.boundingLeaf = null;
664: mirrorAltApp.region = null;
665: }
666:
667: if (bnds != null) {
668: mirrorAltApp.regionOfInfluence = bnds;
669: if (mirrorAltApp.region == null) {
670: mirrorAltApp.region = (Bounds) regionOfInfluence
671: .clone();
672: mirrorAltApp.region.transform(regionOfInfluence,
673: getLastLocalToVworld());
674: }
675: } else {
676: mirrorAltApp.regionOfInfluence = null;
677: }
678:
679: }
680:
681: void clearMirrorObject(Object[] args) {
682: Shape3DRetained shape;
683: ArrayList shapeList = (ArrayList) args[2];
684: ArrayList removeScopeList = new ArrayList();
685:
686: for (int i = 0; i < shapeList.size(); i++) {
687: shape = ((GeometryAtom) shapeList.get(i)).source;
688: shape.removeAltApp(mirrorAltApp);
689: }
690: mirrorAltApp.isScoped = false;
691:
692: }
693:
694: /**
695: * This clearLive routine first calls the superclass's method, then
696: * it removes itself to the list of alt app
697: */
698: void clearLive(SetLiveState s) {
699: int i, j;
700: GroupRetained group;
701:
702: if (appearance != null) {
703: synchronized (appearance.liveStateLock) {
704: appearance.clearLive(s.refCount);
705: }
706: }
707:
708: super .clearLive(s);
709: s.notifyThreads |= J3dThread.UPDATE_RENDERING_ENVIRONMENT
710: | J3dThread.UPDATE_RENDER;
711:
712: // Remove this mirror light as users of the bounding leaf
713: if (mirrorAltApp.boundingLeaf != null)
714: mirrorAltApp.boundingLeaf.removeUser(mirrorAltApp);
715:
716: if ((s.viewScopedNodeList != null) && (s.viewLists != null)) {
717: s.viewScopedNodeList.add(mirrorAltApp);
718: s.scopedNodesViewList.add(s.viewLists.get(0));
719: } else {
720: s.nodeList.add(mirrorAltApp);
721: }
722: if (s.transformTargets != null && s.transformTargets[0] != null) {
723: s.transformTargets[0].addNode(mirrorAltApp,
724: Targets.ENV_TARGETS);
725: s.notifyThreads |= J3dThread.UPDATE_TRANSFORM;
726: }
727: if (s.switchTargets != null && s.switchTargets[0] != null) {
728: s.switchTargets[0].addNode(mirrorAltApp,
729: Targets.ENV_TARGETS);
730: }
731:
732: if (scopes.size() > 0) {
733: J3dMessage createMessage = new J3dMessage();
734: createMessage.threads = J3dThread.UPDATE_RENDERING_ENVIRONMENT;
735: createMessage.universe = universe;
736: createMessage.type = J3dMessage.ALTERNATEAPPEARANCE_CHANGED;
737: createMessage.args[0] = this ;
738: createMessage.args[1] = new Integer(CLEAR_MIRROR);
739: ArrayList removeScopeList = new ArrayList();
740: for (i = 0; i < scopes.size(); i++) {
741: group = (GroupRetained) scopes.get(i);
742: tempKey.reset();
743: group.removeAllNodesForScopedAltApp(mirrorAltApp,
744: removeScopeList, tempKey);
745: }
746: createMessage.args[2] = removeScopeList;
747: VirtualUniverse.mc.processMessage(createMessage);
748: }
749: }
750:
751: void updateTransformChange() {
752: }
753:
754: /**
755: * Called on mirror object
756: */
757: void updateImmediateTransformChange() {
758: // If bounding leaf is null, tranform the bounds object
759: if (boundingLeaf == null) {
760: if (regionOfInfluence != null) {
761: region = regionOfInfluence.copy(region);
762: region.transform(regionOfInfluence, sgAltApp
763: .getCurrentLocalToVworld());
764: }
765:
766: }
767: }
768:
769: final void sendMessage(int attrMask, Object attr) {
770: J3dMessage createMessage = new J3dMessage();
771: createMessage.threads = targetThreads;
772: createMessage.universe = universe;
773: createMessage.type = J3dMessage.ALTERNATEAPPEARANCE_CHANGED;
774: createMessage.args[0] = this ;
775: createMessage.args[1] = new Integer(attrMask);
776: createMessage.args[2] = attr;
777: VirtualUniverse.mc.processMessage(createMessage);
778: }
779:
780: void getMirrorObjects(ArrayList leafList, HashKey key) {
781: leafList.add(mirrorAltApp);
782: }
783:
784: /**
785: * Copies all AlternateAppearance information from
786: * <code>originalNode</code> into
787: * the current node. This method is called from the
788: * <code>cloneNode</code> method which is, in turn, called by the
789: * <code>cloneTree</code> method.<P>
790: *
791: * @param originalNode the original node to duplicate.
792: * @param forceDuplicate when set to <code>true</code>, causes the
793: * <code>duplicateOnCloneTree</code> flag to be ignored. When
794: * <code>false</code>, the value of each node's
795: * <code>duplicateOnCloneTree</code> variable determines whether
796: * NodeComponent data is duplicated or copied.
797: *
798: * @exception RestrictedAccessException if this object is part of a live
799: * or compiled scenegraph.
800: *
801: * @see Node#duplicateNode
802: * @see Node#cloneTree
803: * @see NodeComponent#setDuplicateOnCloneTree
804: */
805: void duplicateAttributes(Node originalNode, boolean forceDuplicate) {
806: throw new RuntimeException("method not implemented");
807:
808: // super.duplicateAttributes(originalNode, forceDuplicate);
809:
810: // AlternateAppearance alternate appearance = (AlternateAppearance) originalNode;
811:
812: // // XXXX: clone appearance
813:
814: // setInfluencingBounds(alternate appearance.getInfluencingBounds());
815:
816: // Enumeration elm = alternate appearance.getAllScopes();
817: // while (elm.hasMoreElements()) {
818: // // this reference will set correctly in updateNodeReferences() callback
819: // addScope((Group) elm.nextElement());
820: // }
821:
822: // // this reference will set correctly in updateNodeReferences() callback
823: // setInfluencingBoundingLeaf(alternate appearance.getInfluencingBoundingLeaf());
824: }
825:
826: // /**
827: // * Callback used to allow a node to check if any nodes referenced
828: // * by that node have been duplicated via a call to <code>cloneTree</code>.
829: // * This method is called by <code>cloneTree</code> after all nodes in
830: // * the sub-graph have been duplicated. The cloned Leaf node's method
831: // * will be called and the Leaf node can then look up any node references
832: // * by using the <code>getNewObjectReference</code> method found in the
833: // * <code>NodeReferenceTable</code> object. If a match is found, a
834: // * reference to the corresponding Node in the newly cloned sub-graph
835: // * is returned. If no corresponding reference is found, either a
836: // * DanglingReferenceException is thrown or a reference to the original
837: // * node is returned depending on the value of the
838: // * <code>allowDanglingReferences</code> parameter passed in the
839: // * <code>cloneTree</code> call.
840: // * <p>
841: // * NOTE: Applications should <i>not</i> call this method directly.
842: // * It should only be called by the cloneTree method.
843: // *
844: // * @param referenceTable a NodeReferenceTableObject that contains the
845: // * <code>getNewObjectReference</code> method needed to search for
846: // * new object instances.
847: // * @see NodeReferenceTable
848: // * @see Node#cloneTree
849: // * @see DanglingReferenceException
850: // */
851: // public void updateNodeReferences(NodeReferenceTable referenceTable) {
852: // throw new RuntimeException("method not implemented");
853: //
854: // Object o;
855: //
856: // BoundingLeaf bl = getInfluencingBoundingLeaf();
857: // if (bl != null) {
858: // o = referenceTable.getNewObjectReference(bl);
859: // setInfluencingBoundingLeaf((BoundingLeaf) o);
860: // }
861: //
862: // for (int i=0; i < numScopes(); i++) {
863: // o = referenceTable.getNewObjectReference(getScope(i));
864: // setScope((Group) o, i);
865: // }
866: // }
867:
868: }
|