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 options = new LinkedList(); int currentOption = -1; String textCurrent = ""; int textPixelWidth = 0; float fontSize = 1.0f; List childrenElements = new LinkedList(); 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 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; } }