Renderer/src/main/java/electrosphere/renderer/ui/elements/StringCarousel.java
austin 20c0bff89d
All checks were successful
studiorailgun/Renderer/pipeline/head This commit looks good
refactor ui framework to use openglstate
2024-03-21 19:51:42 -04:00

334 lines
10 KiB
Java

package electrosphere.renderer.ui.elements;
import java.util.LinkedList;
import java.util.List;
import org.joml.Vector3f;
import electrosphere.engine.Globals;
import electrosphere.renderer.OpenGLState;
import electrosphere.renderer.RenderPipelineState;
import electrosphere.renderer.ui.DrawableElement;
import electrosphere.renderer.ui.Element;
import electrosphere.renderer.ui.FocusableElement;
import electrosphere.renderer.ui.MenuEventElement;
import electrosphere.renderer.ui.ValueElement;
import electrosphere.renderer.ui.events.Event;
import electrosphere.renderer.ui.events.FocusEvent;
import electrosphere.renderer.ui.events.MenuEvent;
import electrosphere.renderer.ui.events.ValueChangeEvent;
import electrosphere.renderer.ui.events.MenuEvent.MenuEventType;
import electrosphere.renderer.ui.font.Font;
import electrosphere.renderer.ui.font.FontUtils;
import electrosphere.renderer.ui.font.bitmapchar.BitmapCharacter;
public class StringCarousel implements DrawableElement, MenuEventElement, FocusableElement, ValueElement {
public int width = 1;
public int height = 1;
public int positionX = 0;
public int positionY = 0;
public int parentWidth = 1;
public int parentHeight = 1;
public boolean visible = false;
MenuEventCallback onMenuEventCallback;
ValueChangeEventCallback onValueChange;
boolean focused = false;
FocusEventCallback onFocusCallback;
FocusEventCallback onLoseFocusCallback;
List<String> options = new LinkedList<String>();
int currentOption = -1;
String textCurrent = "";
int textPixelWidth = 0;
float fontSize = 1.0f;
List<BitmapCharacter> childrenElements = new LinkedList<BitmapCharacter>();
Font font;
public StringCarousel(int x, int y, float fontSize){
this.positionX = x;
this.positionY = y;
this.width = 0;
this.font = Globals.fontManager.getFont("default");
this.height = (int)(font.getFontHeight() * fontSize);
this.fontSize = fontSize;
}
public void addOption(String option){
options.add(option);
if(currentOption == -1){
currentOption = 0;
setText(option);
if(onValueChange != null){
onValueChange.execute(new ValueChangeEvent(option));
}
}
}
public List<String> getOptions(){
return options;
}
public void removeOption(String option){
options.remove(option);
if(currentOption > options.size() - 1){
currentOption = options.size() - 1;
}
}
void generateLetters(){
childrenElements.clear();
int rollingOffset = 0;
for(int i = 0; i < textCurrent.length(); i++){
char toDraw = textCurrent.charAt(i);
Vector3f bitMapDimension = this.font.getDimensionOfCharacterDiscrete(toDraw);
BitmapCharacter newLetter = new BitmapCharacter(this.font,(int)(rollingOffset * fontSize) + positionX, positionY, (int)(bitMapDimension.x * fontSize), this.height, toDraw);
rollingOffset += (int)bitMapDimension.x;
childrenElements.add(newLetter);
}
}
public void setText(String text){
this.textCurrent = text;
textPixelWidth = 0;
for(int i = 0; i < text.length(); i++){
Vector3f bitMapDimension = this.font.getDimensionOfCharacterDiscrete(text.charAt(i));
textPixelWidth = textPixelWidth + (int)bitMapDimension.x;
}
generateLetters();
if(focused){
setColor(new Vector3f(1,0,0));
}
}
public void setColor(Vector3f color){
for(BitmapCharacter character : childrenElements){
character.setColor(color);
}
}
public String getText(){
return textCurrent;
}
@Override
public void draw(RenderPipelineState renderPipelineState, OpenGLState openGLState, int parentFramebufferPointer, int parentWidth, int parentHeight) {
for(DrawableElement child : childrenElements){
child.draw(renderPipelineState, openGLState, parentFramebufferPointer, parentWidth, parentHeight);
}
}
public int getWidth() {
int minX = -1;
int maxX = -1;
for(BitmapCharacter child : childrenElements){
if(minX == -1){
minX = child.getPositionX();
} else if(child.getPositionX() < minX){
minX = child.getPositionX();
}
if(maxX == -1){
maxX = child.getPositionX() + child.getWidth();
} else if(child.getPositionX() + child.getWidth() > maxX){
maxX = child.getPositionX() + child.getWidth();
}
}
if(minX == -1){
minX = 0;
}
if(maxX == -1){
maxX = 0;
}
return maxX - minX;
}
public int getHeight() {
int minY = -1;
int maxY = -1;
for(BitmapCharacter child : childrenElements){
if(minY == -1){
minY = child.getPositionY();
} else if(child.getPositionY() < minY){
minY = child.getPositionY();
}
if(maxY == -1){
maxY = child.getPositionY() + child.getHeight();
} else if(child.getPositionY() + child.getHeight() > maxY){
maxY = child.getPositionY() + child.getHeight();
}
}
if(minY == -1){
minY = 0;
}
if(maxY == -1){
maxY = 0;
}
return maxY - minY;
}
public int getPositionX() {
int minX = -1;
for(BitmapCharacter child : childrenElements){
if(minX == -1){
minX = child.getPositionX();
} else if(child.getPositionX() < minX){
minX = child.getPositionX();
}
}
if(minX == -1){
minX = 0;
}
return minX;
}
public int getPositionY() {
int minY = -1;
for(BitmapCharacter child : childrenElements){
if(minY == -1){
minY = child.getPositionY();
} else if(child.getPositionY() < minY){
minY = child.getPositionY();
}
}
if(minY == -1){
minY = 0;
}
return minY;
}
public boolean getVisible() {
return visible;
}
public void setWidth(int width) {
this.width = width;
}
public void setHeight(int height) {
this.height = height;
}
public void setPositionX(int posX) {
int deltaX = posX - this.positionX;
this.positionX = posX;
for(Element child : childrenElements){
child.setPositionX(child.getPositionX() + deltaX);
}
}
public void setPositionY(int posY) {
int deltaY = posY - this.positionY;
this.positionY = posY;
for(Element child : childrenElements){
child.setPositionY(child.getPositionY() + deltaY);
}
}
public void setVisible(boolean draw) {
this.visible = draw;
}
public void setParentWidth(int width){
parentWidth = width;
}
public void setParentHeight(int height){
this.parentHeight = height;
}
public boolean handleEvent(Event event){
boolean propagate = true;
if(event instanceof MenuEvent){
MenuEvent menuEvent = (MenuEvent)event;
if(onMenuEventCallback != null){
propagate = onMenuEventCallback.execute(menuEvent);
} else {
//default behavior
if(menuEvent.getType() == MenuEventType.INCREMENT){
propagate = false;
if(options.size() > 0){
currentOption++;
if(currentOption > options.size() - 1){
currentOption = 0;
}
String newOption = options.get(currentOption);
setText(newOption);
if(onValueChange != null){
onValueChange.execute(new ValueChangeEvent(newOption));
}
}
} else if(menuEvent.getType() == MenuEventType.DECREMENT){
propagate = false;
if(options.size() > 0){
currentOption--;
if(currentOption < 0){
currentOption = options.size() - 1;
}
String newOption = options.get(currentOption);
setText(newOption);
if(onValueChange != null){
onValueChange.execute(new ValueChangeEvent(newOption));
}
}
}
}
} else if(event instanceof FocusEvent){
FocusEvent focusEvent = (FocusEvent) event;
if(focusEvent.isFocused()){
this.focused = true;
if(onFocusCallback != null){
propagate = onFocusCallback.execute(focusEvent);
} else {
//default behavior
propagate = false;
setColor(new Vector3f(1,0,0));
}
} else {
this.focused = false;
if(onLoseFocusCallback != null){
propagate = onLoseFocusCallback.execute(focusEvent);
} else {
//default behavior
propagate = false;
setColor(new Vector3f(1,1,1));
}
}
}
return propagate;
}
@Override
public void setOnMenuEventCallback(MenuEventCallback callback) {
onMenuEventCallback = callback;
}
@Override
public void setOnValueChangeCallback(ValueChangeEventCallback callback) {
onValueChange = callback;
}
@Override
public boolean isFocused() {
return focused;
}
@Override
public void setOnFocus(FocusEventCallback callback) {
onFocusCallback = callback;
}
@Override
public void setOnLoseFocus(FocusEventCallback callback) {
onLoseFocusCallback = callback;
}
}