com.uwsoft.editor.gdx.sandbox.SandboxInputAdapter.java Source code

Java tutorial

Introduction

Here is the source code for com.uwsoft.editor.gdx.sandbox.SandboxInputAdapter.java

Source

/*
 * ******************************************************************************
 *  * Copyright 2015 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.uwsoft.editor.gdx.sandbox;

import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.Input;
import com.badlogic.gdx.InputAdapter;
import com.badlogic.gdx.scenes.scene2d.Actor;
import com.badlogic.gdx.scenes.scene2d.InputEvent;
import com.badlogic.gdx.scenes.scene2d.utils.Align;
import com.badlogic.gdx.scenes.scene2d.utils.ClickListener;
import com.uwsoft.editor.controlles.flow.FlowActionEnum;
import com.uwsoft.editor.gdx.actors.SelectionRectangle;
import com.uwsoft.editor.renderer.actor.IBaseItem;

import java.awt.*;

/**
 * Adds listeners to everything sandbox related, including
 * items, entire scene, mouse, keys e.g.
 * Communicates user actions/intentions to Sandbox or UAC
 *
 * @author azakhary
 */
public class SandboxInputAdapter extends InputAdapter {

    private Sandbox sandbox;

    private float lastX = 0;
    private float lastY = 0;

    public SandboxInputAdapter(Sandbox sandbox) {
        this.sandbox = sandbox;
    }

    /** When item is touched, managing selections and preparing to drag selection */
    private boolean itemTouchDown(IBaseItem item, InputEvent event, float x, float y, int button) {
        // Making sure we have fresh VO data
        item.updateDataVO();

        // If currently panning do nothing regarding this item, panning will take over
        if (sandbox.cameraPanOn) {
            return false;
        }

        // if shift is pressed we are in add/remove selection mode
        if (Gdx.input.isKeyPressed(Input.Keys.SHIFT_LEFT)) {
            if (sandbox.getSelector().getCurrentSelection().get(item) != null) {
                // item was selected, so we need to release it
                sandbox.getSelector().releaseSelection(item);
            } else {
                // item was not selected, adding it to selection
                sandbox.getSelector().setSelection(item, false);
            }
        } else {
            if (item.isLockedByLayer()) {
                // this is considered empty space click and thus should release all selections
                sandbox.getSelector().clearSelections();
            } else {
                // select this item and remove others from selection
                sandbox.getSelector().setSelection(item, true);
            }
        }

        // remembering local touch position for each of selected items, if planning to drag
        for (SelectionRectangle value : sandbox.getSelector().getCurrentSelection().values()) {
            value.setTouchDiff(event.getStageX() - value.getHostAsActor().getX(),
                    event.getStageY() - value.getHostAsActor().getY());
        }

        // remembering that item was touched
        sandbox.isItemTouched = true;

        // pining UI to update current item properties data
        sandbox.getUIStage().updateCurrentItemState();

        return true;
    }

    private void itemTouchUp(IBaseItem item, InputEvent event, float x, float y, int button) {

        sandbox.getSelector().flushAllSelectedItems();

        // if panning was taking place - do nothing else. (other touch up got this)
        if (sandbox.cameraPanOn) {
            return;
        }

        if (button == Input.Buttons.RIGHT) {
            // if right clicked on an item, drop down for current selection
            sandbox.showDropDown(event.getStageX(), event.getStageY());
        }

        // re-show all selection rectangles as clicking/dragging is finished
        for (SelectionRectangle value : sandbox.getSelector().getCurrentSelection().values()) {
            value.show();
        }

        if (sandbox.dirty) {
            sandbox.saveSceneCurrentSceneData();
        }
        sandbox.isItemTouched = false;
        sandbox.dirty = false;

        // pining UI to update current item properties data
        sandbox.getUIStage().updateCurrentItemState();
    }

    private void itemDoubleClick(IBaseItem item, InputEvent event, float x, float y, int button) {
        sandbox.enterIntoComposite();
        sandbox.flow.setPendingHistory(sandbox.getCurrentScene().getDataVO(), FlowActionEnum.GET_INTO_COMPOSITE);
        sandbox.flow.applyPendingAction();
    }

