com.github.fauu.helix.editor.World.java Source code

Java tutorial

Introduction

Here is the source code for com.github.fauu.helix.editor.World.java

Source

/*
 * Copyright (C) 2014 Helix Engine Developers (http://github.com/fauu/HelixEngine)
 *
 * This software is licensed under the GNU General Public License
 * (version 3 or later). See the COPYING file in this distribution.
 *
 * You should have received a copy of the GNU Library General Public License
 * along with this software. If not, see <http://www.gnu.org/licenses/>.
 *
 * Authored by: Piotr Grabowski <fau999@gmail.com>
 */

package com.github.fauu.helix.editor;

import com.badlogic.gdx.ApplicationListener;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.Input;
import com.badlogic.gdx.assets.AssetDescriptor;
import com.badlogic.gdx.assets.AssetManager;
import com.badlogic.gdx.assets.loaders.resolvers.InternalFileHandleResolver;
import com.badlogic.gdx.graphics.Color;
import com.badlogic.gdx.graphics.g3d.Model;
import com.badlogic.gdx.graphics.g3d.RenderableProvider;
import com.badlogic.gdx.math.Intersector;
import com.badlogic.gdx.math.Matrix4;
import com.badlogic.gdx.math.Vector2;
import com.badlogic.gdx.math.Vector3;
import com.badlogic.gdx.math.collision.BoundingBox;
import com.badlogic.gdx.math.collision.Ray;
import com.badlogic.gdx.utils.Array;
import com.github.fauu.helix.core.*;
import com.github.fauu.helix.core.Object;
import com.github.fauu.helix.editor.model.EditorMode;
import com.github.fauu.helix.editor.model.FacingWrapper;
import com.github.fauu.helix.editor.model.ObjectWrapper;
import com.github.fauu.helix.editor.ui.Sidebar;
import com.github.fauu.helix.editor.ui.StatusBar;

public class World implements ApplicationListener {

    private static final float CAMERA_DRAG_FACTOR = 0.025f;

    private EditorFrame editorFrame;

    private Camera camera;
    private MapRegion mapRegion;
    private AssetManager assets;
    private Renderer renderer;

    private Tile matchedTile;
    private Object matchedObject;
    private boolean currentTilePainted = false;

    public World(EditorFrame editorFrame) {
        this.editorFrame = editorFrame;
    }

    @Override
    public void create() {
        camera = new Camera(new Vector3(66, 76, 0));
        camera.move(new Vector3(10, 0, 10));
        editorFrame.receiveCamera(camera);

        assets = new AssetManager();
        assets.setLoader(GeometrySet.class, new GeometrySetLoader(new InternalFileHandleResolver()));
        assets.setLoader(MapRegion.class, new MapRegionLoader(new InternalFileHandleResolver()));
        assets.load("assets/mapregions/0.hmr", MapRegion.class);
        assets.finishLoading();

        mapRegion = assets.get("assets/mapregions/0.hmr", MapRegion.class);
        editorFrame.receiveMapRegion(mapRegion);

        renderer = new Renderer();
    }

    @Override
    public void render() {
        handleInput();

        if (mapRegion.getMesh().isReady()) {
            Array<RenderableProvider> renderableProviders = new Array<RenderableProvider>();
            renderableProviders.add(mapRegion);
            renderableProviders.addAll(mapRegion.getObjectsModelInstances());

            renderer.render(camera, renderableProviders, null);
        }
    }

    @Override
    public void dispose() {
        // FIXME: There are things to dispose here!
    }

    @Override
    public void resize(int width, int height) {
    }

    @Override
    public void pause() {
    }

    @Override
    public void resume() {
    }

