org.bladecoder.bladeengine.ui.SceneScreen.java Source code

Java tutorial

Introduction

Here is the source code for org.bladecoder.bladeengine.ui.SceneScreen.java

Source

/*******************************************************************************
 * Copyright 2014 Rafael Garcia Moreno.
 * 
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 *   http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 ******************************************************************************/
package org.bladecoder.bladeengine.ui;

import org.bladecoder.bladeengine.model.Actor;
import org.bladecoder.bladeengine.model.Scene;
import org.bladecoder.bladeengine.model.Transition;
import org.bladecoder.bladeengine.model.World;
import org.bladecoder.bladeengine.model.World.AssetState;
import org.bladecoder.bladeengine.ui.UI.State;
import org.bladecoder.bladeengine.util.Config;
import org.bladecoder.bladeengine.util.EngineLogger;
import org.bladecoder.bladeengine.util.RectangleRenderer;

import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.Screen;
import com.badlogic.gdx.graphics.Color;
import com.badlogic.gdx.graphics.GL20;
import com.badlogic.gdx.graphics.g2d.BitmapFont.TextBounds;
import com.badlogic.gdx.graphics.g2d.SpriteBatch;
import com.badlogic.gdx.graphics.g2d.TextureAtlas;
import com.badlogic.gdx.graphics.glutils.ShapeRenderer;
import com.badlogic.gdx.math.Polygon;
import com.badlogic.gdx.math.Rectangle;
import com.badlogic.gdx.math.Vector2;
import com.badlogic.gdx.math.Vector3;
import com.badlogic.gdx.utils.viewport.Viewport;

public class SceneScreen implements Screen {

    UI ui;

    private PieMenu pie;
    private InventoryUI inventoryUI;
    private DialogUI dialogUI;
    private TextManagerUI textManagerUI;
    private ShapeRenderer renderer;

    private boolean pieMode;
    boolean dragging = false;

    private final Recorder recorder;

    private final SceneViewport viewport = new SceneViewport();

    private final Vector3 unprojectTmp = new Vector3();

    // Actor under the cursor
    private Actor currentActor = null;

    private boolean drawHotspots = false;
    private final boolean showDesc = Config.getProperty(Config.SHOW_DESC_PROP, true);

    public SceneScreen(UI ui, boolean pieMode) {
        this.ui = ui;

        recorder = new Recorder();

        pie = new PieMenu(recorder);
        textManagerUI = new TextManagerUI(this);
        inventoryUI = new InventoryUI(this, recorder);
        dialogUI = new DialogUI(this, recorder);

        this.pieMode = pieMode;
    }

    public Recorder getRecorder() {
        return recorder;
    }

    private void update(float delta) {
        World w = World.getInstance();
        currentActor = null;

        if (!World.getInstance().isDisposed()) {
            World.getInstance().update(delta);
        }

        AssetState assetState = World.getInstance().getAssetState();

        if (assetState != AssetState.LOADED) {
            ui.setScreen(State.LOADING_SCREEN);
            return;
        }

        recorder.update(delta);

        if (w.getCurrentDialog() == null && !w.inCutMode()) {

            if (w.getInventory().isVisible()) {
                viewport.getInputUnProject(unprojectTmp);
                currentActor = inventoryUI.getItemAt(unprojectTmp.x, unprojectTmp.y);
            }

            if (currentActor == null) {
                w.getSceneCamera().getInputUnProject(viewport, unprojectTmp);

                currentActor = w.getCurrentScene().getActorAt(unprojectTmp.x, unprojectTmp.y);
            }

            if (currentActor != null) {

                if (showDesc)
                    ui.getPointer().setDesc(currentActor.getDesc());

                if (currentActor.getVerb("leave") != null)
                    ui.getPointer().setLeaveIcon();
                else
                    ui.getPointer().setHotspotIcon();
            } else {
                ui.getPointer().setDefaultIcon();
            }
        } else {
            ui.getPointer().reset();

            if (pie.isVisible()) {
                pie.hide();
            }

            inventoryUI.cancelDragging();
        }
    }

    @Override
    public void render(float delta) {
        World w = World.getInstance();

        update(delta);

        if (w.getAssetState() != AssetState.LOADED)
            return;

        SpriteBatch batch = ui.getBatch();

        Gdx.gl.glClearColor(0, 0, 0, 1);
        Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);

        // WORLD CAMERA
        w.draw();

        if (EngineLogger.debugMode() && EngineLogger.getDebugLevel() == EngineLogger.DEBUG1) {
            renderer.setProjectionMatrix(w.getSceneCamera().combined);
            w.getCurrentScene().drawBBoxLines(renderer);
            renderer.end();
        }

        // SCREEN CAMERA
        batch.setProjectionMatrix(viewport.getCamera().combined);
        batch.begin();

