es.eucm.ead.editor.control.Controller.java Source code

Java tutorial

Introduction

Here is the source code for es.eucm.ead.editor.control.Controller.java

Source

/**
 * eAdventure is a research project of the
 *    e-UCM research group.
 *
 *    Copyright 2005-2014 e-UCM research group.
 *
 *    You can access a list of all the contributors to eAdventure at:
 *          http://e-adventure.e-ucm.es/contributors
 *
 *    e-UCM is a research group of the Department of Software Engineering
 *          and Artificial Intelligence at the Complutense University of Madrid
 *          (School of Computer Science).
 *
 *          CL Profesor Jose Garcia Santesmases 9,
 *          28040 Madrid (Madrid), Spain.
 *
 *          For more info please visit:  <http://e-adventure.e-ucm.es> or
 *          <http://www.e-ucm.es>
 *
 * ****************************************************************************
 *
 *  This file is part of eAdventure
 *
 *      eAdventure is free software: you can redistribute it and/or modify
 *      it under the terms of the GNU Lesser General Public License as published by
 *      the Free Software Foundation, either version 3 of the License, or
 *      (at your option) any later version.
 *
 *      eAdventure is distributed in the hope that it will be useful,
 *      but WITHOUT ANY WARRANTY; without even the implied warranty of
 *      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *      GNU Lesser General Public License for more details.
 *
 *      You should have received a copy of the GNU Lesser General Public License
 *      along with eAdventure.  If not, see <http://www.gnu.org/licenses/>.
 */
package es.eucm.ead.editor.control;

import com.badlogic.gdx.Files;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.files.FileHandle;
import com.badlogic.gdx.graphics.glutils.ShapeRenderer;
import com.badlogic.gdx.scenes.scene2d.Group;
import com.badlogic.gdx.scenes.scene2d.InputEvent;
import com.badlogic.gdx.scenes.scene2d.InputListener;
import com.badlogic.gdx.utils.reflect.ClassReflection;
import com.badlogic.gdx.utils.reflect.ReflectionException;
import es.eucm.ead.editor.assets.ApplicationAssets;
import es.eucm.ead.editor.assets.EditorGameAssets;
import es.eucm.ead.editor.control.actions.ArgumentsValidationException;
import es.eucm.ead.editor.control.actions.EditorActionException;
import es.eucm.ead.editor.control.appdata.ReleaseInfo;
import es.eucm.ead.editor.control.background.BackgroundExecutor;
import es.eucm.ead.editor.control.commands.Command;
import es.eucm.ead.editor.control.engine.EditorEngineInitializer;
import es.eucm.ead.editor.control.engine.Engine;
import es.eucm.ead.editor.control.pastelisteners.BehaviorCopyListener;
import es.eucm.ead.editor.control.pastelisteners.ModelEntityCopyListener;
import es.eucm.ead.editor.control.pastelisteners.TextCopyListener;
import es.eucm.ead.editor.control.workers.WorkerExecutor;
import es.eucm.ead.editor.indexes.ControllerIndex;
import es.eucm.ead.editor.model.Model;
import es.eucm.ead.editor.model.Q;
import es.eucm.ead.editor.platform.Platform;
import es.eucm.ead.editor.view.builders.ViewBuilder;
import es.eucm.ead.engine.EngineInitializer;
import es.eucm.ead.schema.components.behaviors.Behavior;
import es.eucm.ead.schema.entities.ModelEntity;

import java.util.HashMap;
import java.util.Map;

/**
 * Mediator and main controller of the editor's functionality
 * 
 */
public class Controller {

    /**
     * Singletion shaperenderer, shared across the editor
     */
    private ShapeRenderer shapeRenderer;

    /**
     * Game model managed by the editor.
     */
    private Model model;

    /**
     * Platform dependent functionality
     */
    private Platform platform;

    /**
     * Asset manager used for internal's editor assets.
     */
    private ApplicationAssets applicationAssets;

    /**
     * Asset manager for the current openend game's project.
     */
    private EditorGameAssets editorGameAssets;

    protected Views views;

    private Actions actions;

    /**
     * Manages editor preferences
     */
    private Preferences preferences;

    /**
     * Manage editor's command history.
     */
    private Commands commands;

    /**
     * Manage keyboard mappings to editor's functionality
     */
    private ShortcutsMap shortcutsMap;

    private Clipboard clipboard;

    /**
     * Info about the version and release type of the application. Used for
     * checking updates
     */
    private ReleaseInfo releaseInfo;

    private Tracker tracker;

    private Templates templates;

    private BackgroundExecutor backgroundExecutor;

    private WorkerExecutor workerExecutor;

    private DownloadManager downloadManager;

    private LibraryManager libraryManager;

