Added Base Application you can extend from and some small changes

This commit is contained in:
Speiger 2021-08-31 12:45:16 +02:00
parent 33eea0e28b
commit 306f20cd88
4 changed files with 408 additions and 1 deletions

View File

@ -0,0 +1,183 @@
package speiger.src.coreengine.application;
import java.io.File;
import java.util.function.IntConsumer;
import java.util.function.ObjLongConsumer;
import org.lwjgl.glfw.GLFW;
import org.lwjgl.glfw.GLFWErrorCallback;
import speiger.src.coreengine.assets.AssetManager;
import speiger.src.coreengine.assets.reloader.ResourceReloader;
import speiger.src.coreengine.rendering.gui.GuiManager;
import speiger.src.coreengine.rendering.gui.base.DebugOverlay;
import speiger.src.coreengine.rendering.input.Keyboard;
import speiger.src.coreengine.rendering.input.Mouse;
import speiger.src.coreengine.rendering.input.camera.Camera;
import speiger.src.coreengine.rendering.input.window.Window;
import speiger.src.coreengine.rendering.input.window.WindowProvider;
import speiger.src.coreengine.rendering.shader.ProjectionBuffer;
import speiger.src.coreengine.rendering.shader.ShaderTracker;
import speiger.src.coreengine.rendering.textures.TextureManager;
import speiger.src.coreengine.rendering.utils.Cursor;
import speiger.src.coreengine.utils.counters.timers.FPSTimer;
import speiger.src.coreengine.utils.eventbus.EventBus;
import speiger.src.coreengine.utils.helpers.FileUtils;
import speiger.src.coreengine.utils.profiler.GPUProfiler;
import speiger.src.coreengine.utils.profiler.IProfiler;
import speiger.src.coreengine.utils.profiler.Profiler;
public abstract class Application
{
protected FPSTimer timer;
protected ApplicationExecutor executor = new ApplicationExecutor(this);
protected IProfiler clientProfiler = new Profiler("Client Thread");
protected IProfiler gpuProfiler = new GPUProfiler("GPU", clientProfiler);
protected boolean showProfilingInfo = true;
protected WindowProvider provider = new WindowProvider();
protected Window mainWindow;
protected Camera camera;
protected EventBus eventBus = new EventBus();
protected ResourceReloader reloader = new ResourceReloader();
protected AssetManager assetManager;
protected ProjectionBuffer projectionBuffer;
protected GuiManager uiManager;
public void run()
{
GLFWErrorCallback.createPrint(System.err).set();
if(!GLFW.glfwInit()) throw new IllegalStateException("OpenGL can't be loaded");
provider.init();
try
{
mainWindow = createWindow(provider);
mainWindow.finishWindow();
}
catch(Exception e)
{
System.err.println("Could not create a Window!");
e.printStackTrace();
if(mainWindow != null) mainWindow.destroy();
provider.destroy();
System.exit(0);
return;
}
Thread.currentThread().setName("Client Thread");
File file = FileUtils.getBase();
file = file.getName().endsWith(".jar") ? file : new File("bin/main");
internalInit(file);
init(file);
executor.start(mainWindow);
mainWindow.destroy();
reloader.deleteResources();
destroy();
System.exit(0);
}
protected void internalInit(File file)
{
assetManager = reloader.addReloadableResource(new AssetManager(file), true);
ShaderTracker.INSTANCE.init(assetManager);
TextureManager.INSTANCE.init(assetManager);
reloader.addReloadableResource(ShaderTracker.INSTANCE);
reloader.addReloadableResource(TextureManager.INSTANCE);
camera = new Camera(mainWindow);
if(initUI()) uiManager = BaseUIManager.create(this);
Keyboard.INSTANCE.init(eventBus, mainWindow);
Mouse.INSTANCE.init(eventBus, mainWindow, camera);
reloader.addReloadableResource(Cursor.INSTANCE, true);
mainWindow.addListener(camera.getFrustrum(), true);
projectionBuffer = new ProjectionBuffer(camera, mainWindow);
}
public abstract String getMainWindowName();
public void addExtraTickRates(IntConsumer ticks) {};
public void addExtraTimers(ObjLongConsumer<String> profiler) {};
public boolean initUI() { return true; }
public DebugOverlay createCustomDebug() { return null; }
public abstract Window createWindow(WindowProvider provider) throws Exception;
public abstract void init(File file);
public abstract void update();
public abstract void render(float particalTicks);
public abstract void destroy();
protected final void updateInternal()
{
if(uiManager != null)
{
clientProfiler.start("UI");
uiManager.onFixedUpdate();
clientProfiler.stop();
}
clientProfiler.start("Input");
camera.onInput();
Mouse.update();
clientProfiler.stop();
update();
}
protected final void renderInternal(float particalTicks)
{
render(particalTicks);
if(uiManager != null)
{
gpuProfiler.start("UI");
uiManager.render(particalTicks);
gpuProfiler.stop();
}
gpuProfiler.start("camera");
camera.update(particalTicks);
gpuProfiler.stop();
}
public AssetManager getAssetManager()
{
return assetManager;
}
public ResourceReloader getReloader()
{
return reloader;
}
public Window getMainWindow()
{
return mainWindow;
}
public Camera getCamera()
{
return camera;
}
public EventBus getEventBus()
{
return eventBus;
}
public ProjectionBuffer getProjectionBuffer()
{
return projectionBuffer;
}
public FPSTimer getTimer()
{
return timer;
}
public GuiManager getUiManager()
{
return uiManager;
}
public IProfiler getClientProfiler()
{
return clientProfiler;
}
public IProfiler getGPUProfiler()
{
return gpuProfiler;
}
}