    private void itemTouchDragged(IBaseItem item, InputEvent event, float x, float y) {

        // if there is no resizing going on, the item was touched,
        // the button is in and we are dragging... well you can probably be safe about saying - we do.
        if (sandbox.isItemTouched && !sandbox.isResizing && Gdx.input.isButtonPressed(Input.Buttons.LEFT)) {
            sandbox.dirty = true;

            // Selection rectangles should move and follow along
            for (SelectionRectangle value : sandbox.getSelector().getCurrentSelection().values()) {
                float[] diff = value.getTouchDiff();
                value.getHostAsActor().setX(event.getStageX() - diff[0]);
                value.getHostAsActor().setY(event.getStageY() - diff[1]);
                value.hide();
            }
        }

        // pining UI to update current item properties data
        sandbox.getUIStage().updateCurrentItemState();
    }

    private boolean sandboxMouseScrolled(float x, float y, float amount) {
        // well, duh
        if (amount == 0)
            return false;

        // if item is currently being held with mouse (touched in but not touched out)
        // mouse scroll should rotate the selection around it's origin
        if (sandbox.isItemTouched) {
            for (SelectionRectangle value : sandbox.getSelector().getCurrentSelection().values()) {
                float degreeAmmount = 1;
                if (amount < 0)
                    degreeAmmount = -1;
                // And if shift is pressed, the rotation amount is bigger
                if (Gdx.input.isKeyPressed(Input.Keys.SHIFT_LEFT)) {
                    degreeAmmount = degreeAmmount * 30;
                }
                value.getHostAsActor().rotateBy(degreeAmmount);
                value.update();
            }
            sandbox.dirty = true;
        }
        return false;
    }

    private boolean sandboxTouchDown(InputEvent event, float x, float y, int button) {
        // setting key and scroll focus on main area
        sandbox.getUIStage().setKeyboardFocus();
        sandbox.getUIStage().setScrollFocus(sandbox.getSandboxStage().mainBox);
        sandbox.getSandboxStage().setKeyboardFocus();

        // if there was a drop down remove it
        // TODO: this is job for front UI to figure out
        sandbox.getUIStage().mainDropDown.hide();

        switch (button) {
        case Input.Buttons.MIDDLE:
            // if middle button is pressed - PAN the scene
            sandbox.enablePan();
            break;
        case Input.Buttons.LEFT:
            boolean setOpacity = false;

            //TODO: Anyone can explain what was the purpose of this?
            if (!Gdx.input.isKeyPressed(Input.Keys.SPACE)) {
                setOpacity = true;
            }

            // preparing selection tool rectangle to follow mouse
            sandbox.prepareSelectionRectangle(x, y, setOpacity);

            break;
        }
        return !sandbox.isItemTouched;
    }

    private void sandboxTouchUp(InputEvent event, float x, float y, int button) {

        if (button == Input.Buttons.RIGHT) {
            // if clicked on empty space, selections need to be cleared
            sandbox.getSelector().clearSelections();

            // show default dropdown
            if (sandbox.showDropDown(x, y)) {
                return;
            }
        }

        // Basically if panning but space is not pressed, stop panning.? o_O
        // TODO: seriously this needs to be figured out, I am not sure we need it
        if (sandbox.cameraPanOn) {
            sandbox.cameraPanOn = Gdx.input.isKeyPressed(Input.Keys.SPACE);
            return;
        }

        // selection is complete, this will check for what get caught in selection rect, and select 'em
        sandbox.selectionComplete();
    }

    private void sandboxDoubleClick(InputEvent event, float x, float y) {
        // if empty space is double clicked, then get back into previous composite
        // TODO: do not do if we are on root item ( this is somehow impossible to implement o_O )
        sandbox.enterIntoPrevComposite();
        sandbox.flow.setPendingHistory(sandbox.getCurrentScene().getDataVO(), FlowActionEnum.GET_OUT_COMPOSITE);
        sandbox.flow.applyPendingAction();
    }

