Renderer/src/main/java/electrosphere/renderer/ui/elements/Slider.java
2024-03-09 20:45:33 -05:00

342 lines
11 KiB
Java

package electrosphere.renderer.ui.elements;
import org.joml.Vector3f;
import electrosphere.engine.Globals;
import electrosphere.logger.LoggerInterface;
import electrosphere.renderer.debug.DebugRendering;
import electrosphere.renderer.model.Model;
import electrosphere.renderer.ui.ClickableElement;
import electrosphere.renderer.ui.DraggableElement;
import electrosphere.renderer.ui.DrawableElement;
import electrosphere.renderer.ui.FocusableElement;
import electrosphere.renderer.ui.MenuEventElement;
import electrosphere.renderer.ui.ValueElement;
import electrosphere.renderer.ui.events.ClickEvent;
import electrosphere.renderer.ui.events.DragEvent;
import electrosphere.renderer.ui.events.DragEvent.DragEventType;
import electrosphere.renderer.ui.events.Event;
import electrosphere.renderer.ui.events.FocusEvent;
import electrosphere.renderer.ui.events.MenuEvent;
import electrosphere.renderer.ui.events.ValueChangeEvent;
public class Slider implements ClickableElement, DraggableElement, FocusableElement, DrawableElement, MenuEventElement, 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;
boolean focused = false;
FocusEventCallback onFocusCallback;
FocusEventCallback onLoseFocusCallback;
DragEventCallback onDragStart;
DragEventCallback onDrag;
DragEventCallback onDragRelease;
ClickEventCallback onClick;
MenuEventCallback onMenuEvent;
ValueChangeEventCallback onValueChange;
float min = 0.0f;
float max = 1.0f;
float value = 0.5f;
Vector3f colorBackground = new Vector3f(0,0,0);
Vector3f colorForeground = new Vector3f(1,1,1);
static final int idealMargin = 5; //5 pixels margin ideally
static final Vector3f windowDrawDebugColor = new Vector3f(1.0f,1.0f,1.0f);
public Slider(int positionX, int positionY, int width, int height, Vector3f colorBackground, Vector3f colorForeground){
this.positionX = positionX;
this.positionY = positionY;
this.width = width;
this.height = height;
this.colorBackground.set(colorBackground);
this.colorForeground.set(colorForeground);
}
@Override
public void draw(int parentFramebufferPointer, int parentWidth, int parentHeight) {
Globals.renderingEngine.bindFramebuffer(parentFramebufferPointer);
Globals.renderingEngine.setViewportSize(parentWidth, parentHeight);
int marginX = Math.max(width - idealMargin * 2, 0);
if(marginX < idealMargin){
marginX = 0;
} else {
marginX = idealMargin;
}
int marginY = Math.max(height - idealMargin * 2, 0);
if(marginY < idealMargin){
marginY = 0;
} else {
marginY = idealMargin;
}
float ndcX = (float)positionX/parentWidth;
float ndcY = (float)positionY/parentHeight;
float ndcWidth = (float)width/parentWidth;
float ndcHeight = (float)height/parentHeight;
Vector3f boxPosition = new Vector3f(ndcX,ndcY,0);
Vector3f boxDimensions = new Vector3f(ndcWidth,ndcHeight,0);
Model planeModel = Globals.assetManager.fetchModel(Globals.solidPlaneModelID);
if(planeModel != null){
//bounding box/margin
planeModel.pushUniformToMesh("plane", "mPosition", boxPosition);
planeModel.pushUniformToMesh("plane", "mDimension", boxDimensions);
planeModel.pushUniformToMesh(planeModel.getMeshes().get(0).getMeshName(), "color", colorBackground);
planeModel.drawUI();
//actual slider
ndcX = (float)(positionX + marginX)/parentWidth;
ndcY = (float)(positionY + marginY)/parentHeight;
ndcWidth = (float)((width - marginX * 2) * getValueAsPercentage())/parentWidth;
ndcHeight = (float)(height - marginY * 2)/parentHeight;
boxPosition = new Vector3f(ndcX,ndcY,0);
boxDimensions = new Vector3f(ndcWidth,ndcHeight,0);
planeModel.pushUniformToMesh("plane", "mPosition", boxPosition);
planeModel.pushUniformToMesh("plane", "mDimension", boxDimensions);
planeModel.pushUniformToMesh(planeModel.getMeshes().get(0).getMeshName(), "color", colorForeground);
planeModel.drawUI();
} else {
LoggerInterface.loggerRenderer.ERROR("Window unable to find plane model!!", new Exception());
}
if(Globals.RENDER_FLAG_RENDER_UI_BOUNDS && DebugRendering.RENDER_DEBUG_OUTLINE_SLIDER){
boxDimensions.x = (float)((width - marginX * 2) * 1.0f)/parentWidth;
DebugRendering.drawUIBounds(parentFramebufferPointer, boxPosition, boxDimensions, windowDrawDebugColor);
}
}
public float getMinimum(){
return min;
}
public void setMinimum(float min){
this.min = min;
}
public float getMaximum(){
return max;
}
public void setMaximum(float max){
this.max = max;
}
public float getValue(){
return value;
}
public void setValue(float value){
this.value = value;
}
public int getWidth() {
return width;
}
float getValueAsPercentage(){
return (value - min) / (max - min);
}
public int getHeight() {
return height;
}
public int getPositionX() {
return positionX;
}
public int getPositionY() {
return positionY;
}
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) {
this.positionX = posX;
}
public void setPositionY(int posY) {
this.positionY = posY;
}
public void setVisible(boolean draw) {
this.visible = draw;
}
public void setParentWidth(int width){
parentWidth = width;
}
public void setParentHeight(int height){
this.parentHeight = height;
}
@Override
public boolean isFocused() {
return focused;
}
@Override
public void setOnFocus(FocusEventCallback callback) {
onFocusCallback = callback;
}
@Override
public void setOnLoseFocus(FocusEventCallback callback) {
onLoseFocusCallback = callback;
}
@Override
public void setOnDragStart(DragEventCallback callback) {
this.onDragStart = callback;
}
@Override
public void setOnDrag(DragEventCallback callback) {
this.onDrag = callback;
}
@Override
public void setOnDragRelease(DragEventCallback callback) {
this.onDragRelease = callback;
}
@Override
public void setOnClick(ClickEventCallback callback) {
this.onClick = callback;
}
@Override
public void setOnMenuEventCallback(MenuEventCallback callback) {
onMenuEvent = callback;
}
@Override
public void setOnValueChangeCallback(ValueChangeEventCallback callback) {
onValueChange = callback;
}
@Override
public boolean handleEvent(Event event) {
boolean propagate = true;
if(event instanceof FocusEvent){
FocusEvent focusEvent = (FocusEvent)event;
if(focusEvent.isFocused()){
if(this.onFocusCallback != null){
propagate = this.onFocusCallback.execute(focusEvent);
} else {
//default behavior/
colorForeground = new Vector3f(1,0,0);
propagate = true;
}
} else {
if(this.onLoseFocusCallback != null){
propagate = this.onLoseFocusCallback.execute(focusEvent);
} else {
//default behavior
colorForeground = new Vector3f(1,1,1);
propagate = true;
}
}
} else if(event instanceof MenuEvent){
MenuEvent menuEvent = (MenuEvent) event;
if(onMenuEvent != null){
onMenuEvent.execute(menuEvent);
} else {
//default behavior
switch(menuEvent.getType()){
case INCREMENT:
value = Math.min(value + ((max - min) * 0.01f),max);
if(onValueChange != null){
onValueChange.execute(new ValueChangeEvent(value));
}
propagate = false;
break;
case DECREMENT:
value = Math.max(value - ((max - min) * 0.01f),min);
if(onValueChange != null){
onValueChange.execute(new ValueChangeEvent(value));
}
propagate = false;
break;
}
}
} else if(event instanceof DragEvent){
DragEvent dragEvent = (DragEvent) event;
if(dragEvent.getType() == DragEventType.START){
if(onDragStart != null){
propagate = onDragStart.execute(dragEvent);
} else {
//default behavior
propagate = true;
}
} else if(dragEvent.getType() == DragEventType.DRAG){
if(onDrag != null){
propagate = onDrag.execute(dragEvent);
} else {
//default behavior
propagate = false;
}
} else if(dragEvent.getType() == DragEventType.RELEASE){
if(onDragRelease != null){
propagate = onDragRelease.execute(dragEvent);
} else {
//default behavior
propagate = true;
}
}
} else if(event instanceof ClickEvent){
ClickEvent clickEvent = (ClickEvent) event;
if(clickEvent.getButton1()){
if(this.onClick != null){
propagate = this.onClick.execute((ClickEvent)event);
} else {
//default behavior
int percentage = clickEvent.getCurrentX() - positionX;
int max = width;
value = Math.max(Math.min((float)percentage/max,1.0f),0.0f);
if(onValueChange != null){
onValueChange.execute(new ValueChangeEvent(value));
}
propagate = false;
}
}
}
return propagate;
}
}