Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 17 additions & 0 deletions src/main/java/engine/application/Application.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package engine.application;

import engine.input.Input;
import workspace.ui.Graphics;

public interface Application {

void initialize();

void update();

void render(Graphics g);

void cleanup();

void setInput(Input input);
}
63 changes: 63 additions & 0 deletions src/main/java/engine/application/ApplicationContainer.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
package engine.application;

import engine.input.Input;
import workspace.ui.Graphics;

public class ApplicationContainer {

private boolean isInitialized = false;

private Graphics graphics;

private Application application;

public ApplicationContainer(Application application) {
if (application == null) {
throw new IllegalArgumentException("Application cannot be null.");
}
this.application = application;
}

public void initialize() {
if (isInitialized) {
return;
}
application.initialize();
isInitialized = true;
}

public void update() {
application.update();
}

public void render() {
checkInitialization();
if (graphics == null) {
throw new IllegalStateException(
"Graphics context is not initialized. Call setGraphics() first.");
}
application.render(graphics);
}

public void cleanup() {
application.cleanup();
}

private void checkInitialization() {
if (!isInitialized) {
throw new IllegalStateException(
"ApplicationContainer is not initialized. Call initialize() first.");
}
}

public void setInput(Input input) {
application.setInput(input);
}

public void setGraphics(Graphics g) {
if (g == null) {
throw new IllegalArgumentException("Graphics cannot be null.");
}
this.graphics = g;
}
}
135 changes: 135 additions & 0 deletions src/main/java/engine/application/ApplicationSettings.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,135 @@
package engine.application;

/**
* Encapsulates configuration settings for an application, including dimensions, fullscreen mode,
* and title. Provides default values and validation for each setting.
*/
public class ApplicationSettings {

private static final String DEFAULT_TITLE = "Untitled-Application";

private int width;

private int height;

private boolean fullscreen;

private String title;

/**
* Constructs an ApplicationSettings instance with default values:
*
* <ul>
* <li>Width: 1024
* <li>Height: 768
* <li>Fullscreen: false
* <li>Title: "Untitled-Application"
* </ul>
*/
public ApplicationSettings() {
this.width = 1024;
this.height = 768;
this.fullscreen = false;
this.title = DEFAULT_TITLE;
}

/**
* Creates and returns an ApplicationSettings instance with default values.
*
* <ul>
* <li>Width: 1024
* <li>Height: 768
* <li>Fullscreen: false
* <li>Title: "Untitled-Application"
* </ul>
*
* @return A new {@link ApplicationSettings} instance with default values.
*/
public static ApplicationSettings defaultSettings() {
return new ApplicationSettings();
}

/**
* Gets the width of the application window.
*
* @return The width in pixels.
*/
public int getWidth() {
return width;
}

/**
* Sets the width of the application window.
*
* @param width The width in pixels. Must be greater than 0.
* @throws IllegalArgumentException if the width is less than or equal to 0.
*/
public void setWidth(int width) {
if (width <= 0) {
throw new IllegalArgumentException("Width must be greater than 0.");
}
this.width = width;
}

/**
* Gets the height of the application window.
*
* @return The height in pixels.
*/
public int getHeight() {
return height;
}

/**
* Sets the height of the application window.
*
* @param height The height in pixels. Must be greater than 0.
* @throws IllegalArgumentException if the height is less than or equal to 0.
*/
public void setHeight(int height) {
if (height <= 0) {
throw new IllegalArgumentException("Height must be greater than 0.");
}
this.height = height;
}

/**
* Checks if the application is set to fullscreen mode.
*
* @return {@code true} if fullscreen mode is enabled, {@code false} otherwise.
*/
public boolean isFullscreen() {
return fullscreen;
}

/**
* Sets whether the application should run in fullscreen mode.
*
* @param fullscreen {@code true} to enable fullscreen mode, {@code false} to disable it.
*/
public void setFullscreen(boolean fullscreen) {
this.fullscreen = fullscreen;
}

/**
* Gets the title of the application window.
*
* @return The title as a {@link String}.
*/
public String getTitle() {
return title;
}

/**
* Sets the title of the application window.
*
* @param title The title of the application window. Cannot be {@code null} or empty.
* @throws IllegalArgumentException if the title is {@code null} or empty.
*/
public void setTitle(String title) {
if (title == null || title.isEmpty()) {
throw new IllegalArgumentException("Title cannot be null or empty.");
}
this.title = title;
}
}
173 changes: 173 additions & 0 deletions src/main/java/engine/application/BasicApplication.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,173 @@
package engine.application;

