com.sidereal.dolphinoes.ui.MessageBubble.java Source code

Java tutorial

Introduction

Here is the source code for com.sidereal.dolphinoes.ui.MessageBubble.java

Source

/*******************************************************************************
 * Copyright 2014 See AUTHORS file.
 * 
 * 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 com.sidereal.dolphinoes.ui;

import java.util.ArrayList;
import java.util.HashMap;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.graphics.Color;
import com.badlogic.gdx.graphics.Texture;
import com.badlogic.gdx.math.Vector2;
import com.sidereal.dolphinoes.architecture.DolphinOES;
import com.sidereal.dolphinoes.architecture.GameObject;
import com.sidereal.dolphinoes.architecture.GameScene;
import com.sidereal.dolphinoes.architecture.core.input.ActionData;
import com.sidereal.dolphinoes.architecture.core.input.ActionEvent;
import com.sidereal.dolphinoes.architecture.core.input.Input.InputAction;
import com.sidereal.dolphinoes.architecture.core.input.Input.InputEventType;
import com.sidereal.dolphinoes.behaviors.input.Clickable;
import com.sidereal.dolphinoes.behaviors.renderer.Renderer;
import com.sidereal.dolphinoes.behaviors.renderer.sprite.SpriteBuilder;
import com.sidereal.dolphinoes.behaviors.renderer.sprite.SpriteDrawer;
import com.sidereal.dolphinoes.ui.TextBuilder.Anchor;
import com.sidereal.dolphinoes.ui.TextBuilder.Paragraph;

/** Class resembling a message bubble. Messages can be sent to the object,
 * displaying them and dissapearing or waiting to be clicked until closing.
 * 
 * @author Claudiu Bele */
public class MessageBubble extends GameObject {

    // region fields

    private String targetInputProcessor;

    public TextBuilder text;

    public Vector2 size;
    public Color bgColor;
    public float textSize;

    public Renderer renderer;
    public Clickable clickable;

    public ArrayList<MessageBubbleText> texts;
    public boolean inTransition;
    private ShrinkType shrinkType;

    /** The general offset of the text, compared to the top of the Message
     * bubble, initially set to -40 */
    public float textPositionOffset;

    /** The amount we reduce from the size for the word wrap. Being 0 would
     * possibly make the text overlap the frame texture.
     * <p>
     * Set to -40 in {@link MessageBubble#createObject(Object...) }. */
    public float textWrapOffset;

    /** The static hashmap in which we will hold valuable message bubbles ( the
     * ones that when created are being passed a name ) */
    public static HashMap<String, MessageBubble> messageBubbles;

    class MessageBubbleText {
        public ArrayList<Paragraph> paragraphs;
        public float fadeTime;
        public float upTime;
        public float timeRemaining;
        public DisplayStatus displayStatus;

        public boolean closeOnClick;

        public MessageBubbleText(ArrayList<TextBuilder.Paragraph> paragraphs) {

            displayStatus = DisplayStatus.APPEARING;
            fadeTime = 0.4f;
            closeOnClick = false;
            upTime = timeRemaining = 2;
            textSize = 1.4f;
            this.paragraphs = paragraphs;
        }

        public void set(MessageBubble bubble) {

            displayStatus = DisplayStatus.APPEARING;
            timeRemaining = fadeTime;

            bubble.text.clearText();
            for (int i = 0; i < paragraphs.size(); i++) {
                bubble.text.addText(paragraphs.get(i).text, paragraphs.get(i).color);
            }
            if (closeOnClick) {
                bubble.text.addText(" ", Color.BLACK);
                bubble.text.addText("Click window to close.", Color.WHITE);
            }
        }

        public void update(MessageBubble bubble) {

            timeRemaining -= DolphinOES.time.getDeltaTime();
            timeRemaining = Math.max(0, timeRemaining);

            float progress = 0;
            if (displayStatus.equals(DisplayStatus.APPEARING)) {

                progress = 1 - timeRemaining / fadeTime;
                if (timeRemaining == 0) {
                    timeRemaining = upTime;
                    displayStatus = DisplayStatus.DISPLAYED;
                    if (closeOnClick) {
                        bubble.clickable.enabled = true;
                    }
                    inTransition = false;
                }

            }

            if (displayStatus.equals(DisplayStatus.DISPLAYED)) {
                progress = 1;
                if (timeRemaining == 0 && !closeOnClick) {
                    timeRemaining = fadeTime;
                    displayStatus = DisplayStatus.DISSAPEARING;
                }

            }

            if (displayStatus.equals(DisplayStatus.DISSAPEARING)) {
                if (texts.size() == 1) {
                    bubble.inTransition = true;
                }
                progress = timeRemaining / fadeTime;
                if (timeRemaining == 0) {
                    displayStatus = DisplayStatus.HIDDEN;
                    texts.remove(this);
                    if (texts.size() > 0) {
                        texts.get(0).set(bubble);
                    }

                }

            }

            // if has to become smaller or bigger in size, will do that
            // becomes bigger by default initially, becomes smaller when
            // removing the last fade element.
            if (bubble.inTransition) {
                renderer.getDrawer("BG", SpriteDrawer.class).setTransparency(progress, false);

                if (bubble.shrinkType.equals(ShrinkType.Full)) {
                    renderer.getDrawer("BG", SpriteDrawer.class).setSizeAndCenter(size.x * progress,
                            size.y * progress);

                    bubble.text.setScale(textSize * progress);
                }
            }

            bubble.text.alpha = progress;

        }