    private Engine engine;

    private Map<Class, ControllerIndex> indexes;

    public Controller(Platform platform, Files files, Group viewsContainer, Group modalsContainer) {
        this.shapeRenderer = new ShapeRenderer();
        this.platform = platform;
        this.applicationAssets = createApplicationAssets(files);
        this.editorGameAssets = new EditorGameAssets(files, platform.getImageUtils());
        this.templates = new Templates(this);
        this.model = new Model(editorGameAssets);
        this.commands = new Commands(model);
        this.views = createViews(viewsContainer, modalsContainer);
        this.clipboard = new Clipboard(Gdx.app.getClipboard(), this, editorGameAssets);
        this.actions = new Actions(this);
        this.backgroundExecutor = new BackgroundExecutor();
        this.workerExecutor = new WorkerExecutor(this);
        this.downloadManager = new DownloadManager(this);
        this.libraryManager = new LibraryManager(this);
        this.preferences = applicationAssets.loadPreferences();
        // Get the release info from editor assets
        this.releaseInfo = applicationAssets.loadReleaseInfo();
        this.shortcutsMap = new ShortcutsMap(this);
        this.engine = new Engine(this);
        engine.init(buildEngineInitializer());
        setTracker(viewsContainer, modalsContainer);
        setClipboard();
        loadPreferences();
        indexes = new HashMap<Class, ControllerIndex>();
        Q.setController(this);

        boolean firstRun = preferences.getBoolean(Preferences.FIRST_TIME_RUN, true);
        if (firstRun) {
            preferences.putBoolean(Preferences.FIRST_TIME_RUN, false);
            initFirstRun();
        }
    }

    private void initFirstRun() {
        String defaultProjectsFolder = platform.getDefaultProjectsFolder();
        if (defaultProjectsFolder != null) {
            FileHandle projects = editorGameAssets.absolute(defaultProjectsFolder);
            if (!projects.exists()) {
                projects.mkdirs();
            }

            String noMedia = ".nomedia";
            FileHandle noMediaFile = projects.child(noMedia);
            if (!noMediaFile.exists()) {
                noMediaFile.writeString("", false);
            }

            FileHandle library = editorGameAssets.absolute(platform.getLibraryFolder());
            if (!library.exists()) {
                library.mkdirs();
            }

            noMediaFile = library.child(noMedia);
            if (!noMediaFile.exists()) {
                noMediaFile.writeString("", false);
            }
        }
    }

    protected EngineInitializer buildEngineInitializer() {
        return new EditorEngineInitializer(this);
    }

    protected ApplicationAssets createApplicationAssets(Files files) {
        return new ApplicationAssets(files);
    }

    protected Views createViews(Group viewsContainer, Group modalsContainer) {
        return new Views(this, viewsContainer, modalsContainer);
    }

    private void setClipboard() {
        clipboard.registerCopyListener(ModelEntity.class, new ModelEntityCopyListener(this));
        clipboard.registerCopyListener(Behavior.class, new BehaviorCopyListener(this));
        clipboard.registerCopyListener(String.class, new TextCopyListener(this));
    }

    private void setTracker(Group viewsContainer, Group modalsContainer) {
        this.tracker = platform.createTracker(this);
        tracker.setEnabled(preferences.getBoolean(Preferences.TRACKING_ENABLED, false));
        tracker.startSession();
        InputListener buttonsPressed = new InputListener() {
            @Override
            public boolean touchDown(InputEvent event, float x, float y, int pointer, int button) {
                if (event.getTarget().getName() != null) {
                    tracker.buttonPressed(event.getTarget().getName());
                }
                return super.touchDown(event, x, y, pointer, button);
            }
        };

        viewsContainer.addCaptureListener(buttonsPressed);
        modalsContainer.addCaptureListener(buttonsPressed);
    }

    /**
     * Process preferences concerning the controller
     */
    protected void loadPreferences() {
        String language = preferences.getString(Preferences.EDITOR_LANGUAGE);
        setLanguage("".equals(language) || language == null ? platform.getLocale() : language);
    }

    public ShapeRenderer getShapeRenderer() {
        return shapeRenderer;
    }

    public Model getModel() {
        return model;
    }

    public EditorGameAssets getEditorGameAssets() {
        return editorGameAssets;
    }

    public ApplicationAssets getApplicationAssets() {
        return applicationAssets;
    }

    public Platform getPlatform() {
        return platform;
    }

    public Preferences getPreferences() {
        return preferences;
    }

    public Commands getCommands() {
        return commands;
    }

    public Actions getActions() {
        return actions;
    }

    public Views getViews() {
        return views;
    }

    public <T extends ViewBuilder> void view(Class<T> view) {
        views.setView(view);
    }

