com.mbrlabs.mundus.tools.RotateTool.java Source code

Java tutorial

Introduction

Here is the source code for com.mbrlabs.mundus.tools.RotateTool.java

Source

/*
 * Copyright (c) 2016. 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.mbrlabs.mundus.tools;

import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.Input;
import com.badlogic.gdx.graphics.Color;
import com.badlogic.gdx.graphics.g3d.Material;
import com.badlogic.gdx.graphics.g3d.Model;
import com.badlogic.gdx.graphics.g3d.ModelBatch;
import com.badlogic.gdx.graphics.g3d.ModelInstance;
import com.badlogic.gdx.graphics.g3d.Shader;
import com.badlogic.gdx.graphics.g3d.attributes.ColorAttribute;
import com.badlogic.gdx.graphics.glutils.ShapeRenderer;
import com.badlogic.gdx.math.Matrix4;
import com.badlogic.gdx.math.Quaternion;
import com.badlogic.gdx.math.Vector3;
import com.badlogic.gdx.scenes.scene2d.utils.Drawable;
import com.badlogic.gdx.utils.viewport.Viewport;
import com.mbrlabs.mundus.commons.scene3d.GameObject;
import com.mbrlabs.mundus.commons.utils.MathUtils;
import com.mbrlabs.mundus.core.Mundus;
import com.mbrlabs.mundus.core.project.ProjectContext;
import com.mbrlabs.mundus.core.project.ProjectManager;
import com.mbrlabs.mundus.history.CommandHistory;
import com.mbrlabs.mundus.shader.Shaders;
import com.mbrlabs.mundus.tools.picker.GameObjectPicker;
import com.mbrlabs.mundus.tools.picker.ToolHandlePicker;
import com.mbrlabs.mundus.utils.Fa;
import com.mbrlabs.mundus.utils.UsefulMeshs;

import org.lwjgl.opengl.GL11;

/**
 * Rotate tool for game objects
 *
 * @author Marcus Brummer, codengima
 * @version 30-09-2016
 */
public class RotateTool extends TransformTool {

    public static final String NAME = "Rotate Tool";

    private RotateHandle xHandle;
    private RotateHandle yHandle;
    private RotateHandle zHandle;
    private RotateHandle[] handles;

    private Matrix4 shapeRenderMat = new Matrix4();

    private Vector3 temp0 = new Vector3();
    private Vector3 temp1 = new Vector3();
    private Quaternion tempQuat = new Quaternion();

    private ShapeRenderer shapeRenderer;
    private ProjectContext projectContext;

    private TransformState state = TransformState.IDLE;
    private float lastRot = 0;

    public RotateTool(ProjectManager projectManager, GameObjectPicker goPicker, ToolHandlePicker handlePicker,
            Shader shader, ShapeRenderer shapeRenderer, ModelBatch batch, CommandHistory history) {
        super(projectManager, goPicker, handlePicker, shader, batch, history);
        this.shapeRenderer = shapeRenderer;
        this.projectContext = projectManager.current();
        xHandle = new RotateHandle(X_HANDLE_ID, COLOR_X);
        yHandle = new RotateHandle(Y_HANDLE_ID, COLOR_Y);
        zHandle = new RotateHandle(Z_HANDLE_ID, COLOR_Z);
        handles = new RotateHandle[] { xHandle, yHandle, zHandle };
    }

