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

Java tutorial

Introduction

Here is the source code for org.bladecoder.bladeengine.ui.InventoryUI.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.Inventory;
import org.bladecoder.bladeengine.model.SpriteActor;
import org.bladecoder.bladeengine.model.World;
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.graphics.Color;
import com.badlogic.gdx.graphics.g2d.SpriteBatch;
import com.badlogic.gdx.graphics.g2d.TextureAtlas;
import com.badlogic.gdx.graphics.g2d.TextureAtlas.AtlasRegion;
import com.badlogic.gdx.math.Rectangle;
import com.badlogic.gdx.math.Vector3;

public class InventoryUI {
    private final static int TOP = 0;
    private final static int DOWN = 1;
    private final static int LEFT = 2;
    private final static int RIGHT = 3;

    private final static String LEFT_ARROW_TILE = "left";
    private final static String RIGHT_ARROW_TILE = "right";
    //   private final static String COLLAPSE_TILE = "collapse";
    private final static String UNCOLLAPSE_TILE = "uncollapse";
    private final static String CONFIG_TILE = "config";

    private final static float AUTOCOLLAPSE_TIME = 0.5f;
    private final static float SCROLL_TIME = 0.5f;

    private final static float DPI = 160.0f * Gdx.graphics.getDensity();
    private final static Color GRAY = new Color(0.3f, 0.3f, 0.3f, 1f);
    private final static Color BG_COLOR = new Color(0, 0, 0, 0.6f);
    //   private final static Color BG_COLOR = new Color(0, 0, 0, 1f);

    private Rectangle bbox = new Rectangle();
    private Rectangle collapsedBbox = new Rectangle();
    private Rectangle configBbox = new Rectangle();

    /** The tile where the item zone starts */
    private int itemsPos = 2;

    /** Visible item size */
    private int itemsSize;

    private int tileSize = 50;
    private int inventoryPos = DOWN;
    private int scrollItemPos = 0;

    private SpriteActor draggedActor = null;

    //   private AtlasRegion collapseIcon;
    private AtlasRegion uncollapseIcon;
    private AtlasRegion leftArrowIcon;
    private AtlasRegion rightArrowIcon;
    private AtlasRegion configIcon;

    private boolean collapsed = false;
    private boolean autoCollapse = true;
    private float uncollapseTime = 0;
    private float scrollTime = 0;

    private int previousNumItems;

    SceneScreen sceneScreen;

    Recorder recorder;

    public InventoryUI(SceneScreen sceneScreen, Recorder recorder) {
        this.sceneScreen = sceneScreen;
        this.recorder = recorder;

        String pos = Config.getProperty(Config.INVENTORY_POS_PROP, "down");

        if (pos.trim().equals("top"))
            inventoryPos = TOP;
        else if (pos.trim().equals("left"))
            inventoryPos = LEFT;
        else if (pos.trim().equals("right"))
            inventoryPos = RIGHT;
        else
            inventoryPos = DOWN;
    }

    public void resize(int width, int height) {

        // calc tilesize as function of resolution and DPI
        // initial tilesize is 1/10 of screen resolution
        this.tileSize = (int) height / 10;

        // the minimum height of the inventory is 1/3"
        if (this.tileSize < (int) (DPI / 3)) {
            this.tileSize = (int) (DPI / 3);
            EngineLogger.debug("DPI: " + DPI + " New TILESIZE: " + this.tileSize);
        }

        switch (inventoryPos) {
        case TOP:
            setBbox(0, height - this.tileSize, width, this.tileSize);
            break;
        case DOWN:
            setBbox(0, 0, width, this.tileSize);
            break;
        case LEFT:
            setBbox(0, 0, this.tileSize, height);
            break;
        case RIGHT:
            setBbox(width - this.tileSize, 0, this.tileSize, height);
            break;
        }

        if (bbox.width > bbox.height) // horizontal
            this.itemsSize = (int) width / this.tileSize - (itemsPos + 2);
        else
            this.itemsSize = (int) height / this.tileSize - (itemsPos + 2);
    }

    public void retrieveAssets(TextureAtlas atlas) {
        //      collapseIcon = atlas.findRegion(COLLAPSE_TILE);
        uncollapseIcon = atlas.findRegion(UNCOLLAPSE_TILE);

        leftArrowIcon = atlas.findRegion(LEFT_ARROW_TILE);
        rightArrowIcon = atlas.findRegion(RIGHT_ARROW_TILE);

        configIcon = atlas.findRegion(CONFIG_TILE);
    }