        if (EngineLogger.debugMode()) {
            w.getSceneCamera().getInputUnProject(viewport, unprojectTmp);

            StringBuilder sb = new StringBuilder();
            sb.append("Mouse ( ");
            sb.append((int) unprojectTmp.x);
            sb.append(", ");
            sb.append((int) unprojectTmp.y);
            sb.append(") FPS:");
            sb.append(Gdx.graphics.getFramesPerSecond());

            if (w.getCurrentScene().getPlayer() != null) {
                sb.append(" Depth Scale: ");
                sb.append(w.getCurrentScene().getFakeDepthScale(unprojectTmp.y));
            }

            String strDebug = sb.toString();

            TextBounds b = EngineLogger.getDebugFont().getBounds(strDebug);
            RectangleRenderer.draw(batch, 0, viewport.getViewportHeight() - b.height - 10, b.width, b.height + 10,
                    Color.BLACK);
            EngineLogger.getDebugFont().draw(batch, strDebug, 0, viewport.getViewportHeight());
        }

        if (World.getInstance().getCurrentDialog() != null && !recorder.isPlaying()) { // DIALOG MODE

            if (!World.getInstance().inCutMode()) {
                viewport.getInputUnProject(unprojectTmp);
                dialogUI.draw(batch, (int) unprojectTmp.x, (int) unprojectTmp.y);
            }

            textManagerUI.draw(batch);
            ui.getPointer().draw(batch, false, viewport);
        } else {

            textManagerUI.draw(batch);

            viewport.getInputUnProject(unprojectTmp);
            inventoryUI.draw(batch, (int) unprojectTmp.x, (int) unprojectTmp.y);

            if (pieMode)
                pie.draw(batch);

            if (!World.getInstance().inCutMode() && !recorder.isPlaying())
                ui.getPointer().draw(batch, dragging, viewport);
        }

        Transition t = World.getInstance().getCurrentScene().getTransition();

        if (t != null) {
            t.draw(batch, viewport.getViewportWidth(), viewport.getViewportHeight());
        }

        recorder.draw(batch);

        if (drawHotspots)
            drawHotspots(batch);