View File

@ -0,0 +1,143 @@
package speiger.src.coreengine.application;
import java.text.DecimalFormat;
import org.lwjgl.opengl.GL11;
import speiger.src.collections.objects.queues.ObjectArrayFIFOQueue;
import speiger.src.collections.objects.queues.ObjectPriorityQueue;
import speiger.src.coreengine.rendering.input.window.Window;
import speiger.src.coreengine.rendering.utils.AllocationTracker;
import speiger.src.coreengine.rendering.utils.GLStamper;
import speiger.src.coreengine.rendering.utils.GLStamper.GLStamp;
import speiger.src.coreengine.rendering.utils.GLUtils;
import speiger.src.coreengine.utils.counters.averager.TimeAverager;
import speiger.src.coreengine.utils.counters.timers.FPSTimer;
import speiger.src.coreengine.utils.counters.timers.FrameSyncer;
import speiger.src.coreengine.utils.counters.timers.TimerTarget;
import speiger.src.coreengine.utils.helpers.FileUtils;
import speiger.src.coreengine.utils.helpers.TextUtil;
import speiger.src.coreengine.utils.io.GameLog;
import speiger.src.coreengine.utils.io.GameLog.LogLevel;
import speiger.src.coreengine.utils.profiler.IProfiler;
public class ApplicationExecutor
{
public static final DecimalFormat FORMATTER = new DecimalFormat("###");
FPSTimer timer = new FPSTimer();
TimerTarget fps = timer.getFPS();
TimerTarget ups = timer.getUPS();
FrameSyncer sync = new FrameSyncer();
TimeAverager gpuTime = new TimeAverager();
ObjectPriorityQueue<GLStamp> stamps = new ObjectArrayFIFOQueue<>();
StringBuilder builder = new StringBuilder();
long frame = 0L;
Application owner;
public ApplicationExecutor(Application owner)
{
this.owner = owner;
owner.timer = timer;
}
private IProfiler gpu()
{
return owner.gpuProfiler;
}
public void start(Window window)
{
createTimeHacker();
timer.init();
try
{
while(window.shouldRun()) loop(window);
}
catch(Exception e)
{
GameLog.error("Client Has Crashed", e, LogLevel.ERROR);
}
}
private void loop(Window window)
{
GLStamp stamp = GLStamper.INSTANCE.createStamp("MainStamp").start();
stamps.enqueue(stamp);
gpu().start("Client").start("Update");
window.update();
for(long f = timer.getDelta();f >= ups.getTargetNS();f = timer.consumeDelta())
{
ups.tick();
owner.updateInternal();
builder.setLength(0);
builder.append(owner.getMainWindowName());
if(owner.showProfilingInfo) addDebugInfo(builder);
window.setTitle(builder.toString());
}
gpu().next("Render");
render(timer.getParticalTime());
gpu().next("Trackers");
boolean end = timer.update();
stamp.stop();
AllocationTracker.INSTANCE.update();
GLUtils.onFrameEnded();
gpu().next("Window").start("V-Sync");
window.finishFrame();
if(window.isCPULimited()) sync.sync(fps.getTargetTicks());
gpu().next("Input");
window.gatherInputs();
gpu().stop().stop().stop().onFrameEnded(end);
while(!stamps.isEmpty() && stamps.first().isFinished())
{
stamp = stamps.dequeue();
gpuTime.addEntry(stamp.getResult());
stamp.release();
}
frame++;
}
private void render(float particalTicks)
{
gpu().start("Prep");
fps.tick();
GL11.glClear(GL11.GL_COLOR_BUFFER_BIT | GL11.GL_DEPTH_BUFFER_BIT);
gpu().stop();
owner.renderInternal(particalTicks);
}
public void createTimeHacker()
{
Thread thread = new Thread(() -> {
while (true){
try {Thread.sleep(2147483647L);}
catch (InterruptedException e){}
}
}, "Time Fixer Thread");
thread.setDaemon(true);
thread.start();
}
protected void addDebugInfo(StringBuilder builder)
{
builder.append("(");
builder.append(fps.getTicks()).append(":").append(ups.getTicks());
owner.addExtraTickRates(T -> builder.append(":").append(T));
builder.append(",").append(getMemoryUsage());
builder.append(",").append("CPU-A: "+FileUtils.convertBytes(AllocationTracker.INSTANCE.getCPUAllocatedBytes()));
builder.append(",").append("GPU-A: "+FileUtils.convertBytes(AllocationTracker.INSTANCE.getGPUAllocatedBytes()));
builder.append(",").append(TextUtil.convertTime(timer.getUsage(), "Client:", FORMATTER));
builder.append(",").append(TextUtil.convertTime(gpuTime.getAverage(), "GPU:", FORMATTER));
owner.addExtraTimers((N, T) -> builder.append(",").append(TextUtil.convertTime(T, N, FORMATTER)));
builder.append(")");
}
private String getMemoryUsage()
{
Runtime time = Runtime.getRuntime();
long aviable = time.totalMemory();
return "Memory:"+((aviable - time.freeMemory()) >> 20)+"MB/"+(aviable >> 20)+"MB";
}
}