    private void sandboxTouchDragged(InputEvent event, float x, float y) {
        // if resizing is in progress we are not dealing with this
        if (sandbox.isResizing)
            return;

        if (sandbox.cameraPanOn) {
            // if panning, then just move camera
            float currX = sandbox.getSandboxStage().getCamera().position.x + (lastX - Gdx.input.getX());
            float currY = sandbox.getSandboxStage().getCamera().position.y + (Gdx.input.getY() - lastY);

            sandbox.getSandboxStage().getCamera().position.set(currX, currY, 0);

            lastX = Gdx.input.getX();
            lastY = Gdx.input.getY();
        } else {
            // else - using selection tool
            sandbox.isUsingSelectionTool = true;
            sandbox.getSandboxStage().selectionRec.setWidth(x - sandbox.getSandboxStage().selectionRec.getX());
            sandbox.getSandboxStage().selectionRec.setHeight(y - sandbox.getSandboxStage().selectionRec.getY());
        }
    }

    private boolean sandboxKeyDown(int keycode) {
        // the amount of pixels by which to move item if moving
        float deltaMove = 1;

        // if control is pressed then z index is getting modified
        // TODO: key pressed 0 for unckown, should be removed?
        // TODO: need to make sure OSX Command button works too.

        if (Gdx.input.isKeyPressed(Input.Keys.CONTROL_LEFT) || Gdx.input.isKeyPressed(0)) {
            if (keycode == Input.Keys.UP) {
                // going to front of next item in z-index ladder
                sandbox.itemControl.itemZIndexChange(sandbox.getSelector().getCurrentSelection(), true);
            }
            if (keycode == Input.Keys.DOWN) {
                // going behind the next item in z-index ladder
                sandbox.itemControl.itemZIndexChange(sandbox.getSelector().getCurrentSelection(), false);
            }
            if (keycode == Input.Keys.A) {
                // Ctrl+A means select all
                sandbox.getSelector().selectAllItems();
            }
            // Aligning Selections
            if (keycode == Input.Keys.NUM_1 && Gdx.input.isKeyPressed(Input.Keys.CONTROL_LEFT)) {
                sandbox.getSelector().alignSelections(Align.top);
            }
            if (keycode == Input.Keys.NUM_2 && Gdx.input.isKeyPressed(Input.Keys.CONTROL_LEFT)) {
                sandbox.getSelector().alignSelections(Align.left);
            }
            if (keycode == Input.Keys.NUM_3 && Gdx.input.isKeyPressed(Input.Keys.CONTROL_LEFT)) {
                sandbox.getSelector().alignSelections(Align.bottom);
            }
            if (keycode == Input.Keys.NUM_4 && Gdx.input.isKeyPressed(Input.Keys.CONTROL_LEFT)) {
                sandbox.getSelector().alignSelections(Align.right);
            }

            return true;
        }

        if (Gdx.input.isKeyPressed(Input.Keys.SHIFT_LEFT)) {
            // if shift is pressed, move items by 20 pixels instead of one
            deltaMove = 20; //pixels
        }

        if (keycode == Input.Keys.UP) {
            // moving UP
            sandbox.getSelector().moveSelectedItemsBy(0, deltaMove);
        }
        if (keycode == Input.Keys.DOWN) {
            // moving down
            sandbox.getSelector().moveSelectedItemsBy(0, -deltaMove);
        }
        if (keycode == Input.Keys.LEFT) {
            // moving left
            sandbox.getSelector().moveSelectedItemsBy(-deltaMove, 0);
        }
        if (keycode == Input.Keys.RIGHT) {
            //moving right
            sandbox.getSelector().moveSelectedItemsBy(deltaMove, 0);
        }

        // if space is pressed, that means we are going to pan, so set cursor accordingly
        // TODO: this pan is kinda different from what happens when you press middle button, so things need to merge right
        if (keycode == Input.Keys.SPACE && !sandbox.isItemTouched && !sandbox.isUsingSelectionTool) {
            sandbox.getSandboxStage().setCursor(Cursor.HAND_CURSOR);
            sandbox.cameraPanOn = true;
        }

        return true;
    }

    private boolean sandboxKeyUp(int keycode) {
        if (keycode == Input.Keys.DEL) {
            // delete selected item
            sandbox.getSelector().removeCurrentSelectedItems();
        }
        if (keycode == Input.Keys.SPACE) {
            // if pan mode is disabled set cursor back
            // TODO: this should go to sandbox as well
            sandbox.getSandboxStage().setCursor(Cursor.DEFAULT_CURSOR);
            sandbox.cameraPanOn = false;
        }
        return true;
    }

