This commit is contained in:
parent
79e2fdf512
commit
a7c8571afa
@ -1,6 +1,6 @@
|
|||||||
@page humanprogress Human
|
@page skeletonprogres Skeleton
|
||||||
|
|
||||||
Progress on the human creature
|
Progress on the skeleton creature
|
||||||
|
|
||||||
## Third Person Model
|
## Third Person Model
|
||||||
- [X] Meshed
|
- [X] Meshed
|
||||||
|
|||||||
@ -765,6 +765,7 @@ Fix movement packet timing bug
|
|||||||
Fix all items spawning above player head
|
Fix all items spawning above player head
|
||||||
Fix items falling below terrain
|
Fix items falling below terrain
|
||||||
Fix gridded data cell manager saving attached items on realm save
|
Fix gridded data cell manager saving attached items on realm save
|
||||||
|
Fix render signals caching between frames (not reseting global flags per usual)
|
||||||
|
|
||||||
|
|
||||||
# TODO
|
# TODO
|
||||||
|
|||||||
@ -240,8 +240,8 @@ public class Globals {
|
|||||||
//OpenGL - Other
|
//OpenGL - Other
|
||||||
//
|
//
|
||||||
|
|
||||||
public static int WINDOW_WIDTH = 1920;
|
public static int WINDOW_WIDTH;
|
||||||
public static int WINDOW_HEIGHT = 1080;
|
public static int WINDOW_HEIGHT;
|
||||||
public static boolean WINDOW_DECORATED = true; //used to control whether the window is created with decorations or not (ie for testing)
|
public static boolean WINDOW_DECORATED = true; //used to control whether the window is created with decorations or not (ie for testing)
|
||||||
public static boolean WINDOW_FULLSCREEN = false; //used to control whether the window is created fullscreen or not (ie for testing)
|
public static boolean WINDOW_FULLSCREEN = false; //used to control whether the window is created fullscreen or not (ie for testing)
|
||||||
|
|
||||||
@ -444,10 +444,22 @@ public class Globals {
|
|||||||
Globals.javaPID = ManagementFactory.getRuntimeMXBean().getName();
|
Globals.javaPID = ManagementFactory.getRuntimeMXBean().getName();
|
||||||
}
|
}
|
||||||
//load user settings
|
//load user settings
|
||||||
|
Globals.WINDOW_WIDTH = 1920;
|
||||||
|
Globals.WINDOW_HEIGHT = 1080;
|
||||||
UserSettings.loadUserSettings();
|
UserSettings.loadUserSettings();
|
||||||
//timekeeper
|
//timekeeper
|
||||||
timekeeper = new Timekeeper();
|
timekeeper = new Timekeeper();
|
||||||
threadManager = new ThreadManager();
|
Globals.threadManager = new ThreadManager();
|
||||||
|
Globals.threadManager.init();
|
||||||
|
|
||||||
|
//render flags
|
||||||
|
RENDER_FLAG_RENDER_SHADOW_MAP = false;
|
||||||
|
RENDER_FLAG_RENDER_SCREEN_FRAMEBUFFER_CONTENT = false;
|
||||||
|
RENDER_FLAG_RENDER_SCREEN_FRAMEBUFFER = false;
|
||||||
|
RENDER_FLAG_RENDER_BLACK_BACKGROUND = true;
|
||||||
|
RENDER_FLAG_RENDER_WHITE_BACKGROUND = false;
|
||||||
|
RENDER_FLAG_RENDER_UI = true;
|
||||||
|
RENDER_FLAG_RENDER_UI_BOUNDS = false;
|
||||||
//load in default texture map
|
//load in default texture map
|
||||||
textureMapDefault = TextureMap.construct("Textures/default_texture_map.json");
|
textureMapDefault = TextureMap.construct("Textures/default_texture_map.json");
|
||||||
//load model pretransforms
|
//load model pretransforms
|
||||||
@ -667,6 +679,7 @@ public class Globals {
|
|||||||
Globals.clientScene = null;
|
Globals.clientScene = null;
|
||||||
Globals.audioEngine = null;
|
Globals.audioEngine = null;
|
||||||
Globals.renderingEngine = null;
|
Globals.renderingEngine = null;
|
||||||
|
Globals.threadManager = null;
|
||||||
Globals.signalSystem = null;
|
Globals.signalSystem = null;
|
||||||
Globals.serviceManager = null;
|
Globals.serviceManager = null;
|
||||||
Globals.clientConnection = null;
|
Globals.clientConnection = null;
|
||||||
@ -681,6 +694,7 @@ public class Globals {
|
|||||||
Globals.RENDER_FLAG_RENDER_UI = false;
|
Globals.RENDER_FLAG_RENDER_UI = false;
|
||||||
Globals.RENDER_FLAG_RENDER_BLACK_BACKGROUND = false;
|
Globals.RENDER_FLAG_RENDER_BLACK_BACKGROUND = false;
|
||||||
Globals.RENDER_FLAG_RENDER_WHITE_BACKGROUND = false;
|
Globals.RENDER_FLAG_RENDER_WHITE_BACKGROUND = false;
|
||||||
|
Globals.window = -1;
|
||||||
LoggerInterface.destroyLoggers();
|
LoggerInterface.destroyLoggers();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -17,18 +17,27 @@ import electrosphere.util.CodeUtils;
|
|||||||
public class ThreadManager {
|
public class ThreadManager {
|
||||||
|
|
||||||
//Threadsafes the manager
|
//Threadsafes the manager
|
||||||
Semaphore threadLock = new Semaphore(1);
|
Semaphore threadLock;
|
||||||
|
|
||||||
//All threads that are actively running
|
//All threads that are actively running
|
||||||
private List<LabeledThread> activeThreads = new LinkedList<LabeledThread>();
|
private List<LabeledThread> activeThreads;
|
||||||
|
|
||||||
//All loading threads that are actively running
|
//All loading threads that are actively running
|
||||||
private List<LoadingThread> loadingThreads = new LinkedList<LoadingThread>();
|
private List<LoadingThread> loadingThreads;
|
||||||
|
|
||||||
//Used by main thread to alert other threads whether they should keep running or not
|
//Used by main thread to alert other threads whether they should keep running or not
|
||||||
private boolean shouldKeepRunning = true;
|
private boolean shouldKeepRunning;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initializes the thread manager
|
||||||
|
*/
|
||||||
|
public void init(){
|
||||||
|
threadLock = new Semaphore(1);
|
||||||
|
activeThreads = new LinkedList<LabeledThread>();
|
||||||
|
loadingThreads = new LinkedList<LoadingThread>();
|
||||||
|
shouldKeepRunning = true;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Updates what threads are being tracked
|
* Updates what threads are being tracked
|
||||||
|
|||||||
@ -20,7 +20,7 @@ import electrosphere.renderer.shader.ShaderProgram;
|
|||||||
public class OpenGLState {
|
public class OpenGLState {
|
||||||
|
|
||||||
//tracks whether caching should be used or not (to deduplicate opengl calls)
|
//tracks whether caching should be used or not (to deduplicate opengl calls)
|
||||||
private static final boolean DISABLE_CACHING = false;
|
private static final boolean DISABLE_CACHING = true;
|
||||||
|
|
||||||
//the max texture allowed by the current environment
|
//the max texture allowed by the current environment
|
||||||
int MAX_TEXTURE_WIDTH;
|
int MAX_TEXTURE_WIDTH;
|
||||||
@ -67,14 +67,18 @@ public class OpenGLState {
|
|||||||
*/
|
*/
|
||||||
public void init(){
|
public void init(){
|
||||||
this.MAX_TEXTURE_WIDTH = 0;
|
this.MAX_TEXTURE_WIDTH = 0;
|
||||||
this.viewport = new Vector2i(0,0);
|
this.viewport = new Vector2i(Globals.WINDOW_WIDTH,Globals.WINDOW_HEIGHT);
|
||||||
|
GL45.glViewport(0, 0, Globals.WINDOW_WIDTH, Globals.WINDOW_HEIGHT);
|
||||||
this.depthTest = false;
|
this.depthTest = false;
|
||||||
|
GL45.glDisable(GL45.GL_DEPTH_TEST);
|
||||||
this.depthFunction = -1;
|
this.depthFunction = -1;
|
||||||
this.blendTest = false;
|
this.blendTest = false;
|
||||||
|
GL45.glDisable(GL45.GL_BLEND);
|
||||||
this.blendFuncMap = new HashMap<Integer,int[]>();
|
this.blendFuncMap = new HashMap<Integer,int[]>();
|
||||||
activeTexture = 0;
|
activeTexture = -1;
|
||||||
framebufferType = 0;
|
framebufferType = GL45.GL_FRAMEBUFFER;
|
||||||
framebufferPointer = 0;
|
framebufferPointer = 0;
|
||||||
|
GL45.glBindFramebuffer(this.framebufferType, this.framebufferPointer);
|
||||||
activeShader = null;
|
activeShader = null;
|
||||||
this.unitToPointerMap = new HashMap<Integer,Integer>();
|
this.unitToPointerMap = new HashMap<Integer,Integer>();
|
||||||
this.indexBlockMap = new HashMap<Integer,UniformBlockBinding>();
|
this.indexBlockMap = new HashMap<Integer,UniformBlockBinding>();
|
||||||
|
|||||||
@ -1,20 +1,6 @@
|
|||||||
package electrosphere.renderer;
|
package electrosphere.renderer;
|
||||||
|
|
||||||
import static electrosphere.renderer.RenderUtils.createScreenTextureVAO;
|
import static electrosphere.renderer.RenderUtils.createScreenTextureVAO;
|
||||||
import static org.lwjgl.glfw.GLFW.GLFW_CONTEXT_VERSION_MAJOR;
|
|
||||||
import static org.lwjgl.glfw.GLFW.GLFW_CONTEXT_VERSION_MINOR;
|
|
||||||
import static org.lwjgl.glfw.GLFW.GLFW_FALSE;
|
|
||||||
import static org.lwjgl.glfw.GLFW.GLFW_OPENGL_CORE_PROFILE;
|
|
||||||
import static org.lwjgl.glfw.GLFW.GLFW_OPENGL_PROFILE;
|
|
||||||
import static org.lwjgl.glfw.GLFW.glfwCreateWindow;
|
|
||||||
import static org.lwjgl.glfw.GLFW.glfwGetPrimaryMonitor;
|
|
||||||
import static org.lwjgl.glfw.GLFW.glfwInit;
|
|
||||||
import static org.lwjgl.glfw.GLFW.glfwMakeContextCurrent;
|
|
||||||
import static org.lwjgl.glfw.GLFW.glfwMaximizeWindow;
|
|
||||||
import static org.lwjgl.glfw.GLFW.glfwPollEvents;
|
|
||||||
import static org.lwjgl.glfw.GLFW.glfwSwapBuffers;
|
|
||||||
import static org.lwjgl.glfw.GLFW.glfwTerminate;
|
|
||||||
import static org.lwjgl.glfw.GLFW.glfwWindowHint;
|
|
||||||
import static org.lwjgl.opengl.GL11.GL_COLOR_BUFFER_BIT;
|
import static org.lwjgl.opengl.GL11.GL_COLOR_BUFFER_BIT;
|
||||||
import static org.lwjgl.opengl.GL11.GL_DEPTH_TEST;
|
import static org.lwjgl.opengl.GL11.GL_DEPTH_TEST;
|
||||||
import static org.lwjgl.opengl.GL11.GL_ONE_MINUS_SRC_ALPHA;
|
import static org.lwjgl.opengl.GL11.GL_ONE_MINUS_SRC_ALPHA;
|
||||||
@ -190,47 +176,52 @@ public class RenderingEngine {
|
|||||||
|
|
||||||
//
|
//
|
||||||
//set error callback
|
//set error callback
|
||||||
// GLFWErrorCallback
|
//
|
||||||
GLFW.glfwSetErrorCallback((int error, long descriptionPtr) -> {
|
GLFW.glfwSetErrorCallback((int error, long descriptionPtr) -> {
|
||||||
String description = GLFWErrorCallback.getDescription(descriptionPtr);
|
String description = GLFWErrorCallback.getDescription(descriptionPtr);
|
||||||
System.err.println(description);
|
System.err.println(description);
|
||||||
});
|
});
|
||||||
|
|
||||||
//Initializes opengl
|
//Initializes opengl
|
||||||
boolean glfwInited = glfwInit();
|
boolean glfwInited = GLFW.glfwInit();
|
||||||
if(!glfwInited){
|
if(!glfwInited){
|
||||||
String message = "Failed to initialize glfw!\n" +
|
String message = "Failed to initialize glfw!\n" +
|
||||||
"Error code: " + this.getGLFWErrorMessage(this.getGLFWError());
|
"Error code: " + this.getGLFWErrorMessage(this.getGLFWError());
|
||||||
throw new IllegalStateException(message);
|
throw new IllegalStateException(message);
|
||||||
}
|
}
|
||||||
//Gives hints to glfw to control how opengl will be used
|
//Gives hints to glfw to control how opengl will be used
|
||||||
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 4);
|
GLFW.glfwWindowHint(GLFW.GLFW_CONTEXT_VERSION_MAJOR, 4);
|
||||||
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
|
GLFW.glfwWindowHint(GLFW.GLFW_CONTEXT_VERSION_MINOR, 5);
|
||||||
glslVersion = "#version 430";
|
glslVersion = "#version 450";
|
||||||
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
|
GLFW.glfwWindowHint(GLFW.GLFW_OPENGL_PROFILE, GLFW.GLFW_OPENGL_CORE_PROFILE);
|
||||||
//headless option
|
//headless option
|
||||||
if(Globals.RUN_HIDDEN){
|
if(Globals.RUN_HIDDEN){
|
||||||
glfwWindowHint(GLFW.GLFW_VISIBLE, GLFW.GLFW_FALSE);
|
GLFW.glfwWindowHint(GLFW.GLFW_VISIBLE, GLFW.GLFW_FALSE);
|
||||||
}
|
}
|
||||||
if(!Globals.WINDOW_DECORATED){
|
if(!Globals.WINDOW_DECORATED){
|
||||||
glfwWindowHint(GLFW.GLFW_DECORATED, GLFW_FALSE);
|
GLFW.glfwWindowHint(GLFW.GLFW_DECORATED, GLFW.GLFW_FALSE);
|
||||||
|
}
|
||||||
|
if(Globals.ENGINE_DEBUG){
|
||||||
|
GLFW.glfwWindowHint(GLFW.GLFW_OPENGL_DEBUG_CONTEXT, GLFW.GLFW_TRUE);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(Globals.userSettings.getDisplayWidth() <= 0 || Globals.userSettings.getDisplayHeight() <= 0){
|
||||||
|
throw new Error("Trying to create window with width or height less than 1! " + Globals.userSettings.getDisplayWidth() + " " + Globals.userSettings.getDisplayHeight());
|
||||||
}
|
}
|
||||||
// glfwWindowHint(GLFW_TRANSPARENT_FRAMEBUFFER, GLFW_TRUE); Allows you to make the background transparent
|
|
||||||
// glfwWindowHint(GLFW_OPACITY, 23);
|
|
||||||
//Creates the window reference object
|
//Creates the window reference object
|
||||||
if(Globals.userSettings.displayFullscreen() || Globals.WINDOW_FULLSCREEN){
|
if(Globals.userSettings.displayFullscreen() || Globals.WINDOW_FULLSCREEN){
|
||||||
//below line is for fullscreen
|
//below line is for fullscreen
|
||||||
Globals.window = glfwCreateWindow(Globals.WINDOW_WIDTH, Globals.WINDOW_HEIGHT, "ORPG", glfwGetPrimaryMonitor(), NULL);
|
Globals.window = GLFW.glfwCreateWindow(Globals.userSettings.getDisplayWidth(), Globals.userSettings.getDisplayHeight(), "ORPG", GLFW.glfwGetPrimaryMonitor(), NULL);
|
||||||
} else {
|
} else {
|
||||||
Globals.window = glfwCreateWindow(Globals.WINDOW_WIDTH, Globals.WINDOW_HEIGHT, "ORPG", NULL, NULL);
|
Globals.window = GLFW.glfwCreateWindow(Globals.userSettings.getDisplayWidth(), Globals.userSettings.getDisplayHeight(), "ORPG", NULL, NULL);
|
||||||
}
|
}
|
||||||
// Errors for failure to create window (IE: No GUI mode on linux ?)
|
// Errors for failure to create window (IE: No GUI mode on linux ?)
|
||||||
if (Globals.window == NULL) {
|
if (Globals.window == NULL) {
|
||||||
String message = "Failed to create window!\n" +
|
String message = "Failed to create window!\n" +
|
||||||
"Error code: " + this.getGLFWErrorMessage(this.getGLFWError());
|
"Error code: " + this.getGLFWErrorMessage(this.getGLFWError());
|
||||||
;
|
;
|
||||||
LoggerInterface.loggerEngine.ERROR(new Exception(message));
|
GLFW.glfwTerminate();
|
||||||
glfwTerminate();
|
throw new Error(message);
|
||||||
}
|
}
|
||||||
|
|
||||||
//set resize callback
|
//set resize callback
|
||||||
@ -239,9 +230,9 @@ public class RenderingEngine {
|
|||||||
Globals.WINDOW_WIDTH = width;
|
Globals.WINDOW_WIDTH = width;
|
||||||
});
|
});
|
||||||
//Makes the window that was just created the current OS-level window context
|
//Makes the window that was just created the current OS-level window context
|
||||||
glfwMakeContextCurrent(Globals.window);
|
GLFW.glfwMakeContextCurrent(Globals.window);
|
||||||
//Maximize it
|
//Maximize it
|
||||||
glfwMaximizeWindow(Globals.window);
|
GLFW.glfwMaximizeWindow(Globals.window);
|
||||||
GLFW.glfwPollEvents();
|
GLFW.glfwPollEvents();
|
||||||
//grab actual framebuffer
|
//grab actual framebuffer
|
||||||
IntBuffer xBuffer = BufferUtils.createIntBuffer(1);
|
IntBuffer xBuffer = BufferUtils.createIntBuffer(1);
|
||||||
@ -254,10 +245,11 @@ public class RenderingEngine {
|
|||||||
//get title bar size
|
//get title bar size
|
||||||
Globals.WINDOW_TITLE_BAR_HEIGHT = Globals.WINDOW_HEIGHT - bufferHeight;
|
Globals.WINDOW_TITLE_BAR_HEIGHT = Globals.WINDOW_HEIGHT - bufferHeight;
|
||||||
|
|
||||||
// System.out.println(Globals.WINDOW_TITLE_BAR_HEIGHT);
|
|
||||||
|
|
||||||
Globals.WINDOW_WIDTH = bufferWidth;
|
Globals.WINDOW_WIDTH = bufferWidth;
|
||||||
Globals.WINDOW_HEIGHT = bufferHeight;
|
Globals.WINDOW_HEIGHT = bufferHeight;
|
||||||
|
if(bufferWidth == 0 || bufferHeight == 0){
|
||||||
|
throw new Error("Failed to get width or height! " + Globals.WINDOW_WIDTH + " " + Globals.WINDOW_HEIGHT);
|
||||||
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// Attach controls callbacks
|
// Attach controls callbacks
|
||||||
@ -289,7 +281,7 @@ public class RenderingEngine {
|
|||||||
imGuiPipeline = new ImGuiPipeline(Globals.window, glslVersion);
|
imGuiPipeline = new ImGuiPipeline(Globals.window, glslVersion);
|
||||||
|
|
||||||
//This enables Z-buffering so that farther-back polygons are not drawn over nearer ones
|
//This enables Z-buffering so that farther-back polygons are not drawn over nearer ones
|
||||||
glEnable(GL_DEPTH_TEST);
|
openGLState.glDepthTest(true);
|
||||||
|
|
||||||
// Support for transparency
|
// Support for transparency
|
||||||
openGLState.glBlend(true);
|
openGLState.glBlend(true);
|
||||||
@ -300,6 +292,10 @@ public class RenderingEngine {
|
|||||||
if(!Globals.userSettings.graphicsPerformanceEnableVSync()){
|
if(!Globals.userSettings.graphicsPerformanceEnableVSync()){
|
||||||
GLFW.glfwSwapInterval(0);
|
GLFW.glfwSwapInterval(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//clear screen
|
||||||
|
GL45.glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
|
||||||
|
GL45.glClear(GL45.GL_COLOR_BUFFER_BIT | GL45.GL_DEPTH_BUFFER_BIT);
|
||||||
|
|
||||||
// //Hide the cursor and capture it
|
// //Hide the cursor and capture it
|
||||||
// glfwSetInputMode(Globals.window, GLFW_CURSOR, GLFW_CURSOR_DISABLED);
|
// glfwSetInputMode(Globals.window, GLFW_CURSOR, GLFW_CURSOR_DISABLED);
|
||||||
@ -314,7 +310,6 @@ public class RenderingEngine {
|
|||||||
|
|
||||||
//default framebuffer
|
//default framebuffer
|
||||||
defaultFramebuffer = new Framebuffer(GL_DEFAULT_FRAMEBUFFER);
|
defaultFramebuffer = new Framebuffer(GL_DEFAULT_FRAMEBUFFER);
|
||||||
defaultFramebuffer.bind(openGLState);
|
|
||||||
|
|
||||||
//generate framebuffers
|
//generate framebuffers
|
||||||
Texture screenTextureColor = FramebufferUtils.generateScreenTextureColorAlpha(openGLState, Globals.WINDOW_WIDTH, Globals.WINDOW_HEIGHT);
|
Texture screenTextureColor = FramebufferUtils.generateScreenTextureColorAlpha(openGLState, Globals.WINDOW_WIDTH, Globals.WINDOW_HEIGHT);
|
||||||
@ -557,9 +552,9 @@ public class RenderingEngine {
|
|||||||
|
|
||||||
//check and call events and swap the buffers
|
//check and call events and swap the buffers
|
||||||
LoggerInterface.loggerRenderer.DEBUG_LOOP("GLFW Swap buffers");
|
LoggerInterface.loggerRenderer.DEBUG_LOOP("GLFW Swap buffers");
|
||||||
glfwSwapBuffers(Globals.window);
|
GLFW.glfwSwapBuffers(Globals.window);
|
||||||
LoggerInterface.loggerRenderer.DEBUG_LOOP("GLFW Poll Events");
|
LoggerInterface.loggerRenderer.DEBUG_LOOP("GLFW Poll Events");
|
||||||
glfwPollEvents();
|
GLFW.glfwPollEvents();
|
||||||
LoggerInterface.loggerRenderer.DEBUG_LOOP("Check OpenGL Errors");
|
LoggerInterface.loggerRenderer.DEBUG_LOOP("Check OpenGL Errors");
|
||||||
checkError();
|
checkError();
|
||||||
}
|
}
|
||||||
@ -668,9 +663,9 @@ public class RenderingEngine {
|
|||||||
public static void recaptureIfNecessary(){
|
public static void recaptureIfNecessary(){
|
||||||
if(Globals.controlHandler.shouldRecapture()){
|
if(Globals.controlHandler.shouldRecapture()){
|
||||||
//Makes the window that was just created the current OS-level window context
|
//Makes the window that was just created the current OS-level window context
|
||||||
glfwMakeContextCurrent(Globals.window);
|
GLFW.glfwMakeContextCurrent(Globals.window);
|
||||||
// //Maximize it
|
// //Maximize it
|
||||||
glfwMaximizeWindow(Globals.window);
|
GLFW.glfwMaximizeWindow(Globals.window);
|
||||||
//grab focus
|
//grab focus
|
||||||
GLFW.glfwFocusWindow(Globals.window);
|
GLFW.glfwFocusWindow(Globals.window);
|
||||||
//apply mouse controls state
|
//apply mouse controls state
|
||||||
|
|||||||
@ -13,9 +13,9 @@ import java.util.HashMap;
|
|||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
|
import org.lwjgl.BufferUtils;
|
||||||
import org.lwjgl.opengl.GL40;
|
import org.lwjgl.opengl.GL40;
|
||||||
import org.lwjgl.opengl.GL45;
|
import org.lwjgl.opengl.GL45;
|
||||||
import org.lwjgl.system.MemoryUtil;
|
|
||||||
|
|
||||||
import static org.lwjgl.opengl.GL11.GL_NONE;
|
import static org.lwjgl.opengl.GL11.GL_NONE;
|
||||||
import static org.lwjgl.opengl.GL11.GL_TEXTURE;
|
import static org.lwjgl.opengl.GL11.GL_TEXTURE;
|
||||||
@ -291,7 +291,7 @@ public class Framebuffer {
|
|||||||
int type = GL40.GL_UNSIGNED_BYTE;
|
int type = GL40.GL_UNSIGNED_BYTE;
|
||||||
|
|
||||||
|
|
||||||
bind(openGLState);
|
this.bind(openGLState);
|
||||||
GL40.glReadBuffer(GL40.GL_COLOR_ATTACHMENT0);
|
GL40.glReadBuffer(GL40.GL_COLOR_ATTACHMENT0);
|
||||||
if(this.framebufferPointer == 0){
|
if(this.framebufferPointer == 0){
|
||||||
//this is the default framebuffer, read from backbuffer because it is default
|
//this is the default framebuffer, read from backbuffer because it is default
|
||||||
@ -303,11 +303,23 @@ public class Framebuffer {
|
|||||||
} else {
|
} else {
|
||||||
LoggerInterface.loggerRenderer.ERROR(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."));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//error check
|
||||||
|
if(width < 1){
|
||||||
|
throw new Error("Invalid width! " + width);
|
||||||
|
}
|
||||||
|
if(height < 1){
|
||||||
|
throw new Error("Invalid height! " + height);
|
||||||
|
}
|
||||||
|
|
||||||
//get pixel data
|
//get pixel data
|
||||||
try {
|
try {
|
||||||
int bytesPerPixel = pixelFormatToBytes(pixelFormat,type);
|
int bytesPerPixel = pixelFormatToBytes(pixelFormat,type);
|
||||||
int bufferSize = width * height * bytesPerPixel;
|
int bufferSize = width * height * bytesPerPixel;
|
||||||
ByteBuffer buffer = MemoryUtil.memAlloc(bufferSize);
|
ByteBuffer buffer = BufferUtils.createByteBuffer(bufferSize);
|
||||||
|
if(buffer == null || buffer.limit() < bufferSize){
|
||||||
|
throw new Error("Failed to create buffer!");
|
||||||
|
}
|
||||||
openGLState.glViewport(width, height);
|
openGLState.glViewport(width, height);
|
||||||
GL40.glReadPixels(offsetX, offsetY, width, height, pixelFormat, type, buffer);
|
GL40.glReadPixels(offsetX, offsetY, width, height, pixelFormat, type, buffer);
|
||||||
Globals.renderingEngine.checkError();
|
Globals.renderingEngine.checkError();
|
||||||
@ -326,8 +338,6 @@ public class Framebuffer {
|
|||||||
rVal.setRGB(x, height - (y + 1), (alpha << 24) | (red << 16) | (green << 8) | blue);
|
rVal.setRGB(x, height - (y + 1), (alpha << 24) | (red << 16) | (green << 8) | blue);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
//memory management
|
|
||||||
MemoryUtil.memFree(buffer);
|
|
||||||
} catch (OutOfMemoryError e){
|
} catch (OutOfMemoryError e){
|
||||||
LoggerInterface.loggerRenderer.ERROR(new IllegalStateException(e.getMessage()));
|
LoggerInterface.loggerRenderer.ERROR(new IllegalStateException(e.getMessage()));
|
||||||
}
|
}
|
||||||
|
|||||||
@ -385,6 +385,12 @@ public class Texture {
|
|||||||
* @param datatype The data type of a single component of a pixel (ie GL_BYTE, GL_UNSIGNED_INT, etc)
|
* @param datatype The data type of a single component of a pixel (ie GL_BYTE, GL_UNSIGNED_INT, etc)
|
||||||
*/
|
*/
|
||||||
public void glTexImage2D(OpenGLState openGLState, int width, int height, int format, int datatype){
|
public void glTexImage2D(OpenGLState openGLState, int width, int height, int format, int datatype){
|
||||||
|
if(width < 1){
|
||||||
|
throw new Error("Invalid texture width " + width);
|
||||||
|
}
|
||||||
|
if(height < 1){
|
||||||
|
throw new Error("Invalid texture height " + height);
|
||||||
|
}
|
||||||
//store provided values
|
//store provided values
|
||||||
this.width = width;
|
this.width = width;
|
||||||
this.height = height;
|
this.height = height;
|
||||||
@ -420,6 +426,12 @@ public class Texture {
|
|||||||
* @param datatype The data type of a single component of a pixel (ie GL_BYTE, GL_UNSIGNED_INT, etc)
|
* @param datatype The data type of a single component of a pixel (ie GL_BYTE, GL_UNSIGNED_INT, etc)
|
||||||
*/
|
*/
|
||||||
public void glTextureStorage2D(OpenGLState openGLState, int width, int height, int format, int datatype){
|
public void glTextureStorage2D(OpenGLState openGLState, int width, int height, int format, int datatype){
|
||||||
|
if(width < 1){
|
||||||
|
throw new Error("Invalid texture width " + width);
|
||||||
|
}
|
||||||
|
if(height < 1){
|
||||||
|
throw new Error("Invalid texture height " + height);
|
||||||
|
}
|
||||||
//store provided values
|
//store provided values
|
||||||
this.width = width;
|
this.width = width;
|
||||||
this.height = height;
|
this.height = height;
|
||||||
@ -437,6 +449,12 @@ public class Texture {
|
|||||||
* @param data The data to populate the image with
|
* @param data The data to populate the image with
|
||||||
*/
|
*/
|
||||||
public void glTexImage2D(OpenGLState openGLState, int width, int height, int format, int datatype, ByteBuffer data){
|
public void glTexImage2D(OpenGLState openGLState, int width, int height, int format, int datatype, ByteBuffer data){
|
||||||
|
if(width < 1){
|
||||||
|
throw new Error("Invalid texture width " + width);
|
||||||
|
}
|
||||||
|
if(height < 1){
|
||||||
|
throw new Error("Invalid texture height " + height);
|
||||||
|
}
|
||||||
//store provided values
|
//store provided values
|
||||||
this.width = width;
|
this.width = width;
|
||||||
this.height = height;
|
this.height = height;
|
||||||
@ -461,6 +479,12 @@ public class Texture {
|
|||||||
* @param data The data to populate the image with
|
* @param data The data to populate the image with
|
||||||
*/
|
*/
|
||||||
public void glTexImage2D(OpenGLState openGLState, int internalFormat, int width, int height, int format, int datatype, ByteBuffer data){
|
public void glTexImage2D(OpenGLState openGLState, int internalFormat, int width, int height, int format, int datatype, ByteBuffer data){
|
||||||
|
if(width < 1){
|
||||||
|
throw new Error("Invalid texture width " + width);
|
||||||
|
}
|
||||||
|
if(height < 1){
|
||||||
|
throw new Error("Invalid texture height " + height);
|
||||||
|
}
|
||||||
//store provided values
|
//store provided values
|
||||||
this.width = width;
|
this.width = width;
|
||||||
this.height = height;
|
this.height = height;
|
||||||
@ -480,7 +504,7 @@ public class Texture {
|
|||||||
* @return The width
|
* @return The width
|
||||||
*/
|
*/
|
||||||
public int getWidth(){
|
public int getWidth(){
|
||||||
if(pixelFormat == -1){
|
if(width == -1){
|
||||||
throw new IllegalStateException(
|
throw new IllegalStateException(
|
||||||
"The width of the texture you are trying to query from has not been set yet." +
|
"The width of the texture you are trying to query from has not been set yet." +
|
||||||
" The texture was likely constructed by passing the opengl texture pointer into the texture object."
|
" The texture was likely constructed by passing the opengl texture pointer into the texture object."
|
||||||
@ -494,7 +518,7 @@ public class Texture {
|
|||||||
* @return The height
|
* @return The height
|
||||||
*/
|
*/
|
||||||
public int getHeight(){
|
public int getHeight(){
|
||||||
if(pixelFormat == -1){
|
if(height == -1){
|
||||||
throw new IllegalStateException(
|
throw new IllegalStateException(
|
||||||
"The height of the texture you are trying to query from has not been set yet." +
|
"The height of the texture you are trying to query from has not been set yet." +
|
||||||
" The texture was likely constructed by passing the opengl texture pointer into the texture object."
|
" The texture was likely constructed by passing the opengl texture pointer into the texture object."
|
||||||
|
|||||||
100
src/test/java/electrosphere/renderer/ui/UIExtensionTests.java
Normal file
100
src/test/java/electrosphere/renderer/ui/UIExtensionTests.java
Normal file
@ -0,0 +1,100 @@
|
|||||||
|
package electrosphere.renderer.ui;
|
||||||
|
|
||||||
|
import static org.junit.jupiter.api.Assertions.*;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
|
||||||
|
import org.junit.jupiter.api.extension.ExtendWith;
|
||||||
|
|
||||||
|
import static electrosphere.test.testutils.Assertions.*;
|
||||||
|
|
||||||
|
import electrosphere.engine.Globals;
|
||||||
|
import electrosphere.engine.Main;
|
||||||
|
import electrosphere.menu.WindowUtils;
|
||||||
|
import electrosphere.renderer.ui.elements.Div;
|
||||||
|
import electrosphere.test.annotations.IntegrationTest;
|
||||||
|
import electrosphere.test.template.extensions.StateCleanupCheckerExtension;
|
||||||
|
import electrosphere.test.testutils.EngineInit;
|
||||||
|
import electrosphere.test.testutils.TestEngineUtils;
|
||||||
|
import electrosphere.test.testutils.TestRenderingUtils;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tests to verify the ui test template (we're testing our own testing framework woooooo)
|
||||||
|
*/
|
||||||
|
@ExtendWith(StateCleanupCheckerExtension.class)
|
||||||
|
public class UIExtensionTests {
|
||||||
|
|
||||||
|
@IntegrationTest
|
||||||
|
public void test_StartupShutdown_NoThrow(){
|
||||||
|
assertDoesNotThrow(() -> {
|
||||||
|
Globals.WINDOW_DECORATED = false;
|
||||||
|
Globals.WINDOW_FULLSCREEN = true;
|
||||||
|
Globals.RUN_AUDIO = false;
|
||||||
|
Globals.RUN_SCRIPTS = false;
|
||||||
|
Globals.WINDOW_WIDTH = 1920;
|
||||||
|
Globals.WINDOW_HEIGHT = 1080;
|
||||||
|
EngineInit.initGraphicalEngine();
|
||||||
|
TestEngineUtils.flush();
|
||||||
|
|
||||||
|
Main.shutdown();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
@IntegrationTest
|
||||||
|
public void test_Screencapture_Match(){
|
||||||
|
Globals.WINDOW_DECORATED = false;
|
||||||
|
Globals.WINDOW_FULLSCREEN = true;
|
||||||
|
Globals.RUN_AUDIO = false;
|
||||||
|
Globals.RUN_SCRIPTS = false;
|
||||||
|
Globals.WINDOW_WIDTH = 1920;
|
||||||
|
Globals.WINDOW_HEIGHT = 1080;
|
||||||
|
EngineInit.initGraphicalEngine();
|
||||||
|
TestEngineUtils.flush();
|
||||||
|
|
||||||
|
TestEngineUtils.simulateFrames(3);
|
||||||
|
|
||||||
|
String canonicalName = this.getClass().getCanonicalName();
|
||||||
|
//check the render
|
||||||
|
assertEqualsRender("./test/java/renderer/ui/test_Screencapture_Match.png", () -> {
|
||||||
|
|
||||||
|
//on failure, save the failed render
|
||||||
|
String failureSavePath = "./.testcache/" + canonicalName + "-test_Screencapture_Match.png";
|
||||||
|
File saveFile = new File(failureSavePath);
|
||||||
|
System.err.println("[[ATTACHMENT|" + saveFile.getAbsolutePath() + "]]");
|
||||||
|
TestRenderingUtils.saveTestRender(failureSavePath);
|
||||||
|
});
|
||||||
|
Main.shutdown();
|
||||||
|
}
|
||||||
|
|
||||||
|
@IntegrationTest
|
||||||
|
public void test_Screencapture_Blank_Match(){
|
||||||
|
Globals.WINDOW_DECORATED = false;
|
||||||
|
Globals.WINDOW_FULLSCREEN = true;
|
||||||
|
Globals.RUN_AUDIO = false;
|
||||||
|
Globals.RUN_SCRIPTS = false;
|
||||||
|
Globals.WINDOW_WIDTH = 1920;
|
||||||
|
Globals.WINDOW_HEIGHT = 1080;
|
||||||
|
EngineInit.initGraphicalEngine();
|
||||||
|
TestEngineUtils.flush();
|
||||||
|
|
||||||
|
TestEngineUtils.simulateFrames(3);
|
||||||
|
|
||||||
|
WindowUtils.replaceMainMenuContents(Div.createDiv());
|
||||||
|
TestEngineUtils.flush();
|
||||||
|
TestEngineUtils.simulateFrames(2);
|
||||||
|
|
||||||
|
String canonicalName = this.getClass().getCanonicalName();
|
||||||
|
//check the render
|
||||||
|
assertEqualsRender("./test/java/renderer/ui/test_Screencapture_Blank.png", () -> {
|
||||||
|
|
||||||
|
//on failure, save the failed render
|
||||||
|
String failureSavePath = "./.testcache/" + canonicalName + "-test_Screencapture_Blank.png";
|
||||||
|
File saveFile = new File(failureSavePath);
|
||||||
|
System.err.println("[[ATTACHMENT|" + saveFile.getAbsolutePath() + "]]");
|
||||||
|
TestRenderingUtils.saveTestRender(failureSavePath);
|
||||||
|
});
|
||||||
|
|
||||||
|
Main.shutdown();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@ -2,8 +2,6 @@ package electrosphere.renderer.ui.elements;
|
|||||||
|
|
||||||
import electrosphere.test.annotations.IntegrationTest;
|
import electrosphere.test.annotations.IntegrationTest;
|
||||||
|
|
||||||
import org.junit.jupiter.api.Disabled;
|
|
||||||
|
|
||||||
import electrosphere.menu.WindowUtils;
|
import electrosphere.menu.WindowUtils;
|
||||||
import electrosphere.menu.mainmenu.MenuGeneratorsUITesting;
|
import electrosphere.menu.mainmenu.MenuGeneratorsUITesting;
|
||||||
import electrosphere.test.template.UITestTemplate;
|
import electrosphere.test.template.UITestTemplate;
|
||||||
@ -17,7 +15,6 @@ public class WindowTest extends UITestTemplate {
|
|||||||
/**
|
/**
|
||||||
* Tests creating a window
|
* Tests creating a window
|
||||||
*/
|
*/
|
||||||
@Disabled
|
|
||||||
@IntegrationTest
|
@IntegrationTest
|
||||||
public void testCreateWindow(){
|
public void testCreateWindow(){
|
||||||
//create ui testing window
|
//create ui testing window
|
||||||
@ -29,8 +26,8 @@ public class WindowTest extends UITestTemplate {
|
|||||||
|
|
||||||
TestEngineUtils.simulateFrames(60);
|
TestEngineUtils.simulateFrames(60);
|
||||||
|
|
||||||
// TestRenderingUtils.saveTestRender("./test/java/electrosphere/renderer/ui/elements/window.png");
|
// TestRenderingUtils.saveTestRender("./test/java/renderer/ui/elements/window.png");
|
||||||
this.checkRender("Basic", "./test/java/electrosphere/renderer/ui/elements/ui-test.png");
|
this.checkRender("Basic", "./test/java/renderer/ui/elements/ui-test.png");
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -5,10 +5,14 @@ import java.io.File;
|
|||||||
import org.junit.jupiter.api.Tag;
|
import org.junit.jupiter.api.Tag;
|
||||||
import org.junit.jupiter.api.extension.ExtendWith;
|
import org.junit.jupiter.api.extension.ExtendWith;
|
||||||
|
|
||||||
|
import electrosphere.menu.WindowUtils;
|
||||||
|
import electrosphere.renderer.ui.elements.Div;
|
||||||
import electrosphere.test.template.extensions.StateCleanupCheckerExtension;
|
import electrosphere.test.template.extensions.StateCleanupCheckerExtension;
|
||||||
import electrosphere.test.template.extensions.UIExtension;
|
import electrosphere.test.template.extensions.UIExtension;
|
||||||
|
|
||||||
import static electrosphere.test.testutils.Assertions.*;
|
import static electrosphere.test.testutils.Assertions.*;
|
||||||
|
|
||||||
|
import electrosphere.test.testutils.TestEngineUtils;
|
||||||
import electrosphere.test.testutils.TestRenderingUtils;
|
import electrosphere.test.testutils.TestRenderingUtils;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -40,4 +44,13 @@ public class UITestTemplate {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets up a blank view
|
||||||
|
*/
|
||||||
|
public void setupBlankView(){
|
||||||
|
WindowUtils.replaceMainMenuContents(Div.createDiv());
|
||||||
|
TestEngineUtils.flush();
|
||||||
|
TestEngineUtils.simulateFrames(2);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -19,6 +19,7 @@ public class StateCleanupCheckerExtension implements AfterEachCallback {
|
|||||||
Globals.clientSceneWrapper,
|
Globals.clientSceneWrapper,
|
||||||
Globals.clientScene,
|
Globals.clientScene,
|
||||||
Globals.signalSystem,
|
Globals.signalSystem,
|
||||||
|
Globals.threadManager,
|
||||||
Globals.renderingEngine,
|
Globals.renderingEngine,
|
||||||
Globals.audioEngine,
|
Globals.audioEngine,
|
||||||
Globals.javaPID,
|
Globals.javaPID,
|
||||||
@ -35,6 +36,9 @@ public class StateCleanupCheckerExtension implements AfterEachCallback {
|
|||||||
throw new Exception("Failed to cleanup state after test! " + object.toString());
|
throw new Exception("Failed to cleanup state after test! " + object.toString());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if(Globals.window != -1){
|
||||||
|
throw new Exception("Failed to cleanup global window pointer!");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -7,6 +7,7 @@ import org.junit.jupiter.api.extension.ExtensionContext;
|
|||||||
import electrosphere.engine.Globals;
|
import electrosphere.engine.Globals;
|
||||||
import electrosphere.engine.Main;
|
import electrosphere.engine.Main;
|
||||||
import electrosphere.test.testutils.EngineInit;
|
import electrosphere.test.testutils.EngineInit;
|
||||||
|
import electrosphere.test.testutils.TestEngineUtils;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Spins up an tears down generic ui environment
|
* Spins up an tears down generic ui environment
|
||||||
@ -18,9 +19,11 @@ public class UIExtension implements BeforeEachCallback, AfterEachCallback {
|
|||||||
Globals.WINDOW_DECORATED = false;
|
Globals.WINDOW_DECORATED = false;
|
||||||
Globals.WINDOW_FULLSCREEN = true;
|
Globals.WINDOW_FULLSCREEN = true;
|
||||||
Globals.RUN_AUDIO = false;
|
Globals.RUN_AUDIO = false;
|
||||||
|
Globals.RUN_SCRIPTS = false;
|
||||||
Globals.WINDOW_WIDTH = 1920;
|
Globals.WINDOW_WIDTH = 1920;
|
||||||
Globals.WINDOW_HEIGHT = 1080;
|
Globals.WINDOW_HEIGHT = 1080;
|
||||||
EngineInit.initGraphicalEngine();
|
EngineInit.initGraphicalEngine();
|
||||||
|
TestEngineUtils.flush();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@ -10,6 +10,7 @@ import javax.imageio.ImageIO;
|
|||||||
import java.awt.image.BufferedImage;
|
import java.awt.image.BufferedImage;
|
||||||
|
|
||||||
import electrosphere.engine.Globals;
|
import electrosphere.engine.Globals;
|
||||||
|
import electrosphere.engine.Main;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Custom assertion macros
|
* Custom assertion macros
|
||||||
@ -35,6 +36,7 @@ public class Assertions {
|
|||||||
try {
|
try {
|
||||||
testData = ImageIO.read(new File(existingRenderPath));
|
testData = ImageIO.read(new File(existingRenderPath));
|
||||||
} catch (IOException e){
|
} catch (IOException e){
|
||||||
|
Main.shutdown();
|
||||||
fail("Failed to read existing image path " + existingRenderPath);
|
fail("Failed to read existing image path " + existingRenderPath);
|
||||||
}
|
}
|
||||||
BufferedImage screenshot = Globals.renderingEngine.defaultFramebuffer.getPixels(Globals.renderingEngine.getOpenGLState());
|
BufferedImage screenshot = Globals.renderingEngine.defaultFramebuffer.getPixels(Globals.renderingEngine.getOpenGLState());
|
||||||
@ -43,6 +45,7 @@ public class Assertions {
|
|||||||
//width
|
//width
|
||||||
if(testData.getWidth() != screenshot.getWidth()){
|
if(testData.getWidth() != screenshot.getWidth()){
|
||||||
onFailure.run();
|
onFailure.run();
|
||||||
|
Main.shutdown();
|
||||||
}
|
}
|
||||||
assertEquals(testData.getWidth(), screenshot.getWidth());
|
assertEquals(testData.getWidth(), screenshot.getWidth());
|
||||||
|
|
||||||
@ -50,6 +53,7 @@ public class Assertions {
|
|||||||
//height
|
//height
|
||||||
if(testData.getHeight() != screenshot.getHeight()){
|
if(testData.getHeight() != screenshot.getHeight()){
|
||||||
onFailure.run();
|
onFailure.run();
|
||||||
|
Main.shutdown();
|
||||||
}
|
}
|
||||||
assertEquals(testData.getHeight(), screenshot.getHeight());
|
assertEquals(testData.getHeight(), screenshot.getHeight());
|
||||||
|
|
||||||
@ -79,6 +83,7 @@ public class Assertions {
|
|||||||
){
|
){
|
||||||
|
|
||||||
onFailure.run();
|
onFailure.run();
|
||||||
|
Main.shutdown();
|
||||||
String failMessage = "Colors aren't approximately the same!\n" +
|
String failMessage = "Colors aren't approximately the same!\n" +
|
||||||
"Color from disk: " + sourceRed + "," + sourceGreen + "," + sourceBlue + "," + sourceAlpha + "\n" +
|
"Color from disk: " + sourceRed + "," + sourceGreen + "," + sourceBlue + "," + sourceAlpha + "\n" +
|
||||||
"Color from render: " + renderRed + "," + renderGreen + "," + renderBlue + "," + renderAlpha + "\n"
|
"Color from render: " + renderRed + "," + renderGreen + "," + renderBlue + "," + renderAlpha + "\n"
|
||||||
|
|||||||
@ -114,6 +114,10 @@ public class TestEngineUtils {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(frames == 0){
|
||||||
|
TestEngineUtils.simulateFrames(1);
|
||||||
|
}
|
||||||
|
|
||||||
while(
|
while(
|
||||||
Globals.elementService.getSignalQueueCount() > 0
|
Globals.elementService.getSignalQueueCount() > 0
|
||||||
){
|
){
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 33 KiB After Width: | Height: | Size: 33 KiB |
BIN
test/java/renderer/ui/test_Screencapture_Blank.png
Normal file
BIN
test/java/renderer/ui/test_Screencapture_Blank.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 9.9 KiB |
BIN
test/java/renderer/ui/test_Screencapture_Match.png
Normal file
BIN
test/java/renderer/ui/test_Screencapture_Match.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 27 KiB |
Loading…
Reference in New Issue
Block a user