    // TODO: Cleaning
    public void handleInput() {
        final Tile newMatchedTile = matchHoveredTile(Gdx.input.getX(), Gdx.input.getY());
        Object newMatchedObject;

        if (((EditorMode) editorFrame.getSidebar().getEditorModePicker().getSelectedItem())
                .getType() == EditorMode.Type.OBJECT) {
            newMatchedObject = matchHoveredObject(Gdx.input.getX(), Gdx.input.getY());

            if (newMatchedObject != matchedObject) {
                if (matchedObject != null) {
                    mapRegion.setObjectColor(matchedObject, Color.WHITE);
                }

                if (newMatchedObject != null) {
                    mapRegion.setObjectColor(newMatchedObject, new Color(0.5f, 0.5f, 0.5f, 1));
                }

                matchedObject = newMatchedObject;
            }

            if (newMatchedObject != null) {
                if (Gdx.input.isButtonPressed(Input.Buttons.MIDDLE)) {
                    mapRegion.deleteObject(newMatchedObject);
                }
            }
        }

        if (Gdx.input.isTouched()) {
            final EditorMode.Type editorMode = ((EditorMode) editorFrame.getSidebar().getEditorModePicker()
                    .getSelectedItem()).getType();

            if (Gdx.input.isButtonPressed(Input.Buttons.LEFT)) {
                if (!currentTilePainted) {
                    switch (editorMode) {
                    case TILE_GENERAL:
                        paintTile(newMatchedTile);
                        break;
                    case TILE_TYPE:
                        paintTileType(newMatchedTile);
                        break;
                    case OBJECT:
                        paintObject(newMatchedTile);
                        break;
                    default:
                    }

                    currentTilePainted = true;
                }
            } else if (Gdx.input.isButtonPressed(Input.Buttons.RIGHT)) {
                final int deltaX = Gdx.input.getDeltaX();
                final int deltaY = Gdx.input.getDeltaY();

                camera.move(new Vector3(-CAMERA_DRAG_FACTOR * deltaX, 0, -CAMERA_DRAG_FACTOR * deltaY));
            }
        }

        if (matchedTile != newMatchedTile) {
            if (matchedTile != null) {
                matchedTile.setHighlighted(false);

                mapRegion.getMesh().updateTileColor(matchedTile);
            }

            if (newMatchedTile != null) {
                newMatchedTile.setHighlighted(true);

                mapRegion.getMesh().updateTileColor(newMatchedTile);

                // TODO: Add more info to the status bar
                editorFrame.getStatusBar().setTileInfoText("Position: " + newMatchedTile.getPosition());
            } else {
                editorFrame.getStatusBar().setTileInfoText(StatusBar.TILE_INFO_DEFAULT_TEXT);
            }

            matchedTile = newMatchedTile;
            currentTilePainted = false;
        }

        if (Gdx.input.isKeyPressed(Input.Keys.A)) {
            camera.rotateYAround(
                    new Vector2(mapRegion.getCenterCoordinates().x, mapRegion.getCenterCoordinates().y), -2);
        } else if (Gdx.input.isKeyPressed(Input.Keys.D)) {
            camera.rotateYAround(
                    new Vector2(mapRegion.getCenterCoordinates().x, mapRegion.getCenterCoordinates().y), 2);
        } else if (Gdx.input.isKeyPressed(Input.Keys.S)) {
            camera.resetYRotationAround(
                    new Vector2(mapRegion.getCenterCoordinates().x, mapRegion.getCenterCoordinates().y));
        }

        final EditorMode.Type editorMode = ((EditorMode) editorFrame.getSidebar().getEditorModePicker()
                .getSelectedItem()).getType();

        if (editorMode == EditorMode.Type.TILE_GENERAL || editorMode == EditorMode.Type.TILE_TYPE) {
            if (Gdx.input.isKeyPressed(Input.Keys.SPACE)) {
                if (!mapRegion.areObjectsHidden()) {
                    mapRegion.hideObjects();
                }
            } else {
                if (mapRegion.areObjectsHidden()) {
                    mapRegion.showObjects();
                }
            }
        }
    }