    @Override
    public void render() {
        super.render();

        GL11.glClear(GL11.GL_DEPTH_BUFFER_BIT);
        if (state == TransformState.IDLE && projectContext.currScene.currentSelection != null) {
            batch.begin(projectContext.currScene.cam);
            xHandle.render(batch);
            yHandle.render(batch);
            zHandle.render(batch);
            batch.end();
        } else if (projectContext.currScene.currentSelection != null) {
            Viewport vp = projectContext.currScene.viewport;

            GameObject go = projectContext.currScene.currentSelection;
            go.getTransform().getTranslation(temp0);
            Vector3 pivot = projectContext.currScene.cam.project(temp0);

            shapeRenderMat.setToOrtho2D(vp.getScreenX(), vp.getScreenY(), vp.getScreenWidth(),
                    vp.getScreenHeight());
            switch (state) {
            case TRANSFORM_X:
                shapeRenderer.begin(ShapeRenderer.ShapeType.Filled);
                shapeRenderer.setColor(Color.BLACK);
                shapeRenderer.setProjectionMatrix(shapeRenderMat);
                shapeRenderer.rectLine(pivot.x, pivot.y, Gdx.input.getX(),
                        Gdx.graphics.getHeight() - Gdx.input.getY(), 2);
                shapeRenderer.setColor(COLOR_X);
                shapeRenderer.circle(pivot.x, pivot.y, 7);
                shapeRenderer.end();
                break;
            case TRANSFORM_Y:
                shapeRenderer.begin(ShapeRenderer.ShapeType.Filled);
                shapeRenderer.setColor(Color.BLACK);
                shapeRenderer.setProjectionMatrix(shapeRenderMat);
                shapeRenderer.rectLine(pivot.x, pivot.y, Gdx.input.getX(),
                        Gdx.graphics.getHeight() - Gdx.input.getY(), 2);
                shapeRenderer.setColor(COLOR_Y);
                shapeRenderer.circle(pivot.x, pivot.y, 7);
                shapeRenderer.end();
                break;
            case TRANSFORM_Z:
                shapeRenderer.begin(ShapeRenderer.ShapeType.Filled);
                shapeRenderer.setColor(Color.BLACK);
                shapeRenderer.setProjectionMatrix(shapeRenderMat);
                shapeRenderer.rectLine(pivot.x, pivot.y, Gdx.input.getX(),
                        Gdx.graphics.getHeight() - Gdx.input.getY(), 2);
                shapeRenderer.setColor(COLOR_Z);
                shapeRenderer.circle(pivot.x, pivot.y, 7);
                shapeRenderer.end();
                break;
            default:
                break;
            }
        }

    }

    @Override
    public void act() {
        super.act();

        if (projectContext.currScene.currentSelection != null) {
            translateHandles();
            if (state == TransformState.IDLE) {
                return;
            }

            float angle = getCurrentAngle();
            float rot = angle - lastRot;

            boolean modified = false;
            if (null != state) {
                switch (state) {
                case TRANSFORM_X:
                    tempQuat.setEulerAngles(0, -rot, 0);
                    projectContext.currScene.currentSelection.rotate(tempQuat);
                    modified = true;
                    break;
                case TRANSFORM_Y:
                    tempQuat.setEulerAngles(-rot, 0, 0);
                    projectContext.currScene.currentSelection.rotate(tempQuat);
                    modified = true;
                    break;
                case TRANSFORM_Z:
                    tempQuat.setEulerAngles(0, 0, -rot);
                    projectContext.currScene.currentSelection.rotate(tempQuat);
                    modified = true;
                    break;
                default:
                    break;
                }
            }

            if (modified) {
                gameObjectModifiedEvent.setGameObject(projectContext.currScene.currentSelection);
                Mundus.postEvent(gameObjectModifiedEvent);
            }

            lastRot = angle;

        }
    }

    private float getCurrentAngle() {
        if (projectContext.currScene.currentSelection != null) {
            projectContext.currScene.currentSelection.getPosition(temp0);
            Vector3 pivot = projectContext.currScene.cam.project(temp0);
            Vector3 mouse = temp1.set(Gdx.input.getX(), Gdx.graphics.getHeight() - Gdx.input.getY(), 0);

            return MathUtils.angle(pivot.x, pivot.y, mouse.x, mouse.y);
        }

        return 0;
    }