    public void initItemListeners(final IBaseItem eventItem) {
        ClickListener listener = new ClickListener() {

            public boolean touchDown(InputEvent event, float x, float y, int pointer, int button) {
                super.touchDown(event, x, y, pointer, button);

                return itemTouchDown(eventItem, event, x, y, button);
            }

            public void touchUp(InputEvent event, float x, float y, int pointer, int button) {
                super.touchUp(event, x, y, pointer, button);

                itemTouchUp(eventItem, event, x, y, button);

                if (getTapCount() == 2) {
                    // this is double click
                    itemDoubleClick(eventItem, event, x, y, button);
                }
            }

            public void touchDragged(InputEvent event, float x, float y, int pointer) {
                itemTouchDragged(eventItem, event, x, y);
            }
        };

        // tap count interval to correctly manage double clicks
        // if longer then 0.5 second it's not double click
        listener.setTapCountInterval(0.5f);

        // finally adding this huge listener
        ((Actor) eventItem).addListener(listener);
    }

    public void initSandboxEvents() {
        ClickListener listener = new ClickListener() {

            public boolean scrolled(InputEvent event, float x, float y, int amount) {
                return sandboxMouseScrolled(x, y, amount);
            }

            public boolean touchDown(InputEvent event, float x, float y, int pointer, int button) {
                super.touchDown(event, x, y, pointer, button);

                lastX = Gdx.input.getX();
                lastY = Gdx.input.getY();

                return sandboxTouchDown(event, x, y, button);
            }

            public void touchUp(InputEvent event, float x, float y, int pointer, int button) {
                super.touchUp(event, x, y, pointer, button);

                sandboxTouchUp(event, x, y, button);

                if (getTapCount() == 2 && button == Input.Buttons.LEFT) {
                    sandboxDoubleClick(event, x, y);
                }
            }

            public void touchDragged(InputEvent event, float x, float y, int pointer) {
                sandboxTouchDragged(event, x, y);
            }

            public boolean keyDown(InputEvent event, int keycode) {

                return sandboxKeyDown(keycode);

            }

            public boolean keyUp(InputEvent event, int keycode) {
                return sandboxKeyUp(keycode);
            }
        };

        sandbox.getSandboxStage().addListener(listener);

        listener.setTapCountInterval(0.5f);

        ClickListener transformationListeners = new ClickListener() {

            public boolean touchDown(InputEvent event, float x, float y, int pointer, int button) {
                if (sandbox.currTransformHost != null && sandbox.currTransformType >= 0) {
                    sandbox.isResizing = true;
                    sandbox.transformationHandler.setTransforming(sandbox.currTransformType,
                            (Actor) sandbox.currTransformHost);
                }
                return super.touchDown(event, x, y, pointer, button);
            }

            public void touchUp(InputEvent event, float x, float y, int pointer, int button) {
                super.touchUp(event, x, y, pointer, button);

                if (sandbox.transformationHandler.isResizing()) {

                }
                if (sandbox.isResizing == true && sandbox.transformationHandler.isResizing()) {
                    ((IBaseItem) sandbox.transformationHandler.getHost()).updateDataVO();
                }
                sandbox.isResizing = false;

                sandbox.transformationHandler.clear();
                sandbox.currTransformHost = null;
                sandbox.getSandboxStage().setCursor(Cursor.DEFAULT_CURSOR);
            }

            public void touchDragged(InputEvent event, float x, float y, int pointer) {
                if (!sandbox.isResizing) {
                    return;
                }

                sandbox.transformationHandler.touchDragged(event, x, y);

                sandbox.getUIStage().updateCurrentItemState();

                SelectionRectangle selectionRectangle = sandbox.getSelector().getCurrentSelection()
                        .get(sandbox.transformationHandler.getHost());

                //TODO: sometimes it is null, find out why
                if (selectionRectangle != null) {
                    selectionRectangle.update();
                }
            }
        };

        // add the listener
        sandbox.getSandboxStage().addListener(transformationListeners);
    }
}