    public void draw(SpriteBatch batch, int inputX, int inputY) {
        Inventory inventory = World.getInstance().getInventory();

        if (!inventory.isVisible())
            return;

        if (autoCollapse) {
            // If the number of items changes show the inventory.
            // To give feedback to the user when pickup some item.
            if (previousNumItems != inventory.getNumItems()) {
                previousNumItems = inventory.getNumItems();
                collapse(false);

                // Set the scroll position to show the last item
            }

            updateAutocollapse(inputX, inputY);
        }

        if (collapsed) {
            batch.draw(uncollapseIcon, collapsedBbox.x, collapsedBbox.y, collapsedBbox.width, collapsedBbox.height);
        } else {
            boolean horizontal = bbox.width > bbox.height;

            RectangleRenderer.draw(batch, bbox.getX(), bbox.getY(), bbox.getWidth(), bbox.getHeight(), BG_COLOR);

            //         if(!autoCollapse)
            //            batch.draw(collapseIcon, collapsedBbox.x, collapsedBbox.y,
            //               collapsedBbox.width, collapsedBbox.height);

            batch.draw(uncollapseIcon, collapsedBbox.x, collapsedBbox.y, tileSize, tileSize);

            batch.draw(configIcon, configBbox.x, configBbox.y, configBbox.width, configBbox.height);

            // DRAW LEFT ARROW
            if (scrollItemPos == 0) {
                batch.setColor(GRAY);
                batch.draw(leftArrowIcon, horizontal ? (itemsPos - 1) * tileSize : bbox.x,
                        horizontal ? bbox.y : (itemsPos - 1) * tileSize, tileSize, tileSize);
                batch.setColor(Color.WHITE);
            } else {
                batch.draw(leftArrowIcon, horizontal ? (itemsPos - 1) * tileSize : bbox.x,
                        horizontal ? bbox.y : (itemsPos - 1) * tileSize, tileSize, tileSize);
            }

            // DRAW RIGHT ARROW
            if (scrollItemPos + itemsSize >= inventory.getNumItems()) {
                batch.setColor(GRAY);
                batch.draw(rightArrowIcon, horizontal ? (itemsPos + itemsSize) * tileSize : bbox.x,
                        horizontal ? bbox.y : (itemsPos + itemsSize) * tileSize, tileSize, tileSize);
                batch.setColor(Color.WHITE);
            } else {
                batch.draw(rightArrowIcon, horizontal ? (itemsPos + itemsSize) * tileSize : bbox.x,
                        horizontal ? bbox.y : (itemsPos + itemsSize) * tileSize, tileSize, tileSize);
            }

            // DRAW ITEMS
            for (int i = scrollItemPos; i < inventory.getNumItems() && itemsSize > i - scrollItemPos; i++) {

                SpriteActor a = inventory.getItem(i);

                float size = tileSize / a.getHeight() / a.getScale();

                a.getRenderer().draw(batch,
                        horizontal ? (i + itemsPos - scrollItemPos) * tileSize + a.getWidth() * size / 2
                                : bbox.x + a.getWidth() * size / 2,
                        horizontal ? bbox.y : (i + itemsPos - scrollItemPos) * tileSize, size);
            }
        }

        // DRAW DRAGGING
        if (draggedActor != null) {

            float h = draggedActor.getHeight() / draggedActor.getScale();

            float size = tileSize / h * 1.4f;

            //         batch.setBlendFunction(GL20.GL_ONE, GL20.GL_ZERO);
            ////            batch.setColor(0.3f, 0.3f, 0.3f, 1f);
            //            draggedActor.getRenderer().draw(batch, inputX,
            //                  inputY - h * size * 1.3f / 2, size * 1.3f);
            //            batch.setColor(1f, 1f, 1f, 1f);
            //            batch.setBlendFunction(GL20.GL_SRC_ALPHA, GL20.GL_ONE_MINUS_SRC_ALPHA);

            if (sceneScreen.getCurrentActor() == null)
                batch.setColor(0.7f, 0.7f, 0.7f, 1f);

            draggedActor.getRenderer().draw(batch, inputX, inputY - h * size / 2, size);
            batch.setColor(Color.WHITE);

            // Scroll the inventory if the draggedActor is over one inventory arrow
            scrollTime += Gdx.graphics.getDeltaTime();

            if (scrollTime > SCROLL_TIME) {
                scrollTime = 0;
                updateScroll(inputX, inputY);
            }
        }

    }

