package electrosphere.renderer.ui.elements; import java.util.LinkedList; import java.util.List; import org.joml.Vector2f; import org.joml.Vector3f; import electrosphere.logger.LoggerInterface; import electrosphere.main.Globals; import electrosphere.renderer.Material; import electrosphere.renderer.Model; import electrosphere.renderer.framebuffer.Framebuffer; import electrosphere.renderer.framebuffer.FramebufferUtils; import electrosphere.renderer.ui.ContainerElement; import electrosphere.renderer.ui.DrawableElement; import electrosphere.renderer.ui.Element; import electrosphere.renderer.ui.events.Event; import static org.lwjgl.opengl.GL11.*; import static org.lwjgl.opengl.GL30.*; public class ScrollableContainer implements DrawableElement, ContainerElement { boolean focused = false; List childList = new LinkedList(); 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; Framebuffer widgetBuffer; Material customMat = new Material(); Vector3f boxPosition = new Vector3f(); Vector3f boxDimensions = new Vector3f(); Vector3f texPosition = new Vector3f(0,1,0); Vector3f texScale = new Vector3f(1,-1,0); public ScrollableContainer(int positionX, int positionY, int width, int height){ widgetBuffer = FramebufferUtils.generateTextureFramebuffer(width, height); // widgetBuffer = FramebufferUtils.generateScreensizeTextureFramebuffer(); customMat.setTexturePointer(widgetBuffer.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; this.width = width; this.height = height; boxPosition = new Vector3f(ndcX,ndcY,0); boxDimensions = new Vector3f(ndcWidth,ndcHeight,0); } @Override public int getWidth() { return width; } @Override public int getHeight() { return height; } @Override public int getPositionX() { return positionX; } @Override public int getPositionY() { return positionY; } @Override public void setWidth(int width) { // TODO Auto-generated method stub this.width = width; } @Override public void setHeight(int height) { // TODO Auto-generated method stub this.height = height; } @Override public void setPositionX(int positionX) { // TODO Auto-generated method stub this.positionX = positionX; } @Override public void setPositionY(int positionY) { // TODO Auto-generated method stub this.positionY = positionY; } @Override public void setParentWidth(int width) { // TODO Auto-generated method stub parentWidth = width; float ndcX = (float)positionX/parentWidth; float ndcY = (float)positionY/parentHeight; float ndcWidth = (float)width/parentWidth; float ndcHeight = (float)height/parentHeight; boxPosition = new Vector3f(ndcX,ndcY,0); boxDimensions = new Vector3f(ndcWidth,ndcHeight,0); } @Override public void setParentHeight(int height) { // TODO Auto-generated method stub parentHeight = height; float ndcX = (float)positionX/parentWidth; float ndcY = (float)positionY/parentHeight; float ndcWidth = (float)width/parentWidth; float ndcHeight = (float)height/parentHeight; boxPosition = new Vector3f(ndcX,ndcY,0); boxDimensions = new Vector3f(ndcWidth,ndcHeight,0); } @Override public void addChild(Element child) { childList.add(child); if(child instanceof DrawableElement){ DrawableElement drawableChild = (DrawableElement) child; drawableChild.setParentWidth(width); drawableChild.setParentHeight(height); drawableChild.setVisible(false); } } @Override public List getChildren() { return childList; } @Override public void removeChild(Element child) { childList.remove(child); } @Override public boolean handleEvent(Event event) { // TODO Auto-generated method stub return true; } @Override public boolean getVisible() { // TODO Auto-generated method stub return visible; } @Override public void setVisible(boolean visible) { // TODO Auto-generated method stub this.visible = visible; } //recursively check if focused element is child of input element or is input element boolean containsFocusedElement(Element parent){ Element focusedElement = Globals.elementManager.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(int parentFramebufferPointer, 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.elementManager.getFocusedElement(); if( focused.getPositionX() + focused.getWidth() > this.width || focused.getPositionY() + focused.getHeight() > this.height || focused.getPositionX() < 0 || focused.getPositionY() < 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.getPositionX() < 0){ neededOffsetX = -focused.getPositionX(); } else if(focused.getPositionX() + focused.getWidth() > this.width){ if(focused.getWidth() > this.width){ neededOffsetX = -focused.getPositionX(); } else { neededOffsetX = -((focused.getPositionX() - this.width) + focused.getWidth()); } } if(focused.getPositionY() < 0){ neededOffsetY = -focused.getPositionY(); } else if(focused.getPositionY() + focused.getHeight() > this.height){ if(focused.getHeight() > this.height){ neededOffsetY = -focused.getPositionY(); } else { neededOffsetY = -((focused.getPositionY() - 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.getPositionX() + neededOffsetX; int newY = child.getPositionY() + neededOffsetY; child.setPositionX(newX); child.setPositionY(newY); // System.out.println(currentX + " " + currentY); } } } widgetBuffer.bind(); // Globals.renderingEngine.setViewportSize(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(widgetBuffer.getFramebufferPointer(),width,height); } } //this call binds the screen as the "texture" we're rendering to //have to call before actually rendering glBindFramebuffer(GL_FRAMEBUFFER, parentFramebufferPointer); Globals.renderingEngine.setViewportSize(parentWidth, parentHeight); Model planeModel = Globals.assetManager.fetchModel(Globals.planeModelID); if(planeModel != null){ planeModel.pushUniformToMesh("plane", "mPosition", boxPosition); planeModel.pushUniformToMesh("plane", "mDimension", boxDimensions); planeModel.pushUniformToMesh("plane", "tPosition", texPosition); planeModel.pushUniformToMesh("plane", "tDimension", texScale); planeModel.meshes.get(0).setMaterial(customMat); planeModel.drawUI(); } else { LoggerInterface.loggerRenderer.ERROR("ScrollableContainer unable to find plane model!!", new Exception()); } } }