0001: /*
0002: * $RCSfile: BehaviorStructure.java,v $
0003: *
0004: * Copyright 1998-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.8 $
0028: * $Date: 2008/02/28 20:17:19 $
0029: * $State: Exp $
0030: */
0031:
0032: package javax.media.j3d;
0033:
0034: import javax.vecmath.*;
0035: import java.util.ArrayList;
0036: import java.awt.*;
0037: import java.awt.event.*;
0038: import java.util.Arrays;
0039:
0040: /**
0041: * A behavior structure is a object that organizes behaviors,
0042: * wakeup conditions, and other behavior scheduler entities.
0043: */
0044:
0045: class BehaviorStructure extends J3dStructure {
0046:
0047: /**
0048: * The list of behaviors
0049: */
0050: IndexedUnorderSet behaviors;
0051:
0052: /**
0053: * The list of view platforms
0054: */
0055: IndexedUnorderSet viewPlatforms;
0056:
0057: /**
0058: * An array of schedulable behaviors, use in
0059: * removeViewPlatform() to go through only active behaviors
0060: */
0061: IndexedUnorderSet scheduleList;
0062:
0063: /**
0064: * An array of process behaviors
0065: */
0066: UnorderList processList[] = new UnorderList[BehaviorRetained.NUM_SCHEDULING_INTERVALS];
0067:
0068: /**
0069: * A bounds used for getting a view platform scheduling BoundingSphere
0070: */
0071: // BoundingSphere tempSphere = new BoundingSphere();
0072: // BoundingSphere vpsphere = new BoundingSphere();
0073: Point3d vpCenter = new Point3d();
0074: Point3d vpTransCenter = new Point3d();
0075:
0076: /**
0077: * A list of bounds WakeupOnViewPlatformEntry objects that
0078: * have seen ViewPlatformEntry
0079: */
0080: WakeupIndexedList boundsEntryList;
0081:
0082: /**
0083: * A list of bounds WakeupOnViewPlatformExit objects that have
0084: * seen ViewPlatformEntry
0085: */
0086: WakeupIndexedList boundsExitList;
0087:
0088: /**
0089: * A list of WakeupOnSensorEntry objects that have seen a sensor
0090: */
0091: WakeupIndexedList currentSensorEntryList;
0092:
0093: /**
0094: * A list of WakeupOnSensorExit objects that have seen a sensor
0095: */
0096: WakeupIndexedList currentSensorExitList;
0097:
0098: /**
0099: * The lists of the WakeupCriterion objects that the
0100: * behavior scheduler keeps.
0101: */
0102: WakeupIndexedList wakeupOnAWTEvent;
0103: WakeupIndexedList wakeupOnActivation;
0104: WakeupIndexedList wakeupOnDeactivation;
0105: WakeupIndexedList wakeupOnBehaviorPost;
0106: WakeupIndexedList wakeupOnElapsedFrames;
0107: WakeupIndexedList wakeupOnViewPlatformEntry;
0108: WakeupIndexedList wakeupOnViewPlatformExit;
0109: WakeupIndexedList wakeupOnSensorEntry;
0110: WakeupIndexedList wakeupOnSensorExit;
0111:
0112: // Temporary array for processTransformChanged()
0113: UnorderList transformViewPlatformList = new UnorderList(
0114: ViewPlatformRetained.class);
0115:
0116: // The number of active wakeup condition in wakeupOnElapsedFrames
0117: int activeWakeupOnFrameCount = 0;
0118:
0119: // The number of active wakeup condition in wakeupOnSensorEntry/Exit
0120: int activeWakeupOnSensorCount = 0;
0121:
0122: /**
0123: * Buffers to hold events when user thread is in processStimulus()
0124: * while this event is receiving. This avoid any lost of event.
0125: * We did not remove individual element from the following list
0126: * (except clear()) so the order is still preserve.
0127: */
0128: UnorderList awtEventsBuffer = new UnorderList(AWTEvent.class);
0129:
0130: // Use generic integer array to avoid new Integer() for individual element
0131: int postIDBuffer[] = new int[10]; // size of default UnorderList
0132: int clonePostIDBuffer[] = new int[postIDBuffer.length];
0133:
0134: UnorderList behaviorPostBuffer = new UnorderList(Behavior.class);
0135:
0136: // temp values for transformed hotspot used in
0137: // wakeupOnSensorEntry/ExitupdateSensorsHotspot
0138: Transform3D sensorTransform = new Transform3D();
0139: Vector3d sensorLoc = new Vector3d();
0140: Point3d ptSensorLoc = new Point3d();
0141:
0142: // list of active physical environments
0143: UnorderList physicalEnvironments = new UnorderList(1,
0144: PhysicalEnvironment.class);
0145:
0146: // list of Behavior waiting to be add to behavior list and buildTree()
0147: UnorderList pendingBehaviors = new UnorderList(
0148: BehaviorRetained.class);
0149:
0150: // true if branch detach
0151: boolean branchDetach = false;
0152:
0153: // This is used to notify WakeupOnAWTEvent re-enable Canvas3D events
0154: long awtEventTimestamp = 1;
0155:
0156: // used to process transform messages
0157: boolean transformMsg = false;
0158: UpdateTargets targets = null;
0159:
0160: BehaviorStructure(VirtualUniverse u) {
0161: super (u, J3dThread.UPDATE_BEHAVIOR);
0162:
0163: for (int i = BehaviorRetained.NUM_SCHEDULING_INTERVALS - 1; i >= 0; i--) {
0164: processList[i] = new UnorderList(BehaviorRetained.class);
0165: }
0166: behaviors = new IndexedUnorderSet(BehaviorRetained.class,
0167: BehaviorRetained.BEHAIVORS_IN_BS_LIST, u);
0168: viewPlatforms = new IndexedUnorderSet(
0169: ViewPlatformRetained.class,
0170: ViewPlatformRetained.VP_IN_BS_LIST, u);
0171: scheduleList = new IndexedUnorderSet(BehaviorRetained.class,
0172: BehaviorRetained.SCHEDULE_IN_BS_LIST, u);
0173: boundsEntryList = new WakeupIndexedList(
0174: WakeupOnViewPlatformEntry.class,
0175: WakeupOnViewPlatformEntry.BOUNDSENTRY_IN_BS_LIST, u);
0176: boundsExitList = new WakeupIndexedList(
0177: WakeupOnViewPlatformExit.class,
0178: WakeupOnViewPlatformExit.BOUNDSEXIT_IN_BS_LIST, u);
0179: currentSensorEntryList = new WakeupIndexedList(
0180: WakeupOnSensorEntry.class,
0181: WakeupOnSensorEntry.SENSORENTRY_IN_BS_LIST, u);
0182: currentSensorExitList = new WakeupIndexedList(
0183: WakeupOnSensorExit.class,
0184: WakeupOnSensorExit.SENSOREXIT_IN_BS_LIST, u);
0185: wakeupOnAWTEvent = new WakeupIndexedList(
0186: WakeupOnAWTEvent.class,
0187: WakeupOnAWTEvent.COND_IN_BS_LIST, u);
0188: wakeupOnActivation = new WakeupIndexedList(
0189: WakeupOnActivation.class,
0190: WakeupOnActivation.COND_IN_BS_LIST, u);
0191: wakeupOnDeactivation = new WakeupIndexedList(
0192: WakeupOnDeactivation.class,
0193: WakeupOnDeactivation.COND_IN_BS_LIST, u);
0194: wakeupOnBehaviorPost = new WakeupIndexedList(
0195: WakeupOnBehaviorPost.class,
0196: WakeupOnBehaviorPost.COND_IN_BS_LIST, u);
0197: wakeupOnElapsedFrames = new WakeupIndexedList(
0198: WakeupOnElapsedFrames.class,
0199: WakeupOnElapsedFrames.COND_IN_BS_LIST, u);
0200: wakeupOnViewPlatformEntry = new WakeupIndexedList(
0201: WakeupOnViewPlatformEntry.class,
0202: WakeupOnViewPlatformEntry.COND_IN_BS_LIST, u);
0203: wakeupOnViewPlatformExit = new WakeupIndexedList(
0204: WakeupOnViewPlatformExit.class,
0205: WakeupOnViewPlatformExit.COND_IN_BS_LIST, u);
0206: wakeupOnSensorEntry = new WakeupIndexedList(
0207: WakeupOnSensorEntry.class,
0208: WakeupOnSensorEntry.COND_IN_BS_LIST, u);
0209: wakeupOnSensorExit = new WakeupIndexedList(
0210: WakeupOnSensorExit.class,
0211: WakeupOnSensorExit.COND_IN_BS_LIST, u);
0212:
0213: }
0214:
0215: void processMessages(long referenceTime) {
0216:
0217: J3dMessage[] messages = getMessages(referenceTime);
0218: int nMsg = getNumMessage();
0219: J3dMessage m;
0220:
0221: if (nMsg > 0) {
0222: for (int i = 0; i < nMsg; i++) {
0223: m = messages[i];
0224:
0225: switch (m.type) {
0226: case J3dMessage.TRANSFORM_CHANGED: // Compress Message
0227: transformMsg = true;
0228: break;
0229: case J3dMessage.COND_MET:
0230: // No need to compress Message since wakeupCondition
0231: // will make sure that only one message is sent.
0232: processConditionMet((BehaviorRetained) m.args[0],
0233: (Boolean) m.args[1]);
0234: break;
0235: case J3dMessage.INSERT_NODES:
0236: insertNodes((Object[]) m.args[0]);
0237: break;
0238: case J3dMessage.REMOVE_NODES:
0239: removeNodes(m);
0240: break;
0241: case J3dMessage.BEHAVIOR_ACTIVATE:
0242: activateBehaviors();
0243: break;
0244: case J3dMessage.BEHAVIOR_ENABLE:
0245: addToScheduleList((BehaviorRetained) m.args[1]);
0246: reEvaluateWakeupCount();
0247: break;
0248: case J3dMessage.BEHAVIOR_DISABLE:
0249: removeFromScheduleList((BehaviorRetained) m.args[1]);
0250: reEvaluateWakeupCount();
0251: break;
0252: case J3dMessage.SCHEDULING_INTERVAL_CHANGED:
0253: ((BehaviorRetained) m.args[1]).schedulingInterval = ((Integer) m.args[2])
0254: .intValue();
0255: break;
0256: case J3dMessage.SWITCH_CHANGED:
0257: processSwitchChanged(m);
0258: // may need to process dirty switched-on transform
0259: if (universe.transformStructure.getLazyUpdate()) {
0260: transformMsg = true;
0261: }
0262: break;
0263: case J3dMessage.BOUNDINGLEAF_CHANGED:
0264: processBoundingLeafChanged((Object[]) m.args[3],
0265: (Bounds) m.args[2]);
0266: break;
0267: case J3dMessage.UPDATE_VIEW:
0268: reEvaluatePhysicalEnvironments();
0269: ViewPlatform v = ((View) m.args[0])
0270: .getViewPlatform();
0271: if (v != null) {
0272: // ViewPlatform may set to null when deactivate()
0273: processViewPlatformTransform((ViewPlatformRetained) v.retained);
0274: }
0275: break;
0276: case J3dMessage.UPDATE_VIEWPLATFORM:
0277: ViewPlatformRetained vp = (ViewPlatformRetained) m.args[0];
0278: // update cached scheduling region first
0279: vp.updateActivationRadius(((Float) m.args[1])
0280: .floatValue());
0281: // then process the VP transform
0282: processViewPlatformTransform(vp);
0283: break;
0284: case J3dMessage.REGION_BOUND_CHANGED: {
0285: BehaviorRetained behav = (BehaviorRetained) m.args[1];
0286: behav.updateTransformRegion();
0287: processBehaviorTransform(behav);
0288: }
0289: break;
0290: case J3dMessage.BEHAVIOR_REEVALUATE: {
0291: BehaviorRetained behav = (BehaviorRetained) m.args[0];
0292: behav.active = false;
0293: addToScheduleList(behav);
0294: }
0295: break;
0296: }
0297: m.decRefcount();
0298: }
0299:
0300: if (transformMsg) {
0301: // get the targets from the transform structure
0302: targets = universe.transformStructure.getTargetList();
0303:
0304: // process the transform changed for each target
0305: UnorderList arrList;
0306:
0307: arrList = targets.targetList[Targets.BEH_TARGETS];
0308: if (arrList != null) {
0309: processBehXformChanged(arrList);
0310: }
0311:
0312: arrList = targets.targetList[Targets.VPF_TARGETS];
0313: if (arrList != null) {
0314: processVpfXformChanged(arrList);
0315: }
0316:
0317: transformMsg = false;
0318: targets = null;
0319: }
0320: Arrays.fill(messages, 0, nMsg, null);
0321: }
0322:
0323: // wakeup even when message is null since wakeupOnElapsedFrame
0324: // will wakeup this
0325:
0326: if (activeWakeupOnSensorCount <= 0) {
0327: if (activeWakeupOnFrameCount > 0) {
0328: // Wakeup render thread when there is pending wakeupOnElapsedFrames
0329: VirtualUniverse.mc.sendRunMessage(universe,
0330: J3dThread.BEHAVIOR_SCHEDULER
0331: | J3dThread.RENDER_THREAD);
0332:
0333: } else {
0334: VirtualUniverse.mc.sendRunMessage(universe,
0335: J3dThread.BEHAVIOR_SCHEDULER);
0336: }
0337: } else {
0338: checkSensorEntryExit();
0339: // we have to invoke checkSensorEntryExit() next time
0340: if (activeWakeupOnFrameCount > 0) {
0341: VirtualUniverse.mc.sendRunMessage(universe,
0342: J3dThread.UPDATE_BEHAVIOR
0343: | J3dThread.BEHAVIOR_SCHEDULER
0344: | J3dThread.RENDER_THREAD);
0345:
0346: } else {
0347: VirtualUniverse.mc.sendRunMessage(universe,
0348: J3dThread.UPDATE_BEHAVIOR
0349: | J3dThread.BEHAVIOR_SCHEDULER);
0350: }
0351: }
0352: }
0353:
0354: void insertNodes(Object[] nodes) {
0355: for (int i = 0; i < nodes.length; i++) {
0356: Object node = (Object) nodes[i];
0357:
0358: if (node instanceof BehaviorRetained) {
0359: pendingBehaviors.add(node);
0360: } else if (node instanceof ViewPlatformRetained) {
0361: addViewPlatform((ViewPlatformRetained) node);
0362: }
0363: }
0364: }
0365:
0366: void activateBehaviors() {
0367: BehaviorRetained behav;
0368: BehaviorRetained behavArr[] = (BehaviorRetained[]) pendingBehaviors
0369: .toArray(false);
0370:
0371: for (int i = pendingBehaviors.arraySize() - 1; i >= 0; i--) {
0372: behav = behavArr[i];
0373: behav.wakeupCondition = behav.newWakeupCondition;
0374: if (behav.wakeupCondition != null) {
0375: behav.wakeupCondition.buildTree(null, 0, behav);
0376: behav.conditionSet = true;
0377: behaviors.add(behav);
0378: behav.updateTransformRegion();
0379: addToScheduleList(behav);
0380: }
0381: }
0382: pendingBehaviors.clear();
0383: }
0384:
0385: void addViewPlatform(ViewPlatformRetained vp) {
0386: int i;
0387: BehaviorRetained behav;
0388: BehaviorRetained behavArr[] = (BehaviorRetained[]) behaviors
0389: .toArray(false);
0390:
0391: viewPlatforms.add(vp);
0392: vp.updateTransformRegion();
0393:
0394: if (!vp.isActiveViewPlatform()) {
0395: return;
0396: }
0397:
0398: // re-evaulate all behaviors to see if we need to put
0399: // more behaviors in scheduleList
0400:
0401: for (i = behaviors.arraySize() - 1; i >= 0; i--) {
0402: addToScheduleList(behavArr[i]);
0403: }
0404:
0405: // handle ViewPlatform Entry
0406: WakeupOnViewPlatformEntry wakeupOnViewPlatformEntryArr[] = (WakeupOnViewPlatformEntry[]) wakeupOnViewPlatformEntry
0407: .toArray(false);
0408: WakeupOnViewPlatformEntry wentry;
0409:
0410: for (i = wakeupOnViewPlatformEntry.arraySize() - 1; i >= 0; i--) {
0411: wentry = wakeupOnViewPlatformEntryArr[i];
0412: if (!boundsEntryList.contains(wentry)
0413: && wentry.transformedRegion.intersect(vp.center)) {
0414: boundsEntryList.add(wentry);
0415: wentry.triggeredVP = vp;
0416: wentry.setTriggered();
0417: }
0418: }
0419:
0420: // handle ViewPlatform Exit
0421: WakeupOnViewPlatformExit wakeupOnViewPlatformExitArr[] = (WakeupOnViewPlatformExit[]) wakeupOnViewPlatformExit
0422: .toArray(false);
0423: WakeupOnViewPlatformExit wexit;
0424:
0425: for (i = wakeupOnViewPlatformExit.arraySize() - 1; i >= 0; i--) {
0426: wexit = wakeupOnViewPlatformExitArr[i];
0427: if (!boundsExitList.contains(wexit)
0428: && wexit.transformedRegion.intersect(vp.center)) {
0429: wexit.triggeredVP = vp;
0430: boundsExitList.add(wexit);
0431: }
0432: }
0433:
0434: }
0435:
0436: void removeNodes(J3dMessage m) {
0437: Object[] nodes = (Object[]) m.args[0];
0438: boolean behavRemove = false;
0439:
0440: for (int i = 0; i < nodes.length; i++) {
0441: Object node = nodes[i];
0442: if (node instanceof BehaviorRetained) {
0443: behavRemove = true;
0444: removeBehavior((BehaviorRetained) node);
0445: } else if (node instanceof ViewPlatformRetained) {
0446: removeViewPlatform((ViewPlatformRetained) node);
0447: }
0448: }
0449:
0450: // Since BehaviorScheduler will run after BehaviorStructure
0451: // (not in parallel). It is safe to do cleanup here.
0452: wakeupOnAWTEvent.clearMirror();
0453: awtEventsBuffer.clearMirror();
0454: wakeupOnBehaviorPost.clearMirror();
0455: behaviorPostBuffer.clearMirror();
0456: wakeupOnSensorEntry.clearMirror();
0457: wakeupOnSensorExit.clearMirror();
0458: branchDetach = true;
0459:
0460: if (behavRemove) {
0461: // disable AWT Event from Canvas3D
0462: WakeupOnAWTEvent awtConds[] = (WakeupOnAWTEvent[]) wakeupOnAWTEvent
0463: .toArray();
0464: int eventSize = wakeupOnAWTEvent.arraySize();
0465:
0466: // Component Event always Enable
0467: boolean focusEnable = false;
0468: boolean keyEnable = false;
0469: boolean mouseMotionEnable = false;
0470: boolean mouseEnable = false;
0471: boolean mouseWheelEnable = false;
0472: WakeupOnAWTEvent awtCond;
0473: int awtId;
0474: long eventMask;
0475: boolean incTimestamp = false;
0476:
0477: for (int i = 0; i < eventSize; i++) {
0478: awtCond = awtConds[i];
0479: awtId = awtCond.AwtId;
0480: eventMask = awtCond.EventMask;
0481:
0482: if ((awtId >= FocusEvent.FOCUS_FIRST && awtId <= FocusEvent.FOCUS_LAST)
0483: || (eventMask & AWTEvent.FOCUS_EVENT_MASK) != 0) {
0484: focusEnable = true;
0485: }
0486: if ((awtId >= KeyEvent.KEY_FIRST && awtId <= KeyEvent.KEY_LAST)
0487: || (eventMask & AWTEvent.KEY_EVENT_MASK) != 0) {
0488: keyEnable = true;
0489: }
0490: if ((awtId >= MouseEvent.MOUSE_FIRST)
0491: && (awtId <= MouseEvent.MOUSE_LAST)) {
0492: if ((awtId == MouseEvent.MOUSE_DRAGGED)
0493: || (awtId == MouseEvent.MOUSE_MOVED)) {
0494: mouseMotionEnable = true;
0495: } else if ((awtId == MouseEvent.MOUSE_ENTERED)
0496: || (awtId == MouseEvent.MOUSE_EXITED)
0497: || (awtId == MouseEvent.MOUSE_CLICKED)
0498: || (awtId == MouseEvent.MOUSE_PRESSED)
0499: || (awtId == MouseEvent.MOUSE_RELEASED)) {
0500: mouseEnable = true;
0501: } else if (awtId == MouseEvent.MOUSE_WHEEL) {
0502: mouseWheelEnable = true;
0503: }
0504: } else {
0505: if ((eventMask & AWTEvent.MOUSE_EVENT_MASK) != 0) {
0506: mouseEnable = true;
0507: }
0508: if ((eventMask & AWTEvent.MOUSE_MOTION_EVENT_MASK) != 0) {
0509: mouseMotionEnable = true;
0510: }
0511: if ((eventMask & AWTEvent.MOUSE_WHEEL_EVENT_MASK) != 0) {
0512: mouseWheelEnable = true;
0513: }
0514: }
0515: }
0516:
0517: if (!focusEnable && universe.enableFocus) {
0518: incTimestamp = true;
0519: universe.disableFocusEvents();
0520: }
0521: if (!VirtualUniverse.mc.isD3D() && !keyEnable
0522: && universe.enableKey) {
0523: // key event use for toggle to fullscreen/window mode
0524: incTimestamp = true;
0525: universe.disableKeyEvents();
0526: }
0527: if (!mouseWheelEnable && universe.enableMouseWheel) {
0528: incTimestamp = true;
0529: universe.disableMouseWheelEvents();
0530: }
0531: if (!mouseMotionEnable && universe.enableMouseMotion) {
0532: incTimestamp = true;
0533: universe.disableMouseMotionEvents();
0534: }
0535: if (!mouseEnable && universe.enableMouse) {
0536: incTimestamp = true;
0537: universe.disableMouseEvents();
0538: }
0539: if (incTimestamp) {
0540: awtEventTimestamp++;
0541: }
0542: }
0543: }
0544:
0545: void removeViewPlatform(ViewPlatformRetained vp) {
0546: BehaviorRetained behav;
0547: int i;
0548:
0549: viewPlatforms.remove(vp);
0550:
0551: BehaviorRetained scheduleArr[] = (BehaviorRetained[]) scheduleList
0552: .toArray(false);
0553:
0554: // handle Deactive
0555: for (i = scheduleList.arraySize() - 1; i >= 0; i--) {
0556: behav = scheduleArr[i];
0557: // This vp may contribute to the reason that
0558: // behavior is in schedule list
0559: if (!intersectVPRegion(behav.transformedRegion)) {
0560: removeFromScheduleList(behav);
0561: }
0562: }
0563:
0564: // handle ViewPlatform Entry
0565: WakeupOnViewPlatformEntry boundsEntryArr[] = (WakeupOnViewPlatformEntry[]) boundsEntryList
0566: .toArray(false);
0567: WakeupOnViewPlatformEntry wentry;
0568: ViewPlatformRetained triggeredVP;
0569:
0570: for (i = boundsEntryList.arraySize() - 1; i >= 0; i--) {
0571: wentry = boundsEntryArr[i];
0572: // only this thread can modify wentry.transformedRegion, so
0573: // no need to getWithLock()
0574: triggeredVP = intersectVPCenter(wentry.transformedRegion);
0575: if (triggeredVP == null) {
0576: boundsEntryList.remove(wentry);
0577: }
0578: }
0579:
0580: // handle ViewPlatform Exit
0581: WakeupOnViewPlatformExit boundsExitArr[] = (WakeupOnViewPlatformExit[]) boundsExitList
0582: .toArray(false);
0583: WakeupOnViewPlatformExit wexit;
0584:
0585: for (i = boundsExitList.arraySize() - 1; i >= 0; i--) {
0586: wexit = boundsExitArr[i];
0587: // only this thread can modify wentry.transformedRegion, so
0588: // no need to getWithLock()
0589: triggeredVP = intersectVPCenter(wexit.transformedRegion);
0590: if (triggeredVP == null) {
0591: boundsExitList.remove(wexit);
0592: wexit.setTriggered();
0593: }
0594: }
0595: }
0596:
0597: void removeBehavior(BehaviorRetained behav) {
0598: behaviors.remove(behav);
0599:
0600: if ((behav.wakeupCondition != null)
0601: && (behav.wakeupCondition.behav != null)) {
0602: behav.wakeupCondition.cleanTree(this );
0603: if (behav.universe == universe) {
0604: behav.conditionSet = false;
0605: }
0606: }
0607:
0608: // cleanup boundsEntryList
0609: // since we didn't remove it on removeVPEntryCondition
0610: WakeupOnViewPlatformEntry boundsEntryArr[] = (WakeupOnViewPlatformEntry[]) boundsEntryList
0611: .toArray(false);
0612: WakeupOnViewPlatformEntry wentry;
0613:
0614: for (int i = boundsEntryList.arraySize() - 1; i >= 0; i--) {
0615: wentry = boundsEntryArr[i];
0616: if (wentry.behav == behav) {
0617: boundsEntryList.remove(wentry);
0618: }
0619: }
0620:
0621: // cleanup boundsExitList
0622: // since we didn't remove it on removeVPExitCondition
0623: WakeupOnViewPlatformExit boundsExitArr[] = (WakeupOnViewPlatformExit[]) boundsExitList
0624: .toArray(false);
0625: WakeupOnViewPlatformExit wexit;
0626:
0627: for (int i = boundsExitList.arraySize() - 1; i >= 0; i--) {
0628: wexit = boundsExitArr[i];
0629: if (wexit.behav == behav) {
0630: boundsExitList.remove(wexit);
0631: }
0632: }
0633:
0634: // cleanup currentSensorEntryList
0635: // since we didn't remove it on removeSensorEntryCondition
0636: WakeupOnSensorEntry currentSensorEntryArr[] = (WakeupOnSensorEntry[]) currentSensorEntryList
0637: .toArray(false);
0638: WakeupOnSensorEntry sentry;
0639:
0640: for (int i = currentSensorEntryList.arraySize() - 1; i >= 0; i--) {
0641: sentry = currentSensorEntryArr[i];
0642: if (sentry.behav == behav) {
0643: currentSensorEntryList.remove(sentry);
0644: }
0645: }
0646:
0647: // cleanup currentSensorExitList
0648: // since we didn't remove it on removeSensorExitCondition
0649: WakeupOnSensorExit currentSensorExitArr[] = (WakeupOnSensorExit[]) currentSensorExitList
0650: .toArray(false);
0651: WakeupOnSensorExit sexit;
0652:
0653: for (int i = currentSensorExitList.arraySize() - 1; i >= 0; i--) {
0654: sexit = currentSensorExitArr[i];
0655: if (sexit.behav == behav) {
0656: currentSensorExitList.remove(sexit);
0657: }
0658: }
0659: removeFromScheduleList(behav);
0660:
0661: }
0662:
0663: void handleAWTEvent(AWTEvent evt) {
0664: awtEventsBuffer.add(evt);
0665: VirtualUniverse.mc.sendRunMessage(universe,
0666: J3dThread.BEHAVIOR_SCHEDULER);
0667: }
0668:
0669: /**
0670: * This routine takes the awt event list and gives then to the awt event
0671: * conditions
0672: */
0673: void handleAWTEvent() {
0674: WakeupOnAWTEvent awtConds[] = (WakeupOnAWTEvent[]) wakeupOnAWTEvent
0675: .toArray();
0676: AWTEvent events[];
0677: int eventSize = wakeupOnAWTEvent.arraySize();
0678: int awtBufferSize;
0679:
0680: synchronized (awtEventsBuffer) {
0681: events = (AWTEvent[]) awtEventsBuffer.toArray();
0682: awtBufferSize = awtEventsBuffer.size();
0683: awtEventsBuffer.clear();
0684: }
0685: WakeupOnAWTEvent awtCond;
0686: AWTEvent evt;
0687: int id;
0688:
0689: for (int i = 0; i < eventSize; i++) {
0690: awtCond = awtConds[i];
0691: for (int j = 0; j < awtBufferSize; j++) {
0692: evt = events[j];
0693: id = evt.getID();
0694:
0695: if (awtCond.AwtId != 0) {
0696: if (awtCond.AwtId == id) {
0697: // XXXX: how do we clone this event (do we need to?)
0698: // Bug: 4181321
0699: awtCond.addAWTEvent(evt);
0700: }
0701: } else {
0702: if (id >= ComponentEvent.COMPONENT_FIRST
0703: && id <= ComponentEvent.COMPONENT_LAST
0704: && (awtCond.EventMask & AWTEvent.COMPONENT_EVENT_MASK) != 0) {
0705: awtCond.addAWTEvent(evt);
0706: } else if (id >= FocusEvent.FOCUS_FIRST
0707: && id <= FocusEvent.FOCUS_LAST
0708: && (awtCond.EventMask & AWTEvent.FOCUS_EVENT_MASK) != 0) {
0709: awtCond.addAWTEvent(evt);
0710: } else if (id >= KeyEvent.KEY_FIRST
0711: && id <= KeyEvent.KEY_LAST
0712: && (awtCond.EventMask & AWTEvent.KEY_EVENT_MASK) != 0) {
0713: awtCond.addAWTEvent(evt);
0714: } else if ((id == MouseEvent.MOUSE_CLICKED
0715: || id == MouseEvent.MOUSE_ENTERED
0716: || id == MouseEvent.MOUSE_EXITED
0717: || id == MouseEvent.MOUSE_PRESSED || id == MouseEvent.MOUSE_RELEASED)
0718: && (awtCond.EventMask & AWTEvent.MOUSE_EVENT_MASK) != 0) {
0719: awtCond.addAWTEvent(evt);
0720: } else if ((id == MouseEvent.MOUSE_DRAGGED || id == MouseEvent.MOUSE_MOVED)
0721: && (awtCond.EventMask & AWTEvent.MOUSE_MOTION_EVENT_MASK) != 0) {
0722: awtCond.addAWTEvent(evt);
0723: } else if ((id == MouseEvent.MOUSE_WHEEL)
0724: && (awtCond.EventMask & AWTEvent.MOUSE_WHEEL_EVENT_MASK) != 0) {
0725: awtCond.addAWTEvent(evt);
0726: }
0727: }
0728: }
0729: }
0730:
0731: }
0732:
0733: void handleBehaviorPost(Behavior behav, int postid) {
0734:
0735: synchronized (behaviorPostBuffer) {
0736: int size = behaviorPostBuffer.size();
0737: if (postIDBuffer.length == size) {
0738: int oldbuffer[] = postIDBuffer;
0739: postIDBuffer = new int[size << 1];
0740: System.arraycopy(oldbuffer, 0, postIDBuffer, 0, size);
0741: }
0742: postIDBuffer[size] = postid;
0743: behaviorPostBuffer.add(behav);
0744: }
0745: VirtualUniverse.mc.sendRunMessage(universe,
0746: J3dThread.BEHAVIOR_SCHEDULER);
0747: }
0748:
0749: /**
0750: * This goes through all of the criteria waiting for Behavior Posts
0751: * and notifys them.
0752: */
0753: void handleBehaviorPost() {
0754: Behavior behav;
0755: int postid;
0756: WakeupOnBehaviorPost wakeup;
0757: WakeupOnBehaviorPost wakeupConds[] = (WakeupOnBehaviorPost[]) wakeupOnBehaviorPost
0758: .toArray();
0759: Behavior behavArr[];
0760: int behavBufferSize;
0761:
0762: synchronized (behaviorPostBuffer) {
0763: behavArr = (Behavior[]) behaviorPostBuffer.toArray();
0764: behavBufferSize = behaviorPostBuffer.size();
0765: if (clonePostIDBuffer.length < behavBufferSize) {
0766: clonePostIDBuffer = new int[behavBufferSize];
0767: }
0768: System.arraycopy(postIDBuffer, 0, clonePostIDBuffer, 0,
0769: behavBufferSize);
0770: behaviorPostBuffer.clear();
0771: }
0772:
0773: int size = wakeupOnBehaviorPost.arraySize();
0774: for (int i = 0; i < size; i++) {
0775: wakeup = wakeupConds[i];
0776: for (int j = 0; j < behavBufferSize; j++) {
0777: behav = behavArr[j];
0778: postid = clonePostIDBuffer[j];
0779: if ((wakeup.post == postid || wakeup.post == 0)
0780: && (behav == wakeup.armingBehavior || wakeup.armingBehavior == null)) {
0781: wakeup.triggeringBehavior = behav;
0782: wakeup.triggeringPost = postid;
0783: wakeup.setTriggered();
0784: }
0785: }
0786: }
0787:
0788: }
0789:
0790: /**
0791: * This goes through all of the criteria waiting for Elapsed Frames
0792: * and notified them.
0793: */
0794: void incElapsedFrames() {
0795:
0796: WakeupOnElapsedFrames wakeupConds[] = (WakeupOnElapsedFrames[]) wakeupOnElapsedFrames
0797: .toArray(true);
0798: int size = wakeupOnElapsedFrames.arraySize();
0799: int i = 0;
0800:
0801: while (i < size) {
0802: wakeupConds[i++].newFrame();
0803: }
0804:
0805: if (size > 0) {
0806: VirtualUniverse.mc.sendRunMessage(universe,
0807: J3dThread.BEHAVIOR_SCHEDULER
0808: | J3dThread.UPDATE_BEHAVIOR);
0809: }
0810:
0811: if (branchDetach) {
0812: // Since this procedure may call by immediate mode user
0813: // thread, we can't just clear it in removeNodes()
0814: wakeupOnElapsedFrames.clearMirror();
0815: branchDetach = false;
0816: }
0817:
0818: }
0819:
0820: void removeVPEntryCondition(WakeupCondition w) {
0821: wakeupOnViewPlatformEntry.remove(w);
0822: // don't remove boundsEntryList, it is use next time
0823: // when addVPExitCondition invoke to determine whether to
0824: // trigger an event or not.
0825:
0826: }
0827:
0828: void addVPEntryCondition(WakeupOnViewPlatformEntry w) {
0829: boolean needTrigger = true;
0830:
0831: // see if the matching wakeupOnViewPlatformEntry
0832: // condition exists & do cleanup
0833: WakeupOnViewPlatformEntry boundsEntryArr[] = (WakeupOnViewPlatformEntry[]) boundsEntryList
0834: .toArray(false);
0835: WakeupOnViewPlatformEntry wentry;
0836:
0837: for (int i = boundsEntryList.arraySize() - 1; i >= 0; i--) {
0838: wentry = boundsEntryArr[i];
0839: if ((wentry.behav == w.behav)
0840: && (wentry.region.equals(w.region))) {
0841: boundsEntryList.remove(i);
0842: // Case where we wakeOr() both condition together.
0843: // we should avoid calling setTrigger() every time.
0844: needTrigger = false;
0845: break;
0846: }
0847: }
0848:
0849: wakeupOnViewPlatformEntry.add(w);
0850:
0851: ViewPlatformRetained triggeredVP = intersectVPCenter(w.transformedRegion);
0852: if (triggeredVP != null) {
0853: boundsEntryList.add(w);
0854: }
0855:
0856: // we always trigger bound is inside during initialize
0857: if (needTrigger && (triggeredVP != null)) {
0858: w.triggeredVP = triggeredVP;
0859: w.setTriggered();
0860: }
0861: }
0862:
0863: void removeVPExitCondition(WakeupOnViewPlatformExit w) {
0864: wakeupOnViewPlatformExit.remove(w);
0865: // don't remove boundsExitList, it is use next time
0866: // when addVPEntryCondition invoke to determine whether to
0867: // trigger an event or not.
0868: }
0869:
0870: void addVPExitCondition(WakeupOnViewPlatformExit w) {
0871: // Cleanup, since collideEntryList did not remove
0872: // its condition in removeVPEntryCondition
0873: boolean needTrigger = true;
0874: WakeupOnViewPlatformExit boundsExitArr[] = (WakeupOnViewPlatformExit[]) boundsExitList
0875: .toArray(false);
0876: WakeupOnViewPlatformExit wexit;
0877: for (int i = boundsExitList.arraySize() - 1; i >= 0; i--) {
0878: wexit = boundsExitArr[i];
0879: if ((wexit.behav == w.behav)
0880: && (wexit.region.equals(w.region))) {
0881: boundsExitList.remove(i);
0882: needTrigger = false;
0883: break;
0884: }
0885: }
0886:
0887: ViewPlatformRetained triggeredVP = intersectVPCenter(w.transformedRegion);
0888: wakeupOnViewPlatformExit.add(w);
0889:
0890: if (triggeredVP != null) {
0891: w.triggeredVP = triggeredVP;
0892: boundsExitList.add(w);
0893: }
0894:
0895: if (!needTrigger) {
0896: return;
0897: }
0898:
0899: // see if the matching wakeupOnViewPlatformEntry
0900: // condition exists
0901:
0902: WakeupOnViewPlatformEntry boundsEntryArr[] = (WakeupOnViewPlatformEntry[]) boundsEntryList
0903: .toArray(false);
0904: WakeupOnViewPlatformEntry wentry;
0905:
0906: for (int i = boundsEntryList.arraySize() - 1; i >= 0; i--) {
0907: wentry = boundsEntryArr[i];
0908: if ((wentry.behav == w.behav)
0909: && (wentry.region.equals(w.region))) {
0910: // Don't remove this since if user wakeupOr()
0911: // Entry and Exit condition together we may have trouble
0912: // boundsEntryList.remove(i);
0913: if (triggeredVP == null) {
0914: w.setTriggered();
0915: }
0916: break;
0917: }
0918: }
0919:
0920: }
0921:
0922: void removeSensorEntryCondition(WakeupOnSensorEntry w) {
0923: wakeupOnSensorEntry.remove(w);
0924: // don't remove currentSensorEntryList, it is use next time
0925: // when addSensorExitCondition invoke to determine whether to
0926: // trigger an event or not.
0927: }
0928:
0929: void addSensorEntryCondition(WakeupOnSensorEntry w) {
0930: boolean needTrigger = true;
0931:
0932: // see if the matching wakeupOnSensorEntry
0933: // condition exists
0934: WakeupOnSensorEntry sensorEntryArr[] = (WakeupOnSensorEntry[]) currentSensorEntryList
0935: .toArray(false);
0936: WakeupOnSensorEntry wentry;
0937:
0938: for (int i = currentSensorEntryList.arraySize() - 1; i >= 0; i--) {
0939: wentry = sensorEntryArr[i];
0940: if ((wentry.behav == w.behav)
0941: && (wentry.region.equals(w.region))) {
0942: currentSensorEntryList.remove(i);
0943: needTrigger = false;
0944: break;
0945: }
0946: }
0947:
0948: wakeupOnSensorEntry.add(w);
0949:
0950: w.updateTransformRegion();
0951: Sensor target = sensorIntersect(w.transformedRegion);
0952: if (target != null) {
0953: w.setTarget(target);
0954: currentSensorEntryList.add(w);
0955: }
0956:
0957: if (needTrigger && (target != null)) {
0958: w.setTriggered();
0959:
0960: }
0961: VirtualUniverse.mc.sendRunMessage(universe,
0962: J3dThread.UPDATE_BEHAVIOR);
0963: }
0964:
0965: void removeSensorExitCondition(WakeupOnSensorExit w) {
0966: wakeupOnSensorExit.remove(w);
0967: // don't remove currentSensorExitList, it is use next time
0968: // when addSensorEntryCondition invoke to determine whether to
0969: // trigger an event or not
0970: }
0971:
0972: void addSensorExitCondition(WakeupOnSensorExit w) {
0973: // Cleanup
0974: boolean needTrigger = true;
0975:
0976: WakeupOnSensorExit currentSensorExitArr[] = (WakeupOnSensorExit[]) currentSensorExitList
0977: .toArray(false);
0978: WakeupOnSensorExit wexit;
0979: for (int i = currentSensorExitList.arraySize() - 1; i >= 0; i--) {
0980: wexit = currentSensorExitArr[i];
0981: if ((wexit.behav == w.behav)
0982: && (wexit.region.equals(w.region))) {
0983: currentSensorExitList.remove(i);
0984: needTrigger = false;
0985: break;
0986: }
0987: }
0988:
0989: w.updateTransformRegion();
0990: Sensor target = sensorIntersect(w.transformedRegion);
0991: wakeupOnSensorExit.add(w);
0992:
0993: if (target != null) {
0994: w.setTarget(target);
0995: currentSensorExitList.add(w);
0996: }
0997:
0998: if (!needTrigger) {
0999: return;
1000: }
1001: // see if the matching wakeupOnSensorEntry
1002: // condition exists
1003: WakeupOnSensorEntry sensorEntryArr[] = (WakeupOnSensorEntry[]) currentSensorEntryList
1004: .toArray(false);
1005: WakeupOnSensorEntry wentry;
1006:
1007: for (int i = currentSensorEntryList.arraySize() - 1; i >= 0; i--) {
1008: wentry = sensorEntryArr[i];
1009: if ((wentry.behav == w.behav)
1010: && (wentry.region.equals(w.region))) {
1011: // No need to invoke currentSensorEntryList.remove(i);
1012: if (target == null) {
1013: w.setTriggered();
1014: }
1015: break;
1016: }
1017: }
1018: VirtualUniverse.mc.sendRunMessage(universe,
1019: J3dThread.UPDATE_BEHAVIOR);
1020: }
1021:
1022: void processConditionMet(BehaviorRetained behav,
1023: Boolean checkSchedulingRegion) {
1024:
1025: // Since we reuse wakeup condition, the old wakeupCondition
1026: // will not reactivate again while processStimulus is running
1027: // which may set another wakeupCondition.
1028: // Previously we don't reuse wakeupCondition and cleanTree()
1029: // everytime before calling processStimulus() so the flag
1030: // inCallback is not necessary to check.
1031: if (!behav.inCallback
1032: && ((checkSchedulingRegion == Boolean.FALSE) || behav.active)) {
1033: processList[behav.schedulingInterval].add(behav);
1034: } else {
1035: if (((behav.wakeupMask & BehaviorRetained.WAKEUP_TIME) != 0)
1036: && (behav.source != null)
1037: && (behav.source.isLive())
1038: && (behav.wakeupCondition != null)) {
1039: // need to add back wakeupOnElapsedTime condition
1040: // to TimerThread
1041: behav.wakeupCondition.reInsertElapseTimeCond();
1042: }
1043: }
1044: }
1045:
1046: final void processBehXformChanged(UnorderList arrList) {
1047: BehaviorRetained beh;
1048: Object[] nodes, nodesArr;
1049:
1050: int size = arrList.size();
1051: nodesArr = arrList.toArray(false);
1052:
1053: for (int i = 0; i < size; i++) {
1054: nodes = (Object[]) nodesArr[i];
1055: for (int j = 0; j < nodes.length; j++) {
1056: beh = (BehaviorRetained) nodes[j];
1057: beh.updateTransformRegion();
1058: processBehaviorTransform(beh);
1059: }
1060: }
1061: }
1062:
1063: final void processVpfXformChanged(UnorderList arrList) {
1064: ViewPlatformRetained vpf;
1065: Object[] nodes, nodesArr;
1066:
1067: int size = arrList.size();
1068: nodesArr = arrList.toArray(false);
1069:
1070: for (int i = 0; i < size; i++) {
1071: nodes = (Object[]) nodesArr[i];
1072: for (int j = 0; j < nodes.length; j++) {
1073: processViewPlatformTransform((ViewPlatformRetained) nodes[j]);
1074: }
1075: }
1076: }
1077:
1078: final void processTransformChanged(Object leaf[]) {
1079: Object node;
1080: int i;
1081:
1082: // We have to process them in group rather then one by one,
1083: // otherwise we may have both activation/deactivation
1084: // conditions wakeup at the same time when both ViewPlatform
1085: // and Behavior transform under a branch.
1086:
1087: // Update transformRegion first
1088: for (i = 0; i < leaf.length; i++) {
1089: node = leaf[i];
1090: if (node instanceof BehaviorRetained) {
1091: ((BehaviorRetained) node).updateTransformRegion();
1092: processBehaviorTransform((BehaviorRetained) node);
1093:
1094: } else if (node instanceof ViewPlatformRetained) {
1095: ((ViewPlatformRetained) node).updateTransformRegion();
1096: transformViewPlatformList.add(node);
1097: }
1098: }
1099:
1100: // finally handle ViewPlatformRetained Transform change
1101: if (transformViewPlatformList.size() > 0) {
1102: ViewPlatformRetained vpArr[] = (ViewPlatformRetained[]) transformViewPlatformList
1103: .toArray(false);
1104:
1105: int size = transformViewPlatformList.arraySize();
1106: for (i = 0; i < size; i++) {
1107: processViewPlatformTransform((ViewPlatformRetained) vpArr[i]);
1108: }
1109: transformViewPlatformList.clear();
1110: }
1111: }
1112:
1113: // assume behav.updateTransformRegion() invoke before
1114: final void processBehaviorTransform(BehaviorRetained behav) {
1115: if ((behav.wakeupMask & BehaviorRetained.WAKEUP_VP_ENTRY) != 0) {
1116: updateVPEntryTransformRegion(behav);
1117: }
1118:
1119: if ((behav.wakeupMask & BehaviorRetained.WAKEUP_VP_EXIT) != 0) {
1120: updateVPExitTransformRegion(behav);
1121: }
1122:
1123: if (behav.active) {
1124: if (!intersectVPRegion(behav.transformedRegion)) {
1125: removeFromScheduleList(behav);
1126: }
1127: } else {
1128: addToScheduleList(behav);
1129: }
1130: }
1131:
1132: void processViewPlatformTransform(ViewPlatformRetained vp) {
1133: int i;
1134: BehaviorRetained behav;
1135:
1136: vp.updateTransformRegion();
1137:
1138: if (!vp.isActiveViewPlatform()) {
1139: return;
1140: }
1141:
1142: BehaviorRetained behavArr[] = (BehaviorRetained[]) behaviors
1143: .toArray(false);
1144:
1145: // re-evaulate all behaviors affected by this vp
1146: for (i = behaviors.arraySize() - 1; i >= 0; i--) {
1147: behav = behavArr[i];
1148: if (behav.active) {
1149: if (!intersectVPRegion(behav.transformedRegion)) {
1150: removeFromScheduleList(behav);
1151: }
1152: } else {
1153: addToScheduleList(behav);
1154: }
1155: }
1156:
1157: // handle wakeupOnViewPlatformEntry
1158: WakeupOnViewPlatformEntry wakeupOnViewPlatformEntryArr[] = (WakeupOnViewPlatformEntry[]) wakeupOnViewPlatformEntry
1159: .toArray(false);
1160: WakeupOnViewPlatformEntry wentry;
1161: int idx;
1162: ViewPlatformRetained triggeredVP;
1163:
1164: for (i = wakeupOnViewPlatformEntry.arraySize() - 1; i >= 0; i--) {
1165: wentry = wakeupOnViewPlatformEntryArr[i];
1166: idx = boundsEntryList.indexOf(wentry);
1167: if (idx < 0) {
1168: if (wentry.transformedRegion.intersect(vp.center)) {
1169: boundsEntryList.add(wentry);
1170: wentry.triggeredVP = vp;
1171: wentry.setTriggered();
1172: }
1173: } else {
1174: triggeredVP = intersectVPCenter(wentry.transformedRegion);
1175: if (triggeredVP == null) {
1176: boundsEntryList.remove(idx);
1177: }
1178: }
1179: }
1180:
1181: // handle wakeupOnViewPlatformExit;
1182: WakeupOnViewPlatformExit wakeupOnViewPlatformExitArr[] = (WakeupOnViewPlatformExit[]) wakeupOnViewPlatformExit
1183: .toArray(false);
1184: WakeupOnViewPlatformExit wexit;
1185:
1186: for (i = wakeupOnViewPlatformExit.arraySize() - 1; i >= 0; i--) {
1187: wexit = wakeupOnViewPlatformExitArr[i];
1188: idx = boundsExitList.indexOf(wexit);
1189: if (idx < 0) {
1190: if (wexit.transformedRegion.intersect(vp.center)) {
1191: wexit.triggeredVP = vp;
1192: boundsExitList.add(wexit);
1193:
1194: }
1195: } else {
1196: triggeredVP = intersectVPCenter(wexit.transformedRegion);
1197: if (triggeredVP == null) {
1198: boundsExitList.remove(idx);
1199: wexit.setTriggered();
1200: }
1201: }
1202: }
1203: }
1204:
1205: void updateVPEntryTransformRegion(BehaviorRetained behav) {
1206: WakeupOnViewPlatformEntry wakeupOnViewPlatformEntryArr[] = (WakeupOnViewPlatformEntry[]) wakeupOnViewPlatformEntry
1207: .toArray(false);
1208: WakeupOnViewPlatformEntry wentry;
1209: ViewPlatformRetained triggeredVP;
1210:
1211: for (int i = wakeupOnViewPlatformEntry.arraySize() - 1; i >= 0; i--) {
1212: wentry = wakeupOnViewPlatformEntryArr[i];
1213: if (wentry.behav == behav) {
1214: wentry.updateTransformRegion(behav);
1215: int idx = boundsEntryList.indexOf(wentry);
1216:
1217: triggeredVP = intersectVPCenter(wentry.transformedRegion);
1218: if (triggeredVP != null) {
1219: if (idx < 0) {
1220: boundsEntryList.add(wentry);
1221: wentry.triggeredVP = triggeredVP;
1222: wentry.setTriggered();
1223: }
1224: } else {
1225: if (idx >= 0) {
1226: boundsEntryList.remove(idx);
1227: }
1228: }
1229: }
1230:
1231: }
1232: }
1233:
1234: void updateVPExitTransformRegion(BehaviorRetained behav) {
1235: WakeupOnViewPlatformExit wakeupOnViewPlatformExitArr[] = (WakeupOnViewPlatformExit[]) wakeupOnViewPlatformExit
1236: .toArray(false);
1237: WakeupOnViewPlatformExit wexit;
1238: ViewPlatformRetained triggeredVP;
1239:
1240: for (int i = wakeupOnViewPlatformExit.arraySize() - 1; i >= 0; i--) {
1241: wexit = wakeupOnViewPlatformExitArr[i];
1242: if (wexit.behav == behav) {
1243: wexit.updateTransformRegion(behav);
1244: wexit = wakeupOnViewPlatformExitArr[i];
1245: int idx = boundsExitList.indexOf(wexit);
1246: triggeredVP = intersectVPCenter(wexit.transformedRegion);
1247: if (triggeredVP != null) {
1248: if (idx < 0) {
1249: wexit.triggeredVP = triggeredVP;
1250: boundsExitList.add(wexit);
1251: }
1252: } else {
1253: if (idx >= 0) {
1254: boundsExitList.remove(idx);
1255: wexit.setTriggered();
1256: }
1257: }
1258: }
1259: }
1260: }
1261:
1262: void reEvaluatePhysicalEnvironments() {
1263: // we can't just add or remove from the list since
1264: // physicalEnvironment may be share by multiple view
1265: View v;
1266: View views[];
1267: ViewPlatform vp;
1268: ArrayList vpList = universe.viewPlatforms;
1269:
1270: physicalEnvironments.clear();
1271:
1272: for (int i = vpList.size() - 1; i >= 0; i--) {
1273: views = ((ViewPlatformRetained) vpList.get(i))
1274: .getViewList();
1275: for (int j = views.length - 1; j >= 0; j--) {
1276: v = views[j];
1277: if (v.active
1278: && !physicalEnvironments
1279: .contains(v.physicalEnvironment)) {
1280: physicalEnvironments.add(v.physicalEnvironment);
1281: }
1282: }
1283: }
1284: }
1285:
1286: void checkSensorEntryExit() {
1287: int i, idx;
1288: Sensor target;
1289:
1290: // handle WakeupOnSensorEntry
1291: WakeupOnSensorEntry wentry;
1292: WakeupOnSensorEntry wentryArr[] = (WakeupOnSensorEntry[]) wakeupOnSensorEntry
1293: .toArray();
1294:
1295: for (i = wakeupOnSensorEntry.arraySize() - 1; i >= 0; i--) {
1296: wentry = wentryArr[i];
1297: idx = currentSensorEntryList.indexOf(wentry);
1298: wentry.updateTransformRegion();
1299: target = sensorIntersect(wentry.transformedRegion);
1300: if (target != null) {
1301: if (idx < 0) {
1302: currentSensorEntryList.add(wentry);
1303: wentry.setTarget(target);
1304: wentry.setTriggered();
1305: }
1306: } else {
1307: if (idx >= 0) {
1308: currentSensorEntryList.remove(idx);
1309: }
1310: }
1311: }
1312:
1313: // handle WakeupOnSensorExit
1314: WakeupOnSensorExit wexit;
1315: WakeupOnSensorExit wexitArr[] = (WakeupOnSensorExit[]) wakeupOnSensorExit
1316: .toArray();
1317:
1318: for (i = wakeupOnSensorExit.arraySize() - 1; i >= 0; i--) {
1319: wexit = wexitArr[i];
1320: idx = currentSensorExitList.indexOf(wexit);
1321: wexit.updateTransformRegion();
1322: target = sensorIntersect(wexit.transformedRegion);
1323: if (target != null) {
1324: if (idx < 0) {
1325: currentSensorExitList.add(wexit);
1326: wexit.setTarget(target);
1327: }
1328: } else {
1329: if (idx >= 0) {
1330: currentSensorExitList.remove(idx);
1331: wexit.setTriggered();
1332: }
1333: }
1334: }
1335:
1336: }
1337:
1338: /**
1339: * return the Senor that intersect with behregion or null
1340: */
1341: Sensor sensorIntersect(Bounds behregion) {
1342:
1343: if (behregion == null)
1344: return null;
1345:
1346: PhysicalEnvironment env[] = (PhysicalEnvironment[]) physicalEnvironments
1347: .toArray(false);
1348: Sensor sensors[];
1349: Sensor s;
1350: View v;
1351: for (int i = physicalEnvironments.arraySize() - 1; i >= 0; i--) {
1352: if (env[i].activeViewRef > 0) {
1353: sensors = env[i].getSensorList();
1354: if (sensors != null) {
1355: for (int j = env[i].users.size() - 1; j >= 0; j--) {
1356: v = (View) env[i].users.get(j);
1357: synchronized (sensors) {
1358: for (int k = sensors.length - 1; k >= 0; k--) {
1359: s = sensors[k];
1360: if (s != null) {
1361: v.getSensorToVworld(s,
1362: sensorTransform);
1363: sensorTransform.get(sensorLoc);
1364: ptSensorLoc.set(sensorLoc);
1365: if (behregion
1366: .intersect(ptSensorLoc)) {
1367: return s;
1368: }
1369: }
1370: }
1371: }
1372: }
1373: }
1374: }
1375: }
1376: return null;
1377: }
1378:
1379: /**
1380: * return true if one of ViewPlatforms intersect behregion
1381: */
1382: final boolean intersectVPRegion(Bounds behregion) {
1383: if (behregion == null) {
1384: return false;
1385: }
1386:
1387: ViewPlatformRetained vp;
1388: ViewPlatformRetained vpLists[] = (ViewPlatformRetained[]) viewPlatforms
1389: .toArray(false);
1390:
1391: for (int i = viewPlatforms.arraySize() - 1; i >= 0; i--) {
1392: vp = vpLists[i];
1393: if (vp.isActiveViewPlatform()
1394: && vp.schedSphere.intersect(behregion)) {
1395: return true;
1396: }
1397: }
1398: return false;
1399: }
1400:
1401: /**
1402: * return true if one of ViewPlatforms center intersect behregion
1403: */
1404: final ViewPlatformRetained intersectVPCenter(Bounds behregion) {
1405: if (behregion == null) {
1406: return null;
1407: }
1408:
1409: ViewPlatformRetained vp;
1410: ViewPlatformRetained vpLists[] = (ViewPlatformRetained[]) viewPlatforms
1411: .toArray(false);
1412:
1413: for (int i = viewPlatforms.arraySize() - 1; i >= 0; i--) {
1414: vp = vpLists[i];
1415: if (vp.isActiveViewPlatform()
1416: && behregion.intersect(vp.center)) {
1417: return vp;
1418: }
1419: }
1420: return null;
1421: }
1422:
1423: void notifyDeactivationCondition(BehaviorRetained behav) {
1424: WakeupOnDeactivation wakeup;
1425: WakeupOnDeactivation wakeupConds[] = (WakeupOnDeactivation[]) wakeupOnDeactivation
1426: .toArray(false);
1427:
1428: for (int i = wakeupOnDeactivation.arraySize() - 1; i >= 0; i--) {
1429: wakeup = wakeupConds[i];
1430: if (wakeup.behav == behav) {
1431: wakeup.setTriggered();
1432: }
1433: }
1434: }
1435:
1436: void notifyActivationCondition(BehaviorRetained behav) {
1437: WakeupOnActivation wakeup;
1438: WakeupOnActivation wakeupConds[] = (WakeupOnActivation[]) wakeupOnActivation
1439: .toArray(false);
1440:
1441: for (int i = wakeupOnActivation.arraySize() - 1; i >= 0; i--) {
1442: wakeup = wakeupConds[i];
1443: if (wakeup.behav == behav) {
1444: wakeup.setTriggered();
1445: }
1446: }
1447: }
1448:
1449: void processSwitchChanged(J3dMessage m) {
1450:
1451: int i, j;
1452: UnorderList arrList;
1453: int size;
1454: Object[] nodes, nodesArr;
1455:
1456: UpdateTargets targets = (UpdateTargets) m.args[0];
1457: arrList = targets.targetList[Targets.VPF_TARGETS];
1458:
1459: if (arrList != null) {
1460: ViewPlatformRetained vp;
1461: size = arrList.size();
1462: nodesArr = arrList.toArray(false);
1463:
1464: for (j = 0; j < size; j++) {
1465: nodes = (Object[]) nodesArr[j];
1466: for (i = nodes.length - 1; i >= 0; i--) {
1467: vp = (ViewPlatformRetained) nodes[i];
1468: vp.processSwitchChanged();
1469: }
1470: }
1471: }
1472:
1473: arrList = targets.targetList[Targets.BEH_TARGETS];
1474:
1475: if (arrList != null) {
1476: BehaviorRetained behav;
1477: size = arrList.size();
1478: nodesArr = arrList.toArray(false);
1479:
1480: for (j = 0; j < size; j++) {
1481: nodes = (Object[]) nodesArr[j];
1482: for (i = nodes.length - 1; i >= 0; i--) {
1483: behav = (BehaviorRetained) nodes[i];
1484: if (behav.switchState.currentSwitchOn) {
1485: addToScheduleList(behav);
1486: } else {
1487: removeFromScheduleList(behav);
1488: }
1489: }
1490: }
1491: }
1492:
1493: arrList = targets.targetList[Targets.BLN_TARGETS];
1494: if (arrList != null) {
1495: size = arrList.size();
1496: nodesArr = arrList.toArray(false);
1497: Object[] objArr = (Object[]) m.args[1];
1498: Object[] obj;
1499: BoundingLeafRetained mbleaf;
1500:
1501: for (int h = 0; h < size; h++) {
1502: nodes = (Object[]) nodesArr[h];
1503: obj = (Object[]) objArr[h];
1504: for (i = nodes.length - 1; i >= 0; i--) {
1505:
1506: Object[] users = (Object[]) obj[i];
1507: Object[] leafObj = new Object[1];
1508: mbleaf = (BoundingLeafRetained) nodes[i];
1509: for (j = 0; j < users.length; j++) {
1510: if (users[j] instanceof BehaviorRetained) {
1511: leafObj[0] = users[j];
1512: processTransformChanged(leafObj);
1513: }
1514: }
1515: }
1516: }
1517: }
1518: }
1519:
1520: void processBoundingLeafChanged(Object users[], Bounds bound) {
1521: Object leaf;
1522: BehaviorRetained behav;
1523:
1524: for (int i = users.length - 1; i >= 0; i--) {
1525: leaf = users[i];
1526: if (leaf instanceof BehaviorRetained) {
1527: behav = (BehaviorRetained) leaf;
1528: behav.updateTransformRegion(bound);
1529: processBehaviorTransform(behav);
1530: }
1531: }
1532: }
1533:
1534: final void removeFromScheduleList(BehaviorRetained behav) {
1535: if (behav.active) {
1536: if ((behav.wakeupMask & BehaviorRetained.WAKEUP_DEACTIVATE) != 0) {
1537: notifyDeactivationCondition(behav);
1538: }
1539: scheduleList.remove(behav);
1540: behav.active = false;
1541: if (behav.universe != universe) {
1542: J3dMessage m = new J3dMessage();
1543: m.threads = J3dThread.UPDATE_BEHAVIOR;
1544: m.type = J3dMessage.BEHAVIOR_REEVALUATE;
1545: m.universe = behav.universe;
1546: m.args[0] = behav;
1547: VirtualUniverse.mc.processMessage(m);
1548: }
1549: }
1550: }
1551:
1552: final void addToScheduleList(BehaviorRetained behav) {
1553:
1554: if (!behav.inCallback && !behav.active && behav.enable
1555: && behav.switchState.currentSwitchOn
1556: && (behav.wakeupCondition != null)
1557: && ((Behavior) behav.source).isLive()
1558: && intersectVPRegion(behav.transformedRegion)) {
1559:
1560: scheduleList.add(behav);
1561: behav.active = true;
1562: if ((behav.wakeupMask & BehaviorRetained.WAKEUP_ACTIVATE) != 0) {
1563: notifyActivationCondition(behav);
1564: }
1565:
1566: if (behav.wakeupCondition != null) {
1567: // This reset the conditionMet, otherwise
1568: // if conditionMet is true then WakeupCondition
1569: // will never post message to BehaviorStructure
1570: behav.wakeupCondition.conditionMet = false;
1571: }
1572: }
1573: }
1574:
1575: /**
1576: * This prevents wakeupCondition sent out message and sets
1577: * conditionMet to true, but the
1578: * BehaviorStructure/BehaviorScheduler is not fast enough to
1579: * process the message and reset conditionMet to false
1580: * when view deactivate/unregister.
1581: */
1582: void resetConditionMet() {
1583: resetConditionMet(wakeupOnAWTEvent);
1584: resetConditionMet(wakeupOnActivation);
1585: resetConditionMet(wakeupOnDeactivation);
1586: resetConditionMet(wakeupOnBehaviorPost);
1587: resetConditionMet(wakeupOnElapsedFrames);
1588: resetConditionMet(wakeupOnViewPlatformEntry);
1589: resetConditionMet(wakeupOnViewPlatformExit);
1590: resetConditionMet(wakeupOnSensorEntry);
1591: resetConditionMet(wakeupOnSensorExit);
1592: }
1593:
1594: static void resetConditionMet(WakeupIndexedList list) {
1595: WakeupCondition wakeups[] = (WakeupCondition[]) list
1596: .toArray(false);
1597: int i = list.size() - 1;
1598: while (i >= 0) {
1599: wakeups[i--].conditionMet = false;
1600: }
1601: }
1602:
1603: void reEvaluateWakeupCount() {
1604: WakeupOnElapsedFrames wakeupConds[] = (WakeupOnElapsedFrames[]) wakeupOnElapsedFrames
1605: .toArray(true);
1606: int size = wakeupOnElapsedFrames.arraySize();
1607: int i = 0;
1608: WakeupOnElapsedFrames cond;
1609:
1610: activeWakeupOnFrameCount = 0;
1611:
1612: while (i < size) {
1613: cond = wakeupConds[i++];
1614: if (!cond.passive && (cond.behav != null)
1615: && cond.behav.enable) {
1616: activeWakeupOnFrameCount++;
1617: }
1618: }
1619:
1620: activeWakeupOnSensorCount = 0;
1621: WakeupOnSensorEntry wentry;
1622: WakeupOnSensorEntry wentryArr[] = (WakeupOnSensorEntry[]) wakeupOnSensorEntry
1623: .toArray();
1624:
1625: for (i = wakeupOnSensorEntry.arraySize() - 1; i >= 0; i--) {
1626: wentry = wentryArr[i];
1627: if ((wentry.behav != null) && (wentry.behav.enable)) {
1628: activeWakeupOnSensorCount++;
1629: }
1630: }
1631:
1632: WakeupOnSensorExit wexit;
1633: WakeupOnSensorExit wexitArr[] = (WakeupOnSensorExit[]) wakeupOnSensorExit
1634: .toArray();
1635:
1636: for (i = wakeupOnSensorExit.arraySize() - 1; i >= 0; i--) {
1637: wexit = wexitArr[i];
1638: if ((wexit.behav != null) && (wexit.behav.enable)) {
1639: activeWakeupOnSensorCount++;
1640: }
1641: }
1642:
1643: }
1644:
1645: void cleanup() {
1646: behaviors.clear();
1647: viewPlatforms.clear();
1648: scheduleList.clear();
1649: boundsEntryList.clear();
1650: boundsExitList.clear();
1651: currentSensorEntryList.clear();
1652: currentSensorExitList.clear();
1653: wakeupOnAWTEvent.clear();
1654: wakeupOnActivation.clear();
1655: wakeupOnDeactivation.clear();
1656: wakeupOnBehaviorPost.clear();
1657: wakeupOnElapsedFrames.clear();
1658: wakeupOnViewPlatformEntry.clear();
1659: wakeupOnViewPlatformExit.clear();
1660: wakeupOnSensorEntry.clear();
1661: wakeupOnSensorExit.clear();
1662: }
1663: }
|