sink.scene3d.Stage3d.java Source code

Java tutorial

Introduction

Here is the source code for sink.scene3d.Stage3d.java

Source

/*******************************************************************************
 * Copyright 2011 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 sink.scene3d;

import sink.core.Sink;

import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.InputAdapter;
import com.badlogic.gdx.graphics.Camera;
import com.badlogic.gdx.graphics.PerspectiveCamera;
import com.badlogic.gdx.graphics.g3d.Environment;
import com.badlogic.gdx.graphics.g3d.ModelBatch;
import com.badlogic.gdx.graphics.g3d.attributes.ColorAttribute;
import com.badlogic.gdx.graphics.g3d.environment.DirectionalLight;
import com.badlogic.gdx.scenes.scene2d.EventListener;
import com.badlogic.gdx.scenes.scene2d.Group;
import com.badlogic.gdx.utils.Array;
import com.badlogic.gdx.utils.Disposable;

public class Stage3d extends InputAdapter implements Disposable {
    private float viewportX, viewportY, viewportWidth, viewportHeight;
    private float width, height;
    private float gutterWidth, gutterHeight;
    private final ModelBatch modelBatch;
    private final Environment environment;

    private PerspectiveCamera camera;

    private final Group3d root;
    private Actor3d scrollFocus;
    private Actor3d keyboardFocus;

    /** Creates a stage with a {@link #setViewport(float, float, boolean) viewport} equal to the device screen resolution. The stage
    * will use its own {@link SpriteBatch}. */
    public Stage3d() {
        this(Gdx.graphics.getWidth(), Gdx.graphics.getHeight(), false);
    }

    /** Creates a stage with the specified {@link #setViewport(float, float, boolean) viewport} that doesn't keep the aspect ratio.
     * The stage will use its own {@link SpriteBatch}, which will be disposed when the stage is disposed. */
    public Stage3d(float width, float height) {
        this(width, height, false);
    }

    /** Creates a stage with the specified {@link #setViewport(float, float, boolean) viewport}. The stage will use its own
     * {@link SpriteBatch}, which will be disposed when the stage is disposed. */
    public Stage3d(float width, float height, boolean keepAspectRatio) {
        this.width = width;
        this.height = height;

        root = new Group3d();
        root.setStage3d(this);

        modelBatch = new ModelBatch();

        camera = new PerspectiveCamera(67, Gdx.graphics.getWidth(), Gdx.graphics.getHeight());
        camera.position.set(10f, 10f, 10f);
        camera.lookAt(0, 0, 0);
        camera.near = 0.1f;
        camera.far = 300f;
        camera.update();
        environment = new Environment();
        environment.set(new ColorAttribute(ColorAttribute.AmbientLight, 0.4f, 0.4f, 0.4f, 1f));
        environment.add(new DirectionalLight().set(0.8f, 0.8f, 0.8f, -1f, -0.8f, -0.2f));

        setViewport(width, height, keepAspectRatio);
    }

    /** Sets up the stage size using a viewport that fills the entire screen without keeping the aspect ratio.
     * @see #setViewport(float, float, boolean, float, float, float, float) */
    public void setViewport(float width, float height) {
        setViewport(width, height, false, 0, 0, Gdx.graphics.getWidth(), Gdx.graphics.getHeight());
    }

    /** Sets up the stage size using a viewport that fills the entire screen.
     * @see #setViewport(float, float, boolean, float, float, float, float) */
    public void setViewport(float width, float height, boolean keepAspectRatio) {
        setViewport(width, height, keepAspectRatio, 0, 0, Gdx.graphics.getWidth(), Gdx.graphics.getHeight());
    }

    /** Sets up the stage size and viewport. The viewport is the glViewport position and size, which is the portion of the screen
     * used by the stage. The stage size determines the units used within the stage, depending on keepAspectRatio:
     * <p>
     * If keepAspectRatio is false, the stage is stretched to fill the viewport, which may distort the aspect ratio.
     * <p>
     * If keepAspectRatio is true, the stage is first scaled to fit the viewport in the longest dimension. Next the shorter
     * dimension is lengthened to fill the viewport, which keeps the aspect ratio from changing. The {@link #getGutterWidth()} and
     * {@link #getGutterHeight()} provide access to the amount that was lengthened.
     * @param viewportX The top left corner of the viewport in glViewport coordinates (the origin is bottom left).
     * @param viewportY The top left corner of the viewport in glViewport coordinates (the origin is bottom left).
     * @param viewportWidth The width of the viewport in pixels.
     * @param viewportHeight The height of the viewport in pixels. */
    public void setViewport(float stageWidth, float stageHeight, boolean keepAspectRatio, float viewportX,
            float viewportY, float viewportWidth, float viewportHeight) {
        this.viewportX = viewportX;
        this.viewportY = viewportY;
        this.viewportWidth = viewportWidth;
        this.viewportHeight = viewportHeight;
        if (keepAspectRatio) {
            if (viewportHeight / viewportWidth < stageHeight / stageWidth) {
                float toViewportSpace = viewportHeight / stageHeight;
                float toStageSpace = stageHeight / viewportHeight;
                float deviceWidth = stageWidth * toViewportSpace;
                float lengthen = (viewportWidth - deviceWidth) * toStageSpace;
                this.width = stageWidth + lengthen;
                this.height = stageHeight;
                gutterWidth = lengthen / 2;
                gutterHeight = 0;
            } else {
                float toViewportSpace = viewportWidth / stageWidth;
                float toStageSpace = stageWidth / viewportWidth;
                float deviceHeight = stageHeight * toViewportSpace;
                float lengthen = (viewportHeight - deviceHeight) * toStageSpace;
                this.height = stageHeight + lengthen;
                this.width = stageWidth;
                gutterWidth = 0;
                gutterHeight = lengthen / 2;
            }
        } else {
            this.width = stageWidth;
            this.height = stageHeight;
            gutterWidth = 0;
            gutterHeight = 0;
        }

        camera.viewportWidth = this.width;
        camera.viewportHeight = this.height;
    }

    public void draw() {
        camera.update();
        if (!root.isVisible())
            return;
        modelBatch.begin(camera);
        root.drawChildren(modelBatch, environment);
        modelBatch.end();
    }

    /** Calls {@link #act(float)} with {@link Graphics#getDeltaTime()}. */
    public void act() {
        act(Math.min(Gdx.graphics.getDeltaTime(), 1 / 30f));
    }

    /** Calls the {@link Actor#act(float)} method on each actor in the stage. Typically called each frame. This method also fires
     * enter and exit events.
     * @param delta Time in seconds since the last frame. */
    public void act(float delta) {
        root.act(delta);
    }

    /** Adds an actor to the root of the stage.
     * @see Group#addActor(Actor)
     * @see Actor#remove() */
    public void addActor3d(Actor3d actor) {
        root.addActor(actor);
    }

    /** Adds an action to the root of the stage.
     * @see Group#addAction3d(Action) */
    public void addAction3d(Action3d action) {
        root.addAction3d(action);
    }

    /** Returns the root's child actors.
     * @see Group#getChildren() */
    public Array<Actor3d> getActors3d() {
        return root.getChildren();
    }

    /** Adds a listener to the root.
     * @see Actor#addListener(EventListener) */
    public boolean addListener(EventListener listener) {
        return root.addListener(listener);
    }

    /** Removes a listener from the root.
     * @see Actor#removeListener(EventListener) */
    public boolean removeListener(EventListener listener) {
        return root.removeListener(listener);
    }

    /** Removes the root's children, actions, and listeners. */
    public void clear() {
        unfocusAll();
        root.clear();
    }

    /** Removes the touch, keyboard, and scroll focused actors. */
    public void unfocusAll() {
        scrollFocus = null;
        keyboardFocus = null;
        //cancelTouchFocus();
    }

    /** Removes the touch, keyboard, and scroll focus for the specified actor and any descendants. */
    public void unfocus(Actor3d actor) {
        if (scrollFocus != null && scrollFocus.isDescendantOf(actor))
            scrollFocus = null;
        if (keyboardFocus != null && keyboardFocus.isDescendantOf(actor))
            keyboardFocus = null;
    }

    /** Sets the actor that will receive key events.
     * @param actor May be null. */
    public void setKeyboardFocus(Actor3d actor) {
        if (keyboardFocus == actor)
            return;
    }

    /** Gets the actor that will receive key events.
     * @return May be null. */
    public Actor3d getKeyboardFocus() {
        return keyboardFocus;
    }

    /** Sets the actor that will receive scroll events.
     * @param actor May be null. */
    public void setScrollFocus(Actor3d actor) {
        if (scrollFocus == actor)
            return;
    }

    /** Gets the actor that will receive scroll events.
     * @return May be null. */
    public Actor3d getScrollFocus() {
        return scrollFocus;
    }

    public ModelBatch getModelBatch() {
        return modelBatch;
    }

    public PerspectiveCamera getCamera() {
        return camera;
    }

    /** Sets the stage's camera. The camera must be configured properly or {@link #setViewport(float, float, boolean)} can be called
     * after the camera is set. {@link Sink#draw()} will call {@link Camera#update()} and use the {@link Camera#combined} matrix
     * for the SpriteBatch {@link SpriteBatch#setProjectionMatrix(com.badlogic.gdx.math.Matrix4) projection matrix}. */
    public void setCamera(PerspectiveCamera camera) {
        this.camera = camera;
    }

    /** Returns the root group which holds all actors in the stage. */
    public Group3d getRoot() {
        return root;
    }

    public Environment getEnvironment() {
        return environment;
    }

    @Override
    public void dispose() {
        clear();
        modelBatch.dispose();
    }
}