package electrosphere.renderer.ui.elements; import org.joml.Vector3f; import electrosphere.engine.Globals; import electrosphere.logger.LoggerInterface; import electrosphere.renderer.OpenGLState; import electrosphere.renderer.RenderPipelineState; import electrosphere.renderer.framebuffer.Framebuffer; import electrosphere.renderer.framebuffer.FramebufferUtils; import electrosphere.renderer.model.Material; import electrosphere.renderer.model.Model; import electrosphere.renderer.texture.Texture; import electrosphere.renderer.ui.elementtypes.ContainerElement; import electrosphere.renderer.ui.elementtypes.DrawableElement; import electrosphere.renderer.ui.elementtypes.Element; import electrosphere.renderer.ui.events.Event; import static org.lwjgl.opengl.GL11.*; import static org.lwjgl.opengl.GL30.*; public class ScrollableContainer extends StandardContainerElement implements DrawableElement { Vector3f color = new Vector3f(1.0f); boolean focused = false; public boolean visible = false; Framebuffer widgetBuffer; Material customMat = new Material(); Vector3f boxPosition = new Vector3f(); Vector3f boxDimensions = new Vector3f(); Vector3f texPosition = new Vector3f(0,0,0); Vector3f texScale = new Vector3f(1,1,0); public ScrollableContainer(OpenGLState openGLState, int positionX, int positionY, int width, int height){ super(); try { widgetBuffer = FramebufferUtils.generateTextureFramebuffer(openGLState, width, height); } catch(Exception e){ LoggerInterface.loggerRenderer.ERROR(e); } // widgetBuffer = FramebufferUtils.generateScreensizeTextureFramebuffer(); customMat.setTexturePointer(widgetBuffer.getTexture().getTexturePointer()); // customMat.setTexturePointer(Globals.assetManager.fetchTexture("Textures/Testing1.png").getTexturePointer()); float ndcX = (float)positionX/Globals.WINDOW_WIDTH; float ndcY = (float)positionY/Globals.WINDOW_HEIGHT; float ndcWidth = (float)width/Globals.WINDOW_WIDTH; float ndcHeight = (float)height/Globals.WINDOW_HEIGHT; setWidth(width); setHeight(height); boxPosition = new Vector3f(ndcX,ndcY,0); boxDimensions = new Vector3f(ndcWidth,ndcHeight,0); } @Override public boolean handleEvent(Event event) { return false; } @Override public boolean getVisible() { return visible; } @Override public void setVisible(boolean visible) { this.visible = visible; } //recursively check if focused element is child of input element or is input element boolean containsFocusedElement(Element parent){ Element focusedElement = Globals.elementService.getFocusedElement(); if(parent == focusedElement){ return true; } else if(parent instanceof ContainerElement){ ContainerElement container = (ContainerElement)parent; for(Element child : container.getChildren()){ if(containsFocusedElement(child)){ return true; } } } return false; } @Override public void draw( RenderPipelineState renderPipelineState, OpenGLState openGLState, int parentFramebufferPointer, int parentPosX, int parentPosY, int parentWidth, int parentHeight ) { //figure out if currently focused element is a child or subchild of this container if(containsFocusedElement(this)){ //if it is, if it is offscreen, calculate offset to put it onscreen Element focused = Globals.elementService.getFocusedElement(); if( focused.getRelativeX() + focused.getWidth() > this.width || focused.getRelativeY() + focused.getHeight() > this.height || focused.getRelativeX() < 0 || focused.getRelativeY() < 0 ){ int neededOffsetX = 0; int neededOffsetY = 0; //basically if we're offscreen negative, pull to positive //if we're offscreen positive and we're not as large as the screen, pull from the positive into focus //if we are larger than the screen, set position to 0 if(focused.getRelativeX() < 0){ neededOffsetX = -focused.getRelativeX(); } else if(focused.getRelativeX() + focused.getWidth() > this.width){ if(focused.getWidth() > this.width){ neededOffsetX = -focused.getRelativeX(); } else { neededOffsetX = -((focused.getRelativeX() - this.width) + focused.getWidth()); } } if(focused.getRelativeY() < 0){ neededOffsetY = -focused.getRelativeY(); } else if(focused.getRelativeY() + focused.getHeight() > this.height){ if(focused.getHeight() > this.height){ neededOffsetY = -focused.getRelativeY(); } else { neededOffsetY = -((focused.getRelativeY() - this.height) + focused.getHeight()); // System.out.println(focused.getPositionY() + " " + this.height + " " + focused.getHeight()); } } //apply offset to all children for(Element child : childList){ int newX = child.getRelativeX() + neededOffsetX; int newY = child.getRelativeY() + neededOffsetY; child.setPositionX(newX); child.setPositionY(newY); // System.out.println(currentX + " " + currentY); } } } float ndcX = (float)internalPositionX/parentWidth; float ndcY = (float)internalPositionY/parentHeight; float ndcWidth = (float)internalWidth/parentWidth; float ndcHeight = (float)internalHeight/parentHeight; boxPosition = new Vector3f(ndcX,ndcY,0); boxDimensions = new Vector3f(ndcWidth,ndcHeight,0); //grab assets required to render window Model planeModel = Globals.assetManager.fetchModel(Globals.imagePlaneModelID); Texture windowFrame = Globals.assetManager.fetchTexture("Textures/ui/uiFrame1.png"); widgetBuffer.bind(openGLState); openGLState.glViewport(width, height); glClearColor(0.0f, 0.0f, 0.0f, 0.0f); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); for(Element child : childList){ if(child instanceof DrawableElement){ DrawableElement drawableChild = (DrawableElement) child; drawableChild.draw(renderPipelineState,openGLState,widgetBuffer.getFramebufferPointer(),0,0,width,height); } } //this call binds the screen as the "texture" we're rendering to //have to call before actually rendering openGLState.glBindFramebuffer(GL_FRAMEBUFFER, parentFramebufferPointer); openGLState.glViewport(parentWidth, parentHeight); //render background of window if(planeModel != null && windowFrame != null){ planeModel.pushUniformToMesh("plane", "mPosition", boxPosition); planeModel.pushUniformToMesh("plane", "mDimension", boxDimensions); planeModel.pushUniformToMesh("plane", "tPosition", texPosition); planeModel.pushUniformToMesh("plane", "tDimension", texScale); planeModel.pushUniformToMesh(planeModel.getMeshes().get(0).getMeshName(), "color", color); customMat.setTexturePointer(windowFrame.getTexturePointer()); planeModel.getMeshes().get(0).setMaterial(customMat); planeModel.drawUI(); } if(planeModel != null){ planeModel.pushUniformToMesh("plane", "mPosition", boxPosition); planeModel.pushUniformToMesh("plane", "mDimension", boxDimensions); planeModel.pushUniformToMesh("plane", "tPosition", texPosition); planeModel.pushUniformToMesh("plane", "tDimension", texScale); planeModel.pushUniformToMesh(planeModel.getMeshes().get(0).getMeshName(), "color", color); customMat.setTexturePointer(widgetBuffer.getTexture().getTexturePointer()); planeModel.getMeshes().get(0).setMaterial(customMat); planeModel.drawUI(); } else { LoggerInterface.loggerRenderer.ERROR("ScrollableContainer unable to find plane model!!", new Exception()); } } }