public static org.lgna.project.ast.AbstractType<?, ?, ?>[] getArgumentTypes( org.lgna.project.ast.AbstractType<?, ?, ?> ancestorType, org.lgna.project.ast.AbstractType<?, ?, ?> resourceType) { java.util.List<org.lgna.project.ast.AbstractType<?, ?, ?>> types = edu.cmu.cs.dennisc.java.util.Lists.newLinkedList(); updateArgumentTypes( types, ConstructorArgumentUtilities.getContructor0Parameter0Type(ancestorType), resourceType); org.lgna.project.ast.AbstractType<?, ?, ?>[] rv = new org.lgna.project.ast.AbstractType<?, ?, ?>[types.size()]; types.toArray(rv); return rv; }
/** * An object that receives <code>VMObserver</code> events from the <code>VMObserverManager</code>, * processes these events, creates the appropriate <code>EventNode</code>, and then notifies any * listeners of statement execution. * * @author Paul Gross */ public class VMExecutionObserver implements VMObserver { private boolean isRecording = false; private boolean hasInvokedEntryPoint = false; private final Map<Object, UserField> instanceMap = Maps.newHashMap(); private final Set<CurrentExecutionListener> executionListeners = Sets.newHashSet(); private final java.util.Map<Statement, java.util.ArrayList<AbstractEventNode<?>>> statementEventNodes = Maps.newHashMap(); private final java.util.List<LambdaEventNode> lambdaEventNodes = Lists.newLinkedList(); private final KeyedStack<ComponentThread, AbstractEventNode<?>> eventNodeStack = new KeyedStack<ComponentThread, AbstractEventNode<?>>(); private AbstractEventNode<?> rootEventNode; private UserInstance sceneInstance; public VMExecutionObserver(MessagingVirtualMachine virtualMachine) { virtualMachine.addObserver(this); } public void addCurrentExecutionListener(CurrentExecutionListener listener) { synchronized (this.executionListeners) { this.executionListeners.add(listener); } } public boolean removeCurrentExecutionListener(CurrentExecutionListener listener) { synchronized (this.executionListeners) { return this.executionListeners.remove(listener); } } public UserInstance getSceneInstance() { return this.sceneInstance; } public boolean eventNodesExistForStatement(Statement statement) { java.util.Collection<AbstractEventNode<?>> nodes = this.statementEventNodes.get(statement); return (nodes != null) && (nodes.size() > 0); } public java.util.ArrayList<AbstractEventNode<?>> getEventNodesForStatement(Statement statement) { return this.statementEventNodes.get(statement); } public AbstractEventNode<?> getEventNodeForStatementAtTime(Statement statement, double time) { for (AbstractEventNode<?> event : getEventNodesForStatement(statement)) { if (event.isExecutingAtTime(time)) { return event; } } return null; } public boolean isRootEventNode(AbstractEventNode<?> eventNode) { return (eventNode == this.rootEventNode); } public AbstractEventNode<?> getRootEventNode() { return this.rootEventNode; } public java.util.List<LambdaEventNode> getLambdaEventNodes() { return this.lambdaEventNodes; } public Map<Object, UserField> getInstanceMap() { return this.instanceMap; } public boolean hasInvokedEntryPoint() { return this.hasInvokedEntryPoint; } public boolean isRecording() { return this.isRecording; } public void setIsRecording(boolean value) { this.isRecording = value; } /** * Called when a new {@link VMObservableEvent} is passed. Executes the correct method based on the * {@link VMMessage} for the event. * * @param event {@link VMObservableEvent} passed from {@link VMObserverManager} */ @Override public synchronized void update(VMObservableEvent event) { VMMessage eventMsg = event.getVMMessage(); if (eventMsg == VMMessage.START_RECORDING) { this.isRecording = true; } else if (eventMsg == VMMessage.STOP_RECORDING) { this.isRecording = false; } else if (eventMsg == VMMessage.CREATE_INSTANCE) { if ((event.getProperties().length == 1) && (event.getProperties()[0] instanceof UserField)) { UserField field = (UserField) event.getProperties()[0]; Object instance = event.getObject(); if (instance instanceof UserInstance) { if (((UserInstance) instance).getType().isAssignableTo(SScene.class)) { this.sceneInstance = (UserInstance) instance; } instance = ((UserInstance) instance).getJavaInstance(); } this.instanceMap.put(instance, field); } } // Lambda invocations come from eventListeners and are // recorded outside the default record loop if (eventMsg == VMMessage.START_LAMBDA_INVOKE) { if (event.getObject() instanceof UserLambda) { startLambdaInvocation(event); } else { throw new ExecutionObserverException(event); } } else if (eventMsg == VMMessage.END_LAMBDA_INVOKE) { if (event.getObject() instanceof UserLambda) { endLambdaInvocation(event); } else { throw new ExecutionObserverException(event); } } // Should we record this message? boolean shouldRecord = isRecording(); if (!shouldRecord) { if (event.getThread() != null) { shouldRecord = event.getThread().getDescription().contentEquals("eventThread"); } } synchronized (this) { if (shouldRecord) { switch (eventMsg) { case RESET: reset(); break; case START_INVOKE_ENTRY_POINT: this.hasInvokedEntryPoint = true; break; case START_EXP_EVAL: if (this.hasInvokedEntryPoint) { if (event.getObject() instanceof Expression) { // Non-function method invocations are handled separately if (event.getObject() instanceof MethodInvocation) { MethodInvocation methodInvocation = (MethodInvocation) event.getObject(); if (methodInvocation.method.getValue().isFunction()) { startExpressionEvaluation(event); } } else { startExpressionEvaluation(event); } } else { throw new ExecutionObserverException(event); } } break; case END_EXP_EVAL: if (this.hasInvokedEntryPoint) { if (event.getObject() instanceof Expression) { // Non-function method invocations are handled separately if (event.getObject() instanceof MethodInvocation) { MethodInvocation methodInvocation = (MethodInvocation) event.getObject(); if (methodInvocation.method.getValue().isFunction()) { endExpressionEvaluation(event); } } else { endExpressionEvaluation(event); } } else { throw new ExecutionObserverException(event); } } break; case START_METHOD_INVOKE: if (this.hasInvokedEntryPoint) { if (event.getObject() instanceof MethodInvocation) { startMethodInvocation(event); } else { throw new ExecutionObserverException(event); } } break; case START_STMT_EXEC: if (this.hasInvokedEntryPoint) { if (event.getObject() instanceof BlockStatement) { // pass // } else if( event.getObject() instanceof Comment ) { // //pass // } else { } else { startStatement(event); } } break; case END_STMT_EXEC: if (this.hasInvokedEntryPoint) { if (event.getObject() instanceof BlockStatement) { // //pass // } else if( event.getObject() instanceof Comment ) { // //pass // } else { } else { endStatement(event); } } break; case START_CONTAINER: if (this.hasInvokedEntryPoint) { if ((event.getObject() instanceof AbstractStatementWithBody) || (event.getObject() instanceof BlockStatement)) { startContainer(event); } else { throw new ExecutionObserverException(event); } } break; case END_CONTAINER: if (this.hasInvokedEntryPoint) { if ((event.getObject() instanceof AbstractStatementWithBody) || (event.getObject() instanceof BlockStatement)) { endContainer(event); } else { throw new ExecutionObserverException(event); } } break; } } } } private void startLambdaInvocation(VMObservableEvent event) { org.lgna.project.ast.UserLambda lambda = (UserLambda) event.getObject(); ComponentThread thread = event.getThread(); double startTime = event.getTime(); org.lgna.project.ast.AbstractMethod method = (AbstractMethod) event.getProperties()[0]; // We ignore scene activation if (!method.getName().contentEquals("sceneActivated")) { AbstractEventNode<?> eventNode = EventNodeFactory.createEventNode(lambda, thread, startTime, null); ((LambdaEventNode) eventNode).setInvokingEventMethod(method); pushEventNode(eventNode, false); } } private void endLambdaInvocation(VMObservableEvent event) { org.lgna.project.ast.UserLambda lambda = (UserLambda) event.getObject(); org.lgna.project.ast.AbstractMethod method = (AbstractMethod) event.getProperties()[0]; ComponentThread thread = event.getThread(); double endTime = event.getTime(); if (!method.getName().contentEquals("sceneActivated")) { AbstractEventNode<?> eventNode = popEventNode(thread, false); lambdaEventNodes.add((LambdaEventNode) eventNode); if ((eventNode != null) && (eventNode.getAstNode() == lambda) && (eventNode.getThread() == thread)) { eventNode.setEndTime(endTime); } else { throw new ExecutionObserverException("EventNode invalid: " + eventNode.toString(), event); } } } /** * Handles the beginning of evaluation of an {@link Expression}. * * @param event VMObservableEvent event for expression */ private void startExpressionEvaluation(VMObservableEvent event) { Expression expression = (Expression) event.getObject(); ComponentThread thread = event.getThread(); double startTime = event.getTime(); AbstractEventNode<?> parentNode = peekEventNode(thread); ExpressionEvaluationEventNode eventNode = (ExpressionEvaluationEventNode) EventNodeFactory.createEventNode(expression, thread, startTime, parentNode); // Add expression evaluation to ExpressionStatementEventNode if (parentNode instanceof ExpressionStatementEventNode) { ((ExpressionStatementEventNode) parentNode).addExpressionEvaluationNode(eventNode); } // Handle expression evaluation for ConditionalEventNode else if (parentNode instanceof ConditionalStatementEventNode) { ((ConditionalStatementEventNode) parentNode).addConditionalEvaluation(eventNode); } // Handle expression evaluation for CountLoopEventNode else if (parentNode instanceof CountLoopEventNode) { ((CountLoopEventNode) parentNode).setCountExpressionNode(eventNode); } // Handle expression evaluation for EachInArrayTogetherEventNode else if (parentNode instanceof EachInArrayTogetherEventNode) { ((EachInArrayTogetherEventNode) parentNode).setArrayExpressionNode(eventNode); } // Handle expression evaluation for ForEachInArrayLoopEventNode else if (parentNode instanceof ForEachInArrayLoopEventNode) { ((ForEachInArrayLoopEventNode) parentNode).setArrayExpressionNode(eventNode); } // Handle expression evaluation for WhileLoopEventNode else if (parentNode instanceof WhileLoopEventNode) { ((WhileLoopEventNode) parentNode).addConditionalEvaluation(eventNode); } // Handle expression evaluation for LocalDeclarationStatementEventNode else if (parentNode instanceof LocalDeclarationStatementEventNode) { ((LocalDeclarationStatementEventNode) parentNode).setInitializerExpression(eventNode); } // Handle expression evaluation for ReturnStatementEventNode else if (parentNode instanceof ReturnStatementEventNode) { ((ReturnStatementEventNode) parentNode).setExpressionNode(eventNode); } // Handle expression evaluation for ExpressionEvaluationEventNode else if (parentNode instanceof ExpressionEvaluationEventNode) { // pass - handled on endExpressionEvaluation } else { throw new ExecutionObserverException("Parent node invalid:" + parentNode.toString(), event); } pushEventNode(eventNode, false); } /** * Handles the ending of evaluation of an {@link Expression}. * * @param event VMObservableEvent event for expression */ private void endExpressionEvaluation(VMObservableEvent event) { Expression expression = (Expression) event.getObject(); ComponentThread thread = event.getThread(); double endTime = event.getTime(); Object value = event.getProperties()[0]; AbstractEventNode<?> eventNode = popEventNode(thread, false); if ((eventNode != null) && (eventNode.getAstNode() == expression) && (eventNode.getThread() == thread)) { eventNode.setEndTime(endTime); ((ExpressionEvaluationEventNode) eventNode).setValue(value); UserField field = this.getUserFieldForInstance(value); if (field != null) { ((ExpressionEvaluationEventNode) eventNode).setValueField(field); } } else { throw new ExecutionObserverException("EventNode invalid: " + eventNode.toString(), event); } } /** * Handles beginning execution of a {@link Statement}. * * @param event {@link VMObservableEvent} event for statement */ private void startStatement(VMObservableEvent event) { Statement statement = (Statement) event.getObject(); ComponentThread thread = event.getThread(); double startTime = event.getTime(); AbstractEventNode<?> parentNode = peekEventNode(getThreadForNode(statement, thread)); // A Statement should always have a parent node (which can only be a ContainerEventNode) if (parentNode instanceof ContainerEventNode) { ContainerEventNode<?> containerNode = (ContainerEventNode<?>) parentNode; AbstractEventNode<?> eventNode = EventNodeFactory.createEventNode(statement, thread, startTime, containerNode); pushEventNode(eventNode, false); } else { throw new ExecutionObserverException("Parent node invalid: " + parentNode.toString(), event); } } /** * Handles ending execution of a {@link Statement}. * * @param event {@link VMObservableEvent} event for statement */ private void endStatement(VMObservableEvent event) { Statement statement = (Statement) event.getObject(); ComponentThread thread = event.getThread(); double endTime = event.getTime(); AbstractEventNode<?> eventNode = popEventNode(thread, true); if ((eventNode != null) && (eventNode.getAstNode() == statement) && (eventNode.getThread() == thread)) { eventNode.setEndTime(endTime); } else { throw new ExecutionObserverException("EventNode invalid: " + eventNode.toString(), event); } } /** * Handles beginning execution of container statement ( {@link AbstractStatementWithBody} or * {@link BlockStatement}). * * @param event {@link VMObservableEvent} event for container type statement */ private void startContainer(VMObservableEvent event) { Statement statement = (Statement) event.getObject(); ComponentThread thread = event.getThread(); double startTime = event.getTime(); AbstractEventNode<?> parentNode = peekEventNode(getThreadForNode(statement, thread)); // Root case if (parentNode == null) { AbstractEventNode<?> eventNode = EventNodeFactory.createEventNode(statement, thread, startTime, null); this.rootEventNode = eventNode; pushEventNode(eventNode, true); } else if (parentNode instanceof ConditionalStatementEventNode) { AbstractEventNode<?> eventNode = EventNodeFactory.createEventNode(statement, thread, startTime, parentNode); pushEventNode(eventNode, true); } else if (parentNode instanceof ContainerEventNode) { AbstractEventNode<?> eventNode = EventNodeFactory.createEventNode(statement, thread, startTime, parentNode); pushEventNode(eventNode, true); } else if (parentNode instanceof ExpressionStatementEventNode) { AbstractEventNode<?> eventNode = EventNodeFactory.createEventNode(statement, thread, startTime, parentNode); ((ExpressionStatementEventNode) parentNode) .addUserMethodEventNode((ContainerEventNode<?>) eventNode); pushEventNode(eventNode, true); } else if (parentNode instanceof ExpressionEvaluationEventNode) { AbstractEventNode<?> eventNode = EventNodeFactory.createEventNode(statement, thread, startTime, parentNode); pushEventNode(eventNode, true); } else if (parentNode instanceof LambdaEventNode) { AbstractEventNode<?> eventNode = EventNodeFactory.createEventNode(statement, thread, startTime, parentNode); ((LambdaEventNode) parentNode).addBodyEventNode((ContainerEventNode<?>) eventNode); pushEventNode(eventNode, true); } else { throw new ExecutionObserverException("Parent node invalid: " + parentNode.toString(), event); } } /** * Handles ending execution of Container statement ( {@link AbstractStatementWithBody} or {@link * BlockStatement}). * * @param event {@link VMObservableEvent} event for container type statement */ private void endContainer(VMObservableEvent event) { Statement statement = (Statement) event.getObject(); ComponentThread thread = event.getThread(); double endTime = event.getTime(); AbstractEventNode<?> eventNode = popEventNode(thread, true); if ((eventNode != null) && (eventNode.getAstNode() == statement) && (eventNode.getThread() == thread)) { eventNode.setEndTime(endTime); } else { throw new ExecutionObserverException("EventNode invalid: " + eventNode.toString(), event); } } /** * Handles beginning execution of {@link MethodInvocation}. * * @param event {@link VMObservableEvent} event for invocation */ private void startMethodInvocation(VMObservableEvent event) { MethodInvocation invocation = (MethodInvocation) event.getObject(); ComponentThread thread = event.getThread(); Object instance = event.getProperties()[1]; UserField field = getUserFieldForInstance(instance); AbstractEventNode<?> parentNode = peekEventNode(getThreadForNode(invocation, thread)); // Add instance and referencing field to parent node if (parentNode instanceof ExpressionStatementEventNode) { ExpressionStatementEventNode statementNode = (ExpressionStatementEventNode) parentNode; if ((instance != null) & (field != null)) { statementNode.setCallerInstance(instance); statementNode.setCallerField(field); } if ((instance != null) & (field != null)) { notifyListenersOfStart(statementNode); // Now that caller has been set, notify listeners } if (invocation.method.getValue() instanceof UserMethod) { UserMethod userMethod = (UserMethod) invocation.method.getValue(); if (!userMethod.isFunction()) { statementNode.setUserMethod(userMethod); } } } else if (parentNode instanceof ExpressionEvaluationEventNode) { if (field != null) { ((ExpressionEvaluationEventNode) parentNode).setValueField(field); } } } /** * Clears all maps involved in tracking. Note: this method does <i>not</i> remove <code> * CurrentExecutionListeners</code>. */ private void reset() { statementEventNodes.clear(); eventNodeStack.clear(); } /** * Pushes an {@link AbstractEventNode<?>} onto the stack and executes associated functions. * * @param eventNode <code>AbstractEventNode<?></code> to push onto the stack * @param shouldNotify boolean dictating whether listeners should be notified of push */ private void pushEventNode(AbstractEventNode<?> eventNode, boolean shouldNotify) { ArrayList<AbstractEventNode<?>> eventNodes = this.statementEventNodes.get(eventNode.getAstNode()); if (eventNodes == null) { eventNodes = new ArrayList<AbstractEventNode<?>>(); if (eventNode.getAstNode() instanceof Statement) { this.statementEventNodes.put((Statement) eventNode.getAstNode(), eventNodes); } } eventNodes.add(eventNode); this.eventNodeStack.push(eventNode, eventNode.getThread()); if (shouldNotify) { notifyListenersOfStart(eventNode); } } /** * Peeks {@link AbstractEventNode<?>} from top of stack for given thread. * * @param thread {@link ComponentThread} to check stack for * @return AbstractEventNode<?> on top of stack */ private AbstractEventNode<?> peekEventNode(ComponentThread thread) { return this.eventNodeStack.peek(thread); } /** * Removes and returns {@link AbstractEventNode<?>} from top of stack for a given thread. * * @param thread {@link ComponentThread} to remove stack for * @return <code>AbstractEventNode<?></code> removed from stack */ private AbstractEventNode<?> popEventNode(ComponentThread thread, boolean shouldNotify) { AbstractEventNode<?> rv = this.eventNodeStack.pop(thread); if (shouldNotify) { notifyListenersOfEnd(rv); } return rv; } /** * Gets the correct thread for lookup in {@link KeyedStack}. In the instance of parallel execution * (<code>DoTogether</code> and <code>EachInArrayTogether</code> statements) we want to get the * parent thread. * * @param astNode {@link Node} in AST to check * @param thread {@link ComponentThread} to reference * @return the correct <code>ComponentThread</code> for lookup */ private ComponentThread getThreadForNode(Node astNode, ComponentThread thread) { if (astNode.getParent() instanceof BlockStatement) { BlockStatement blockStatement = (BlockStatement) astNode.getParent(); if (blockStatement.getParent() instanceof DoTogether) { DoTogether doTogether = (DoTogether) blockStatement.getParent(); // special case for DoTogether with only one statement if (doTogether.body.getValue().statements.size() > 1) { return thread.getParentThread(); } else { return thread; } } else { return thread; } } else if (astNode.getParent() instanceof EachInArrayTogether) { return thread.getParentThread(); } else { return thread; } } private void notifyListenersOfStart(AbstractEventNode<?> eventNode) { synchronized (this.executionListeners) { for (CurrentExecutionListener listener : this.executionListeners) { listener.startingExecution(eventNode); } } } private void notifyListenersOfEnd(AbstractEventNode<?> eventNode) { synchronized (this.executionListeners) { for (CurrentExecutionListener listener : this.executionListeners) { listener.endingExecution(eventNode); } } } /** * Based on provided <code>Object</code>, finds the applicable field set during instance creation. * * @param caller object evaluated by vm * @return mapped <code>UserField</code> for value */ private UserField getUserFieldForInstance(Object instance) { if (instance instanceof UserInstance) { instance = ((UserInstance) instance).getJavaInstance(); } // Get instance from invocation - special case for joints else if (instance instanceof org.lgna.story.SJoint) { org.lgna.story.SJoint joint = (org.lgna.story.SJoint) instance; org.lgna.story.implementation.JointImp jointImp = org.lgna.story.EmployeesOnly.getImplementation(joint); org.lgna.story.implementation.JointedModelImp<?, ?> jointedModelImp = jointImp.getJointedModelParent(); org.lgna.story.SJointedModel jointedModel = jointedModelImp.getAbstraction(); instance = jointedModel; } return this.instanceMap.get(instance); } /** * Specialized stack-like structure that allows for multiple stacks based on a key. Each key * passed into the <code>KeyedStack</code> is given a unique <code>Stack</code> and all * interactions with the <code>KeyedStack</code> require said key. * * @author Michael Pogran */ private class KeyedStack<K, V> { private HashMap<K, java.util.Stack<V>> stackMap = Maps.newHashMap(); public V push(V value, K key) { java.util.Stack<V> stack = this.stackMap.get(key); if (stack == null) { stack = new java.util.Stack<V>(); this.stackMap.put(key, stack); } return stack.push(value); } public V peek(K key) { java.util.Stack<V> stack = this.stackMap.get(key); if (stack != null) { return stack.peek(); } else { return null; } } public V pop(K key) { java.util.Stack<V> stack = this.stackMap.get(key); if (stack != null) { return stack.pop(); } else { return null; } } public void clear() { stackMap = edu.cmu.cs.dennisc.java.util.Maps.newHashMap(); } } }
/** @author Dennis Cosgrove */ public class GlrScene extends GlrComposite<edu.cmu.cs.dennisc.scenegraph.Scene> { @Override public void initialize(edu.cmu.cs.dennisc.scenegraph.Scene sgElement) { super.initialize(sgElement); for (edu.cmu.cs.dennisc.scenegraph.Component sgComponent : edu.cmu.cs.dennisc.pattern.VisitUtilities.getAll( owner, edu.cmu.cs.dennisc.scenegraph.Component.class)) { GlrComponent<?> glrComponent = AdapterFactory.getAdapterFor(sgComponent); this.addDescendant(glrComponent); } } public GlrBackground getBackgroundAdapter() { return this.backgroundAdapter; } protected void addDescendant(GlrComponent<?> glrDescendant) { if (glrDescendant instanceof GlrGhost) { synchronized (this.glrGhostDescendants) { this.glrGhostDescendants.add((GlrGhost) glrDescendant); } } else if (glrDescendant instanceof GlrVisual<?>) { synchronized (this.glrVisualDescendants) { this.glrVisualDescendants.add((GlrVisual<?>) glrDescendant); } if (glrDescendant instanceof GlrPlanarReflector) { synchronized (this.glrPlanarReflectorDescendants) { this.glrPlanarReflectorDescendants.add((GlrPlanarReflector) glrDescendant); } } } } protected void removeDescendant(GlrComponent<?> glrDescendant) { if (glrDescendant instanceof GlrGhost) { synchronized (this.glrGhostDescendants) { this.glrGhostDescendants.remove(glrDescendant); } } else if (glrDescendant instanceof GlrVisual<?>) { synchronized (this.glrVisualDescendants) { this.glrVisualDescendants.remove(glrDescendant); } if (glrDescendant instanceof GlrPlanarReflector) { synchronized (this.glrPlanarReflectorDescendants) { this.glrPlanarReflectorDescendants.remove(glrDescendant); } } } } @Deprecated public void EPIC_HACK_FOR_THUMBNAIL_MAKER_removeDescendant(GlrComponent<?> glrDescendant) { this.removeDescendant(glrDescendant); } public void renderAlphaBlended(RenderContext rc) { // todo depth sort // rc.gl.glDisable( GL_DEPTH_TEST ); // rc.gl.glDepthMask( false ); // try { synchronized (this.glrGhostDescendants) { for (GlrGhost ghostAdapter : this.glrGhostDescendants) { ghostAdapter.renderGhost(rc, ghostAdapter); } } synchronized (this.glrVisualDescendants) { for (GlrVisual<? extends edu.cmu.cs.dennisc.scenegraph.Visual> visualAdapter : this.glrVisualDescendants) { if (visualAdapter.isAlphaBlended()) { // todo: adapters should be removed if ((visualAdapter.owner != null) && (visualAdapter.owner.getRoot() instanceof edu.cmu.cs.dennisc.scenegraph.Scene)) { if (visualAdapter.isAllAlpha()) { visualAdapter.renderAllAlphaBlended(rc); } else { visualAdapter.renderAlphaBlended(rc); } } } } } // } finally { // rc.gl.glDepthMask( true ); // } // rc.gl.glEnable( GL_DEPTH_TEST ); } @Override public void setupAffectors(RenderContext rc) { rc.setGlobalBrightness(this.globalBrightness); rc.beginAffectorSetup(); super.setupAffectors(rc); rc.endAffectorSetup(); } private void renderScene(RenderContext rc) { rc.gl.glDisable(GL_BLEND); renderOpaque(rc); rc.gl.glEnable(GL_BLEND); rc.gl.glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); renderAlphaBlended(rc); rc.gl.glDisable(GL_BLEND); } public void renderScene( RenderContext rc, GlrAbstractCamera<? extends edu.cmu.cs.dennisc.scenegraph.AbstractCamera> cameraAdapter, GlrBackground backgroundAdapter) { rc.gl.glMatrixMode(GL_MODELVIEW); synchronized (cameraAdapter) { rc.gl.glLoadMatrixd(cameraAdapter.accessInverseAbsoluteTransformationAsBuffer()); } if (backgroundAdapter != null) { // pass } else { backgroundAdapter = this.backgroundAdapter; } if (backgroundAdapter != null) { backgroundAdapter.setup(rc); } if (this.glrPlanarReflectorDescendants.size() > 0) { GlrPlanarReflector planarReflectorAdapter = this.glrPlanarReflectorDescendants.get(0); if (planarReflectorAdapter.isFacing(cameraAdapter)) { rc.gl.glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); rc.gl.glColorMask(false, false, false, false); rc.gl.glEnable(GL_STENCIL_TEST); rc.gl.glStencilFunc(GL_ALWAYS, 1, 1); rc.gl.glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE); rc.gl.glDisable(GL_DEPTH_TEST); planarReflectorAdapter.renderStencil(rc, GlrVisual.RenderType.OPAQUE); rc.gl.glEnable(GL_DEPTH_TEST); rc.gl.glColorMask(true, true, true, true); rc.gl.glStencilFunc(GL_EQUAL, 1, 1); rc.gl.glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP); rc.gl.glEnable(GL_CLIP_PLANE0); rc.gl.glPushMatrix(); planarReflectorAdapter.applyReflection(rc); rc.gl.glFrontFace(GL_CW); setupAffectors(rc); renderScene(rc); rc.gl.glFrontFace(GL_CCW); rc.gl.glPopMatrix(); rc.gl.glDisable(GL_CLIP_PLANE0); rc.gl.glDisable(GL_STENCIL_TEST); setupAffectors(rc); rc.gl.glEnable(GL_BLEND); rc.gl.glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); planarReflectorAdapter.renderStencil(rc, GlrVisual.RenderType.ALPHA_BLENDED); rc.gl.glDisable(GL_BLEND); } else { rc.gl.glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); setupAffectors(rc); } } else { rc.gl.glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); setupAffectors(rc); } renderScene(rc); } @Override protected void propertyChanged(edu.cmu.cs.dennisc.property.InstanceProperty<?> property) { if (property == owner.background) { this.backgroundAdapter = AdapterFactory.getAdapterFor(owner.background.getValue()); } else if (property == owner.globalBrightness) { this.globalBrightness = owner.globalBrightness.getValue(); } else { super.propertyChanged(property); } } private GlrBackground backgroundAdapter; private float globalBrightness; private final java.util.List<GlrGhost> glrGhostDescendants = edu.cmu.cs.dennisc.java.util.Lists.newLinkedList(); private final java.util.List<GlrVisual<?>> glrVisualDescendants = edu.cmu.cs.dennisc.java.util.Lists.newLinkedList(); private final java.util.List<GlrPlanarReflector> glrPlanarReflectorDescendants = edu.cmu.cs.dennisc.java.util.Lists.newLinkedList(); }