diff --git a/assets/Models/falloak1.fbx b/assets/Models/falloak1.fbx index 7e622a75..c30e1a9d 100644 Binary files a/assets/Models/falloak1.fbx and b/assets/Models/falloak1.fbx differ diff --git a/assets/Models/shrine2.fbx b/assets/Models/shrine2.fbx new file mode 100644 index 00000000..0577aa3e Binary files /dev/null and b/assets/Models/shrine2.fbx differ diff --git a/assets/Shaders/grass1/grass1.gs b/assets/Shaders/grass1/grass1.gs index ec1a2a07..cfedca08 100644 --- a/assets/Shaders/grass1/grass1.gs +++ b/assets/Shaders/grass1/grass1.gs @@ -8,6 +8,9 @@ uniform mat4 model; uniform mat4 view; uniform mat4 projection; +//uniforms +uniform float time; + out vec3 origCoord; void main() { @@ -18,20 +21,27 @@ void main() { //Each new vertex is a new triangle using the previous two // + float timeS = time * 0.0051; + float bladeHeight = 0.2; + float rotateRadius = 0.01; for(float x = 0; x < 4; x++){ for(float y = 0; y < 4; y++){ float xPos = x / 20.0; float yPos = y / 20.0; + + float cOffX = sin(timeS + (x + y) * y) * rotateRadius; + float cOffY = cos(timeS + (x + y) * y) * rotateRadius; + origCoord = (triangle1Pos + vec4( 0.0 + xPos, 0.45, 0.0 + yPos, 0.0)).xyz; gl_Position = projection * view * model * (triangle1Pos + vec4( 0.0 + xPos, 0.45, 0.0 + yPos, 0.0)); EmitVertex(); origCoord = (triangle1Pos + vec4( 0.05 + xPos, 0.45, 0.0 + yPos, 0.0)).xyz; gl_Position = projection * view * model * (triangle1Pos + vec4( 0.05 + xPos, 0.45, 0.0 + yPos, 0.0)); EmitVertex(); - origCoord = (triangle1Pos + vec4( 0.025 + xPos, 0.95, 0.025 + yPos, 0.0)).xyz; - gl_Position = projection * view * model * (triangle1Pos + vec4( 0.025 + xPos, 0.45 + bladeHeight, 0.025 + yPos, 0.0)); + origCoord = (triangle1Pos + vec4( 0.025 + xPos + cOffX, 0.95, 0.025 + yPos + cOffY, 0.0)).xyz; + gl_Position = projection * view * model * (triangle1Pos + vec4( 0.025 + xPos + cOffX, 0.45 + bladeHeight, 0.025 + yPos + cOffY, 0.0)); EmitVertex(); origCoord = (triangle1Pos + vec4( 0.05 + xPos, 0.45, 0.05 + yPos, 0.0)).xyz; gl_Position = projection * view * model * (triangle1Pos + vec4( 0.05 + xPos, 0.45, 0.05 + yPos, 0.0)); @@ -39,8 +49,8 @@ void main() { origCoord = (triangle1Pos + vec4( 0.0 + xPos, 0.45, 0.05 + yPos, 0.0)).xyz; gl_Position = projection * view * model * (triangle1Pos + vec4( 0.0 + xPos, 0.45, 0.05 + yPos, 0.0)); EmitVertex(); - origCoord = (triangle1Pos + vec4( 0.025 + xPos, 0.95, 0.025 + yPos, 0.0)).xyz; - gl_Position = projection * view * model * (triangle1Pos + vec4( 0.025 + xPos, 0.45 + bladeHeight, 0.025 + yPos, 0.0)); + origCoord = (triangle1Pos + vec4( 0.025 + xPos + cOffX, 0.95, 0.025 + yPos + cOffY, 0.0)).xyz; + gl_Position = projection * view * model * (triangle1Pos + vec4( 0.025 + xPos + cOffX, 0.45 + bladeHeight, 0.025 + yPos + cOffY, 0.0)); EmitVertex(); origCoord = (triangle1Pos + vec4( 0.0 + xPos, 0.45, 0.0 + yPos, 0.0)).xyz; gl_Position = projection * view * model * (triangle1Pos + vec4( 0.0 + xPos, 0.45, 0.0 + yPos, 0.0)); diff --git a/assets/Shaders/water1/water.fs b/assets/Shaders/water1/water.fs index 260820fe..fd6b5bdd 100644 --- a/assets/Shaders/water1/water.fs +++ b/assets/Shaders/water1/water.fs @@ -26,7 +26,9 @@ THIS MAKES USE OF OPENSIMPLEX2, A NOISE ALGORITHM CREATED BY THE FINE FOLKS OVER AT https://github.com/KdotJPG/OpenSimplex2 PLEASE GIVE THEM SOME LOVE. -THE FLAME FUNCTION IS ONE CREATED BY ME BLENDING A LOG2 INTO A EXPONENTIAL. +IT ALSO MAKES USE OF FUNCTIONS FROM THE_FORCE, A SHADER IDE +https://github.com/shawnlawson/The_Force + */ //version @@ -61,13 +63,16 @@ vec4 openSimplex2_Conventional(vec3 X); vec4 openSimplex2_ImproveXY(vec3 X); float flameTex(float x, float y); float getNoise(float scale, float timeScale); +float voronoi(vec2 point); +vec3 voronoi(vec3 x); +float linearCenterAroundPoint(float input, float centerpoint, float falloff); /* Main method */ void main(){ - float timeS = time * 0.01; + float timeS = time * 0.003; // Normalized pixel coordinates (from 0 to 1) vec3 projCoordNorm = projCoord.xyz / projCoord.w / 2.0 + 0.5; @@ -77,7 +82,7 @@ void main(){ float closeDepth = texture(volumeDepthFrontface, finalProd.xy).r; float farDepth = texture(volumeDepthBackface, finalProd.xy).r; //distance between the two - float volume = abs(farDepth - closeDepth); + float volume = min(abs(farDepth - closeDepth),1); //based on distance of model coords from center @@ -106,7 +111,36 @@ void main(){ float red = 0.1984; float green = 0.6464; float blue = 0.7366; - float alpha = volume * 10.0; + float alpha = volume * 7.0; + + volume = volume * 3; + + float foamFallout = max(1 - (volume * 7),0); + float lightWaterVal = max(1 - (volume * 3),0); + float darkWaterVal = linearCenterAroundPoint(volume,0.5,0.5); + float blackWaterVal = max((volume * 3) - 2,0); + + red = 0.1984 * lightWaterVal + darkWaterVal * 0.0000 + blackWaterVal * 0.0000; + green = 0.6464 * lightWaterVal + darkWaterVal * 0.1370 + blackWaterVal * 0.0980; + blue = 0.7366 * lightWaterVal + darkWaterVal * 0.3140 + blackWaterVal * 0.2200; + + if(dot(Normal,vec3(0,1,0)) > 0.5){ + float foamVal = voronoi(vec3(modelCoord.x * 8,modelCoord.z * 8,timeS)).x; + // foamVal = foamVal * foamVal * min(1 - volume * 10,0); + foamVal = foamVal * foamVal; + red = red + foamVal;// * foamFallout; + blue = blue + foamVal;// * foamFallout; + green = green + foamVal;// * foamFallout; + alpha = alpha + foamVal;// * foamFallout; + // // float foamVal = openSimplex2_ImproveXY(vec3(modelCoord.x * 5.0,modelCoord.z * 5.0,timeS)).x; + // // if(foamVal > 0.4 && foamVal < 0.7){ + // // foamVal = 1.0 - foamVal * foamVal; + // // red = foamVal + red; + // // green = foamVal + green; + // // blue = foamVal + blue; + // // alpha = foamVal + alpha; + // // } + } // alpha = 0.5; @@ -250,4 +284,68 @@ vec4 openSimplex2_ImproveXY(vec3 X) { return vec4(result.xyz * orthonormalMap, result.w); } -//////////////////////////////// End noise code //////////////////////////////// \ No newline at end of file +const mat2 myt = mat2(.12121212,.13131313,-.13131313,.12121212); +const vec2 mys = vec2(1e4, 1e6); +vec2 rhash(vec2 uv) { + uv *= myt; + uv *= mys; + return fract(fract(uv/mys)*uv); +} + +vec3 hash( vec3 p ){ + return fract(sin(vec3( dot(p,vec3(1.0,57.0,113.0)), + dot(p,vec3(57.0,113.0,1.0)), + dot(p,vec3(113.0,1.0,57.0))))*43758.5453); + +} + +float voronoi(vec2 point){ + vec2 p = floor( point ); + vec2 f = fract( point ); + float res = 0.0; + for( int j=-1; j<=1; j++ ) { + for( int i=-1; i<=1; i++ ) { + vec2 b = vec2( i, j ); + vec2 r = vec2( b ) - f + rhash( p + b); + res += 1./pow(dot(r,r),8.); + } + } + return pow(1./res, 0.0625); +} + +vec3 voronoi(vec3 x) { + vec3 p = floor( x ); + vec3 f = fract( x ); + + float id = 0.0; + vec2 res = vec2( 100.0 ); + for( int k=-1; k<=1; k++ ) { + for( int j=-1; j<=1; j++ ) { + for( int i=-1; i<=1; i++ ) { + vec3 b = vec3( float(i), float(j), float(k) ); + vec3 r = vec3( b ) - f + hash( p + b ); + float d = dot( r, r ); + + if( d < res.x ) { + id = dot( p+b, vec3(1.0,57.0,113.0 ) ); + res = vec2( d, res.x ); + } + else if( d < res.y ) { + res.y = d; + } + } + } + } + + return vec3( sqrt( res ), abs(id) ); +} + +//////////////////////////////// End noise code //////////////////////////////// + + +float linearCenterAroundPoint(float input, float centerpoint, float falloff){ + return max(((-abs(input - centerpoint)) + centerpoint)*falloff,0); +} + + + diff --git a/assets/Textures/Fonts/myFont2Map.json b/assets/Textures/Fonts/myFont2Map.json index d41782e3..834aa62b 100644 --- a/assets/Textures/Fonts/myFont2Map.json +++ b/assets/Textures/Fonts/myFont2Map.json @@ -441,14 +441,14 @@ "symbol": ".", "startX": 2605, "startY": 1, - "width": 40, + "width": 24, "height": 58 }, { "symbol": "!", - "startX": 2647, + "startX": 2632, "startY": 1, - "width": 40, + "width": 24, "height": 58 }, { @@ -478,6 +478,13 @@ "startY": 1, "width": 40, "height": 58 + }, + { + "symbol": "/", + "startX": 2844, + "startY": 1, + "width": 40, + "height": 58 } ] } \ No newline at end of file diff --git a/assets/Textures/Fonts/myfont2.png b/assets/Textures/Fonts/myfont2.png index 4af3caf8..50dc40ee 100644 Binary files a/assets/Textures/Fonts/myfont2.png and b/assets/Textures/Fonts/myfont2.png differ diff --git a/assets/Textures/default_texture_map.json b/assets/Textures/default_texture_map.json index 506c85af..d1fd3eac 100644 --- a/assets/Textures/default_texture_map.json +++ b/assets/Textures/default_texture_map.json @@ -183,7 +183,11 @@ ] }, "Models/falloak1.fbx" : { - "Cube" : [ + "Tree" : [ + "/Textures/falloak1.png", + "/Textures/falloak1.png" + ], + "Cube.003" : [ "/Textures/falloak1.png", "/Textures/falloak1.png" ] diff --git a/src/main/java/electrosphere/controls/ControlHandler.java b/src/main/java/electrosphere/controls/ControlHandler.java index 9d7895b9..0073d48d 100644 --- a/src/main/java/electrosphere/controls/ControlHandler.java +++ b/src/main/java/electrosphere/controls/ControlHandler.java @@ -18,6 +18,7 @@ import electrosphere.entity.types.camera.CameraEntityUtils; import electrosphere.entity.types.collision.CollisionObjUtils; import electrosphere.entity.types.item.ItemUtils; import electrosphere.game.client.targeting.crosshair.Crosshair; +import electrosphere.logger.LoggerInterface; import electrosphere.main.Globals; import electrosphere.main.Main; import electrosphere.menu.WindowStrings; @@ -118,6 +119,7 @@ public class ControlHandler { public static final String DATA_STRING_INPUT_CODE_MENU_TYPE_X = "menuTypeX"; public static final String DATA_STRING_INPUT_CODE_MENU_TYPE_Y = "menuTypeY"; public static final String DATA_STRING_INPUT_CODE_MENU_TYPE_Z = "menuTypeZ"; + public static final String INPUT_CODE_MENU_TYPE_FORWARD_SLASH = "menuTypeForwardSlash"; public static final String INPUT_CODE_INVENTORY_CLOSE = "inventoryClose"; public static final String INPUT_CODE_INVENTORY_ITEM_MANIPULATE = "inventoryItemManipulate"; @@ -242,6 +244,7 @@ public class ControlHandler { handler.addControl(DATA_STRING_INPUT_CODE_MENU_TYPE_X, new Control(ControlType.KEY,GLFW_KEY_X)); handler.addControl(DATA_STRING_INPUT_CODE_MENU_TYPE_Y, new Control(ControlType.KEY,GLFW_KEY_Y)); handler.addControl(DATA_STRING_INPUT_CODE_MENU_TYPE_Z, new Control(ControlType.KEY,GLFW_KEY_Z)); + handler.addControl(INPUT_CODE_MENU_TYPE_FORWARD_SLASH, new Control(ControlType.KEY,GLFW_KEY_SLASH)); /* Inventory controls @@ -906,12 +909,13 @@ public class ControlHandler { DATA_STRING_INPUT_CODE_MENU_TYPE_X, DATA_STRING_INPUT_CODE_MENU_TYPE_Y, DATA_STRING_INPUT_CODE_MENU_TYPE_Z, + INPUT_CODE_MENU_TYPE_FORWARD_SLASH, }; for(String currentKey : typeKeybinds){ typingControlList.add(controls.get(currentKey)); controls.get(currentKey).setOnPress(new ControlMethod(){public void execute(){ Globals.elementManager.fireEvent( - new KeyboardEvent(currentKey), + new KeyboardEvent(convertKeycodeToName(controls.get(currentKey).keyValue)), Globals.elementManager.getFocusedElement().getPositionX(), Globals.elementManager.getFocusedElement().getPositionY() ); @@ -1096,6 +1100,12 @@ public class ControlHandler { public static String convertKeycodeToName(int code){ String rVal = ""; switch(code){ + case 46: + rVal = "."; + break; + case 47: + rVal = "/"; + break; case 48: rVal = "0"; break; @@ -1204,9 +1214,15 @@ public class ControlHandler { case 90: rVal = "Z"; break; + case 259: + rVal = "bs"; //backspace + break; case 256: rVal = "Escape"; break; + default: + LoggerInterface.loggerEngine.WARNING("Unable to convert keycode " + code + " in control handler."); + break; } return rVal; } diff --git a/src/main/java/electrosphere/engine/LoadingThread.java b/src/main/java/electrosphere/engine/LoadingThread.java index 79b56bcd..f8d5ae1f 100644 --- a/src/main/java/electrosphere/engine/LoadingThread.java +++ b/src/main/java/electrosphere/engine/LoadingThread.java @@ -120,6 +120,7 @@ public class LoadingThread extends Thread { case LOAD_MAIN_GAME: WindowUtils.recursiveSetVisible(Globals.elementManager.getWindow(WindowStrings.WINDOW_MENU_MAIN), false); + WindowUtils.replaceMainMenuContents(MenuGenerators.createEmptyMainMenu()); loadingWindow.setVisible(true); //disable menu input @@ -223,6 +224,7 @@ public class LoadingThread extends Thread { case LOAD_ARENA: WindowUtils.recursiveSetVisible(Globals.elementManager.getWindow(WindowStrings.WINDOW_MENU_MAIN), false); + WindowUtils.replaceMainMenuContents(MenuGenerators.createEmptyMainMenu()); loadingWindow.setVisible(true); //disable menu input @@ -643,7 +645,7 @@ public class LoadingThread extends Thread { // Entity tree = EntityUtils.spawnDrawableEntity(treePath); // EntityUtils.getPosition(tree).set(rand.nextFloat() * 105 + 1, 0, rand.nextFloat() * 105 + 1); // EntityUtils.getRotation(tree).rotateLocalX(-(float)Math.PI/2.0f).rotateZ(rand.nextFloat()); -//// EntityUtils.getEntityRotation(tree).rotateAxis((float)-Math.PI/2.0f, new Vector3f(1,0,0)); +// // EntityUtils.getEntityRotation(tree).rotateAxis((float)-Math.PI/2.0f, new Vector3f(1,0,0)); // } // Random rand = new Random(); @@ -716,15 +718,15 @@ public class LoadingThread extends Thread { // EntityUtils.getPosition(grass).set(3,0,1); //queue grass shader - Globals.assetManager.addShaderToQueue("Shaders/grass1/grass1.vs", "Shaders/grass1/grass1.gs", "Shaders/grass1/grass1.fs"); - for(int x = 0; x < 10; x++){ - for(int y = 0; y < 10; y++){ - Entity grass = EntityUtils.spawnDrawableEntity("Models/grass1.fbx"); - //shader mask - EntityUtils.getActor(grass).maskShader("Cube", "Shaders/grass1/grass1.vs", "Shaders/grass1/grass1.gs", "Shaders/grass1/grass1.fs"); - EntityUtils.getPosition(grass).set(3 + x / 5.0f,0.0,1 + y / 5.0f); - } - } + // Globals.assetManager.addShaderToQueue("Shaders/grass1/grass1.vs", "Shaders/grass1/grass1.gs", "Shaders/grass1/grass1.fs"); + // for(int x = 0; x < 10; x++){ + // for(int y = 0; y < 10; y++){ + // Entity grass = EntityUtils.spawnDrawableEntity("Models/grass1.fbx"); + // //shader mask + // EntityUtils.getActor(grass).maskShader("Cube", "Shaders/grass1/grass1.vs", "Shaders/grass1/grass1.gs", "Shaders/grass1/grass1.fs"); + // EntityUtils.getPosition(grass).set(3 + x / 5.0f,0.0,1 + y / 5.0f); + // } + // } //water cube @@ -732,6 +734,9 @@ public class LoadingThread extends Thread { EntityUtils.getActor(water).maskShader("Cube", "Shaders/water1/water.vs", "Shaders/water1/water.fs"); Globals.assetManager.addShaderToQueue("Shaders/water1/water.vs", "Shaders/water1/water.fs"); EntityUtils.getPosition(water).set(5,0.51,5); + EntityUtils.getRotation(water).rotationX((float)Math.PI/4.0f); + // EntityUtils.getPosition(water).set(5,-0.1,5); + EntityUtils.getScale(water).set(1,1,1); //texture mask EntityUtils.getActor(water).addTextureMask(RenderUtils.generateVolumetricTextureMask("Cube")); //set draw volumetric diff --git a/src/main/java/electrosphere/menu/MenuGenerators.java b/src/main/java/electrosphere/menu/MenuGenerators.java index a8ce4994..ba80622e 100644 --- a/src/main/java/electrosphere/menu/MenuGenerators.java +++ b/src/main/java/electrosphere/menu/MenuGenerators.java @@ -119,6 +119,11 @@ public class MenuGenerators { return rVal; } + + public static Element createEmptyMainMenu(){ + Div rVal = new Div(); + return rVal; + } public static Element createWorldSelectMenu(){ FormElement rVal = new FormElement(); @@ -309,7 +314,7 @@ public class MenuGenerators { rVal.addChild(addressLabel); //text entry (address) - TextInput addressInput = new TextInput(100,screenTop + 125,40*15, 40); + TextInput addressInput = new TextInput(100,screenTop + 125,1.0f); addressInput.setText(NetUtils.getAddress()); rVal.addChild(addressInput); @@ -319,7 +324,7 @@ public class MenuGenerators { rVal.addChild(portLabel); //text entry (port) - TextInput portInput = new TextInput(100,screenTop + 275,40*5, 40); + TextInput portInput = new TextInput(100,screenTop + 275,1.0f); rVal.addChild(portInput); //button (connect) @@ -540,15 +545,9 @@ public class MenuGenerators { //text entry (port) - TextInput modelDebugInput = new TextInput(100,150, 40*5, 40); + TextInput modelDebugInput = new TextInput(100,150,fontSize); scrollable.addChild(modelDebugInput); modelDebugInput.setText("Model path goes here"); - modelDebugInput.setOnFocus(new FocusEventCallback() {public boolean execute(FocusEvent event) { - return false; - }}); - modelDebugInput.setOnLoseFocus(new FocusEventCallback() {public boolean execute(FocusEvent event) { - return false; - }}); //label 3 (load model and debug) Button debugModelButton = new Button(); @@ -583,9 +582,30 @@ public class MenuGenerators { return false; }}); - for(int i = 0; i < 9; i++){ + //disable drawing player character + Button toggleDrawPlayerButton = new Button(); + Label toggleDrawPlayerLabel = new Label(100,450,fontSize); + toggleDrawPlayerLabel.setText("Toggle draw character"); + toggleDrawPlayerButton.addChild(toggleDrawPlayerLabel); + scrollable.addChild(toggleDrawPlayerButton); + toggleDrawPlayerButton.setOnClick(new ClickableElement.ClickEventCallback(){public boolean execute(ClickEvent event){ + // Main.running = false; + if(Globals.playerCharacter != null){ + if(Globals.playerCharacter.getDataKeys().contains(EntityDataStrings.DATA_STRING_DRAW)){ + boolean draw = (boolean)Globals.playerCharacter.getData(EntityDataStrings.DATA_STRING_DRAW); + Globals.playerCharacter.putData(EntityDataStrings.DATA_STRING_DRAW, !draw); + } + if(Globals.playerCharacter.getDataKeys().contains(EntityDataStrings.DRAW_CAST_SHADOW)){ + boolean drawShadow = (boolean)Globals.playerCharacter.getData(EntityDataStrings.DRAW_CAST_SHADOW); + Globals.playerCharacter.putData(EntityDataStrings.DRAW_CAST_SHADOW, !drawShadow); + } + } + return false; + }}); + + for(int i = 0; i < 7; i++){ Button someButton = new Button(); - Label someLabel = new Label(100,450 + i * 100,fontSize); + Label someLabel = new Label(100,550 + i * 100,fontSize); someLabel.setText("aaaaaa" + i); someButton.addChild(someLabel); scrollable.addChild(someButton); diff --git a/src/main/java/electrosphere/net/server/Server.java b/src/main/java/electrosphere/net/server/Server.java index d234a473..508132e1 100644 --- a/src/main/java/electrosphere/net/server/Server.java +++ b/src/main/java/electrosphere/net/server/Server.java @@ -4,6 +4,7 @@ import electrosphere.main.Main; import electrosphere.net.NetUtils; import electrosphere.net.parser.net.message.NetworkMessage; import java.io.IOException; +import java.net.BindException; import java.net.InetSocketAddress; import java.net.ServerSocket; import java.net.Socket; @@ -41,6 +42,9 @@ public class Server implements Runnable{ initServer(); try { serverSocket = new ServerSocket(port); + } catch(BindException ex){ + System.err.println("Failed to bind server socket!"); + ex.printStackTrace(); } catch (IOException ex) { System.err.println("Failed to start server socket!"); ex.printStackTrace(); diff --git a/src/main/java/electrosphere/renderer/RenderingEngine.java b/src/main/java/electrosphere/renderer/RenderingEngine.java index c2443b3f..c29eef6e 100644 --- a/src/main/java/electrosphere/renderer/RenderingEngine.java +++ b/src/main/java/electrosphere/renderer/RenderingEngine.java @@ -148,6 +148,9 @@ public class RenderingEngine { static Framebuffer transparencyBuffer; static ShaderProgram oitCompositeProgram; + /* + Perspective volumetrics + */ static Matrix4f nearVolumeProjectionMatrix = new Matrix4f(); static Matrix4f midVolumeProjectionMatrix = new Matrix4f(); static Matrix4f farVolumeProjectionMatrix = new Matrix4f(); @@ -158,6 +161,15 @@ public class RenderingEngine { static Texture volumeDepthFrontfaceTexture; static float volumeDepthLinearCoef = 0.1f; static float volumeDepthQuadCoef = 0.01f; + + /* + Vertical volumetrics + TODO: implement + */ + // static Texture volumeVerticalBackfaceTexture; + // static Framebuffer volumeVerticalBackfaceBuffer; + // static Texture volumeVerticalFrontfaceTexture; + // static Framebuffer volumeVerticalFrontfaceBuffer; // public static boolean renderHitboxes = false; // public static boolean renderPhysics = false; diff --git a/src/main/java/electrosphere/renderer/ShaderProgram.java b/src/main/java/electrosphere/renderer/ShaderProgram.java index 3dedf887..3c447ac4 100644 --- a/src/main/java/electrosphere/renderer/ShaderProgram.java +++ b/src/main/java/electrosphere/renderer/ShaderProgram.java @@ -1,6 +1,7 @@ package electrosphere.renderer; import electrosphere.logger.LoggerInterface; +import electrosphere.main.Globals; import electrosphere.main.Main; import electrosphere.util.FileUtils; import java.io.BufferedReader; @@ -337,7 +338,9 @@ public class ShaderProgram { //Tests for the success of the shader program creation success = glGetProgrami(rVal.shaderProgram, GL_LINK_STATUS); if (success != GL_TRUE) { - throw new RuntimeException(glGetProgramInfoLog(rVal.shaderProgram)); + LoggerInterface.loggerRenderer.ERROR(glGetProgramInfoLog(rVal.shaderProgram), new RuntimeException(glGetProgramInfoLog(rVal.shaderProgram))); + return Globals.defaultMeshShader; + // throw new RuntimeException(glGetProgramInfoLog(rVal.shaderProgram)); } //Deletes the individual shader objects to free up memory diff --git a/src/main/java/electrosphere/renderer/ui/KeyEventElement.java b/src/main/java/electrosphere/renderer/ui/KeyEventElement.java new file mode 100644 index 00000000..97b3b2fc --- /dev/null +++ b/src/main/java/electrosphere/renderer/ui/KeyEventElement.java @@ -0,0 +1,13 @@ +package electrosphere.renderer.ui; + +import electrosphere.renderer.ui.events.KeyboardEvent; + +public interface KeyEventElement extends Element { + + public void setOnPress(KeyboardEventCallback event); + + public interface KeyboardEventCallback { + public boolean execute(KeyboardEvent event); + } + +} diff --git a/src/main/java/electrosphere/renderer/ui/elements/Label.java b/src/main/java/electrosphere/renderer/ui/elements/Label.java index c28b52c7..73fa7735 100644 --- a/src/main/java/electrosphere/renderer/ui/elements/Label.java +++ b/src/main/java/electrosphere/renderer/ui/elements/Label.java @@ -17,6 +17,18 @@ import org.joml.Vector3f; */ public class Label implements DrawableElement { + 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; + + String text = ""; int textPixelWidth = 0; @@ -71,17 +83,6 @@ public class Label implements DrawableElement { } } - 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; - public int getWidth() { int minX = -1; int maxX = -1; diff --git a/src/main/java/electrosphere/renderer/ui/elements/TextInput.java b/src/main/java/electrosphere/renderer/ui/elements/TextInput.java index 38d981d1..24d012bf 100644 --- a/src/main/java/electrosphere/renderer/ui/elements/TextInput.java +++ b/src/main/java/electrosphere/renderer/ui/elements/TextInput.java @@ -8,184 +8,29 @@ import electrosphere.renderer.framebuffer.Framebuffer; import electrosphere.renderer.framebuffer.FramebufferUtils; import electrosphere.renderer.texture.Texture; import electrosphere.renderer.ui.DrawableElement; +import electrosphere.renderer.ui.Element; import electrosphere.renderer.ui.FocusableElement; +import electrosphere.renderer.ui.KeyEventElement; import electrosphere.renderer.ui.events.Event; import electrosphere.renderer.ui.events.FocusEvent; +import electrosphere.renderer.ui.events.KeyboardEvent; import electrosphere.renderer.ui.font.FontUtils; +import electrosphere.renderer.ui.font.bitmapchar.BitmapCharacter; + import org.joml.Vector3f; import static org.lwjgl.opengl.GL30.GL_FRAMEBUFFER; import static org.lwjgl.opengl.GL30.glBindFramebuffer; +import java.util.LinkedList; +import java.util.List; +import java.util.regex.Pattern; + /** * * @author amaterasu */ -public class TextInput implements DrawableElement, FocusableElement { +public class TextInput implements DrawableElement, FocusableElement, KeyEventElement { - Framebuffer widgetBuffer; - Material customMat = new Material(); - - Vector3f boxPosition = new Vector3f(0,0,0); - Vector3f boxDimensions = new Vector3f(1,1,0); - Vector3f texPosition = new Vector3f(0,0,0); - Vector3f texScale = new Vector3f(1,1,0); - - String text = ""; - - int fontWidth = 10; - int fontHeight = 20; - - int linePaddingHorizonal = 2; - int linePaddingVertical = 5; - - boolean focused = false; - FocusEventCallback onFocusCallback = null; - FocusEventCallback onLoseFocusCallback = null; - - Vector3f color = new Vector3f(0,0,0); - - public TextInput(int positionX, int positionY, int width, int height){ - //TODO: figure out why this has to be 1920x1080 -// widgetBuffer = FramebufferUtils.generateTextureFramebuffer(500, 500); - widgetBuffer = FramebufferUtils.generateScreensizeTextureFramebuffer(); - customMat.setTexturePointer(widgetBuffer.getTexturePointer()); -// customMat.setTexturePointer(Globals.assetManager.fetchTexture("Textures/Testing1.png").getTexturePointer()); -// customMat.setTexturePointer(Globals.assetManager.fetchTexture("Textures/default_diffuse.png").getTexturePointer()); - setPositionX(positionX); - setPositionY(positionY); - setWidth(width); - setHeight(height); - } - - @Override - public void setPositionY(int positionY) { - float ndcY = (float)positionY/(float)Globals.WINDOW_HEIGHT; - boxPosition.y = ndcY; - this.positionY = positionY; - } - - @Override - public void setPositionX(int positionX) { - float ndcX = (float)positionX/(float)Globals.WINDOW_WIDTH; - boxPosition.x = ndcX; - this.positionX = positionX; - } - - @Override - public void setHeight(int height) { - float ndcHeight = (float)height/(float)parentHeight; - boxDimensions.y = ndcHeight; - Framebuffer newBuffer = FramebufferUtils.generateTextureFramebuffer(width, height); - Framebuffer oldBuffer = widgetBuffer; - widgetBuffer = newBuffer; - customMat.setTexturePointer(widgetBuffer.getTexturePointer()); - oldBuffer.free(); -// customMat.setTexturePointer(Globals.assetManager.fetchTexture("Textures/Testing1.png").getTexturePointer()); - this.height = height; - } - - @Override - public void setWidth(int width) { - float ndcWidth = (float)width/(float)parentWidth; - boxDimensions.x = ndcWidth; - Framebuffer newBuffer = FramebufferUtils.generateTextureFramebuffer(width, height); - Framebuffer oldBuffer = widgetBuffer; - widgetBuffer = newBuffer; - customMat.setTexturePointer(widgetBuffer.getTexturePointer()); - oldBuffer.free(); -// widgetBuffer = FramebufferUtils.generateTextureFramebuffer(width, height); -// customMat.setTexturePointer(Globals.assetManager.fetchTexture("Textures/Testing1.png").getTexturePointer()); - this.width = width; - } - - @Override - public void setParentWidth(int parentWidth){ - this.parentWidth = parentWidth; - } - - @Override - public void setParentHeight(int parentHeight){ - this.parentHeight = parentHeight; - } - - public void setFontWidth(int width){ - fontWidth = width; - } - - public void setFontHeight(int height){ - fontHeight = height; - } - - public int getFontWidth(){ - return fontWidth; - } - - public int getFontHeight(){ - return fontHeight; - } - - public String getText(){ - return text; - } - - public void setText(String text){ - this.text = text; - } - - @Override - public void draw(int parentFramebufferPointer, int parentWidth, int parentHeight) { - widgetBuffer.bind(); - Globals.renderingEngine.setViewportSize(width, height); - - //monowidth for the moment - float charWidth = (float)fontWidth/(float)width; - float charHeight = (float)fontHeight/(float)height; - float charSpacing = (float)linePaddingHorizonal/(float)width; - float lineSpacing = (float)linePaddingVertical/(float)height; - - Model charModel = Globals.assetManager.fetchModel(AssetDataStrings.ASSET_STRING_BITMAP_FONT); - int verticalPosition = 0; - int horizontalPosition = 0; - int charPos = 0; - while(charPos < text.length()){ - char currentChar = text.charAt(charPos); - if(currentChar == '\n'){ - verticalPosition++; - horizontalPosition = 0; - } else { - - Vector3f characterPosition = new Vector3f(horizontalPosition * (charWidth + charSpacing),-verticalPosition * (charHeight + lineSpacing),0); - Vector3f characterDimensions = new Vector3f(charWidth,charHeight,0); - Vector3f bitMapPosition = FontUtils.getPositionOfCharacter(currentChar); - Vector3f bitMapDimension = FontUtils.getDimensionOfCharacter(currentChar); - - if(charModel != null && currentChar != ' '){ - charModel.pushUniformToMesh(AssetDataStrings.ASSET_STRING_BITMAP_FONT_MESH_NAME, "mPosition", characterPosition); - charModel.pushUniformToMesh(AssetDataStrings.ASSET_STRING_BITMAP_FONT_MESH_NAME, "mDimension", characterDimensions); - charModel.pushUniformToMesh(AssetDataStrings.ASSET_STRING_BITMAP_FONT_MESH_NAME, "tPosition", bitMapPosition); - charModel.pushUniformToMesh(AssetDataStrings.ASSET_STRING_BITMAP_FONT_MESH_NAME, "tDimension", bitMapDimension); - charModel.pushUniformToMesh(AssetDataStrings.ASSET_STRING_BITMAP_FONT_MESH_NAME, "color", color); - charModel.drawUI(); - } - horizontalPosition++; - } - charPos++; - } - - - //draw the previous texture to a quad - Globals.renderingEngine.bindFramebuffer(parentFramebufferPointer); - Globals.renderingEngine.setViewportSize(parentWidth, parentHeight); - - Model planeModel = Globals.assetManager.fetchModel(Globals.planeModelID); - planeModel.pushUniformToMesh("plane", "mPosition", boxPosition); - planeModel.pushUniformToMesh("plane", "mDimension", boxDimensions); - planeModel.pushUniformToMesh("plane", "tPosition", new Vector3f(0,0,0)); - planeModel.pushUniformToMesh("plane", "tDimension", new Vector3f(1,1,0)); - planeModel.meshes.get(0).setMaterial(customMat); - planeModel.drawUI(); - } - public int width = 1; public int height = 1; @@ -197,38 +42,215 @@ public class TextInput implements DrawableElement, FocusableElement { public boolean visible = false; + boolean focused = false; + FocusEventCallback onFocusCallback; + FocusEventCallback onLoseFocusCallback; + KeyboardEventCallback onKeyPressCallback; + + String text = ""; + int textPixelWidth = 0; + + float fontSize = 1.0f; + + List childrenElements = new LinkedList(); + + public TextInput(int x, int y, float fontSize){ + this.positionX = x; + this.positionY = y; + this.width = 0; + this.height = (int)(FontUtils.getFontHeight() * fontSize); + this.fontSize = fontSize; + } + + void generateLetters(){ + childrenElements.clear(); + int rollingOffset = 0; + for(int i = 0; i < text.length(); i++){ + char toDraw = text.charAt(i); + Vector3f bitMapDimension = FontUtils.getDimensionOfCharacterDiscrete(toDraw); + BitmapCharacter newLetter = new BitmapCharacter((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.text = text; + textPixelWidth = 0; + for(int i = 0; i < text.length(); i++){ + Vector3f bitMapDimension = FontUtils.getDimensionOfCharacterDiscrete(text.charAt(i)); + textPixelWidth = textPixelWidth + (int)bitMapDimension.x; + } + generateLetters(); + } + + public void setColor(Vector3f color){ + for(BitmapCharacter character : childrenElements){ + character.setColor(color); + } + } + + public String getText(){ + return text; + } + + @Override + public void draw(int parentFramebufferPointer, int parentWidth, int parentHeight) { + for(DrawableElement child : childrenElements){ + child.draw(parentFramebufferPointer, parentWidth, parentHeight); + } + } + public int getWidth() { - return width; + 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() { - return height; + 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() { - return positionX; + 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() { - return positionY; + 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 FocusEvent){ - this.focused = ((FocusEvent)event).isFocused(); - if(this.focused && onFocusCallback != null){ - propagate = onFocusCallback.execute((FocusEvent)event); - } else if(!this.focused && onLoseFocusCallback != null){ - propagate = onLoseFocusCallback.execute((FocusEvent)event); + FocusEvent focusEvent = (FocusEvent)event; + if(focusEvent.isFocused()){ + if(this.onFocusCallback != null){ + this.onFocusCallback.execute(focusEvent); + } else { + this.setColor(new Vector3f(1,0,0)); + propagate = false; + } + } else { + if(this.onLoseFocusCallback != null){ + this.onLoseFocusCallback.execute(focusEvent); + } else { + this.setColor(new Vector3f(1,1,1)); + propagate = false; + } + } + } else if(event instanceof KeyboardEvent){ + KeyboardEvent keyEvent = (KeyboardEvent)event; + if(onKeyPressCallback != null){ + onKeyPressCallback.execute(keyEvent); + } else { + if(keyEvent.getKey().matches(Pattern.quote("bs"))){ + if(this.text.length() > 0){ + this.setText(this.text.substring(0, this.text.length() - 1)); + } + } else { + this.setText(this.text + keyEvent.getKey()); + } + propagate = false; } } return propagate; @@ -251,5 +273,11 @@ public class TextInput implements DrawableElement, FocusableElement { // TODO Auto-generated method stub onLoseFocusCallback = callback; } + + @Override + public void setOnPress(KeyboardEventCallback callback) { + // TODO Auto-generated method stub + onKeyPressCallback = callback; + } }