Java tutorial
/* * 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); } }