        public MessageBubbleText addParagraph(String text, Color color) {

            paragraphs.add(new Paragraph(text, color));
            return this;
        }

        public MessageBubbleText setFadeTime(float fadeTime) {

            this.fadeTime = fadeTime;
            return this;
        }

        public MessageBubbleText setUpTime(float upTime) {

            this.upTime = upTime;
            return this;
        }

        public MessageBubbleText setCloseOnClick(boolean value) {

            closeOnClick = value;
            return this;
        }

    }

    enum DisplayStatus {
        APPEARING, DISPLAYED, DISSAPEARING, HIDDEN
    }

    public static enum ShrinkType {
        Full, AlphaChannel
    }

    // endregion fields

    // region constructors

    public MessageBubble(String name, GameScene scene, ShrinkType shrinkType, String targetInputProcessor) {

        super(scene, targetInputProcessor);

        if (messageBubbles == null) {
            messageBubbles = new HashMap<String, MessageBubble>();
        }

        if (name != null) {
            messageBubbles.put(name, this);
        }

        this.shrinkType = shrinkType;

    }

    @Override
    public void createObject(Object... params) {

        this.targetInputProcessor = (String) params[0];

        this.pos.setRelative(0, 0, 10);
        this.textPositionOffset = 0;
        this.textWrapOffset = 0;
        size = new Vector2(Gdx.graphics.getHeight() * 0.2f, Gdx.graphics.getHeight() * 0.4f);
        bgColor = new Color(0, 0, 0, 0.5f);
        renderer = new Renderer(this);
        clickable = new Clickable(this);
        clickable.enabled = false;
        clickable.setAreaSize(size.x, size.y);

        clickable.addActionEvent(targetInputProcessor, InputAction.ANY_ACTION, new ActionEvent() {
            @Override
            public boolean run(ActionData inputData) {

                if (texts.size() == 0)
                    return false;

                if (texts.get(0).closeOnClick && texts.get(0).displayStatus.equals(DisplayStatus.DISPLAYED)) {
                    texts.get(0).displayStatus = DisplayStatus.DISSAPEARING;
                    texts.get(0).timeRemaining = texts.get(0).fadeTime;
                    clickable.enabled = false;
                    return true;
                }
                return false;
            }

        }, InputEventType.Down, true);

        setGameBatch("UI");

        DolphinOES.assets.load(DolphinOES.assets.frameworkAssetsFolder + "White.png", Texture.class);

        renderer.addDrawer("BG", new SpriteBuilder(DolphinOES.assets.frameworkAssetsFolder + "White.png")
                .setSizeAndCenter(size).setTransparency(0).setColor(bgColor));

        text = new TextBuilder(scene, true);
        text.setGameBatch("UI");
        text.setAnchor(Anchor.Middle);
        text.setParent(this);
        text.pos.setLocal(0, 0);
        text.pos.setRelative(0, 0, 1);
        texts = new ArrayList<MessageBubble.MessageBubbleText>();
        inTransition = true;
    }

    // endregion constructors

    // region methods

    public void setColor(float r, float g, float b, float a) {

        bgColor.set(r, g, b, a);
        renderer.getDrawer("BG", SpriteDrawer.class).setColor(bgColor);
    }

    public void setSize(float width, float height) {

        size = new Vector2(width, height);
        text.setWindowSize(width + textWrapOffset);

        renderer.getDrawer("BG", SpriteDrawer.class).setSizeAndCenter(size.x, size.y);

        clickable.setAreaSize(width, height);

        text.pos.setLocal(0, textPositionOffset);

    }

    public void setTextWrapOffset(float value) {

        this.textWrapOffset = value;
        text.setWindowSize(size.x + textWrapOffset);
    }

    public void setTextPositionOffset(float value) {

        this.textPositionOffset = value;
        text.pos.setLocal(0, textPositionOffset);
    }

    @Override
    public void update() {

        if (texts.size() > 0) {
            texts.get(0).update(this);
        }
    }

    public void add(MessageBubbleText text) {

        texts.add(text);
        // if numbers of texts is 1 after adding our own text, we make it
        // appear. IF it isn't we just add it to the queue
        if (texts.size() == 1) {
            texts.get(0).set(this);
        }

    }

    public void add(String text) {

        add(text, Color.WHITE);
    }

    public void add(String text, Color color) {

        add(text, color, false);
    }

    public void add(String text, Color color, boolean closeOnClick) {

        add(text, color, closeOnClick, 2f, 0.5f);
    }

    public void add(String text, Color color, boolean closeOnClick, float upTime, float fadeTime) {

        ArrayList<Paragraph> paragraphs = new ArrayList<TextBuilder.Paragraph>();
        paragraphs.add(new Paragraph(text, color));

        add(paragraphs, closeOnClick, upTime, fadeTime);
    }

    public void add(ArrayList<Paragraph> paragraphs, boolean closeOnClick, float upTime, float fadeTime) {

        add(new MessageBubbleText(paragraphs).setCloseOnClick(closeOnClick).setUpTime(upTime)
                .setFadeTime(fadeTime));
    }

    public boolean isDisplayingMessage() {

        return texts.size() != 0;
    }

    public void clear() {

        texts.clear();
    }

    @Override
    protected void onPositionChange() {

        if (text != null) {
            text.pos.setLocal(0, 0);
        }
    }

    @Override
    public void onResize(float x, float y, float oldX, float oldY) {

        setSize(size.x * (x / oldX), size.y * (y / oldY));
        pos.set(gameBatch.camera.position.x, gameBatch.camera.position.y, pos.getZ());

    }

    // endregion methods
}