diff --git a/assets/Data/voxelTypes.json b/assets/Data/voxelTypes.json index 2bb72a01..9fbc402e 100644 --- a/assets/Data/voxelTypes.json +++ b/assets/Data/voxelTypes.json @@ -16,11 +16,6 @@ "Green Grass" ], "texture" : "/Textures/Ground/GrassTileable256.png" - }, - { - "id" : 3, - "name" : "baguette", - "texture" : "/Textures/Ground/baguette256.png" } ] } \ No newline at end of file diff --git a/docs/src/progress/renderertodo.md b/docs/src/progress/renderertodo.md index 2e2af399..c009118b 100644 --- a/docs/src/progress/renderertodo.md +++ b/docs/src/progress/renderertodo.md @@ -522,6 +522,7 @@ gltf Support - Fix bad data with human mesh textures not mapping - Texture loading from gltf file +FileUtils sanitation function check if requested file is in game root dir Cellular Automata Fluid Dynamics System - Advect force diff --git a/src/main/java/electrosphere/controls/ControlHandler.java b/src/main/java/electrosphere/controls/ControlHandler.java index bca161b8..0c977791 100644 --- a/src/main/java/electrosphere/controls/ControlHandler.java +++ b/src/main/java/electrosphere/controls/ControlHandler.java @@ -106,6 +106,7 @@ import electrosphere.renderer.ui.events.ClickEvent; import electrosphere.renderer.ui.events.KeyboardEvent; import electrosphere.renderer.ui.events.MenuEvent; import electrosphere.renderer.ui.events.MenuEvent.MenuEventType; +import electrosphere.util.FileUtils; import electrosphere.renderer.ui.events.MouseEvent; import electrosphere.renderer.ui.events.ScrollEvent; @@ -1195,7 +1196,10 @@ public class ControlHandler { */ menuNavigationControlList.add(controls.get(MENU_CAPTURE_SCREEN)); controls.get(MENU_CAPTURE_SCREEN).setOnPress(new Control.ControlMethod() {public void execute(){ - RenderingEngine.screenFramebuffer.getPixels(Globals.renderingEngine.getOpenGLState()); + FileUtils.writeBufferedImage( + RenderingEngine.defaultFramebuffer.getPixels(Globals.renderingEngine.getOpenGLState()), + "Screenshots/" + System.currentTimeMillis() + ".png" + ); }}); diff --git a/src/main/java/electrosphere/renderer/RenderingEngine.java b/src/main/java/electrosphere/renderer/RenderingEngine.java index 8c080098..49f0d3c3 100644 --- a/src/main/java/electrosphere/renderer/RenderingEngine.java +++ b/src/main/java/electrosphere/renderer/RenderingEngine.java @@ -116,6 +116,7 @@ public class RenderingEngine { public static int screenTextureVAO; public static ShaderProgram screenTextureShaders; public static ShaderProgram drawChannel; + public static Framebuffer defaultFramebuffer; @@ -319,6 +320,9 @@ public class RenderingEngine { // initScreenTextureShaderProgram(); screenTextureShaders = ShaderProgram.loadSpecificShader("/Shaders/screentexture/simple1/simple1.vs", "/Shaders/screentexture/simple1/simple1.fs"); // screenTextureShaders = ShaderProgram.loadSpecificShader("/Shaders/screentexture/drawDepthBuffer/drawDepthBuffer.vs", "/Shaders/screentexture/drawDepthBuffer/drawDepthBuffer.fs"); + + //default framebuffer + defaultFramebuffer = new Framebuffer(0); //generate framebuffers screenTextureColor = FramebufferUtils.generateScreenTextureColor(openGLState, Globals.userSettings.getRenderResolutionX(), Globals.userSettings.getRenderResolutionY()); diff --git a/src/main/java/electrosphere/renderer/framebuffer/Framebuffer.java b/src/main/java/electrosphere/renderer/framebuffer/Framebuffer.java index 33c0b405..d2c8696e 100644 --- a/src/main/java/electrosphere/renderer/framebuffer/Framebuffer.java +++ b/src/main/java/electrosphere/renderer/framebuffer/Framebuffer.java @@ -46,6 +46,14 @@ public class Framebuffer { framebufferPointer = glGenFramebuffers(); } + /** + * Creates a framebuffer with a predefined id + * @param framebufferId The predefined framebuffer id + */ + public Framebuffer(int framebufferId){ + this.framebufferPointer = framebufferId; + } + /** * Sets the texture attached to the framebuffer * @param texture The texture attached to the framebuffer @@ -229,22 +237,27 @@ public class Framebuffer { */ public BufferedImage getPixels(OpenGLState openGLState){ BufferedImage rVal = null; - bind(openGLState); - GL40.glReadBuffer(GL40.GL_COLOR_ATTACHMENT0); int offsetX = 0; int offsetY = 0; int width = openGLState.getViewport().x; int height = openGLState.getViewport().y; int pixelFormat = GL40.GL_RGBA; int type = GL40.GL_UNSIGNED_INT; - if(attachTextureMap.containsKey(0)){ + + + bind(openGLState); + GL40.glReadBuffer(GL40.GL_COLOR_ATTACHMENT0); + if(this.framebufferPointer == 0){ + //this is the default framebuffer, read from backbuffer because it is default + GL40.glReadBuffer(GL40.GL_BACK); + } else if(attachTextureMap.containsKey(0)){ Texture texture = attachTextureMap.get(0); pixelFormat = texture.getFormat(); type = texture.getDataType(); width = texture.getWidth(); height = texture.getHeight(); } else { - throw new IllegalStateException("Tried to get pixels from a framebuffer that does not have a texture attached to attachment point 0."); + LoggerInterface.loggerRenderer.ERROR(new IllegalStateException("Tried to get pixels from a framebuffer that does not have a texture attached to attachment point 0.")); } //get pixel data try { @@ -262,10 +275,6 @@ public class Framebuffer { int red = buffer.get(i) & 0xFF; int green = buffer.get(i + 1) & 0xFF; int blue = buffer.get(i + 2) & 0xFF; - if(red != 0 || green != 0 || blue != 0){ - System.out.println(x + " " + y); - System.out.println(red + " " + green + " " + blue); - } int alpha = 255; if(pixelFormat == GL40.GL_RGBA){ alpha = buffer.get(i + 3) & 0xFF; @@ -273,19 +282,6 @@ public class Framebuffer { rVal.setRGB(x, height - (y + 1), (alpha << 24) | (red << 16) | (green << 8) | blue); } } - //write the buffered image out - try { - File outputFile = FileUtils.getAssetFile("Screenshots/" + System.currentTimeMillis() + ".png"); - if(!outputFile.getParentFile().exists()){ - outputFile.getParentFile().mkdirs(); - } - if(!outputFile.exists()){ - outputFile.createNewFile(); - } - ImageIO.write(rVal,"png",outputFile); - } catch (IOException e) { - LoggerInterface.loggerRenderer.ERROR(e); - } //memory management MemoryUtil.memFree(buffer); } catch (OutOfMemoryError e){ diff --git a/src/main/java/electrosphere/util/FileUtils.java b/src/main/java/electrosphere/util/FileUtils.java index 11239b34..a7024974 100644 --- a/src/main/java/electrosphere/util/FileUtils.java +++ b/src/main/java/electrosphere/util/FileUtils.java @@ -3,12 +3,12 @@ package electrosphere.util; import com.google.gson.Gson; import com.google.gson.GsonBuilder; -import electrosphere.engine.Main; import electrosphere.game.data.creature.type.movement.MovementSystem; import electrosphere.game.data.creature.type.movement.MovementSystemSerializer; import electrosphere.logger.LoggerInterface; import electrosphere.util.annotation.AnnotationExclusionStrategy; +import java.awt.image.BufferedImage; import java.io.BufferedReader; import java.io.File; import java.io.IOException; @@ -16,27 +16,48 @@ import java.io.InputStream; import java.io.InputStreamReader; import java.nio.file.Files; import java.nio.file.Path; -import java.nio.file.StandardOpenOption; +import java.nio.file.Paths; import java.util.LinkedList; import java.util.List; import java.util.concurrent.TimeUnit; -import java.util.logging.Level; -import java.util.logging.Logger; +import javax.imageio.ImageIO; + +/** + * Utilities for dealing with files + */ public class FileUtils { + /** + * Creates the gson instance + */ static { + //init gson GsonBuilder gsonBuilder = new GsonBuilder(); gsonBuilder.registerTypeAdapter(MovementSystem.class, new MovementSystemSerializer()); gsonBuilder.addDeserializationExclusionStrategy(new AnnotationExclusionStrategy()); gsonBuilder.addSerializationExclusionStrategy(new AnnotationExclusionStrategy()); gson = gsonBuilder.create(); + + //init gamedir + gameDir = Paths.get("").toFile(); } + //used for serialization/deserialization in file operations static Gson gson; + + //the game's root directory + static File gameDir = null; + //maximum number of attempt to read the file static final int maxReadFails = 3; + //Timeout duration between read attempts static final int READ_TIMEOUT_DURATION = 5; + /** + * Reads a file to a string + * @param f The file + * @return The string + */ public static String readFileToString(File f){ String rVal = ""; BufferedReader reader; @@ -113,16 +134,6 @@ public class FileUtils { } - -// public static String sanitizeBakedFilePath(String filePath){ -// String rVal = new String(filePath); -// rVal = rVal.trim(); -// if(!rVal.startsWith("/")){ -// rVal = "/" + rVal; -// } -// return rVal; -// } - /** * Sanitizes a relative file path, guaranteeing that the initial slash is correct * @param filePath The raw file path @@ -139,14 +150,11 @@ public class FileUtils { return rVal; } -// public static String readStringFromBakedFile(String bakedFilePath){ -// String rVal = ""; -// String sanitizedFilePath = sanitizeBakedFilePath(bakedFilePath); -// rVal = readStreamToString(Main.class.getResourceAsStream(sanitizedFilePath)); -// return rVal; -// } - - + /** + * Serializes an object to a filepath + * @param filePath The filepath + * @param object The object + */ public static void serializeObjectToFilePath(String filePath, Object object){ Path path = new File(filePath).toPath(); try { @@ -156,12 +164,23 @@ public class FileUtils { } } + /** + * Gets an assets file + * @param pathName The relative path in the assets folder + * @return The file + */ public static File getAssetFile(String pathName){ String sanitizedFilePath = sanitizeFilePath(pathName); File targetFile = new File("./assets" + sanitizedFilePath); return targetFile; } + /** + * Gets a save file + * @param saveName The name of the save + * @param pathName The relative path in the save's folder + * @return the file + */ public static File getSaveFile(String saveName, String pathName){ String sanitizedFilePath = sanitizeFilePath(pathName); String fullPath = "./saves/" + saveName + "/" + sanitizedFilePath; @@ -169,29 +188,54 @@ public class FileUtils { return targetFile; } + /** + * Gets an asset file as a stream + * @param pathName The path of the file + * @return The stream + * @throws IOException Thrown if Files fails to create the stream + */ public static InputStream getAssetFileAsStream(String pathName) throws IOException{ String sanitizedFilePath = sanitizeFilePath(pathName); File targetFile = new File("./assets" + sanitizedFilePath); return Files.newInputStream(targetFile.toPath()); } + /** + * Gets an asset file as a string + * @param pathName The path of the file + * @return The string + * @throws IOException Thrown if Files fails to read the file + */ public static String getAssetFileAsString(String pathName) throws IOException{ String sanitizedFilePath = sanitizeFilePath(pathName); File targetFile = new File("./assets" + sanitizedFilePath); return Files.readString(targetFile.toPath()); } + /** + * Loads an object from the assets folder + * @param The type of object + * @param pathName The relative path to the file + * @param className The class of the object inside the file + * @return The file + */ public static T loadObjectFromAssetPath(String pathName, Class className){ T rVal = null; String sanitizedFilePath = sanitizeFilePath(pathName); try { rVal = gson.fromJson(Files.newBufferedReader(getAssetFile(sanitizedFilePath).toPath()), className); } catch (IOException ex) { - ex.printStackTrace(); + LoggerInterface.loggerFileIO.ERROR(ex); } return rVal; } + /** + * Gets an sql script file as a string + * @param pathName The path of the sql script + * @return The file's contents as a string + * @throws IOException Thrown if the engine fails to read the file + */ public static String getSQLScriptFileAsString(String pathName) throws IOException { String sanitizedFilePath = sanitizeFilePath(pathName); File targetFile = new File("./src/main/sql" + sanitizedFilePath); @@ -306,7 +350,11 @@ public class FileUtils { } } - + /** + * Lists the files in a directory + * @param directoryName The path of the directory + * @return A list containing the names of all files inside that directory + */ public static List listDirectory(String directoryName){ List rVal = new LinkedList(); String sanitizedPath = sanitizeFilePath(directoryName); @@ -318,6 +366,10 @@ public class FileUtils { return rVal; } + /** + * Recursively deletes a path + * @param path The path + */ public static void recursivelyDelete(String path){ File file = new File(path); if(file.isDirectory()){ @@ -334,36 +386,29 @@ public class FileUtils { } } } + + /** + * Writes a buffered image to a given path + * @param image The image + * @param path The path + */ + public static void writeBufferedImage(BufferedImage image, String path){ + //write the buffered image out + try { + File outputFile = FileUtils.getAssetFile(path); + if(!outputFile.getParentFile().exists()){ + outputFile.getParentFile().mkdirs(); + } + if(!outputFile.exists()){ + outputFile.createNewFile(); + } + ImageIO.write(image,"png",outputFile); + } catch (IOException e) { + LoggerInterface.loggerRenderer.ERROR(e); + } + } - -// public static T loadModelObjectFromBakedJsonFile(String fileName, Class className){ -// T rVal = null; -// String sanitizedFilePath = sanitizeBakedFilePath(fileName); -// String rawJSON = readStreamToString(Main.class.getResourceAsStream(sanitizedFilePath)); -// Gson gson = new Gson(); -// rVal = gson.fromJson(rawJSON, className); -// return rVal; -// } -// -// public static File unpackBakedFileToFilePath(String bakedFilePath){ -// String sanitizedFilePath = sanitizeBakedFilePath(bakedFilePath); -// if(!Files.exists(new File("./Models").toPath())){ -// try { -// Files.createDirectory(new File("./Models").toPath()); -// } catch (IOException ex) { -// ex.printStackTrace(); -// } -// } -// File targetFile = new File("." + sanitizedFilePath); -// try { -// Files.write(targetFile.toPath(), Main.class.getResourceAsStream(sanitizedFilePath).readAllBytes(),StandardOpenOption.CREATE,StandardOpenOption.WRITE); -// } catch (IOException ex) { -// ex.printStackTrace(); -// } -// return targetFile; -// } - }