    @Override
    public boolean touchDown(int screenX, int screenY, int pointer, int button) {
        super.touchDown(screenX, screenY, pointer, button);

        if (button == Input.Buttons.LEFT && projectContext.currScene.currentSelection != null) {
            lastRot = getCurrentAngle();

            RotateHandle handle = (RotateHandle) handlePicker.pick(handles, projectContext.currScene, screenX,
                    screenY);
            if (handle == null) {
                state = TransformState.IDLE;
                return false;
            }

            switch (handle.getId()) {
            case X_HANDLE_ID:
                state = TransformState.TRANSFORM_X;
                break;
            case Y_HANDLE_ID:
                state = TransformState.TRANSFORM_Y;
                break;
            case Z_HANDLE_ID:
                state = TransformState.TRANSFORM_Z;
                break;
            default:
                break;
            }
        }

        return false;
    }

    @Override
    public boolean touchUp(int screenX, int screenY, int pointer, int button) {
        state = TransformState.IDLE;
        return false;
    }

    @Override
    public void gameObjectSelected(GameObject selection) {
        super.gameObjectSelected(selection);
        scaleHandles();
        rotateHandles();
        translateHandles();
    }

    @Override
    protected void rotateHandles() {
        xHandle.rotationEuler.set(0, 90, 0);
        xHandle.applyTransform();
        yHandle.rotationEuler.set(90, 0, 0);
        yHandle.applyTransform();
        zHandle.rotationEuler.set(0, 0, 0);
        zHandle.applyTransform();
    }

    @Override
    protected void translateHandles() {
        final Vector3 pos = projectContext.currScene.currentSelection.getTransform().getTranslation(temp0);
        xHandle.position.set(pos);
        xHandle.applyTransform();
        yHandle.position.set(pos);
        yHandle.applyTransform();
        zHandle.position.set(pos);
        zHandle.applyTransform();
    }

    @Override
    protected void scaleHandles() {

        Vector3 pos = projectContext.currScene.currentSelection.getPosition(temp0);
        float scaleFactor = projectContext.currScene.cam.position.dst(pos) * 0.005f;
        xHandle.scale.set(scaleFactor, scaleFactor, scaleFactor);
        xHandle.applyTransform();

        yHandle.scale.set(scaleFactor, scaleFactor, scaleFactor);
        yHandle.applyTransform();

        zHandle.scale.set(scaleFactor, scaleFactor, scaleFactor);
        zHandle.applyTransform();
    }

    @Override
    public String getName() {
        return NAME;
    }

    @Override
    public Drawable getIcon() {
        return null;
    }

    @Override
    public String getIconFont() {
        return Fa.REFRESH;
    }

    @Override
    public void dispose() {
        super.dispose();
        xHandle.dispose();
        yHandle.dispose();
        zHandle.dispose();
    }

    /**
     *
     */
    private class RotateHandle extends ToolHandle {

        private Model model;
        private ModelInstance modelInstance;

        public RotateHandle(int id, Color color) {
            super(id);
            model = UsefulMeshs.torus(new Material(ColorAttribute.createDiffuse(color)), 20, 1f, 50, 50);
            modelInstance = new ModelInstance(model);
            modelInstance.materials.first().set(idAttribute);
            switch (id) {
            case X_HANDLE_ID:
                this.rotationEuler.y = 90;
                this.scale.x = 0.9f;
                this.scale.y = 0.9f;
                this.scale.z = 0.9f;
                break;
            case Y_HANDLE_ID:
                this.rotationEuler.x = 90;
                break;
            case Z_HANDLE_ID:
                this.rotationEuler.z = 90;
                this.scale.x = 1.1f;
                this.scale.y = 1.1f;
                this.scale.z = 1.1f;
                break;
            }
            // mi.transform.translate(0, 100, 0);
        }

        @Override
        public void render(ModelBatch batch) {
            batch.render(modelInstance);
        }

        @Override
        public void renderPick(ModelBatch modelBatch) {
            batch.render(modelInstance, Shaders.pickerShader);
        }

        @Override
        public void act() {

        }

        @Override
        public void applyTransform() {
            rotation.setEulerAngles(rotationEuler.y, rotationEuler.x, rotationEuler.z);
            modelInstance.transform.set(position, rotation, scale);
        }

        @Override
        public void dispose() {
            model.dispose();
        }
    }

}