import engine.Timer;
import engine.debug.DebugInfoUpdater;
import engine.debug.DebugOverlay;
import engine.debug.FpsGraph;
import engine.debug.FpsHistory;
import engine.input.Input;
import engine.input.Key;
import engine.processing.ProcessingApplication;
import engine.scene.Scene;
import engine.scene.SceneNode;
import workspace.ui.Graphics;

public abstract class BasicApplication implements Application {

private boolean launched;

private boolean displayInfoText = true;

private boolean isPaused = false;

private Timer timer;

protected Input input;

protected Scene activeScene;

protected SceneNode rootUI;

protected DebugOverlay debugOverlay;

protected DebugInfoUpdater debugInfoUpdater;

protected FpsGraph fpsGraph;

public BasicApplication() {
this.timer = new Timer();
}

public abstract void onInitialize();

public abstract void onUpdate(float tpf);

public abstract void onRender(Graphics g);

public abstract void onCleanup();

private boolean lastZ;

public void launch(ApplicationSettings settings) {
if (launched) {
throw new IllegalStateException("Application already launched.");
}
launched = true;
ApplicationContainer container = new ApplicationContainer(this);
ProcessingApplication.launchApplication(container, settings);
Runtime.getRuntime()
.addShutdownHook(
new Thread(
() -> {
System.out.println("Cleanup application.");
cleanup();
}));
}

public void launch() {
launch(ApplicationSettings.defaultSettings());
}

@Override
public void initialize() {
rootUI = new SceneNode();
initializeDebugOverlay();
fpsGraph = new FpsGraph(new FpsHistory());
onInitialize();
}

private void initializeDebugOverlay() {
debugOverlay = new DebugOverlay();
debugInfoUpdater = new DebugInfoUpdater(debugOverlay);
}

@Override
public void update() {
if (activeScene != null) {

if (input.isKeyPressed(Key.Z) && !lastZ) {
activeScene.setWireframeMode(!activeScene.isWireframeMode());
}

lastZ = input.isKeyPressed(Key.Z);
}

timer.update();
fpsGraph.update(timer);
debugInfoUpdater.update(timer, activeScene, input);

float tpf = timer.getTimePerFrame();
if (input != null) {
input.update();
}
if (!isPaused) {
if (activeScene != null) {
activeScene.update(tpf);
}
}
rootUI.update(tpf);
onUpdate(tpf);
}

@Override
public void render(Graphics g) {
if (activeScene != null) {
activeScene.render(g);
}

onRender(g);

g.disableDepthTest();
g.lightsOff();
g.camera();

g.strokeWeight(1);
renderUi(g);
renderDebugUi(g);
fpsGraph.render(g);

g.enableDepthTest();
}

private void renderUi(Graphics g) {
rootUI.render(g);
}

private void renderDebugUi(Graphics g) {
if (!displayInfoText) return;
debugOverlay.render(g);
}

@Override
public void cleanup() {
if (activeScene != null) {
activeScene.cleanup();
}
rootUI.cleanup();
onCleanup();
}

public void pause() {
isPaused = true;
}

public void resume() {
isPaused = false;
}

public void setInput(Input input) {
this.input = input;
}

public Input getInput() {
return input;
}

public Scene getActiveScene() {
return activeScene;
}

public void setActiveScene(Scene activeScene) {
this.activeScene = activeScene;
}
}
Loading
Loading