Package de.venjinx.editor.debug

Source Code of de.venjinx.editor.debug.DebugState

package de.venjinx.editor.debug;

import java.util.HashMap;

import org.bushe.swing.event.EventTopicSubscriber;

import com.jme3.app.Application;
import com.jme3.app.FlyCamAppState;
import com.jme3.app.SimpleApplication;
import com.jme3.app.StatsAppState;
import com.jme3.app.state.AbstractAppState;
import com.jme3.app.state.AppStateManager;
import com.jme3.app.state.ScreenshotAppState;
import com.jme3.asset.AssetManager;
import com.jme3.font.BitmapFont;
import com.jme3.font.BitmapText;
import com.jme3.input.FlyByCamera;
import com.jme3.input.InputManager;
import com.jme3.input.controls.ActionListener;
import com.jme3.input.controls.AnalogListener;
import com.jme3.light.AmbientLight;
import com.jme3.light.DirectionalLight;
import com.jme3.material.Material;
import com.jme3.math.ColorRGBA;
import com.jme3.math.Vector3f;
import com.jme3.renderer.Camera;
import com.jme3.scene.Geometry;
import com.jme3.scene.Mesh.Mode;
import com.jme3.scene.Node;
import com.jme3.scene.Spatial;
import com.jme3.scene.control.BillboardControl;
import com.jme3.scene.debug.Arrow;
import com.jme3.scene.debug.Grid;
import com.jme3.scene.shape.Sphere;

import de.lessvoid.nifty.Nifty;
import de.lessvoid.nifty.NiftyEventSubscriber;
import de.lessvoid.nifty.controls.CheckBoxStateChangedEvent;
import de.lessvoid.nifty.controls.DropDownSelectionChangedEvent;
import de.lessvoid.nifty.controls.MenuItemActivatedEvent;
import de.lessvoid.nifty.controls.SliderChangedEvent;
import de.lessvoid.nifty.controls.TreeItem;
import de.lessvoid.nifty.screen.Screen;
import de.lessvoid.nifty.screen.ScreenController;
import de.venjinx.jme3.VoxelObjectNode;
import de.venjinx.jme3.VoxelState;
import de.venjinx.jme3.scenegraph.Scenegraph;
import de.venjinx.jme3.scenegraph.ScenegraphListener;
import de.venjinx.jme3.scenegraph.ScenegraphNode;
import de.venjinx.jme3.tests.AdvancedApplication;
import de.venjinx.util.Keys;
import de.venjinx.util.Materials;

