package com.game.libgdx.roguelikeengine.ui; import java.util.LinkedList; import com.badlogic.gdx.Gdx; import com.badlogic.gdx.graphics.Color; import com.badlogic.gdx.graphics.Texture; import com.badlogic.gdx.graphics.g2d.BitmapFont; import com.badlogic.gdx.graphics.g2d.NinePatch; import com.badlogic.gdx.graphics.g2d.SpriteBatch; import com.badlogic.gdx.math.Rectangle; import com.badlogic.gdx.math.Vector2; public abstract class BaseButton implements IVisibleButton { public static final int BUTTON_STATE_DOWN = 0; public static final int BUTTON_STATE_UP = 1; protected LinkedList<ButtonAction> actionListeners = new LinkedList<ButtonAction>(); protected Rectangle screenRectangle; protected float relativeX; protected float relativeY; protected float width; protected float height; protected boolean mouseOver = false; protected int buttonState = BUTTON_STATE_UP; protected long timeMouseOver = 0L; protected BitmapFont font; private String text; private Color backgroundColor; private Color foregroundColor; private NinePatch ninePatcherBackground; protected Texture upTexture; protected Texture downTexture; private float textX; private float textY; protected boolean fitOnScreen = false; protected boolean wasMoved = false; public BaseButton(float relativeX, float relativeY, float width, float height) { this(relativeX, relativeY, width, height, true); } public BaseButton(float relativeX, float relativeY, float width, float height, boolean fitOnScreen) { this.relativeX = Math.max(0, Math.min(1, relativeX)); this.relativeY = Math.max(0, Math.min(1, relativeY)); this.width = width; this.height = height; this.fitOnScreen = fitOnScreen; handleResize(); this.upTexture = new Texture("UI/ninePatchButtonUp.png"); this.downTexture = new Texture("UI/ninePatchButtonDown.png"); this.ninePatcherBackground = new NinePatch(upTexture); } @Override public void handleResize() { float screenWidth = Gdx.graphics.getWidth(); float screenHeight = Gdx.graphics.getHeight(); float potentialX = screenWidth * this.relativeX; float potentialY = screenHeight * this.relativeY; if(fitOnScreen) { potentialX = Math.min(potentialX, screenWidth - width); potentialY = Math.min(potentialY, screenHeight - height); this.width = Math.min(this.width, screenWidth); this.height = Math.min(this.height, screenHeight); } this.screenRectangle = new Rectangle(potentialX, potentialY, this.width, this.height); this.wasMoved = false; } @Override public void setX(float x) { this.relativeX = x / Gdx.graphics.getWidth(); this.wasMoved = true; } @Override public void setY(float y) { this.relativeY = y / Gdx.graphics.getHeight(); this.wasMoved = true; } @Override public void addActionListener(ButtonAction bca) { actionListeners.add(bca); } @Override public void removeActionListener(ButtonAction bca) { actionListeners.remove(bca); } @Override public Vector2 getScreenCoordinates() { return new Vector2(this.screenRectangle.getX(), this.screenRectangle.getY()); } @Override public float getScreenX() { return this.screenRectangle.getX(); } @Override public float getScreenY() { return this.screenRectangle.getY(); } @Override public float getWidth() { return width; } @Override public float getHeight() { return height; } @Override public boolean getIsInScreenCoordinates(float x, float y) { return this.screenRectangle.contains(x, y); } @Override public boolean getIsInScreenCoordinates(Vector2 position) { return this.screenRectangle.contains(position); } @Override public boolean getIsMouseover() { return mouseOver; } @Override public float getRelativeX() { return this.relativeX; } @Override public float getRelativeY() { return this.relativeY; } @Override public boolean isDown() { return buttonState == BaseButton.BUTTON_STATE_DOWN; } @Override public void drawOnScreen(SpriteBatch batch) { if(backgroundColor != null && this.ninePatcherBackground != null) { this.ninePatcherBackground.draw(batch, getScreenX(), getScreenY(), width, height); } if(foregroundColor != null && text != "") { font.draw(batch, text, getScreenX() + textX, getScreenY() + textY); } onRender(batch); } @Override public void update() { if(wasMoved) handleResize(); float mouseX = Gdx.input.getX(); float invertedMouseY = Gdx.graphics.getHeight() - Gdx.input.getY(); boolean over = this.screenRectangle.contains(mouseX, invertedMouseY); if(!mouseOver && over) { mouseOver = true; for(ButtonAction ba : actionListeners) { ba.onMouseEnter(this); } timeMouseOver = 0; } else if(mouseOver && !over) { mouseOver = false; stateUp(); for(ButtonAction ba : actionListeners) { ba.onMouseExit(this); } } if(over) { timeMouseOver += 1L; if(Gdx.input.isTouched()) { stateDown(); } else if(buttonState == BaseButton.BUTTON_STATE_DOWN) { stateUp(); for(ButtonAction ba : actionListeners) { ba.onClicked(this); } } } onUpdate(); } public void stateDown() { buttonState = BaseButton.BUTTON_STATE_DOWN; if(backgroundColor != null) { this.ninePatcherBackground = new NinePatch(this.downTexture, backgroundColor); } else { this.ninePatcherBackground = new NinePatch(this.downTexture); } } public void stateUp() { buttonState = BaseButton.BUTTON_STATE_UP; if(backgroundColor != null) { this.ninePatcherBackground = new NinePatch(this.upTexture, backgroundColor); } else { this.ninePatcherBackground = new NinePatch(this.upTexture); } } @Override public String getText() { return text; } @Override public void setText(String text) { if(text != this.text) { this.text = text; { // setup font font = new BitmapFont(); while(font.getScaleX() > 0.1f && font.getBounds(text).width > width - 10) { font.setScale(font.getScaleX() - 0.1f); } } float textWidth = font.getBounds(text).width; textX = width * 0.5f - textWidth * 0.5f; float textHeight = font.getLineHeight() * font.getScaleY(); textY = height * 0.5f + textHeight * 0.5f; } } @Override public Color getBackgroundColor() { return this.backgroundColor; } @Override public void setBackgroundColor(Color color) { this.backgroundColor = color; if(this.buttonState == BUTTON_STATE_UP) { this.ninePatcherBackground = new NinePatch(upTexture, color); } else { this.ninePatcherBackground = new NinePatch(downTexture, color); } } @Override public Color getForegroundColor() { return this.foregroundColor; } @Override public void setForegroundColor(Color color) { this.foregroundColor = color; } public abstract void onUpdate(); public abstract void onRender(SpriteBatch batch); }