    public ShortcutsMap getShortcutsMap() {
        return shortcutsMap;
    }

    public Clipboard getClipboard() {
        return clipboard;
    }

    public Tracker getTracker() {
        return tracker;
    }

    public Templates getTemplates() {
        return templates;
    }

    public BackgroundExecutor getBackgroundExecutor() {
        return backgroundExecutor;
    }

    public WorkerExecutor getWorkerExecutor() {
        return workerExecutor;
    }

    public DownloadManager getDownloadManager() {
        return downloadManager;
    }

    public LibraryManager getLibraryManager() {
        return libraryManager;
    }

    public Engine getEngine() {
        return engine;
    }

    /**
     * Executes an editor action with the given name and arguments
     * 
     * @param actionClass
     *            the action class
     * @param args
     *            the arguments for the action
     */
    public boolean action(Class actionClass, Object... args) {
        try {
            return actions.perform(actionClass, args);
        } catch (ClassCastException e) {
            throw new EditorActionException(getErrorMessage(actionClass, args), e);
        } catch (NullPointerException e) {
            throw new EditorActionException(getErrorMessage(actionClass, args), e);
        } catch (ArgumentsValidationException e) {
            Gdx.app.error("Controller", "Invalid arguments exception for " + actionClass, e);
        }
        return false;
    }

    private String getErrorMessage(Class actionClass, Object... args) {
        String message = "Something went wrong when executing action \n" + actionClass + " with arguments \n{";

        for (int i = 0; i < args.length; i++) {
            Object object = args[i];
            message += " \n\t" + (object == null ? "null" : object.toString());
            if (i < args.length - 1) {
                message += ", ";
            }
        }
        message += "\n}\nPerhaps the number of arguments is not correct or these are not valid";
        return message;
    }

    /**
     * Executes a command, an takes care of notifying to all model listeners all
     * the changes performed by it
     * 
     * @param command
     *            the command
     */
    public void command(Command command) {
        commands.command(command);
    }

    public String getLoadingPath() {
        return editorGameAssets.getLoadingPath();
    }

    public void setLanguage(String language) {
        getApplicationAssets().getI18N().setLang(language);
        getEditorGameAssets().getI18N().setLang(language);
        views.reinitializeAllViews();
        preferences.putString(Preferences.EDITOR_LANGUAGE, language);
    }

    /**
     * @return The object with all information related to the current
     *         installation
     */
    public ReleaseInfo getReleaseInfo() {
        return releaseInfo;
    }

    /**
     * Returns the version of the application (e.g. 2.0.0). Needed for setting
     * {@link es.eucm.ead.schema.editor.components.Versions#appVersion} when the
     * game is created and saved.
     * 
     * See {@link es.eucm.ead.editor.assets.ApplicationAssets#loadReleaseInfo()}
     * and ReleaseInfoTest for more details
     * 
     * @return The version number of the application (e.g. "2.0.0").
     */
    public String getAppVersion() {
        return releaseInfo.getAppVersion();
    }

    /**
     * Returns the path that points to the engine-with-dependencies.jar file
     * used to export games as jar files. It is read from release.json. Can be a
     * relative or absolute path
     * 
     * @return The path to the engine jar (e.g. "libs/engine.jar")
     */
    public String getEngineLibPath() {
        return releaseInfo.getEngineLibPath();
    }

    /**
     * Returnst the index of the given class
     */
    public <T extends ControllerIndex> T getIndex(Class<T> indexClass) {
        ControllerIndex controllerIndex = indexes.get(indexClass);
        if (controllerIndex == null) {
            try {
                controllerIndex = ClassReflection.newInstance(indexClass);
                controllerIndex.initialize(this);
                indexes.put(indexClass, controllerIndex);
            } catch (ReflectionException e) {
                Gdx.app.error("Model", "Impossible to create index " + indexClass);
            }
        }
        return (T) controllerIndex;
    }

    /**
     * The editor is exiting. Perform all operations before finalizing the
     * editor completely
     */
    public void exit() {
        applicationAssets.dispose();
        editorGameAssets.dispose();
        shapeRenderer.dispose();
        tracker.endSession();
        preferences.flush();
    }

    /**
     * The controller checks and updates pending tasks (e.g., state of
     * background tasks)
     * 
     * @return true if is done loading
     */
    public boolean act(float delta) {
        editorGameAssets.update();
        applicationAssets.update();
        backgroundExecutor.act();
        workerExecutor.act();
        engine.update(delta);

        if (!editorGameAssets.isDoneLoading() || !applicationAssets.isDoneLoading() || workerExecutor.isWorking()
                || !backgroundExecutor.isDone()) {
            Gdx.graphics.requestRendering();
            return false;
        }

        return true;
    }

}