Package org.jdesktop.wonderland.modules.affordances.client.cell

Source Code of org.jdesktop.wonderland.modules.affordances.client.cell.AffordanceCellComponent$AffordanceCloseListener

/**
* Project Wonderland
*
* Copyright (c) 2004-2009, Sun Microsystems, Inc., All Rights Reserved
*
* Redistributions in source code form must reproduce the above
* copyright and this condition.
*
* The contents of this file are subject to the GNU General Public
* License, Version 2 (the "License"); you may not use this file
* except in compliance with the License. A copy of the License is
* available at http://www.opensource.org/licenses/gpl-license.php.
*
* Sun designates this particular file as subject to the "Classpath"
* exception as provided by Sun in the License file that accompanied
* this code.
*/
package org.jdesktop.wonderland.modules.affordances.client.cell;

import com.jme.scene.Node;
import java.util.logging.Logger;
import org.jdesktop.mtgame.RenderComponent;
import org.jdesktop.wonderland.client.cell.Cell;
import org.jdesktop.wonderland.client.cell.Cell.RendererType;
import org.jdesktop.wonderland.client.cell.CellComponent;
import org.jdesktop.wonderland.client.cell.ComponentChangeListener;
import org.jdesktop.wonderland.client.cell.ComponentChangeListener.ChangeType;
import org.jdesktop.wonderland.client.cell.MovableComponent;
import org.jdesktop.wonderland.client.input.Event;
import org.jdesktop.wonderland.client.input.EventClassListener;
import org.jdesktop.wonderland.client.input.InputManager;
import org.jdesktop.wonderland.client.jme.CellRefComponent;
import org.jdesktop.wonderland.client.jme.cellrenderer.CellRendererJME;
import org.jdesktop.wonderland.common.cell.CellID;
import org.jdesktop.wonderland.common.cell.CellStatus;
import org.jdesktop.wonderland.common.cell.messages.CellServerComponentMessage;
import org.jdesktop.wonderland.common.messages.ErrorMessage;
import org.jdesktop.wonderland.common.messages.ResponseMessage;
import org.jdesktop.wonderland.modules.affordances.client.event.AffordanceRemoveEvent;
import org.jdesktop.wonderland.modules.affordances.client.jme.Affordance;

/**
* A client-side cell component base class for affordance components.
*
* @author Jordan Slott <jslott@dev.java.net>
*/
public abstract class AffordanceCellComponent extends CellComponent {
    protected static Logger logger = Logger.getLogger(AffordanceCellComponent.class.getName());
    private AffordanceCloseListener listener = null;
    private float size = 1.5f;
    protected Affordance affordance = null;
    protected MovableComponent movableComp = null;

    public AffordanceCellComponent(Cell cell) {
        super(cell);

        // Listen for the global event to turn off all affordances
        listener = new AffordanceCloseListener();
        InputManager.inputManager().addGlobalEventListener(listener);
    }

    @Override
    protected void setStatus(CellStatus status, boolean increasing) {

        // If we are making this component active, then create the affordance,
        // if the first time through.
        super.setStatus(status, increasing);
        if (increasing && status == CellStatus.ACTIVE) {
            // Add a cell ref component to the entity. This will let us associated
            // the entity with the cell and make it easy to detect when we click
            // off of the cell
            CellRefComponent refComponent = new CellRefComponent(cell);
            affordance.addComponent(CellRefComponent.class, refComponent);

            // First try to add the movable component. The presence of the
            // movable component will determine when we actually add the
            // affordance to the scene graph. We do this in a separate thread
            // because adding the movable component is a synchronous call (it
            // waits for a response message. That would block the thread calling
            // the setStatus() method. This won't work since this thread cannot
            // be blocked when adding the component.
            new Thread() {
                @Override
                public void run() {
                    checkMovableComponent();
                    if (movableComp == null) {
                        addMovableComponent();
                    }
                    addAffordanceToScene();
                }
            }.start();
        }
        else if (!increasing && status == CellStatus.DISK) {
            // Remove the affordance and clean it up. Set it to null, because
            // it must be created again when the Cell becomes visible.
            affordance.dispose();
            affordance = null;
        }
    }

