package Roguelike.UI; import Roguelike.Global; import Roguelike.Tiles.Point; import Roguelike.Util.Controls; import com.badlogic.gdx.Gdx; import com.badlogic.gdx.Input; import com.badlogic.gdx.math.Vector2; import com.badlogic.gdx.scenes.scene2d.Actor; import com.badlogic.gdx.scenes.scene2d.EventListener; import com.badlogic.gdx.scenes.scene2d.InputEvent; import com.badlogic.gdx.scenes.scene2d.InputListener; import com.badlogic.gdx.scenes.scene2d.ui.*; import com.badlogic.gdx.scenes.scene2d.utils.ClickListener; import com.badlogic.gdx.utils.Array; import com.badlogic.gdx.utils.Pools; /** * Created by Philip on 25-Feb-16. */ public class ButtonKeyboardHelper { public Array<Column> grid = new Array<Column>( ); public Actor cancel; public ScrollPane scrollPane; public int currentx; public int currenty; public int currentz; private Actor active; private float updateAccumulator; private boolean cleared = false; private boolean first = true; // ---------------------------------------------------------------------- public ButtonKeyboardHelper() { } // ---------------------------------------------------------------------- public ButtonKeyboardHelper( Actor cancel ) { this.cancel = cancel; add( cancel ); } // ---------------------------------------------------------------------- public void add( Actor actor ) { add(actor, 0); } // ---------------------------------------------------------------------- public void add( Actor... actors ) { int x = 0; int y = grid.size > 0 ? grid.get( 0 ).cells.get( grid.get( 0 ).cells.size - 1 ).y + 1 : 0; for (Actor a : actors) { add( a, x, y ); } } // ---------------------------------------------------------------------- public void add( Actor actor, int x ) { add(actor, x, grid.size > 0 ? grid.get( 0 ).cells.get( grid.get( 0 ).cells.size - 1 ).y + 1 : 0); } // ---------------------------------------------------------------------- public void add( Actor actor, int x, int y ) { Column column = null; for (int i = 0; i < grid.size; i++) { if (grid.get( i ).x == x) { column = grid.get( i ); break; } else if (grid.get( i ).x > x) { column = new Column(); column.x = x; grid.insert( i, column ); break; } } if (column == null) { column = new Column(); column.x = x; grid.add( column ); } Cell cell = null; for (int i = 0; i < column.cells.size; i++) { if (column.cells.get( i ).y == y) { cell = column.cells.get( i ); break; } else if (column.cells.get( i ).y > y) { cell = new Cell(); cell.y = y; column.cells.insert( i, cell ); break; } } if (cell == null) { cell = new Cell(); cell.y = y; column.cells.add( cell ); } cell.actors.add( actor ); if (first) { trySetCurrent( x, y, 0 ); first = false; } } // ---------------------------------------------------------------------- public Actor getCurrent() { return get( currentx, currenty, currentz ); } // ---------------------------------------------------------------------- public Actor get(int x, int y, int z) { return getColumn( x ).getCell( y ).getActor( z ); } // ---------------------------------------------------------------------- public Column getColumn(int x) { for (Column col : grid) { if (col.x == x) { return col; } else if (col.x > x) { return col; } } return grid.get( grid.size - 1 ); } // ---------------------------------------------------------------------- public void clear() { if (!cleared) { cleared = true; exit( getCurrent() ); } } // ---------------------------------------------------------------------- public void trySetCurrent(int x, int y, int z) { cleared = false; exit( getCurrent() ); currentx = x; currenty = y; currentz = z; currentx = getColumn( currentx ).x; currenty = getColumn( currentx ).getCell( currenty ).y; Cell cell = getColumn( currentx ).getCell( currenty ); currentz = cell.actors.indexOf( cell.getActor( currentz ), true ); Actor current = getCurrent(); enter( current ); if (scrollPane != null) { Vector2 stagePos = current.localToStageCoordinates( new Vector2( 0, 0 ) ); Vector2 relativePos = scrollPane.getWidget().stageToLocalCoordinates( stagePos ); scrollPane.scrollTo( relativePos.x, relativePos.y, current.getWidth(), current.getHeight() ); } } // ---------------------------------------------------------------------- public void update( float delta ) { updateAccumulator -= delta; if (updateAccumulator < 0) { updateAccumulator = 0.01f; if (active != null && active instanceof Slider) { Slider slider = (Slider)active; if ( Global.Controls.isKeyDown( Controls.Keys.LEFT ) ) { slider.setValue( slider.getValue() - slider.getStepSize() ); } else if ( Global.Controls.isKeyDown( Controls.Keys.RIGHT ) ) { slider.setValue( slider.getValue() + slider.getStepSize() ); } } } } // ---------------------------------------------------------------------- public boolean keyDown( int keycode ) { if (active != null) { if (active instanceof Slider) { Slider slider = (Slider)active; if ( Global.Controls.isKey( Controls.Keys.CANCEL, keycode ) || Global.Controls.isKey( Controls.Keys.ACCEPT, keycode ) ) { float val = slider.getValue(); touchUp( slider ); slider.setValue( val ); active = null; } else if ( Global.Controls.isKey( Controls.Keys.LEFT, keycode ) ) { slider.setValue( slider.getValue() - slider.getStepSize() ); } else if ( Global.Controls.isKey( Controls.Keys.RIGHT, keycode ) ) { slider.setValue( slider.getValue() + slider.getStepSize() ); } } else if (active instanceof SelectBox) { SelectBox selectBox = (SelectBox)active; if ( Global.Controls.isKey( Controls.Keys.CANCEL, keycode ) || Global.Controls.isKey( Controls.Keys.ACCEPT, keycode ) ) { selectBox.hideList(); active = null; } else if ( Global.Controls.isKey( Controls.Keys.UP, keycode ) ) { int newIndex = selectBox.getSelectedIndex() - 1; if (newIndex < 0) { newIndex = 0; } selectBox.setSelectedIndex( newIndex ); selectBox.hideList(); selectBox.showList(); } else if ( Global.Controls.isKey( Controls.Keys.DOWN, keycode ) ) { int newIndex = selectBox.getSelectedIndex() + 1; if (newIndex >= selectBox.getItems().size) { newIndex = selectBox.getItems().size-1; } selectBox.setSelectedIndex( newIndex ); selectBox.hideList(); selectBox.showList(); } } } else { if ( Global.Controls.isKey( Controls.Keys.CANCEL, keycode ) ) { if (cancel != null) { pressButton( cancel ); } } else if ( Global.Controls.isKey( Controls.Keys.ACCEPT, keycode ) ) { Actor actor = getCurrent(); if ( actor instanceof Button ) { pressButton( actor ); } else if ( actor instanceof Slider ) { active = actor; Slider slider = (Slider)actor; float val = slider.getValue(); touchDown( active ); slider.setValue( val ); } else if ( actor instanceof SelectBox ) { active = actor; SelectBox selectBox = (SelectBox)active; selectBox.showList(); } } else if ( Global.Controls.isKey( Controls.Keys.LEFT, keycode ) ) { // check if move within cell if ( currentz > 0 ) { trySetCurrent( currentx, currenty, currentz - 1 ); } else { Column current = getColumn( currentx ); if ( current != grid.first() ) { int index = grid.indexOf( current, true ); Column prev = grid.get( index - 1 ); trySetCurrent( prev.x, currenty, 100 ); } } } else if ( Global.Controls.isKey( Controls.Keys.RIGHT, keycode ) ) { // check if move within cell Cell cell = getColumn( currentx ).getCell( currenty ); if ( currentz < cell.actors.size - 1 ) { trySetCurrent( currentx, currenty, currentz + 1 ); } else { Column current = getColumn( currentx ); if ( current != grid.first() ) { int index = grid.indexOf( current, true ); Column next = grid.get( index + 1 ); trySetCurrent( next.x, currenty, 0 ); } } } else if ( Global.Controls.isKey( Controls.Keys.UP, keycode ) ) { trySetCurrent( currentx, currenty - 1, currentz ); } else if ( Global.Controls.isKey( Controls.Keys.DOWN, keycode ) ) { trySetCurrent( currentx, currenty + 1, currentz ); } } return true; } // ---------------------------------------------------------------------- private boolean pressButton( Actor actor ) { for ( EventListener listener : actor.getListeners() ) { if (listener instanceof ClickListener) { ((ClickListener)listener).clicked( null, 0, 0 ); } } return true; } // ---------------------------------------------------------------------- private void enter( Actor actor ) { InputEvent event = new InputEvent(); event.setType(InputEvent.Type.enter); event.setPointer( -1 ); actor.fire(event); } // ---------------------------------------------------------------------- private void exit( Actor actor ) { InputEvent event = new InputEvent(); event.setType(InputEvent.Type.exit); event.setPointer( -1 ); actor.fire(event); } // ---------------------------------------------------------------------- private void touchDown( Actor actor ) { InputEvent event = new InputEvent(); event.setType(InputEvent.Type.touchDown); actor.fire(event); } // ---------------------------------------------------------------------- private void touchUp( Actor actor ) { InputEvent event = new InputEvent(); event.setType(InputEvent.Type.touchUp); actor.fire(event); } // ---------------------------------------------------------------------- private class Column { public int x; public Array<Cell> cells = new Array<Cell>( ); // ---------------------------------------------------------------------- public Cell getCell( int y ) { for (Cell cell : cells) { if (cell.y == y) { return cell; } else if ( cell.y > y ) { return cell; } } return cells.get( cells.size - 1 ); } } // ---------------------------------------------------------------------- private class Cell { public int y; public Array<Actor> actors = new Array<Actor>( ); // ---------------------------------------------------------------------- public Actor getActor( int z ) { if ( z >= actors.size ) { return actors.get( actors.size - 1 ); } return actors.get( z ); } } }