    private Tile matchHoveredTile(int screenX, int screenY) {
        final Ray ray = camera.getPickRay(screenX, screenY);
        final GeometrySet geometrySet = mapRegion.getGeometrySet();
        final Tile[] tiles = mapRegion.getTiles();
        Tile newMatchedTile = null;

        for (Tile tile : tiles) {
            final BoundingBox boundingBox = geometrySet.getGeometryBoundingBox(tile.getGeometryId());
            final Matrix4 transformationMatrix = new Matrix4();
            transformationMatrix
                    .translate(new Vector3(0.5f + tile.getPosition().x, 0, 0.5f + tile.getPosition().y));
            boundingBox.mul(transformationMatrix);

            if (Intersector.intersectRayBoundsFast(ray, boundingBox)) {
                newMatchedTile = tile;

                break;
            }
        }

        return newMatchedTile;
    }

    private Object matchHoveredObject(int screenX, int screenY) {
        final Ray ray = camera.getPickRay(screenX, screenY);
        final Array<Object> objects = mapRegion.getObjects();
        Object matchedObject = null;

        for (Object object : objects) {
            final BoundingBox boundingBox = new BoundingBox();
            object.getModelInstance().calculateBoundingBox(boundingBox);
            final Matrix4 transformationMatrix = new Matrix4();
            transformationMatrix
                    .translate(new Vector3(2f + object.getPosition().x, 0, 0.5f + object.getPosition().y));
            boundingBox.mul(transformationMatrix);

            if (Intersector.intersectRayBoundsFast(ray, boundingBox)) {
                matchedObject = object;

                break;
            }
        }

        return matchedObject;
    }

    private void paintTile(Tile tile) {
        final Sidebar editorSidebar = editorFrame.getSidebar();

        final int selectedGeometryNo = editorSidebar.getGeometryPicker().getSelectedGeometry().getNo();
        final int selectedTextureNo = editorSidebar.getTexturePicker().getSelectedTexture().getNo();
        final Direction selectedFacing = ((FacingWrapper) editorSidebar.getFacingPicker().getSelectedItem())
                .getFacing();
        final int selectedElevation = (Integer) editorSidebar.getElevationPicker().getValue();

        tile.setGeometryId(selectedGeometryNo);
        tile.setTextureId(selectedTextureNo);
        tile.setFacing(selectedFacing);
        tile.setElevation(selectedElevation);

        mapRegion.getMesh().update();
    }

    private void paintTileType(Tile tile) {
        final Tile.Type tileType = tile.getType();

        // FIXME: Not DRY (eee: Sidebar.setEditorMode)
        final Color nonWalkableColor = new Color(1, 0, 0, 1);
        final Color walkableColor = new Color(0, 1, 0, 1);

        if (tileType == Tile.Type.DEFAULT_NONWALKABLE) {
            tile.setType(Tile.Type.DEFAULT_WALKABLE);
            tile.setColor(walkableColor);
        } else {
            tile.setType(Tile.Type.DEFAULT_NONWALKABLE);
            tile.setColor(nonWalkableColor);
        }

        mapRegion.getMesh().updateTileColor(tile);
    }

    private void paintObject(Tile tile) {
        final Sidebar editorSidebar = editorFrame.getSidebar();

        final ObjectWrapper newObjectWrapper = editorSidebar.getObjectPicker().getSelectedObject();
        final int selectedElevation = (Integer) editorSidebar.getElevationPicker().getValue();
        final Direction selectedFacing = ((FacingWrapper) editorSidebar.getFacingPicker().getSelectedItem())
                .getFacing();

        final String modelPath = "assets/objects/" + newObjectWrapper.getModelName() + ".g3db";

        if (!assets.isLoaded(modelPath)) {
            assets.load(new AssetDescriptor(modelPath, Model.class));
            assets.finishLoading();
        }

        final Model newObjectModel = assets.get(modelPath);

        final Object newObject = new Object(tile.getPosition(), newObjectWrapper.getModelName(), newObjectModel,
                selectedElevation, selectedFacing);

        mapRegion.getObjects().add(newObject);
    }

}