    /**
     * Adds the affordance to the scene graph.
     */
    public void addAffordanceToScene() {
        // We should add a listener just in case the movable component gets
        // added. We add the listener first, just in case the component gets
        // added inbetween the time we check and the time we add the listener.
        if (movableComp == null) {
            cell.addComponentChangeListener(new ComponentChangeListener() {
                public void componentChanged(Cell cell, ChangeType type, CellComponent component) {
                    if (type == ChangeType.ADDED && component instanceof MovableComponent) {
                        checkMovableComponent();
                        updateSceneGraph();
                    }
                }
            });
        }

        // Recheck whether the movable component exists here. If so, then add
        // to the scene graph right away.
        checkMovableComponent();
        if (movableComp != null) {
            updateSceneGraph();
        }

    }

    /**
     * Checks whether the movable component exists and sets it if so.
     */
    private synchronized void checkMovableComponent() {
        if (movableComp == null) {
            movableComp = cell.getComponent(MovableComponent.class);
        }
    }

    /**
     * Sets the size of the affordance. The size is a floating point value where
     * 1.0 designates the same size of the cell.
     *
     * @param size The new size of the affordance
     */
    public void setSize(float size) {
        this.size = size;
        affordance.setSize(size);
    }

    /**
     * Returns the current size of the afforance.
     *
     * @return The size of the affordance
     */
    public float getSize() {
        return this.size;
    }

    /**
     * Remove the affordance component from the cell
     */
    public void remove() {
        // Remove the listener for the event that causes all affordances to
        // disappear and then remove this component itself. This will cause
        // the affordance to be removed in setStatus()
        InputManager.inputManager().removeGlobalEventListener(listener);
        cell.removeComponent(getClass());
    }

    /**
     * Returns the scene root for the Cell's scene graph
     */
    protected Node getSceneGraphRoot() {
        CellRendererJME renderer = (CellRendererJME)
                cell.getCellRenderer(RendererType.RENDERER_JME);
        RenderComponent cellRC = (RenderComponent)
                renderer.getEntity().getComponent(RenderComponent.class);
        return cellRC.getSceneRoot();
    }

    /**
     * Adds the movable component, assumes it does not already exist.
     */
    private void addMovableComponent() {

        // Go ahead and try to add the affordance. If we cannot, then log an
        // error and return.
        CellID cellID = cell.getCellID();
        String className = "org.jdesktop.wonderland.server.cell.MovableComponentMO";
        CellServerComponentMessage cscm =
                CellServerComponentMessage.newAddMessage(cellID, className);
        ResponseMessage response = cell.sendCellMessageAndWait(cscm);
        if (response instanceof ErrorMessage) {
            logger.warning("Unable to add movable component for Cell" +
                    cell.getName() + " with ID " + cell.getCellID());
        }
    }

    /* True if the affordance has been added to the scene graph. */
    private boolean addedToSceneGraph = false;

    /**
     * Updates the scene graph to add this affordance
     */
    private synchronized void updateSceneGraph() {
        // This method is synchronized and we keep track of whether it has been
        // added in a boolean. This ensures that it only gets added once.
        if (addedToSceneGraph == false) {
            affordance.setVisible(true);
            addedToSceneGraph = true;
        }
    }

    /**
     * Inner class that listens for an event signalling that the afforance
     * should remove itself
     */
    class AffordanceCloseListener extends EventClassListener {

        @Override
        public Class[] eventClassesToConsume() {
            return new Class[] { AffordanceRemoveEvent.class };
        }


        @Override
        public void commitEvent(Event event) {
            // Just tell the affordance to remove itself
            remove();
        }
    }
}
TOP

Related Classes of org.jdesktop.wonderland.modules.affordances.client.cell.AffordanceCellComponent$AffordanceCloseListener

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.