    private void updateAutocollapse(int inputX, int inputY) {

        if (collapsed) {
            if (collapsedBbox.contains(inputX, inputY) || inputY < 5) {
                collapse(false);
            }
        } else {

            if (bbox.contains(inputX, inputY)) {
                uncollapseTime = 0;
            } else {

                uncollapseTime += Gdx.graphics.getDeltaTime();

                if (uncollapseTime > AUTOCOLLAPSE_TIME) {
                    uncollapseTime = 0;
                    collapse(true);
                }
            }
        }
    }

    /**
     * Scrolls the inventory if the coordinates are over one inventory arrow
     * 
     * @param x X coordinate over inventory
     * @param y Y coordinate over inventory
     */
    private void updateScroll(float x, float y) {
        Inventory inventory = World.getInstance().getInventory();
        int selected = (int) ((bbox.width > bbox.height ? x : y) / tileSize);

        if (selected == itemsPos - 1 && scrollItemPos > 0) {
            scrollItemPos--;
        } else if (selected == itemsPos + itemsSize && scrollItemPos + itemsSize < inventory.getNumItems()) {
            scrollItemPos++;
        }
    }

    public boolean contains(float x, float y) {
        Inventory inventory = World.getInstance().getInventory();

        if (!inventory.isVisible())
            return false;

        if (collapsed)
            return collapsedBbox.contains(x, y);
        else
            return bbox.contains(x, y);
    }

    private void setBbox(float x, float y, float width, float height) {
        bbox.set(x, y, width, height);

        collapsedBbox.set(bbox.x, bbox.y, tileSize, tileSize);

        configBbox.set(bbox.width < bbox.height ? bbox.x : bbox.width - tileSize,
                bbox.width < bbox.height ? bbox.height - tileSize : bbox.y, tileSize, tileSize);
    }

    public void cancelDragging() {
        draggedActor = null;
    }

    private void startDragging(float x, float y) {
        draggedActor = getItemAt(x, y);
    }

    private final Vector3 mousepos = new Vector3();

    private void stopDragging(int inputX, int inputY) {
        World.getInstance().getSceneCamera().getInputUnProject(sceneScreen.getViewport(), mousepos);

        Actor targetActor = sceneScreen.getCurrentActor();

        if (targetActor != null) {
            use(targetActor, draggedActor);
        }

        draggedActor = null;
    }

    private void use(Actor a1, Actor a2) {
        if (a1.getVerb("use", a2.getId()) != null) {
            if (recorder.isRecording()) {
                recorder.add(a1.getId(), "use", a2.getId());
            }

            a1.runVerb("use", a2.getId());
        } else {
            if (recorder.isRecording()) {
                recorder.add(a2.getId(), "use", a1.getId());
            }

            a2.runVerb("use", a1.getId());
        }
    }

    public SpriteActor getItemAt(float x, float y) {

        if (collapsed == false && bbox.contains(x, y)) {
            Inventory inventory = World.getInstance().getInventory();

            int selected = (int) ((bbox.width > bbox.height ? x : y) / tileSize);

            if (selected >= itemsPos && selected < itemsPos + itemsSize) { // item
                // clicked
                int item = selected - itemsPos + scrollItemPos;

                if (item < inventory.getNumItems()) {
                    return inventory.getItem(item);
                }

            }
        }

        return null;
    }

    public void collapse(boolean collapse) {
        this.collapsed = collapse;
    }

    public void touchEvent(int type, float x, float y, int pointer, int button) {
        switch (type) {
        case SceneInputProcessor.TOUCH_UP:
            if (draggedActor != null) {
                stopDragging((int) x, (int) y);
            } else if (collapsedBbox.contains(x, y)) {
                if (collapsed)
                    collapse(false);
                else
                    collapse(true);
            } else if (configBbox.contains(x, y)) {
                sceneScreen.showMenu();
            } else {
                Actor actor = getItemAt(x, y);

                if (actor != null) {
                    sceneScreen.actorClick(actor, button == 1);
                } else {
                    updateScroll(x, y);
                }
            }
            break;

        case SceneInputProcessor.TOUCH_DOWN:
            // TODO if points over collapse or options. color it
            break;

        case SceneInputProcessor.DRAG:
            startDragging(x, y);
            break;
        }
    }

    public int getInventoryPos() {
        return inventoryPos;
    }

    public void setInventoryPos(int inventoryPos) {
        this.inventoryPos = inventoryPos;
    }

}