/* * ----------------------------------------------------------------------- * Copyright 2014 - Alistair Rutherford - www.netthreads.co.uk * ----------------------------------------------------------------------- * * 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.netthreads.libgdx.director; import aurelienribon.tweenengine.Tween; import com.badlogic.gdx.Gdx; import com.badlogic.gdx.graphics.GL20; import com.badlogic.gdx.graphics.g2d.SpriteBatch; import com.badlogic.gdx.scenes.scene2d.Actor; import com.badlogic.gdx.scenes.scene2d.Group; import com.badlogic.gdx.utils.Disposable; import com.badlogic.gdx.utils.viewport.StretchViewport; import com.badlogic.gdx.utils.viewport.Viewport; import com.google.inject.Singleton; import com.netthreads.libgdx.event.ActorEvent; import com.netthreads.libgdx.event.ActorEventObserver; import com.netthreads.libgdx.event.ActorEventSource; import com.netthreads.libgdx.scene.Scene; import com.netthreads.libgdx.tween.ActorAccessor; import com.netthreads.libgdx.tween.GroupAccessor; /** * Scene director. * * This class routes actor events around observers and updates the view. It also maintains global note of view width and * height. * */ @Singleton public class Director implements Disposable { private static final float DEFAULT_CLEAR_COLOUR_RED = 0.0f; private static final float DEFAULT_CLEAR_COLOUR_BLUE = 0.0f; private static final float DEFAULT_CLEAR_COLOUR_GREEN = 0.0f; private static final float DEFAULT_CLEAR_COLOUR_ALPHA = 1.0f; private ActorEventSource eventSource; private Viewport viewport; private Scene scene; private float scaleFactorX; private float scaleFactorY; private SpriteBatch spriteBatch; private float clearColourR = DEFAULT_CLEAR_COLOUR_RED; private float clearColourB = DEFAULT_CLEAR_COLOUR_BLUE; private float clearColourG = DEFAULT_CLEAR_COLOUR_GREEN; private float clearColourA = DEFAULT_CLEAR_COLOUR_ALPHA; private static final int DEFAULT_WIDTH = 320; private static final int DEFAULT_HEIGHT = 480; /** * Construct Director elements. * */ public Director() { scene = null; // This required Graphics context. spriteBatch = new SpriteBatch(); // Director maintains event source. eventSource = new ActorEventSource(); // These are scale factors for adjusting touch events to the actual size // of the view-port. scaleFactorX = 1; scaleFactorY = 1; // All scenes share the same viewport. viewport = null; // Set up tween default configuration. Tween.registerAccessor(Actor.class, new ActorAccessor()); Tween.registerAccessor(Group.class, new GroupAccessor()); } /** * Update main loop. * */ public void update() { // Update events. eventSource.update(); // Update View Gdx.gl.glClearColor(clearColourR, clearColourB, clearColourG, clearColourA); Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT); if (scene != null) { float delta = Gdx.graphics.getDeltaTime(); scene.act(delta); scene.draw(); } else { Gdx.app.log("Director", "WTF! - No scene"); } } /** * Set the current scene. * * @param scene */ public synchronized void setScene(Scene scene) { // If already active scene... if (this.scene != null) { // Exit stage left.. this.scene.exit(); } this.scene = scene; if (this.scene != null) { // Enter stage right.. this.scene.enter(); // NOTE: Route input events to the scene. Gdx.input.setInputProcessor(scene.getInputMultiplexer()); } } /** * Return currently running scene. * * @return The current scene view. */ public synchronized Scene getScene() { return scene; } /** * Return scene width. * * @return The width. */ public float getWidth() { return getViewport().getWorldWidth(); } /** * Return scene height. * * @return The height. */ public float getHeight() { return getViewport().getWorldHeight(); } /** * Set display width/height. * * We need to ensure this is done when a client application is created otherwise the default viewport will be used. * * @param width * @param height */ public void setWidthHeight(int width, int height) { if (viewport == null) { viewport = new StretchViewport(width, height); } if (scene != null) { viewport.update(width, height, true); } } /** * Adjust the scale factors for touch/mouse events to match the size of the stage. * * @param width * The new width. * @param height * The new height. */ public void resize(int width, int height) { setWidthHeight(width, height); float worldWidth = viewport.getWorldWidth(); float worldHeight = viewport.getWorldHeight(); scaleFactorX = (float) worldWidth / width; scaleFactorY = (float) worldHeight / height; } /** * Send event to observers. * * @param id * The event id. * @param actor * The associated actor. */ public void sendEvent(int id, Actor actor) { eventSource.sendEvent(id, actor, ActorEvent.DEFAULT_PRIORITY); } /** * Send event to observers. * * @param id * The event id. * @param actor * The associated actor. * @param priority * Adopt a priority value. Must be > 0. */ public void sendEvent(int id, Actor actor, int priority) { eventSource.sendEvent(id, actor, priority); } /** * Add event observer event handler. * * DO NOT PUT THIS INTO THE CONSTRUCTOR. IT MUST GO INTO THE "ENTER" HANDLER. * * @param observer * The event observer. */ public void registerEventHandler(ActorEventObserver observer) { eventSource.addObserver(observer); } /** * Remove event observer event handler. * * DO NOT FORGET TO PUT THIS INTO THE "EXIT" HANDLER IF YOU HAVE MATCHING "REGISTER" IN THE ENTER HANDLER. * * @param observer * The event observer. */ public void deregisterEventHandler(ActorEventObserver observer) { eventSource.removeObserver(observer); } /** * Clear all handlers. * */ public void clearEventHandlers() { // Clear all event subscriptions. eventSource.clear(); } /** * Return scale factor for touch/mouse events. * * @return The x scale factor. */ public float getScaleFactorX() { return scaleFactorX; } /** * Return scale factor for touch/mouse events. * * @return The y scale factor. */ public float getScaleFactorY() { return scaleFactorY; } public SpriteBatch getSpriteBatch() { return spriteBatch; } public void setSpriteBatch(SpriteBatch spriteBatch) { this.spriteBatch = spriteBatch; } @Override public void dispose() { spriteBatch.dispose(); } public void setEventSource(ActorEventSource eventSource) { this.eventSource = eventSource; } public void setClearColourR(float clearColourR) { this.clearColourR = clearColourR; } public void setClearColourB(float clearColourB) { this.clearColourB = clearColourB; } public void setClearColourG(float clearColourG) { this.clearColourG = clearColourG; } public void setClearColourA(float clearColourA) { this.clearColourA = clearColourA; } /** * We have to create a dummy viewport if one doesn't exist or things will crash. * * @return The current viewport. */ public Viewport getViewport() { if (viewport == null) { viewport = new StretchViewport(DEFAULT_WIDTH, DEFAULT_HEIGHT); } return viewport; } }