public class DebugState extends AbstractAppState implements ActionListener,
AnalogListener,
ScreenController,
ScenegraphListener,
EventTopicSubscriber<MenuItemActivatedEvent<String>> {

    private static String[] inputKeys = { Keys.SHOW_COORD_GRID, Keys.SHOW_NORMALS,
                                          Keys.SHOW_WIREFRAME, Keys.DEBUG_CAM_ACTIVATE,
                                          Keys.SELECT_NODE, Keys.SHOW_CONTEXT_MENU };

    // Simple application stuff
    private SimpleApplication simpleApp;
    private AssetManager am;
    private InputManager im;
    private AppStateManager sm;
    private Camera cam;
    private FlyByCamera flyCam;

    // Advanced application stuff
    private Scenegraph scenegraph;

    // GUI stuff
    private DebugGUI gui;
    private BitmapFont guiFont;
    private BillboardControl bc = new BillboardControl();
    private HashMap<Spatial, TreeItem<String>> treeItems = new HashMap<>();
    private HashMap<String, AbstractAppState> states = new HashMap<>();

    // Debug stuff
    private Geometry camPosGeom;
    private Geometry activeGeometry;
    private ScenegraphNode debugNode = new ScenegraphNode("Debug");
    private HashMap<Spatial, DebugNode> debugNodes = new HashMap<>();
    private ScenegraphNode coordNode;
    private DebugMouse mouse;

    private DirectionalLight directionalLight;
    private AmbientLight ambientLight;

    private ScreenshotAppState screenshotState;

    // Voxel world stuff
    private VoxelState voxelState;
    private Geometry worldCalcBoundGeom;

    // Flags
    private boolean showGrid = true;
    private boolean showWire = false;

    @Override
    public void initialize(AppStateManager stateManager, Application app) {
        super.initialize(stateManager, app);

        // Initialize simple application stuff
        if (app instanceof SimpleApplication) {
            simpleApp = (SimpleApplication) app;

            am = app.getAssetManager();
            im = app.getInputManager();
            sm = app.getStateManager();
            cam = app.getCamera();

            DebugMaterials.setAssetManager(am);

            Sphere s = new Sphere(4, 4, 1);
            camPosGeom = new Geometry("Camera position", s);
            camPosGeom.setMaterial(new Material(am, Materials.UNSHADED));
            debugNode.attachChild(camPosGeom);

            simpleApp.getRootNode().attachChild(debugNode);
            setEnabled(true);
        }

        if (!sm.hasState(sm.getState(FlyCamAppState.class))) {
            flyCam = new DebugCam(cam);
            flyCam.registerWithInput(im);
            flyCam.setDragToRotate(true);
        } else flyCam = simpleApp.getFlyByCamera();

        // Initialize advanced application stuff
        if (app instanceof AdvancedApplication) {
            scenegraph = ((AdvancedApplication) app).getScenegraph();
            scenegraph.addScenegraphListener(this);
        }

        // Initialize GUI stuff
        gui = new DebugGUI(simpleApp, this);
        gui.getNifty().fromXml("interface/debugInterface.xml", "DebugInfo", this);
        gui.getNifty().setIgnoreKeyboardEvents(true);
        // gui.getNifty().setDebugOptionPanelColors(true);

        guiFont = am.loadFont("Interface/Fonts/Default.fnt");

        // Initialize debug stuff
        coordNode = createCoordinationNode(256, 1);
        debugNode.attachChild(coordNode);
        debugNode.updateModelBound();

        mouse = sm.getState(DebugMouse.class);
        if (mouse == null) {
            mouse = new DebugMouse();
            Material mat = new Material(app.getAssetManager(), Materials.UNSHADED);
            mat.setColor("Color", ColorRGBA.Orange);
            mouse.setMaterial(mat);

            sm.attach(mouse);
            debugNode.attachChild(mouse.getPointer());
        }

        directionalLight = new DirectionalLight();
        directionalLight.setName("Debug light");
        directionalLight.setColor(ColorRGBA.White);
        directionalLight.setDirection(new Vector3f(.5f, -1f, -.1f).normalizeLocal());
        simpleApp.getRootNode().addLight(directionalLight);

        ambientLight = new AmbientLight();
        ambientLight.setColor(ColorRGBA.Gray);
        simpleApp.getRootNode().addLight(ambientLight);

        screenshotState = new ScreenshotAppState();
        screenshotState.setFilePath("d:/");
        sm.attach(screenshotState);

        // Initialize voxel world stuff
        if (sm.getState(VoxelState.class) != null) {
            voxelState = sm.getState(VoxelState.class);
            Sphere s = new Sphere(32, 32, voxelState.getCalcBound().getRadius());
            s.setMode(Mode.Lines);
            worldCalcBoundGeom = new Geometry("Voxel world calculation bound", s);
            worldCalcBoundGeom.setMaterial(new Material(am, Materials.UNSHADED));
            // debugNode.attachChild(worldCalcBoundGeom);
            addState(voxelState);
        }

        loadDfltKeys();
    }

    @Override
    public void update(float tpf) {
        gui.updateInterface();

        if ((voxelState != null) && voxelState.isEnabled())
            camPosGeom.setLocalTranslation(cam.getLocation());

        // worldCalcBoundGeom.setLocalTranslation(world.getCalcBound().getCenter());

        if (!(simpleApp instanceof AdvancedApplication)) {
            treeItems.clear();

            TreeItem<String> sceneRootItem = createTreeItem(simpleApp.getRootNode());
            TreeItem<String> viewRootItem = new TreeItem<String>();
            viewRootItem.addTreeItem(sceneRootItem);
            viewRootItem.setExpanded(true);
            gui.scenegraphView.setRoot(viewRootItem);
        }
    }

    @Override
    public void onAction(String name, boolean isPressed, float tpf) {
        if (name.equals(Keys.DEBUG_CAM_ACTIVATE) && !isPressed)
            flyCam.setDragToRotate(!flyCam.isDragToRotate());

        if (name.equals(Keys.SHOW_COORD_GRID) && isPressed)
            gui.showGridCheckBox.setChecked((!showGrid));

        if (name.equals(Keys.SHOW_WIREFRAME) && isPressed)
            gui.showWireframeCheckBox.setChecked(!showWire);

        if (name.equals(Keys.SELECT_NODE) && isPressed)
            if (mouse.getHitGeometry() != null) {
                activeGeometry = mouse.getHitGeometry();
                TreeItem<String> item = treeItems.get(activeGeometry);
                gui.scenegraphView.select(item);
            }

        if (name.equals(Keys.SHOW_CONTEXT_MENU) && !isPressed)
            if (mouse.getHitGeometry() != null) {
                activeGeometry = mouse.getHitGeometry();
                gui.showContextMenu(true, activeGeometry);
            }
    }

    @Override
    public void onAnalog(String name, float value, float tpf) {
    }

    @Override
    public void onEvent(String id, MenuItemActivatedEvent<String> event) {
        VoxelObjectNode vObject;
        Node parent;
        DebugNode debug = debugNodes.get(activeGeometry);
        if (debug == null) {
            debug = new DebugNode(activeGeometry);
            debugNodes.put(activeGeometry, debug);
        }

        gui.showContextMenu(false, activeGeometry);

        debug.setLocalTranslation(activeGeometry.getWorldTranslation());
        debugNode.attachChild(debug);
        switch (event.getItem()) {
            case DebugGUI.MENU_SHOW_BOUND:
                debug.showBound();
                break;
            case DebugGUI.MENU_SHOW_CHUNK_BOUNDS:
                parent = activeGeometry.getParent();
                while (!(parent instanceof VoxelObjectNode))
                    parent = parent.getParent();
                vObject = (VoxelObjectNode) parent;
                vObject.showChunkBounds();
                break;
            case DebugGUI.MENU_SHOW_CHUNK_LODS:
                parent = activeGeometry.getParent();
                while (!(parent instanceof VoxelObjectNode))
                    parent = parent.getParent();
                vObject = (VoxelObjectNode) parent;
                vObject.showChunkLODs();
                break;
            case DebugGUI.MENU_SHOW_NORMALS:
                debug.showNormals();
                break;
            case DebugGUI.MENU_SHOW_WIREFRAME:
                debug.showWireframe();
                break;
            case DebugGUI.MENU_SHOW_VOXEL_GRID:
                debug.showVoxelGrid();
                break;
        }

        if (debug.getChildren().size() == 0)
            debugNode.detachChild(debug);
    }

    @Override
    public void onGraphChanged(GraphChangedEvent e) {
        TreeItem<String> parent = treeItems.get(e.getParent());
        TreeItem<String> child = treeItems.get(e.getChild());
        String value = "";
        switch (e.getType()) {
            case ATTACHED:
                if (child == null)
                    child = createTreeItem(e.getChild());

                gui.scenegraphView.insert(parent, child);
                value += "(" + (e.getParent().getChildren().size() + 1) + ") ";
                break;
            case DETACHED:
                gui.scenegraphView.remove(child);
                value += "(" + (e.getParent().getChildren().size() - 1) + ") ";
                break;
        }
        value += e.getParent().toString();
        parent.setValue(value);
        gui.scenegraphView.refresh();
    }

    @NiftyEventSubscriber(pattern = ".*CheckBox")
    public void onCheckBoxStateChanged(String id, CheckBoxStateChangedEvent event) {
        boolean checked = event.isChecked();
        switch (id) {
            case "showGridCheckBox":
                showGrid(checked);
                break;
            case "showWireframeCheckBox":
                showWireFrame(simpleApp.getRootNode(), checked);
                break;
            case "pauseStateCheckBox":
                states.get(gui.stateDropDown.getSelection()).setEnabled(checked);
                break;
        }
    }

    @NiftyEventSubscriber(pattern = ".*Slider")
    public void onSliderStateChanged(String id, SliderChangedEvent event) {
        System.out.println("slider change");
        switch (id) {
            case "cameraSpeedSlider":
                flyCam.setMoveSpeed(event.getValue());
                break;
            case "viewDistanceSlider":
                cam.setFrustumFar(event.getValue());
                cam.update();
                if (voxelState != null) {
                    voxelState.getCalcBound().setRadius(cam.getFrustumFar() * .9f);
                    Sphere s = new Sphere(32, 32, voxelState.getCalcBound().getRadius());
                    s.setMode(Mode.Lines);
                    worldCalcBoundGeom.setMesh(s);
                }
                break;
        }
    }

    @NiftyEventSubscriber(pattern = ".*DropDown")
    public void onDropDownSelectionChanged(String id,
                                           DropDownSelectionChangedEvent<String> event) {
        switch (id) {
            case "stateSelectDropDown":
                AbstractAppState state = states.get(gui.stateDropDown.getSelection());
                gui.pauseStateCheckBox.setChecked(state.isEnabled());
                break;
        }
    }

    public void listBoxItemClicked() {
        System.out.println("tree click");
    }

    public void expandButtonClicked() {
        System.out.println("expand");
    }

    public void mouseClick() {
        System.out.println("mouseClick");
    }

    public void downClick() {
        System.out.println("rightClick");
    }

    public void click() {
        System.out.println("---------click");
    }

    public void upClick() {
        System.out.println("leftClick");
    }

    public void showGrid(boolean enabled) {
        showGrid = enabled;
        if (showGrid)
            debugNode.attachChild(coordNode);
        else debugNode.detachChild(coordNode);
    }

    public void showWireFrame(Node node, boolean show) {
        showWire = show;
        Geometry geom;
        for (Spatial s : node.getChildren())
            if (s instanceof Node) {
                if (s != debugNode)
                    showWireFrame((Node) s, show);
            } else
                if (s instanceof Geometry) {
                    geom = (Geometry) s;
                    geom.getMaterial().getAdditionalRenderState().setWireframe(showWire);
                }
    }

    public void addState(AbstractAppState state) {
        states.put(state.getClass().getSimpleName(), state);
        gui.addStateToControl(state.getClass().getSimpleName());
    }

    public DebugMouse getMouse() {
        return mouse;
    }

    public ScenegraphNode getDebugNode() {
        return debugNode;
    }

    public FlyByCamera getDebugCamera() {
        return flyCam;
    }

    @Override
    public void setEnabled(boolean enabled) {
        super.setEnabled(enabled);

        if (sm.hasState(sm.getState(StatsAppState.class))) {
            sm.getState(StatsAppState.class).setEnabled(!enabled);
            simpleApp.setDisplayFps(!enabled);
            simpleApp.setDisplayStatView(!enabled);
        }

        if (enabled)
            im.addListener(this);
        else im.removeListener(this);
    }

    /**
     * Creates one arrow for each axis colored in x=red, y=green, z=blue
     * and one grid plane for each plane colored xz=red, xy=green, yz=blue.
     *
     * @author Torge Rothe
     * @param size
     *            - int - The size of the arrows and grids
     * @param segSize
     *            - int - The segment size of the grids.
     * @return Node - A node with 3 direction arrows for x, y, z axis and 3 coordination
     *         grid planes for xz, xy, yz planes.
     */
    private ScenegraphNode createCoordinationNode(int size, int segSize) {
        float offset = size / 2;

        Material mat;

        Geometry xAxis;
        Geometry yAxis;
        Geometry zAxis;
        Geometry xzGrid;
        Geometry xyGrid;
        Geometry yzGrid;

        ScenegraphNode coordNode = new ScenegraphNode("Coodination Grid");
        ScenegraphNode labelNode = new ScenegraphNode("Grid labels");
        coordNode.attachChild(labelNode);

        // create x-axis
        Arrow arrowX = new Arrow(new Vector3f(size, 0.0f, 0.0f));
        xAxis = new Geometry("X-Axis", arrowX);
        mat = new Material(am, Materials.UNSHADED);
        mat.setColor("Color", ColorRGBA.Red);
        xAxis.setMaterial(mat);

        // create xy-grid
        Grid xyPlane = new Grid(size, size, segSize);
        xyGrid = new Geometry("XY-Plane", xyPlane);
        xyGrid.setMaterial(mat);
        xyGrid.rotateUpTo(new Vector3f(0.0f, 0.0f, 1.0f));
        xyGrid.setLocalTranslation(new Vector3f(-offset, offset, 0.0f));

        // create y-axis
        Arrow arrowY = new Arrow(new Vector3f(0.0f, size, 0.0f));
        yAxis = new Geometry("Y-Axis", arrowY);
        mat = new Material(am, Materials.UNSHADED);
        mat.setColor("Color", ColorRGBA.Green);
        yAxis.setMaterial(mat);

        // create yz-grid
        Grid yzPlane = new Grid(size, size, segSize);
        yzGrid = new Geometry("YZ-Plane", yzPlane);
        yzGrid.setMaterial(mat);
        yzGrid.rotateUpTo(new Vector3f(1.0f, 0.0f, 0.0f));
        yzGrid.setLocalTranslation(new Vector3f(0.0f, offset, -offset));

        // create z-axis
        Arrow arrowZ = new Arrow(new Vector3f(0.0f, 0.0f, size));
        zAxis = new Geometry("Z-Axis", arrowZ);
        mat = new Material(am, Materials.UNSHADED);
        mat.setColor("Color", ColorRGBA.Blue);
        zAxis.setMaterial(mat);

        // create xz-grid
        Grid xzPlane = new Grid(size, size, segSize);
        xzGrid = new Geometry("XZ-Plane", xzPlane);
        xzGrid.setMaterial(mat);
        xzGrid.rotateUpTo(new Vector3f(0.0f, 1.0f, 0.0f));
        xzGrid.setLocalTranslation(new Vector3f(-offset, 0.0f, -offset));

        // attach arrows to coordination node
        coordNode.attachChild(xAxis);
        coordNode.attachChild(yAxis);
        coordNode.attachChild(zAxis);

        // attach grids to coordination node
        coordNode.attachChild(xyGrid);
        coordNode.attachChild(xzGrid);
        coordNode.attachChild(yzGrid);

        Vector3f pos = new Vector3f(0, 0, 0);

        BitmapText vertId = new BitmapText(guiFont);
        vertId.setSize(.1f);
        vertId.setText("x0, y0, z0");
        vertId.setName("Gridlabel - x0, y0, z0");
        vertId.setLocalTranslation(pos);
        vertId.addControl(bc.cloneForSpatial(vertId));
        labelNode.attachChild(vertId);

        for (int x = 1; x < offset; x++) {
            pos.set(x, 0, 0);
            vertId = new BitmapText(guiFont);
            vertId.setSize(.2f);
            vertId.setText("x" + x);
            vertId.setName("Gridlabel - x" + x);
            vertId.setLocalTranslation(pos);
            vertId.addControl(bc.cloneForSpatial(vertId));
            labelNode.attachChild(vertId);
        }
        for (int y = 1; y < offset; y++) {
            pos.set(0, y, 0);
            vertId = new BitmapText(guiFont);
            vertId.setSize(.2f);
            vertId.setText("y" + y);
            vertId.setName("Gridlabel - y" + y);
            vertId.setLocalTranslation(pos);
            vertId.addControl(bc.cloneForSpatial(vertId));
            labelNode.attachChild(vertId);
        }
        for (int z = 1; z < offset; z++) {
            pos.set(0, 0, z);
            vertId = new BitmapText(guiFont);
            vertId.setSize(.2f);
            vertId.setText("z" + z);
            vertId.setName("Gridlabel - z" + z);
            vertId.setLocalTranslation(pos);
            vertId.addControl(bc.cloneForSpatial(vertId));
            labelNode.attachChild(vertId);
        }
        return coordNode;
    }

    private TreeItem<String> createTreeItem(Spatial spatial) {
        TreeItem<String> newItem, tmpItem;
        String value = "";
        if (spatial instanceof Node)
            value += "(" + ((Node) spatial).getChildren().size() + ") ";
        value += spatial.toString();

        newItem = new TreeItem<>(value);
        treeItems.put(spatial, newItem);

        if (spatial instanceof Node) {
            Node sNode = (Node) spatial;

            for (Spatial sp : sNode.getChildren()) {
                tmpItem = treeItems.get(sp);
                if (tmpItem == null)
                    tmpItem = createTreeItem(sp);
                newItem.addTreeItem(tmpItem);
            }
        }
        return newItem;
    }

    private void loadDfltKeys() {
        im.addMapping(Keys.DEBUG_CAM_ACTIVATE, Keys.KEY_LCONTROL);
        im.addMapping(Keys.SHOW_COORD_GRID, Keys.KEY_G);
        im.addMapping(Keys.SHOW_NORMALS, Keys.KEY_1);
        im.addMapping(Keys.SHOW_WIREFRAME, Keys.KEY_2);
        im.addMapping(Keys.SELECT_NODE, Keys.L_MOUSE);
        im.addMapping(Keys.SHOW_CONTEXT_MENU, Keys.R_MOUSE);

        im.addListener(this, inputKeys);
    }

    @Override
    public void cleanup() {
        super.cleanup();

        for (String s : inputKeys)
            im.deleteMapping(s);

        im.removeListener(this);
        simpleApp.getRootNode().removeLight(ambientLight);
        simpleApp.getRootNode().removeLight(directionalLight);
        simpleApp.getRootNode().detachChild(debugNode);
    }

    @Override
    public void bind(Nifty nifty, Screen screen) {
        gui.init(screen);

        gui.showGridCheckBox.setChecked(showGrid);
        gui.showWireframeCheckBox.setChecked(showWire);

        gui.cameraSpeedSlider.setValue(flyCam.getMoveSpeed());
        gui.viewDistanceSlider.setValue(cam.getFrustumFar());

        TreeItem<String> sceneRootItem = createTreeItem(simpleApp.getRootNode());
        TreeItem<String> viewRootItem = new TreeItem<String>();
        viewRootItem.addTreeItem(sceneRootItem);
        viewRootItem.setExpanded(true);
        gui.scenegraphView.setRoot(viewRootItem);
    }

    @Override
    public void onStartScreen() {

    }

    @Override
    public void onEndScreen() {

    }
}
TOP

Related Classes of de.venjinx.editor.debug.DebugState

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.