View File

@ -0,0 +1,81 @@
package speiger.src.coreengine.application;
import speiger.src.coreengine.rendering.gui.GuiManager;
import speiger.src.coreengine.rendering.gui.base.DebugOverlay;
import speiger.src.coreengine.rendering.models.UniformBuffer;
import speiger.src.coreengine.utils.collections.FlagHolder;
import speiger.src.coreengine.utils.profiler.EmptyProfiler;
import speiger.src.coreengine.utils.profiler.IProfiler;
public class BaseUIManager extends GuiManager
{
Application application;
public BaseUIManager(Application application)
{
super(application.mainWindow, application.eventBus);
this.application = application;
}
public static BaseUIManager create(Application app)
{
return new BaseUIManager(app) {
@Override
public DebugOverlay createOverlay()
{
DebugOverlay overlay = app.createCustomDebug();
return overlay != null ? overlay : new InternalDebugOverlay();
}
};
}
@Override
public IProfiler getGPUProfiler()
{
return application.gpuProfiler;
}
@Override
public IProfiler getCPUProfiler()
{
return application.clientProfiler;
}
@Override
public IProfiler getServerProfiler()
{
return EmptyProfiler.INSTANCE;
}
@Override
public UniformBuffer getOrthoMatrixBuffer()
{
return application.projectionBuffer.getOrthoViewMatrixBuffer();
}
@Override
public DebugOverlay createOverlay()
{
DebugOverlay overlay = application.createCustomDebug();
return overlay != null ? overlay : new InternalDebugOverlay();
}
public static class InternalDebugOverlay extends DebugOverlay
{
public static final int UPDATING = 1;
public static final int RENDERING = 2;
FlagHolder flags = new FlagHolder(RENDERING);
@Override
public void toggleUI() { flags.flipFlag(RENDERING); }
@Override
public void toggleUpdate() { flags.flipFlag(UPDATING); }
@Override
public void toggleDebug() {}
@Override
public boolean toggleFPS() { return false; }
@Override
public boolean isUpdating() { return flags.isFlagSet(UPDATING); }
@Override
public boolean isRendering() { return flags.isFlagSet(RENDERING); }
}
}

View File

@ -55,7 +55,7 @@ public class AllocationTracker
return cpuAllocation.getAverage();
}
public long getGPUAllocationBytes()
public long getGPUAllocatedBytes()
{
return gpuAllocation.getAverage();
}