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; } }