        batch.end();
    }

    private void drawHotspots(SpriteBatch batch) {

        for (Actor a : World.getInstance().getCurrentScene().getActors().values()) {
            if (a == World.getInstance().getCurrentScene().getPlayer() || !a.hasInteraction() || !a.isVisible())
                continue;

            Polygon p = a.getBBox();

            if (p == null) {
                EngineLogger.error("ERROR DRAWING HOTSPOT FOR: " + a.getId());
            }

            Rectangle r = a.getBBox().getBoundingRectangle();

            unprojectTmp.set(r.getX() + r.getWidth() / 2, r.getY() + r.getHeight() / 2, 0);
            World.getInstance().getSceneCamera().scene2screen(viewport, unprojectTmp);

            ui.getPointer().drawHotspot(batch, unprojectTmp.x, unprojectTmp.y, showDesc ? a.getDesc() : null);
        }
    }

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

        if (!World.getInstance().isDisposed()) {
            viewport.setWorldSize(World.getInstance().getWidth(), World.getInstance().getHeight());
        } else {
            viewport.setWorldSize(width, height);
        }

        viewport.update(width, height, true);
        World.getInstance().getSceneCamera().update();

        pie.resize(viewport.getViewportWidth(), viewport.getViewportHeight());
        inventoryUI.resize(viewport.getViewportWidth(), viewport.getViewportHeight());
        dialogUI.resize(viewport.getViewportWidth(), viewport.getViewportHeight());
        textManagerUI.resize(viewport.getViewportWidth(), viewport.getViewportHeight());
    }

    public void dispose() {
        textManagerUI.dispose();
        dialogUI.dispose();
        renderer.dispose();
    }

    private void retrieveAssets(TextureAtlas atlas) {
        renderer = new ShapeRenderer();
        pie.retrieveAssets(atlas);
        inventoryUI.retrieveAssets(atlas);
        textManagerUI.retrieveAssets(atlas);
    }

    public void touchEvent(int type, float x, float y, int pointer, int button) {
        World w = World.getInstance();

        if (w.isPaused() || recorder.isPlaying())
            return;

        viewport.getInputUnProject(unprojectTmp);

        switch (type) {
        case SceneInputProcessor.TOUCH_UP:

            if (w.inCutMode() && !recorder.isRecording()) {
                w.getTextManager().next();
            } else if (w.getCurrentDialog() != null) {
                dialogUI.touchEvent(SceneInputProcessor.TOUCH_UP, unprojectTmp.x, unprojectTmp.y, pointer, button);
            } else if (w.getCurrentScene().getOverlay() != null) {
                w.getCurrentScene().getOverlay().click();
            } else if (dragging) {
                inventoryUI.touchEvent(SceneInputProcessor.TOUCH_UP, unprojectTmp.x, unprojectTmp.y, pointer,
                        button);
                dragging = false;
            } else if (pie.isVisible()) {
                ui.getPointer().setFreezeHotSpot(false, viewport);
                pie.touchEvent(SceneInputProcessor.TOUCH_UP, unprojectTmp.x, unprojectTmp.y, pointer, button);
            } else if (inventoryUI.contains(unprojectTmp.x, unprojectTmp.y)) {
                inventoryUI.touchEvent(SceneInputProcessor.TOUCH_UP, unprojectTmp.x, unprojectTmp.y, pointer,
                        button);
            } else {
                sceneClick(button == 1);
            }
            break;

        case SceneInputProcessor.TOUCH_DOWN:
            if (pie.isVisible()) {
                pie.touchEvent(SceneInputProcessor.TOUCH_DOWN, unprojectTmp.x, unprojectTmp.y, pointer, button);
            } else if (!w.inCutMode() && inventoryUI.contains(unprojectTmp.x, unprojectTmp.y)) {
                inventoryUI.touchEvent(SceneInputProcessor.TOUCH_DOWN, unprojectTmp.x, unprojectTmp.y, pointer,
                        button);
            }

            break;

        case SceneInputProcessor.DRAG:
            if (inventoryUI.contains(unprojectTmp.x, unprojectTmp.y)
                    && inventoryUI.getItemAt(unprojectTmp.x, unprojectTmp.y) != null && !dragging) {

                inventoryUI.touchEvent(SceneInputProcessor.DRAG, unprojectTmp.x, unprojectTmp.y, pointer, button);

                dragging = true;

                if (pie.isVisible()) {
                    pie.hide();
                    ui.getPointer().setFreezeHotSpot(false, viewport);
                }
            }
            break;
        }
    }

    private void sceneClick(boolean lookat) {
        World w = World.getInstance();

        w.getSceneCamera().getInputUnProject(viewport, unprojectTmp);

        Scene s = w.getCurrentScene();

        if (currentActor != null) {

            if (EngineLogger.debugMode()) {
                EngineLogger.debug(currentActor.toString());
            }

            actorClick(currentActor, lookat);
        } else if (s.getPlayer() != null) {
            if (s.getPlayer().getVerb("goto") != null) {
                if (recorder.isRecording()) {
                    recorder.add(s.getPlayer().getId(), "goto", null);
                }

                s.getPlayer().runVerb("goto");
            } else {
                Vector2 pos = new Vector2(unprojectTmp.x, unprojectTmp.y);

                if (recorder.isRecording()) {
                    recorder.add(pos);
                }

                s.getPlayer().goTo(pos, null);
            }
        }
    }

    public void actorClick(Actor a, boolean lookat) {
        if (a.getVerb("leave") != null) {
            if (recorder.isRecording()) {
                recorder.add(a.getId(), "leave", null);
            }

            a.runVerb("leave");
        } else if (!pieMode) {
            String verb = "lookat";

            if (!lookat) {
                verb = a.getVerb("talkto") != null ? "talkto" : "pickup";
            }

            if (recorder.isRecording()) {
                recorder.add(a.getId(), verb, null);
            }

            a.runVerb(verb);
        } else {
            viewport.getInputUnProject(unprojectTmp);
            pie.show(a, unprojectTmp.x, unprojectTmp.y);
            ui.getPointer().setFreezeHotSpot(true, viewport);
        }
    }

    public void showMenu() {
        ui.setScreen(State.MENU_SCREEN);
    }

    private void resetUI() {

        if (pie.isVisible()) {
            pie.hide();
        }

        ui.getPointer().reset();

        dragging = false;
        currentActor = null;
    }

    public InventoryUI getInventoryUI() {
        return inventoryUI;
    }

    @Override
    public void show() {
        dialogUI.loadAssets();
        retrieveAssets(ui.getUIAtlas());

        Gdx.input.setInputProcessor(new SceneInputProcessor(this));

        if (World.getInstance().isDisposed()) {
            try {
                World.getInstance().load();
            } catch (Exception e) {
                EngineLogger.error("ERROR LOADING GAME", e);

                dispose();
                Gdx.app.exit();
            }
        }

        World.getInstance().resume();
    }

    @Override
    public void hide() {
        World.getInstance().pause();
        resetUI();
        dispose();
    }

    @Override
    public void pause() {
        World.getInstance().pause();
    }

    @Override
    public void resume() {
        World.getInstance().resume();
    }

    public Viewport getViewport() {
        return viewport;
    }

    public Actor getCurrentActor() {
        return currentActor;
    }

}