diff --git a/build.gradle b/build.gradle index 55c4f540..5cf71bb6 100644 --- a/build.gradle +++ b/build.gradle @@ -30,8 +30,7 @@ tasks.register("javadocAll", Javadoc) { ":base", ":ansi", ":slf4j-compat", - ":windowing", - ":windowing:glfw", + ":rendering", ":notification", ] diff --git a/windowing/README.md b/rendering/README.md similarity index 100% rename from windowing/README.md rename to rendering/README.md diff --git a/windowing/glfw/build.gradle b/rendering/build.gradle similarity index 88% rename from windowing/glfw/build.gradle rename to rendering/build.gradle index 88197aee..508cb332 100644 --- a/windowing/glfw/build.gradle +++ b/rendering/build.gradle @@ -61,16 +61,17 @@ dependencies { // LWJGL implementation(platform("org.lwjgl:lwjgl-bom:${dependencyLwjgl}")) implementation("org.lwjgl:lwjgl") - implementation("org.lwjgl:lwjgl-glfw") implementation("org.lwjgl:lwjgl-stb") + implementation("org.lwjgl:lwjgl-glfw") + implementation("org.lwjgl:lwjgl-bgfx") runtimeOnly("org.lwjgl:lwjgl::${dependencyLwjglNatives}") - runtimeOnly("org.lwjgl:lwjgl-glfw::${dependencyLwjglNatives}") runtimeOnly("org.lwjgl:lwjgl-stb::${dependencyLwjglNatives}") + runtimeOnly("org.lwjgl:lwjgl-glfw::${dependencyLwjglNatives}") + runtimeOnly("org.lwjgl:lwjgl-bgfx::${dependencyLwjglNatives}") if (project.dependencyLwjglNatives == "natives-macos" || project.dependencyLwjglNatives == "natives-macos-arm64") runtimeOnly("org.lwjgl:lwjgl-vulkan::${dependencyLwjglNatives}") // Project implementation(project(":base")) - implementation(project(":windowing")) } // Javadoc configuration @@ -96,26 +97,6 @@ javadoc { } } -// Unit testing configuration -test { - useJUnitPlatform() - - // Pass test configuration to test VMs - Map testConfiguration = new HashMap<>() - for (String property : project.properties.keySet()) - if (property.startsWith("test.")) - testConfiguration.put(property, project.properties.get(property).toString()) - systemProperties(testConfiguration) - - setMaxParallelForks(project.hasProperty("jobs") ? Integer.parseInt((String) project.property("jobs")) : 8) - setForkEvery(1) - setFailFast(true) - - testLogging { - events("passed", "skipped", "failed") - } -} - // Include javadoc and source jar during publishing java { withJavadocJar() diff --git a/windowing/gradle b/rendering/gradle similarity index 100% rename from windowing/gradle rename to rendering/gradle diff --git a/windowing/gradlew b/rendering/gradlew similarity index 100% rename from windowing/gradlew rename to rendering/gradlew diff --git a/windowing/gradlew.bat b/rendering/gradlew.bat similarity index 100% rename from windowing/gradlew.bat rename to rendering/gradlew.bat diff --git a/rendering/src/main/java/de/staropensource/engine/rendering/RenderingSubsystem.java b/rendering/src/main/java/de/staropensource/engine/rendering/RenderingSubsystem.java new file mode 100644 index 00000000..90e9692f --- /dev/null +++ b/rendering/src/main/java/de/staropensource/engine/rendering/RenderingSubsystem.java @@ -0,0 +1,323 @@ +/* + * STAROPENSOURCE ENGINE SOURCE FILE + * Copyright (c) 2024 The StarOpenSource Engine Authors + * Licensed under the GNU Affero General Public License v3 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +package de.staropensource.engine.rendering; + +import de.staropensource.engine.base.annotation.EngineSubsystem; +import de.staropensource.engine.base.annotation.EventListener; +import de.staropensource.engine.base.implementable.SubsystemClass; +import de.staropensource.engine.base.implementable.helper.EventHelper; +import de.staropensource.engine.base.logging.Logger; +import de.staropensource.engine.base.type.EventPriority; +import de.staropensource.engine.base.utility.Math; +import de.staropensource.engine.base.utility.information.EngineInformation; +import de.staropensource.engine.base.implementation.versioning.StarOpenSourceVersioningSystem; +import de.staropensource.engine.base.event.InternalEngineShutdownEvent; +import de.staropensource.engine.base.type.DependencyVector; +import de.staropensource.engine.base.utility.Miscellaneous; +import de.staropensource.engine.rendering.event.InputEvent; +import de.staropensource.engine.rendering.event.RenderingErrorEvent; +import de.staropensource.engine.rendering.exception.NotOnMainThreadException; +import de.staropensource.engine.rendering.type.Window; +import de.staropensource.engine.rendering.type.window.VsyncMode; +import lombok.Getter; +import org.jetbrains.annotations.NotNull; +import org.lwjgl.glfw.*; + +import java.util.LinkedHashMap; +import java.util.LinkedList; +import java.util.concurrent.atomic.AtomicReference; + +import static org.lwjgl.glfw.GLFW.*; + +/** + * Main class of the {@code rendering} subsystem. + * + * @since v1-alpha9 + */ +@EngineSubsystem +@SuppressWarnings({ "JavadocDeclaration" }) +public final class RenderingSubsystem extends SubsystemClass { + /** + * Contains the class instance. + * + * @since v1-alpha9 + * -- GETTER -- + * Returns the class instance. + * + * @return class instance unless the subsystem is uninitialized + * @since v1-alpha9 + */ + @Getter + private static RenderingSubsystem instance = null; + + /** + * The {@link GLFWErrorCallback} to use. + *

+ * Only declared publicly for freeing during engine shutdown. + * + * @since v1-alpha2 + */ + private GLFWErrorCallback errorCallback = null; + + // -----> Subsystem + /** + * Initializes this subsystem. + * + * @since v1-alpha9 + */ + public RenderingSubsystem() { + // Only allow one instance + if (instance == null) + instance = this; + else + Logger.crash("Only one instance of this class is allowed, use getInstance() instead of creating a new instance"); + } + + /** {@inheritDoc} */ + @Override + public @NotNull String getName() { + return "rendering"; + } + + /** {@inheritDoc} */ + @Override + public @NotNull DependencyVector getDependencyVector() { + return new DependencyVector.Builder() + .setIdentifier(getName()) + .setVersioningSystem(StarOpenSourceVersioningSystem.class) + .setVersion(EngineInformation.getVersioningString()) + .build(); + } + + /** {@inheritDoc} */ + @Override + public void initializeSubsystem() { + if (!Miscellaneous.onMainThread()) + Logger.crash("Unable to initialize the rendering subsystem whilst running on a non-main thread", new NotOnMainThreadException()); + + // Initialize WindowingSubsystemConfiguration and load it + new RenderingSubsystemConfiguration().loadConfiguration(); + + // Precompute event listeners + cacheEvents(); + initGlfw(); + + // Warn about subsystem and API instability + Logger.warn("The rendering subsystem is experimental. Subsystem and API stability are not guaranteed."); + } + + /** + * Caches all windowing subsystem events. + * + * @since v1-alpha9 + */ + private void cacheEvents() { + EventHelper.cacheEvent(RenderingErrorEvent.class); + EventHelper.cacheEvent(InputEvent.class); + } + + /** + * Initializes GLFW. + * + * @since v1-alpha9 + */ + private void initGlfw() { + try { + Logger.verb("Initializing GLFW"); + + // Set error callback + Logger.diag("Setting error callback"); + errorCallback = GLFWErrorCallback.create((error, description) -> new RenderingErrorEvent().callEvent("GLFW: " + GLFWErrorCallback.getDescription(description) + " [" + error + "]")).set(); + + // Set init hints + Logger.diag("Setting initialization hints"); + switch (RenderingSubsystemConfiguration.getInstance().getInitialPlatform()) { + case ANY -> glfwInitHint(GLFW_PLATFORM, GLFW_ANY_PLATFORM); + case WAYLAND -> tryPlatform(GLFW_PLATFORM_WAYLAND); + case X11 -> tryPlatform(GLFW_PLATFORM_X11); + case WIN32 -> tryPlatform(GLFW_PLATFORM_WIN32); + case COCOA -> tryPlatform(GLFW_PLATFORM_COCOA); + case NONE -> glfwInitHint(GLFW_PLATFORM, GLFW_PLATFORM_NULL); + } + glfwInitHint(GLFW_WAYLAND_LIBDECOR, RenderingSubsystemConfiguration.getInstance().isInitialDisableLibdecor() ? GLFW_WAYLAND_DISABLE_LIBDECOR : GLFW_WAYLAND_PREFER_LIBDECOR); + + // Initialize GLFW + Logger.diag("Invoking glfwInit"); + if (!glfwInit()) + Logger.crash("Failed to initialize GLFW"); + } catch (UnsatisfiedLinkError error) { + Logger.crash("Failed to load LWJGL native libraries", error); + } + } + + /** + * Shuts the subsystem down. + * + * @since v1-alpha9 + */ + @EventListener(event = InternalEngineShutdownEvent.class) + @SuppressWarnings({ "unused" }) + protected static void shutdownSubsystem() { + if (instance == null) + return; + + Logger.verb("Shutting down"); + + long shutdownTime = Miscellaneous.measureExecutionTime(() -> { + // Close all windows + for (Window window : Window.getWindows()) + window.close(); + + instance.errorCallback.free(); + glfwTerminate(); + }); + + Logger.info("Shut down in " + shutdownTime + "ms"); + } + + /** + * Logs about rendering errors. + * + * @see RenderingSubsystemConfiguration#errorRenderingFailures + * @since v1-alpha9 + */ + @EventListener(event = RenderingErrorEvent.class, priority = EventPriority.EXCLUSIVELY_IMPORTANT) + private static void logRenderingError(@NotNull String error) { + Logger.error("Rendering error occurred: " + error); + } + + // -----> APIs + /** + * Renders all windows once. + * To render all windows continuously, invoke + * {@link #runRenderLoop(Runnable)} instead. + * + * @return map of windows and their {@link Throwable}s + * @throws NotOnMainThreadException if not running on the main thread + * @since v1-alpha9 + */ + public LinkedHashMap<@NotNull Window, @NotNull Throwable> renderWindows() throws NotOnMainThreadException { + // Ensure running on the main thread + if (!Miscellaneous.onMainThread()) + throw new NotOnMainThreadException(); + + LinkedHashMap<@NotNull Window, @NotNull Throwable> throwables = new LinkedHashMap<>(); + + // Update and render all windows + for (Window window : Window.getWindows()) { + if (!window.isRendering()) + continue; + + try { + window.updateState(); + window.render(); + } catch (Throwable throwable) { + Logger.error("Rendering window " + window + " failed: Threw throwable " + throwable.getClass().getName() + (throwable.getMessage() == null ? "" : ": " + throwable.getMessage())); + throwables.put(window, throwable); + } + } + + // Poll for events + glfwPollEvents(); + + return throwables; + } + /** + * Renders all windows continuously. + * To render all windows just once, invoke + * {@link #renderWindows()} instead. + *

+ * Immediately returns when a {@link #renderWindows()} call fails. + * + * @param frameCode code which shall be invoked before a frame is rendered + * @return see {@link #renderWindows()} (on failure) + * @throws NotOnMainThreadException if not running on the main thread + * @since v1-alpha9 + */ + public LinkedHashMap<@NotNull Window, @NotNull Throwable> runRenderLoop(@NotNull Runnable frameCode) throws NotOnMainThreadException { + // Ensure running on the main thread + if (!Miscellaneous.onMainThread()) + throw new NotOnMainThreadException(); + + // Define variables + AtomicReference> output = new AtomicReference<>(new LinkedHashMap<>()); // runRenderLoop output + long renderTime; // Amount of time spent rendering + long sleepDuration; // Time spent sleeping the thread + LinkedList splitDeltaTime = new LinkedList<>(); // Used for calculating the delta time (render time average over one second) + long reportDuration = System.currentTimeMillis() + 1000; // Used for determining when to report frame count and delta time + double deltaTime; // Contains the average render time over one second (delta time) + + // Check if delta time and frame count shall be printed to console. + // Unless this code is ran 292 billion years into the future, + // this should sufficiently disable the reporting feature. + if (!RenderingSubsystemConfiguration.getInstance().isDebugFrames()) + reportDuration = Long.MAX_VALUE; + + // Run while the 'output' is empty + while (output.get().isEmpty()) { + renderTime = Miscellaneous.measureExecutionTime(() -> { + output.set(renderWindows()); + frameCode.run(); + }); + + if (RenderingSubsystemConfiguration.getInstance().getVsyncMode() != VsyncMode.OFF) + // V-Sync is enabled, no need for manual busy waiting + sleepDuration = 0L; + else + // Calculate amount of time the thread should spend sleeping + sleepDuration = (long) (1d / RenderingSubsystemConfiguration.getInstance().getMaximumFramesPerSecond() * 1000d) - renderTime; + // Add render and sleep time to list used for calculating the delta time value + splitDeltaTime.add(renderTime + sleepDuration); + + // Busy wait unless V-Sync is enabled + if (RenderingSubsystemConfiguration.getInstance().getVsyncMode() == VsyncMode.OFF && RenderingSubsystemConfiguration.getInstance().getMaximumFramesPerSecond() >= 1) { + sleepDuration += System.currentTimeMillis(); + while (System.currentTimeMillis() < sleepDuration) + Thread.onSpinWait(); + } + + // Calculate delta time and frame count every second + if (System.currentTimeMillis() >= reportDuration) { + deltaTime = Math.getMeanLong(splitDeltaTime); // Calculate delta time + Logger.diag("Delta time average: " + deltaTime + " | Frames/s: " + 1000 / deltaTime); // Print delta time and frame count to console + + reportDuration = System.currentTimeMillis() + 1000; // Update 'reportDuration' + splitDeltaTime.clear(); // Clear 'splitDeltaTime' list + } + } + + return output.get(); + } + + // -----> Utility methods + /** + * Checks if the specified platform is compatible, + * and if so, specifies it as the platform to use. + * + * @param platform platform to try + * @since v1-alpha9 + */ + private void tryPlatform(int platform) { + if (glfwPlatformSupported(platform)) + glfwInitHint(GLFW_PLATFORM, platform); + else + glfwInitHint(GLFW_PLATFORM, GLFW_ANY_PLATFORM); + } +} diff --git a/rendering/src/main/java/de/staropensource/engine/rendering/RenderingSubsystemConfiguration.java b/rendering/src/main/java/de/staropensource/engine/rendering/RenderingSubsystemConfiguration.java new file mode 100644 index 00000000..32ed27cc --- /dev/null +++ b/rendering/src/main/java/de/staropensource/engine/rendering/RenderingSubsystemConfiguration.java @@ -0,0 +1,311 @@ +/* + * STAROPENSOURCE ENGINE SOURCE FILE + * Copyright (c) 2024 The StarOpenSource Engine Authors + * Licensed under the GNU Affero General Public License v3 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +package de.staropensource.engine.rendering; + +import de.staropensource.engine.base.implementable.Configuration; +import de.staropensource.engine.base.logging.Logger; +import de.staropensource.engine.base.utility.PropertiesReader; +import de.staropensource.engine.rendering.event.RenderingErrorEvent; +import de.staropensource.engine.rendering.type.window.RenderingPlatform; +import de.staropensource.engine.rendering.type.window.VsyncMode; +import lombok.Getter; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +/** + * Provides the configuration for the rendering subsystem. + * + * @since v1-alpha9 + */ +@Getter +@SuppressWarnings({ "JavadocDeclaration" }) +public final class RenderingSubsystemConfiguration extends Configuration { + /** + * Contains the class instance. + * + * @since v1-alpha9 + * -- GETTER -- + * Returns the class instance. + * + * @return class instance unless {@link RenderingSubsystem} is uninitialized + * @since v1-alpha9 + */ + @Getter + private static RenderingSubsystemConfiguration instance; + + /** + * Contains the configuration prefix. + * + * @since v1-alpha9 + * -- GETTER -- + * Returns the configuration prefix. + * + * @return property group + * @since v1-alpha9 + */ + @Getter + public final @NotNull String group = "sosengine.rendering."; + + /** + * Contains if debugging options should be allowed. + * All debugging options will be forcefully set to + * {@code false} if this option is set to {@code false}. + * + * @since v1-alpha9 + * -- GETTER -- + * Returns if debugging options should be allowed. + * All debugging options will be forcefully set to + * {@code false} if this option is set to {@code false}. + * + * @return debugging enabled? + * @since v1-alpha9 + */ + private boolean debug; + + /** + * Contains whether or not key presses + * and releases should be logged. + * + * @since v1-alpha9 + * -- GETTER -- + * Returns whether or not key presses + * and releases should be logged. + * + * @return log key presses and releases? + * @since v1-alpha9 + */ + private boolean debugInput; + + /** + * Contains whether or not the delta time and + * FPS count should be logged to the console + * every second. + *

+ * Changes will no longer be picked up as + * soon as the rendering loop is running. + * + * @since v1-alpha9 + * -- GETTER -- + * Returns whether or not the delta time and + * FPS count should be logged to the console + * every second. + *

+ * Changes will no longer be picked up as + * soon as the rendering loop is running. + * + * @return print delta time and FPS count? + * @since v1-alpha9 + */ + private boolean debugFrames; + + + /** + * Contains the platform GLFW shall try initialising. + * + * @since v1-alpha9 + * -- GETTER -- + * Returns the platform GLFW shall try initialising. + * + * @return GLFW platform + * @since v1-alpha9 + */ + private RenderingPlatform initialPlatform; + + /** + * Contains whether or not to disable support for + * libdecor. + *

+ * Only affects the {@link RenderingPlatform#WAYLAND} platform. + * + * @since v1-alpha9 + * -- GETTER -- + * Returns whether or not to disable support for + * libdecor. + *

+ * Only affects the {@link RenderingPlatform#WAYLAND} platform. + * + * @return libdecor support disabled? + * @since v1-alpha9 + */ + private boolean initialDisableLibdecor; + + + /** + * Contains whether or not rendering + * errors should be logged. + *

+ * The {@link RenderingErrorEvent} will + * be emitted anyway, regardless of the + * value of this variable. + * + * @see RenderingErrorEvent + * @since v1-alpha9 + * -- GETTER -- + * Returns whether or not rendering + * errors should be logged. + *

+ * The {@link RenderingErrorEvent} will + * be emitted anyway, regardless of the + * value of this variable. + * + * @return log rendering failures? + * @see RenderingErrorEvent + * @since v1-alpha9 + */ + private boolean errorRenderingFailures; + + + /** + * Contains which {@link VsyncMode} to use. + *

+ * This setting determines if and how V-Sync + * will operate, which (if enabled) tries to + * synchronize the frame rate to the monitor's + * refresh rate. See {@link VsyncMode} + * for more information. + * + * @see VsyncMode + * @since v1-alpha9 + * -- GETTER -- + * Returns which {@link VsyncMode} to use. + *

+ * This setting determines if and how V-Sync + * will operate, which (if enabled) tries to + * synchronize the frame rate to the monitor's + * refresh rate. See {@link VsyncMode} + * for more information. + * + * @return active V-Sync mode + * @see VsyncMode + * @since v1-alpha9 + */ + private VsyncMode vsyncMode; + + /** + * Contains the maximum value of frames + * which can be rendered per second. + *

+ * This value will have no effect on + * windows with V-Sync enabled. + * Set to {@code 0} for effectively + * no limit. Not recommended. + * + * @since v1-alpha9 + * -- GETTER -- + * Returns the maximum value of frames + * which can be rendered per second. + *

+ * This value will have no effect on + * windows with V-Sync enabled. + * Set to {@code 0} for effectively + * no limit. Not recommended. + * + * @return maximum amount of frames per second + * @since v1-alpha9 + */ + private int maximumFramesPerSecond; + + /** + * Creates and initializes an instance of this class. + * + * @see RenderingSubsystem + * @since v1-alpha9 + */ + RenderingSubsystemConfiguration() { + instance = this; + + loadDefaultConfiguration(); + } + + /** {@inheritDoc} */ + @Override + protected void matchProperty(@NotNull PropertiesReader parser, @NotNull String property) { + switch (property) { + case "debug" -> debug = parser.getBoolean(group + property); + case "debugInput" -> debugInput = parser.getBoolean(group + property); + case "debugFrames" -> debugFrames = parser.getBoolean(group + property); + + case "initialPlatform" -> { + try { + initialPlatform = RenderingPlatform.valueOf(parser.getString(group + property).toUpperCase()); + } catch (IllegalArgumentException ignored) { + Logger.error("Platform " + parser.getString(group + property) + " is not valid"); + } + } + case "initialDisableLibdecor" -> initialDisableLibdecor = parser.getBoolean(group + property); + + case "errorRenderingFailures" -> errorRenderingFailures = parser.getBoolean(group + property); + + case "vsyncMode" -> { + try { + vsyncMode = VsyncMode.valueOf(parser.getString(group + property).toUpperCase()); + } catch (IllegalArgumentException exception) { + Logger.error("V-Sync mode " + parser.getString(group + property) + " is not valid"); + } + } + case "maximumFramesPerSecond" -> maximumFramesPerSecond = parser.getInteger(group + property, true); + } + } + + /** {@inheritDoc} */ + @Override + protected void processSettings(@NotNull PropertiesReader parser) { + // Disable all debug options if 'debug' is disabled + if (!debug) { + debugInput = false; + debugFrames = false; + } + } + + /** {@inheritDoc} */ + @Override + public void loadDefaultConfiguration() { + debug = false; + debugInput = false; + debugFrames = false; + + initialPlatform = RenderingPlatform.ANY; + initialDisableLibdecor = false; + + errorRenderingFailures = true; + + vsyncMode = VsyncMode.ON; + maximumFramesPerSecond = 60; + } + + /** {@inheritDoc} */ + @Override + public @Nullable Object getSetting(@NotNull String setting) { + switch (setting) { + case "debug" -> { return debug; } + case "debugInput" -> { return debugInput; } + case "debugFrames" -> { return debugFrames; } + + case "initialPlatform" -> { return initialPlatform; } + case "disableLibdecor" -> { return initialDisableLibdecor; } + + case "errorRenderingFailures" -> { return errorRenderingFailures; } + + case "vsyncMode" -> { return vsyncMode; } + case "maximumFramesPerSecond" -> { return maximumFramesPerSecond; } + default -> { return null; } + } + } +} diff --git a/windowing/glfw/src/main/java/de/staropensource/engine/windowing/glfw/callback/KeyCallback.java b/rendering/src/main/java/de/staropensource/engine/rendering/callback/KeyCallback.java similarity index 95% rename from windowing/glfw/src/main/java/de/staropensource/engine/windowing/glfw/callback/KeyCallback.java rename to rendering/src/main/java/de/staropensource/engine/rendering/callback/KeyCallback.java index 00b288f7..28fe6aab 100644 --- a/windowing/glfw/src/main/java/de/staropensource/engine/windowing/glfw/callback/KeyCallback.java +++ b/rendering/src/main/java/de/staropensource/engine/rendering/callback/KeyCallback.java @@ -17,13 +17,13 @@ * along with this program. If not, see . */ -package de.staropensource.engine.windowing.glfw.callback; +package de.staropensource.engine.rendering.callback; -import de.staropensource.engine.windowing.implementable.Window; -import de.staropensource.engine.windowing.event.InputEvent; -import de.staropensource.engine.windowing.glfw.implementable.WindowCallback; -import de.staropensource.engine.windowing.type.input.Key; -import de.staropensource.engine.windowing.type.input.KeyState; +import de.staropensource.engine.rendering.type.Window; +import de.staropensource.engine.rendering.event.InputEvent; +import de.staropensource.engine.rendering.callback.WindowCallback; +import de.staropensource.engine.rendering.type.input.Key; +import de.staropensource.engine.rendering.type.input.KeyState; import org.jetbrains.annotations.NotNull; import org.lwjgl.glfw.GLFWKeyCallbackI; @@ -32,7 +32,7 @@ import static org.lwjgl.glfw.GLFW.*; /** * A {@link GLFWKeyCallbackI} implementation, which emits {@link InputEvent}. * - * @since v1-alpha2 + * @since v1-alpha9 */ public final class KeyCallback extends WindowCallback implements GLFWKeyCallbackI { /** @@ -40,7 +40,7 @@ public final class KeyCallback extends WindowCallback implements GLFWKeyCallback * and making too many allocations, which would potentially decrease * performance. * - * @since v1-alpha2 + * @since v1-alpha9 */ private static final InputEvent event = new InputEvent(); @@ -48,7 +48,7 @@ public final class KeyCallback extends WindowCallback implements GLFWKeyCallback * Creates and initializes an instance of this class. * * @param window {@link Window} class - * @since v1-alpha2 + * @since v1-alpha9 */ public KeyCallback(@NotNull Window window) { super(window); diff --git a/windowing/glfw/src/main/java/de/staropensource/engine/windowing/glfw/callback/MouseButtonCallback.java b/rendering/src/main/java/de/staropensource/engine/rendering/callback/MouseButtonCallback.java similarity index 86% rename from windowing/glfw/src/main/java/de/staropensource/engine/windowing/glfw/callback/MouseButtonCallback.java rename to rendering/src/main/java/de/staropensource/engine/rendering/callback/MouseButtonCallback.java index 44164848..bf121f05 100644 --- a/windowing/glfw/src/main/java/de/staropensource/engine/windowing/glfw/callback/MouseButtonCallback.java +++ b/rendering/src/main/java/de/staropensource/engine/rendering/callback/MouseButtonCallback.java @@ -17,13 +17,12 @@ * along with this program. If not, see . */ -package de.staropensource.engine.windowing.glfw.callback; +package de.staropensource.engine.rendering.callback; -import de.staropensource.engine.windowing.implementable.Window; -import de.staropensource.engine.windowing.event.InputEvent; -import de.staropensource.engine.windowing.glfw.implementable.WindowCallback; -import de.staropensource.engine.windowing.type.input.Key; -import de.staropensource.engine.windowing.type.input.KeyState; +import de.staropensource.engine.rendering.type.Window; +import de.staropensource.engine.rendering.event.InputEvent; +import de.staropensource.engine.rendering.type.input.Key; +import de.staropensource.engine.rendering.type.input.KeyState; import org.jetbrains.annotations.NotNull; import org.lwjgl.glfw.GLFWMouseButtonCallbackI; @@ -32,7 +31,7 @@ import static org.lwjgl.glfw.GLFW.*; /** * A {@link GLFWMouseButtonCallbackI} implementation, which forward them to {@link InputEvent}. * - * @since v1-alpha2 + * @since v1-alpha9 */ public final class MouseButtonCallback extends WindowCallback implements GLFWMouseButtonCallbackI { /** @@ -40,7 +39,7 @@ public final class MouseButtonCallback extends WindowCallback implements GLFWMou * and making too many allocations, which would potentially decrease * performance. * - * @since v1-alpha2 + * @since v1-alpha9 */ private static final InputEvent event = new InputEvent(); @@ -48,7 +47,7 @@ public final class MouseButtonCallback extends WindowCallback implements GLFWMou * Creates and initializes an instance of this class. * * @param window {@link Window} class - * @since v1-alpha2 + * @since v1-alpha9 */ public MouseButtonCallback(@NotNull Window window) { super(window); @@ -72,7 +71,7 @@ public final class MouseButtonCallback extends WindowCallback implements GLFWMou case GLFW_MOUSE_BUTTON_RIGHT -> Key.MOUSE_RIGHT; case GLFW_MOUSE_BUTTON_4, GLFW_MOUSE_BUTTON_5, GLFW_MOUSE_BUTTON_6, GLFW_MOUSE_BUTTON_7, - GLFW_MOUSE_BUTTON_8 -> Key.UNKNOWN_MOUSE; + GLFW_MOUSE_BUTTON_8 -> Key.UNKNOWN_MOUSE_BUTTON; default -> throw new IllegalStateException("Mouse button " + key + " is invalid"); }, // Key state diff --git a/windowing/glfw/src/main/java/de/staropensource/engine/windowing/glfw/implementable/WindowCallback.java b/rendering/src/main/java/de/staropensource/engine/rendering/callback/WindowCallback.java similarity index 88% rename from windowing/glfw/src/main/java/de/staropensource/engine/windowing/glfw/implementable/WindowCallback.java rename to rendering/src/main/java/de/staropensource/engine/rendering/callback/WindowCallback.java index 3cce3b2e..13f15787 100644 --- a/windowing/glfw/src/main/java/de/staropensource/engine/windowing/glfw/implementable/WindowCallback.java +++ b/rendering/src/main/java/de/staropensource/engine/rendering/callback/WindowCallback.java @@ -17,9 +17,9 @@ * along with this program. If not, see . */ -package de.staropensource.engine.windowing.glfw.implementable; +package de.staropensource.engine.rendering.callback; -import de.staropensource.engine.windowing.implementable.Window; +import de.staropensource.engine.rendering.type.Window; import lombok.Getter; import org.jetbrains.annotations.NotNull; @@ -27,7 +27,7 @@ import org.jetbrains.annotations.NotNull; * Abstract class used for easily implementing * callbacks which require a {@link Window} instance. * - * @since v1-alpha2 + * @since v1-alpha9 */ @Getter @SuppressWarnings({ "JavadocDeclaration" }) @@ -36,13 +36,13 @@ public class WindowCallback { * Refers to the {@link Window} instance * this callback is tied to. * - * @since v1-alpha2 + * @since v1-alpha9 * -- GETTER -- * Returns the {@link Window} instance * this callback is tied to. * * @return attached {@link Window} instance - * @since v1-alpha2 + * @since v1-alpha9 */ private final @NotNull Window attachedWindow; @@ -50,7 +50,7 @@ public class WindowCallback { * Creates and initializes an instance of this abstract class. * * @param window {@link Window} class - * @since v1-alpha2 + * @since v1-alpha9 */ public WindowCallback(@NotNull Window window) { this.attachedWindow = window; diff --git a/windowing/glfw/src/main/java/de/staropensource/engine/windowing/glfw/callback/package-info.java b/rendering/src/main/java/de/staropensource/engine/rendering/callback/package-info.java similarity index 92% rename from windowing/glfw/src/main/java/de/staropensource/engine/windowing/glfw/callback/package-info.java rename to rendering/src/main/java/de/staropensource/engine/rendering/callback/package-info.java index 8dc481a3..4029cc3e 100644 --- a/windowing/glfw/src/main/java/de/staropensource/engine/windowing/glfw/callback/package-info.java +++ b/rendering/src/main/java/de/staropensource/engine/rendering/callback/package-info.java @@ -20,6 +20,6 @@ /** * Callbacks, which emit {@link de.staropensource.engine.base.implementable.Event}s. * - * @since v1-alpha2 + * @since v1-alpha9 */ -package de.staropensource.engine.windowing.glfw.callback; +package de.staropensource.engine.rendering.callback; diff --git a/windowing/src/main/java/de/staropensource/engine/windowing/event/InputEvent.java b/rendering/src/main/java/de/staropensource/engine/rendering/event/InputEvent.java similarity index 83% rename from windowing/src/main/java/de/staropensource/engine/windowing/event/InputEvent.java rename to rendering/src/main/java/de/staropensource/engine/rendering/event/InputEvent.java index 8717d514..7d2a7d18 100644 --- a/windowing/src/main/java/de/staropensource/engine/windowing/event/InputEvent.java +++ b/rendering/src/main/java/de/staropensource/engine/rendering/event/InputEvent.java @@ -17,28 +17,28 @@ * along with this program. If not, see . */ -package de.staropensource.engine.windowing.event; +package de.staropensource.engine.rendering.event; import de.staropensource.engine.base.implementable.Event; import de.staropensource.engine.base.implementable.helper.EventHelper; import de.staropensource.engine.base.logging.Logger; -import de.staropensource.engine.windowing.WindowingSubsystemConfiguration; -import de.staropensource.engine.windowing.implementable.Window; -import de.staropensource.engine.windowing.type.input.Key; -import de.staropensource.engine.windowing.type.input.KeyState; +import de.staropensource.engine.rendering.RenderingSubsystemConfiguration; +import de.staropensource.engine.rendering.type.Window; +import de.staropensource.engine.rendering.type.input.Key; +import de.staropensource.engine.rendering.type.input.KeyState; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; /** * Called when a key or button is pressed. * - * @since v1-alpha2 + * @since v1-alpha9 */ public final class InputEvent implements Event { /** * Creates and initializes an instance of this event. * - * @since v1-alpha2 + * @since v1-alpha9 */ public InputEvent() {} @@ -57,10 +57,10 @@ public final class InputEvent implements Event { * @param window window the input originated from. May be {@code null}, depending on the windowing API * @param key key * @param state key state - * @since v1-alpha0 + * @since v1-alpha9 */ public void callEvent(@Nullable Window window, @NotNull Key key, @NotNull KeyState state) { - if (WindowingSubsystemConfiguration.getInstance().isDebugInput()) + if (RenderingSubsystemConfiguration.getInstance().isDebugInput()) Logger.diag("Got input event: window=" + (window == null ? "\\" : window.getUniqueIdentifier()) + " key=" + key.name() + " state=" + state.name()); EventHelper.invokeAnnotatedMethods(getClass(), window, key, state); diff --git a/windowing/src/main/java/de/staropensource/engine/windowing/event/RenderingErrorEvent.java b/rendering/src/main/java/de/staropensource/engine/rendering/event/RenderingErrorEvent.java similarity index 87% rename from windowing/src/main/java/de/staropensource/engine/windowing/event/RenderingErrorEvent.java rename to rendering/src/main/java/de/staropensource/engine/rendering/event/RenderingErrorEvent.java index cbbd63e9..3925a35a 100644 --- a/windowing/src/main/java/de/staropensource/engine/windowing/event/RenderingErrorEvent.java +++ b/rendering/src/main/java/de/staropensource/engine/rendering/event/RenderingErrorEvent.java @@ -17,29 +17,30 @@ * along with this program. If not, see . */ -package de.staropensource.engine.windowing.event; +package de.staropensource.engine.rendering.event; import de.staropensource.engine.base.implementable.Event; import de.staropensource.engine.base.implementable.helper.EventHelper; import org.jetbrains.annotations.NotNull; /** - * Called when an error occurs in the renderer API (e.g. OpenGL, Vulkan). + * Emitted when a rendering error occurs. * - * @since v1-alpha0 + * @since v1-alpha9 */ public final class RenderingErrorEvent implements Event { /** * Creates and initializes an instance of this event. * - * @since v1-alpha0 + * @since v1-alpha9 */ public RenderingErrorEvent() {} /** * {@inheritDoc} + * * @deprecated use the {@code callEvent} method with arguments - * @see #callEvent(String) + * @see #callEvent(String) */ @Deprecated @Override @@ -49,7 +50,7 @@ public final class RenderingErrorEvent implements Event { * Emits the event and calls all event listeners. * * @param error error description - * @since v1-alpha0 + * @since v1-alpha9 */ public void callEvent(@NotNull String error) { EventHelper.invokeAnnotatedMethods(getClass(), error); diff --git a/windowing/src/main/java/de/staropensource/engine/windowing/event/package-info.java b/rendering/src/main/java/de/staropensource/engine/rendering/event/package-info.java similarity index 92% rename from windowing/src/main/java/de/staropensource/engine/windowing/event/package-info.java rename to rendering/src/main/java/de/staropensource/engine/rendering/event/package-info.java index 3e4a07d6..451dc9f2 100644 --- a/windowing/src/main/java/de/staropensource/engine/windowing/event/package-info.java +++ b/rendering/src/main/java/de/staropensource/engine/rendering/event/package-info.java @@ -20,6 +20,6 @@ /** * Events. There's nothing more to say. * - * @since v1-alpha0 + * @since v1-alpha9 */ -package de.staropensource.engine.windowing.event; +package de.staropensource.engine.rendering.event; diff --git a/windowing/src/main/java/de/staropensource/engine/windowing/exception/InvalidMonitorException.java b/rendering/src/main/java/de/staropensource/engine/rendering/exception/InvalidMonitorException.java similarity index 91% rename from windowing/src/main/java/de/staropensource/engine/windowing/exception/InvalidMonitorException.java rename to rendering/src/main/java/de/staropensource/engine/rendering/exception/InvalidMonitorException.java index 1fb7ba36..aab8a472 100644 --- a/windowing/src/main/java/de/staropensource/engine/windowing/exception/InvalidMonitorException.java +++ b/rendering/src/main/java/de/staropensource/engine/rendering/exception/InvalidMonitorException.java @@ -17,18 +17,18 @@ * along with this program. If not, see . */ -package de.staropensource.engine.windowing.exception; +package de.staropensource.engine.rendering.exception; /** * Thrown when the specified monitor does not exist. * - * @since v1-alpha2 + * @since v1-alpha9 */ public final class InvalidMonitorException extends RuntimeException { /** * Creates and initializes an instance of this exception. * - * @since v1-alpha2 + * @since v1-alpha9 */ public InvalidMonitorException() {} } diff --git a/windowing/src/main/java/de/staropensource/engine/windowing/exception/NoMonitorsFoundException.java b/rendering/src/main/java/de/staropensource/engine/rendering/exception/NoMonitorsFoundException.java similarity index 91% rename from windowing/src/main/java/de/staropensource/engine/windowing/exception/NoMonitorsFoundException.java rename to rendering/src/main/java/de/staropensource/engine/rendering/exception/NoMonitorsFoundException.java index 4a28b25b..aeecdd0c 100644 --- a/windowing/src/main/java/de/staropensource/engine/windowing/exception/NoMonitorsFoundException.java +++ b/rendering/src/main/java/de/staropensource/engine/rendering/exception/NoMonitorsFoundException.java @@ -17,18 +17,18 @@ * along with this program. If not, see . */ -package de.staropensource.engine.windowing.exception; +package de.staropensource.engine.rendering.exception; /** * Thrown when trying to access one or more monitors but none are found. * - * @since v1-alpha2 + * @since v1-alpha9 */ public final class NoMonitorsFoundException extends RuntimeException { /** * Creates and initializes an instance of this exception. * - * @since v1-alpha2 + * @since v1-alpha9 */ public NoMonitorsFoundException() {} } diff --git a/windowing/src/main/java/de/staropensource/engine/windowing/exception/NotOnMainThreadException.java b/rendering/src/main/java/de/staropensource/engine/rendering/exception/NotOnMainThreadException.java similarity index 91% rename from windowing/src/main/java/de/staropensource/engine/windowing/exception/NotOnMainThreadException.java rename to rendering/src/main/java/de/staropensource/engine/rendering/exception/NotOnMainThreadException.java index 653faa68..3b8f1192 100644 --- a/windowing/src/main/java/de/staropensource/engine/windowing/exception/NotOnMainThreadException.java +++ b/rendering/src/main/java/de/staropensource/engine/rendering/exception/NotOnMainThreadException.java @@ -17,18 +17,18 @@ * along with this program. If not, see . */ -package de.staropensource.engine.windowing.exception; +package de.staropensource.engine.rendering.exception; /** * Thrown when trying to communicate with a windowing API over a non-main thread. * - * @since v1-alpha2 + * @since v1-alpha9 */ public final class NotOnMainThreadException extends RuntimeException { /** * Creates and initializes an instance of this exception. * - * @since v1-alpha2 + * @since v1-alpha9 */ public NotOnMainThreadException() {} } diff --git a/windowing/src/main/java/de/staropensource/engine/windowing/exception/WindowCreationFailureException.java b/rendering/src/main/java/de/staropensource/engine/rendering/exception/WindowCreationFailureException.java similarity index 88% rename from windowing/src/main/java/de/staropensource/engine/windowing/exception/WindowCreationFailureException.java rename to rendering/src/main/java/de/staropensource/engine/rendering/exception/WindowCreationFailureException.java index b60c7eb3..522571af 100644 --- a/windowing/src/main/java/de/staropensource/engine/windowing/exception/WindowCreationFailureException.java +++ b/rendering/src/main/java/de/staropensource/engine/rendering/exception/WindowCreationFailureException.java @@ -17,21 +17,21 @@ * along with this program. If not, see . */ -package de.staropensource.engine.windowing.exception; +package de.staropensource.engine.rendering.exception; -import de.staropensource.engine.windowing.implementable.Window; +import de.staropensource.engine.rendering.type.Window; import org.jetbrains.annotations.NotNull; /** * Thrown when a {@link Window} cannot be created. * - * @since v1-alpha2 + * @since v1-alpha9 */ public final class WindowCreationFailureException extends RuntimeException { /** * Creates and initializes an instance of this exception. * - * @since v1-alpha2 + * @since v1-alpha9 */ public WindowCreationFailureException() {} @@ -39,7 +39,7 @@ public final class WindowCreationFailureException extends RuntimeException { * Creates and initializes an instance of this exception. * * @param message error message - * @since v1-alpha2 + * @since v1-alpha9 */ public WindowCreationFailureException(@NotNull String message) { super(message); diff --git a/windowing/src/main/java/de/staropensource/engine/windowing/exception/package-info.java b/rendering/src/main/java/de/staropensource/engine/rendering/exception/package-info.java similarity index 93% rename from windowing/src/main/java/de/staropensource/engine/windowing/exception/package-info.java rename to rendering/src/main/java/de/staropensource/engine/rendering/exception/package-info.java index d98c274c..a847a91d 100644 --- a/windowing/src/main/java/de/staropensource/engine/windowing/exception/package-info.java +++ b/rendering/src/main/java/de/staropensource/engine/rendering/exception/package-info.java @@ -23,6 +23,6 @@ * These aren't meant for the windowing subsystem, * but instead for windowing APIs, which may throw them. * - * @since v1-alpha2 + * @since v1-alpha9 */ -package de.staropensource.engine.windowing.exception; +package de.staropensource.engine.rendering.exception; diff --git a/windowing/src/main/java/de/staropensource/engine/windowing/package-info.java b/rendering/src/main/java/de/staropensource/engine/rendering/package-info.java similarity index 93% rename from windowing/src/main/java/de/staropensource/engine/windowing/package-info.java rename to rendering/src/main/java/de/staropensource/engine/rendering/package-info.java index 34eba525..a55ddcae 100644 --- a/windowing/src/main/java/de/staropensource/engine/windowing/package-info.java +++ b/rendering/src/main/java/de/staropensource/engine/rendering/package-info.java @@ -20,6 +20,6 @@ /** * Code of the windowing subsystem. * - * @since v1-alpha0 + * @since v1-alpha9 */ -package de.staropensource.engine.windowing; +package de.staropensource.engine.rendering; diff --git a/windowing/src/main/java/de/staropensource/engine/windowing/implementable/Monitor.java b/rendering/src/main/java/de/staropensource/engine/rendering/type/Monitor.java similarity index 57% rename from windowing/src/main/java/de/staropensource/engine/windowing/implementable/Monitor.java rename to rendering/src/main/java/de/staropensource/engine/rendering/type/Monitor.java index 062db905..b2f1a483 100644 --- a/windowing/src/main/java/de/staropensource/engine/windowing/implementable/Monitor.java +++ b/rendering/src/main/java/de/staropensource/engine/rendering/type/Monitor.java @@ -17,43 +17,45 @@ * along with this program. If not, see . */ -package de.staropensource.engine.windowing.implementable; +package de.staropensource.engine.rendering.type; import de.staropensource.engine.base.type.vector.Vec2i; -import de.staropensource.engine.windowing.WindowingSubsystem; -import de.staropensource.engine.windowing.exception.InvalidMonitorException; -import de.staropensource.engine.windowing.exception.NoMonitorsFoundException; -import lombok.AccessLevel; +import de.staropensource.engine.rendering.exception.InvalidMonitorException; +import de.staropensource.engine.rendering.exception.NoMonitorsFoundException; import lombok.Getter; -import lombok.Setter; import org.jetbrains.annotations.NotNull; +import org.lwjgl.PointerBuffer; +import org.lwjgl.glfw.GLFWVidMode; import java.util.LinkedHashSet; +import java.util.Objects; import java.util.UUID; +import static org.lwjgl.glfw.GLFW.*; + /** * Abstract class for implementing monitors in a windowing API. *

* Note that monitors stop working unannounced when disconnected, * call {@link #isConnected()} before using to avoid unexpected behaviour. * - * @since v1-alpha2 + * @since v1-alpha9 */ @SuppressWarnings({ "JavadocDeclaration" }) -public abstract class Monitor { +public final class Monitor { /** * Contains the unique identifier. *

* This identifier is unique to every monitor and does not change during runtime. * - * @since v1-alpha2 + * @since v1-alpha9 * -- GETTER -- * Returns the unique identifier. *

* This identifier is unique to every monitor and does not change during runtime. * * @return unique identifier - * @since v1-alpha2 + * @since v1-alpha9 */ @Getter private final UUID uniqueIdentifier = UUID.randomUUID(); @@ -63,47 +65,59 @@ public abstract class Monitor { *

* This identifier is used by the windowing API to refer to a monitor and may change during runtime. * - * @since v1-alpha1 + * @since v1-alpha9 * -- GETTER -- * Returns the monitor identifier. *

* This identifier is used by the windowing API to refer to a monitor and may change during runtime. * * @return monitor identifier - * @since v1-alpha2 + * @since v1-alpha9 * -- SETTER -- * Sets the monitor identifier. *

* This identifier is used by the windowing API to refer to a monitor and may change during runtime. * * @param identifier new monitor identifier - * @since v1-alpha2 + * @since v1-alpha9 */ - @Setter(AccessLevel.PROTECTED) - private String identifier = null; + private final long identifier; /** * Creates and initializes an instance of this abstract class. * - * @since v1-alpha2 + * @throws InvalidMonitorException if the monitor isn't connected + * @since v1-alpha9 */ - public Monitor() {} + public Monitor(long identifier) throws InvalidMonitorException { + this.identifier = identifier; - /** - * Returns all connected monitors. - * - * @return connected monitors - * @since v1-alpha2 - */ - public static @NotNull LinkedHashSet<@NotNull Monitor> getMonitors() throws NoMonitorsFoundException { - return WindowingSubsystem.getInstance().getApi().getInternalApi().getMonitors(); + checkConnected(); } /** - * Checks if the monitor is actually connected. + * Returns a set of all connected monitors. + * + * @return connected monitors + * @since v1-alpha9 + */ + public static @NotNull LinkedHashSet<@NotNull Monitor> getMonitors() throws NoMonitorsFoundException { + PointerBuffer monitors = glfwGetMonitors(); + LinkedHashSet<@NotNull Monitor> output = new LinkedHashSet<>(); + if (monitors == null) + throw new NoMonitorsFoundException(); + + while (monitors.hasRemaining()) + output.add(new Monitor(monitors.get())); + + return output; + } + + /** + * Checks if this monitor is actually connected. * If not, throws an {@link InvalidMonitorException}. * - * @since v1-alpha2 + * @since v1-alpha9 */ public void checkConnected() throws InvalidMonitorException, NoMonitorsFoundException { if (!isConnected()) @@ -111,34 +125,48 @@ public abstract class Monitor { } /** - * Checks if the monitor is connected or not. + * Checks if this monitor is connected. * * @return connection status - * @since v1-alpha2 + * @since v1-alpha9 */ - public abstract boolean isConnected() throws NoMonitorsFoundException; + public boolean isConnected() throws NoMonitorsFoundException { + return glfwGetMonitorName(identifier) != null; + } /** - * Returns the monitor name. + * Returns the name of this monitor. * * @return monitor name - * @since v1-alpha2 + * @since v1-alpha9 */ - public abstract @NotNull String getName() throws InvalidMonitorException, NoMonitorsFoundException; + public @NotNull String getName() throws InvalidMonitorException, NoMonitorsFoundException { + checkConnected(); + return Objects.requireNonNull(glfwGetMonitorName(identifier)); + } /** - * Returns the monitor size. + * Returns size of this monitor. * * @return monitor size - * @since v1-alpha2 + * @since v1-alpha9 */ - public abstract @NotNull Vec2i getSize() throws InvalidMonitorException, NoMonitorsFoundException; + public @NotNull Vec2i getSize() throws InvalidMonitorException, NoMonitorsFoundException { + checkConnected(); + + GLFWVidMode videoMode = Objects.requireNonNull(glfwGetVideoMode(identifier)); + + return new Vec2i(videoMode.width(), videoMode.height()); + } /** - * Returns the monitor refresh rate. + * Returns refresh rate of this monitor in hertz. * * @return monitor refresh rate - * @since v1-alpha2 + * @since v1-alpha9 */ - public abstract short getRefreshRate() throws InvalidMonitorException, NoMonitorsFoundException; + public short getRefreshRate() throws InvalidMonitorException, NoMonitorsFoundException { + checkConnected(); + return (short) Objects.requireNonNull(glfwGetVideoMode(identifier)).refreshRate(); + } } diff --git a/windowing/src/main/java/de/staropensource/engine/windowing/implementable/Window.java b/rendering/src/main/java/de/staropensource/engine/rendering/type/Window.java similarity index 55% rename from windowing/src/main/java/de/staropensource/engine/windowing/implementable/Window.java rename to rendering/src/main/java/de/staropensource/engine/rendering/type/Window.java index e0996117..f89e5532 100644 --- a/windowing/src/main/java/de/staropensource/engine/windowing/implementable/Window.java +++ b/rendering/src/main/java/de/staropensource/engine/rendering/type/Window.java @@ -17,22 +17,39 @@ * along with this program. If not, see . */ -package de.staropensource.engine.windowing.implementable; +package de.staropensource.engine.rendering.type; import de.staropensource.engine.base.logging.Logger; import de.staropensource.engine.base.type.Tristate; import de.staropensource.engine.base.type.vector.Vec2i; -import de.staropensource.engine.windowing.WindowingSubsystem; -import de.staropensource.engine.windowing.type.window.WindowMode; +import de.staropensource.engine.base.utility.Miscellaneous; +import de.staropensource.engine.rendering.callback.KeyCallback; +import de.staropensource.engine.rendering.callback.MouseButtonCallback; +import de.staropensource.engine.rendering.event.InputEvent; +import de.staropensource.engine.rendering.exception.NotOnMainThreadException; +import de.staropensource.engine.rendering.exception.WindowCreationFailureException; +import de.staropensource.engine.rendering.type.window.WindowMode; import lombok.AccessLevel; import lombok.Getter; import lombok.Setter; +import org.jetbrains.annotations.ApiStatus; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import org.lwjgl.bgfx.BGFXInit; +import org.lwjgl.glfw.*; +import org.lwjgl.stb.STBImage; +import org.lwjgl.system.MemoryStack; +import java.nio.ByteBuffer; +import java.nio.IntBuffer; import java.nio.file.Path; import java.util.*; +import static org.lwjgl.bgfx.BGFX.*; +import static org.lwjgl.glfw.GLFW.*; +import static org.lwjgl.system.MemoryStack.*; +import static org.lwjgl.system.MemoryUtil.*; + /** * Abstract class for implementing windows in a windowing API. *

@@ -40,32 +57,64 @@ import java.util.*; * window manager or compositor. Make sure to poll for changes * in {@link #updateState()}. * - * @since v1-alpha0 + * @since v1-alpha9 */ @Getter @SuppressWarnings({ "JavadocDeclaration" }) -public abstract class Window implements AutoCloseable { +public final class Window implements AutoCloseable { /** * A set of all active windows. * - * @since v1-alpha6 + * @since v1-alpha9 */ private static final @NotNull List<@NotNull Window> windows = new ArrayList<>(); + /** + * Contains the internal window identifier. + * + * @since v1-alpha9 + * -- GETTER -- + * Returns the internal window identifier. + * + * @return window identifier + * @since v1-alpha9 + */ + private long identifier; + + /** + * Contains if this window is fresh. + *

+ * Only enabled during the window's + * initialization phase to prevent + * crashes and segmentation faults. + * + * @since v1-alpha9 + * -- GETTER -- + * Returns if this window is fresh. + *

+ * Only enabled during the window's + * initialization phase to prevent + * crashes and segmentation faults. + * + * @return fresh flag state + * @since v1-alpha9 + */ + private boolean fresh = true; + /** * Contains if this window can be interacted with or not. * - * @since v1-alpha2 + * @since v1-alpha9 * -- GETTER -- * Returns if this window can be interacted with or not. * * @return closed flag state - * @since v1-alpha2 + * @since v1-alpha9 * -- SETTER -- * Sets if this window can be interacted with or not. * * @param closed new closed flag state - * @since v1-alpha2 + * @since v1-alpha9 */ @Setter(AccessLevel.PROTECTED) private boolean terminated; @@ -75,41 +124,17 @@ public abstract class Window implements AutoCloseable { *

* This identifier is unique to every window and does not change during runtime. * - * @since v1-alpha2 + * @since v1-alpha9 * -- GETTER -- * Returns the unique window identifier. *

* This identifier is unique to every window and does not change during runtime. * * @return unique identifier - * @since v1-alpha2 + * @since v1-alpha9 */ private final UUID uniqueIdentifier; - /** - * Contains the window identifier. - *

- * This identifier is used by the windowing API to refer to a window and may change during runtime. - * - * @since v1-alpha1 - * -- GETTER -- - * Returns the window identifier. - *

- * This identifier is used by the windowing API to refer to a window and may change during runtime. - * - * @return window identifier - * @since v1-alpha2 - * -- SETTER -- - * Sets the window identifier. - *

- * This identifier is used by the windowing API to refer to a window and may change during runtime. - * - * @param identifier new window identifier - * @since v1-alpha2 - */ - @Setter(AccessLevel.PROTECTED) - private String identifier = null; - /** * Contains the name of this window. *

@@ -127,7 +152,7 @@ public abstract class Window implements AutoCloseable { * managers and compositors can use this information to identify * windows and customize them. * - * @since v1-alpha1 + * @since v1-alpha9 * -- GETTER -- * Returns the name of this window. *

@@ -146,85 +171,46 @@ public abstract class Window implements AutoCloseable { * windows and customize them. * * @return window title - * @since v1-alpha2 - * -- SETTER -- - * Sets the name of this window. - *

- * Window names should: - *

- *

- * On some platforms this may be used for window identification. - * A prime example of this is X11 and Wayland, where window - * managers and compositors can use this information to identify - * windows and customize them. - * - * @param name new name - * @since v1-alpha2 + * @since v1-alpha9 */ - @Setter private @NotNull String name; /** * Contains the title of this window. * - * @since v1-alpha1 + * @since v1-alpha9 * -- GETTER -- * Returns the window title. * * @return window title - * @since v1-alpha2 - * -- SETTER -- - * Sets the window title. - * - * @param title new title - * @since v1-alpha2 + * @since v1-alpha9 */ - @Setter private @NotNull String title; /** * Contains file paths to window * icons in the PNG format. * - * @since v1-alpha6 + * @since v1-alpha9 * -- GETTER -- * Returns file paths to window * icons in the PNG format. * * @return file paths to icons - * @since v1-alpha6 - * -- SETTER -- - * Sets file paths to window - * icons in the PNG format. - * - * @param icons new file paths to icons - * @since v1-alpha6 + * @since v1-alpha9 */ - @Setter - protected @NotNull Path @Nullable [] icons; + private @NotNull Path @Nullable [] icons; /** * Contains the size of this window. * - * @since v1-alpha1 + * @since v1-alpha9 * -- GETTER -- * Returns the window size. * * @return window size - * @since v1-alpha2 - * -- SETTER -- - * Sets the window size. - * - * @param size new size - * @since v1-alpha2 + * @since v1-alpha9 */ - @Setter private @NotNull Vec2i size; /** @@ -232,23 +218,15 @@ public abstract class Window implements AutoCloseable { *

* If set to {@code -1}, will enforce no minimum window size. * - * @since v1-alpha1 + * @since v1-alpha9 * -- GETTER -- * Returns the minimum window size. *

* If set to {@code -1}, will enforce no minimum window size. * * @return minimum window size - * @since v1-alpha2 - * -- SETTER -- - * Sets the minimum window size. - *

- * If set to {@code -1}, will enforce no minimum window size. - * - * @param minimumSize new minimum size - * @since v1-alpha2 + * @since v1-alpha9 */ - @Setter private @NotNull Vec2i minimumSize; /** @@ -256,75 +234,55 @@ public abstract class Window implements AutoCloseable { *

* If set to {@code -1}, will enforce no maximum window size. * - * @since v1-alpha1 + * @since v1-alpha9 * -- GETTER -- * Returns the maximum window size. *

* If set to {@code -1}, will enforce no maximum window size. * * @return maximum window size - * @since v1-alpha2 - * -- SETTER -- - * Sets the maximum window size. - *

- * If set to {@code -1}, will enforce no maximum window size. - * - * @param maximumSize new maximum size - * @since v1-alpha2 + * @since v1-alpha9 */ - @Setter private @NotNull Vec2i maximumSize; /** * Contains the position of this window. * - * @since v1-alpha2 + * @since v1-alpha9 * -- GETTER -- * Returns the window position. * * @return window position - * @since v1-alpha2 - * -- SETTER -- - * Sets the window position. - * - * @param position new position - * @since v1-alpha2 + * @since v1-alpha9 */ - @Setter private @NotNull Vec2i position; /** * Contains in which {@link WindowMode} this window is in. * - * @since v1-alpha1 + * @since v1-alpha9 * -- GETTER -- * Returns the window mode. * * @return window mode - * @since v1-alpha2 - * -- SETTER -- - * Sets the window mode. - * - * @param windowMode new mode - * @since v1-alpha2 + * @since v1-alpha9 */ - @Setter private @NotNull WindowMode windowMode; /** * Contains on which {@link Monitor} the window is displayed on. * - * @since v1-alpha2 + * @since v1-alpha9 * -- GETTER -- * Returns the {@link Monitor} the window is displayed on. * * @return target monitor - * @since v1-alpha2 + * @since v1-alpha9 * -- SETTER -- * Sets the {@link Monitor} the window is displayed on. * * @param monitor new target monitor - * @since v1-alpha2 + * @since v1-alpha9 */ @Setter private @NotNull Monitor monitor; @@ -332,17 +290,17 @@ public abstract class Window implements AutoCloseable { /** * Contains how fast the window may update it's contents. * - * @since v1-alpha1 + * @since v1-alpha9 * -- GETTER -- * Returns how fast the window may update it's contents. * * @return new window frame limit - * @since v1-alpha2 + * @since v1-alpha9 * -- SETTER -- * Sets how fast the window may update it's contents. * * @param framerate new frame limit - * @since v1-alpha2 + * @since v1-alpha9 */ @Setter private int framerate; @@ -350,37 +308,25 @@ public abstract class Window implements AutoCloseable { /** * Contains if this window can be resized by the user. * - * @since v1-alpha1 + * @since v1-alpha9 * -- GETTER -- * Returns if the window is resizable. * * @return resizable flag state - * @since v1-alpha2 - * -- SETTER -- - * Sets if the window is resizable. - * - * @param resizable new resizable flag state - * @since v1-alpha2 + * @since v1-alpha9 */ - @Setter private boolean resizable; /** * Contains if this window should have a border and decorations. * - * @since v1-alpha1 + * @since v1-alpha9 * -- GETTER -- * Returns if the window should be rendered without any decorations. * * @return borderless flag state - * @since v1-alpha2 - * -- SETTER -- - * Sets if the window should be rendered without any decorations. - * - * @param borderless new borderless flag state - * @since v1-alpha2 + * @since v1-alpha9 */ - @Setter private boolean borderless; /** @@ -389,32 +335,20 @@ public abstract class Window implements AutoCloseable { * Returns if the window can be focused. * * @return focusable flag state - * @since v1-alpha2 - * -- SETTER -- - * Sets if the window can be focused. - * - * @param focusable new focusable flag state - * @since v1-alpha2 + * @since v1-alpha9 */ - @Setter private boolean focusable; /** * Contains if this window should be displayed on top of all other windows. * - * @since v1-alpha1 + * @since v1-alpha9 * -- GETTER -- * Returns if the window is displayed over regular windows. * * @return on top flag state - * @since v1-alpha2 - * -- SETTER -- - * Sets if the window is displayed over regular windows. - * - * @param onTop new on top flag state - * @since v1-alpha2 + * @since v1-alpha9 */ - @Setter private boolean onTop; /** @@ -423,7 +357,7 @@ public abstract class Window implements AutoCloseable { * Availability depends on the windowing API, compositor or * window manager and potentially system settings. * - * @since v1-alpha2 + * @since v1-alpha9 * -- GETTER -- * Returns if the window can be transparent. *

@@ -431,42 +365,49 @@ public abstract class Window implements AutoCloseable { * window manager and potentially system settings. * * @return transparency flag state - * @since v1-alpha2 - * -- SETTER -- - * Sets if the window can be transparent. - *

- * Availability depends on the windowing API, compositor or - * window manager and potentially system settings. - * - * @param transparent new transparency flag state - * @since v1-alpha2 + * @since v1-alpha9 */ - @Setter private boolean transparent; /** * Contains if this window should be rendered. * - * @since v1-alpha2 + * @since v1-alpha9 * -- GETTER -- * Returns if the window should be rendered. * * @return rendering flag state - * @since v1-alpha2 + * @since v1-alpha9 * -- SETTER -- * Sets if the window should be rendered. * * @param rendering new rendering flag state - * @since v1-alpha2 + * @since v1-alpha9 */ @Setter private boolean rendering; + /** + * Contains the {@link GLFWKeyCallback} used + * for emitting {@link InputEvent}s. + * + * @since v1-alpha9 + */ + private GLFWKeyCallback keyCallback; + + /** + * Contains the {@link GLFWMouseButtonCallback} used + * for emitting {@link InputEvent}s. + * + * @since v1-alpha9 + */ + private GLFWMouseButtonCallback mouseButtonCallback; + /** * Returns a set of active windows. * * @return active windows - * @since v1-alpha2 + * @since v1-alpha9 */ public static @NotNull HashSet<@NotNull Window> getWindows() { return new HashSet<>(windows); @@ -490,10 +431,24 @@ public abstract class Window implements AutoCloseable { * @param onTop on top flag * @param transparent transparency flag * @param rendering rendering flag - * @throws Exception stuff thrown by the {@link #initializeWindow()} and {@link #render()} methods of the implementing windowing API - * @since v1-alpha2 + * @throws NotOnMainThreadException if not running on the main thread + * @since v1-alpha9 */ - protected Window(@NotNull String name, @NotNull String title, @NotNull Path @Nullable [] icons, @NotNull Vec2i size, @NotNull Vec2i minimumSize, @NotNull Vec2i maximumSize, @NotNull Vec2i position, @NotNull WindowMode windowMode, @NotNull Monitor monitor, boolean resizable, boolean borderless, boolean focusable, boolean onTop, boolean transparent, boolean rendering) throws Exception { + private Window(@NotNull String name, + @NotNull String title, + @NotNull Path @Nullable [] icons, + @NotNull Vec2i size, + @NotNull Vec2i minimumSize, + @NotNull Vec2i maximumSize, + @NotNull Vec2i position, + @NotNull WindowMode windowMode, + @NotNull Monitor monitor, + boolean resizable, + boolean borderless, + boolean focusable, + boolean onTop, + boolean transparent, + boolean rendering) throws NotOnMainThreadException { // Initialize variables this.uniqueIdentifier = UUID.randomUUID(); this.name = name; @@ -518,11 +473,12 @@ public abstract class Window implements AutoCloseable { // Allow windowing API to initialize window initializeWindow(); - // Update state and render first image + // Update state updateState(); // Add to window set windows.add(this); + fresh = false; } /** @@ -532,9 +488,119 @@ public abstract class Window implements AutoCloseable { * API-specific window initialization code in here * or stuff may break unexpectedly. * - * @since v1-alpha2 + * @throws NotOnMainThreadException if not running on the main thread + * @since v1-alpha9 */ - protected abstract void initializeWindow() throws Exception; + private void initializeWindow() throws NotOnMainThreadException { + // Ensure running on the main thread + if (!Miscellaneous.onMainThread()) + throw new NotOnMainThreadException(); + + // Get current focus and destroy existing window + boolean focused = false; + if (!fresh) { + focused = isFocused(); + closeInternal(); + } + + // Set window hints + glfwWindowHint(GLFW_VISIBLE, GLFW_FALSE); // The window's visibility is later changed in setWindowState, this is just for setting up the window + glfwWindowHint(GLFW_POSITION_X, getPosition().getX()); + glfwWindowHint(GLFW_POSITION_Y, getPosition().getY()); + glfwWindowHint(GLFW_CENTER_CURSOR, 0); + glfwWindowHint(GLFW_FOCUSED, Miscellaneous.getIntegerizedBoolean(focused)); + glfwWindowHint(GLFW_TRANSPARENT_FRAMEBUFFER, Miscellaneous.getIntegerizedBoolean(isTransparent())); + glfwWindowHint(GLFW_CLIENT_API, GLFW_NO_API); + glfwWindowHint(GLFW_COCOA_RETINA_FRAMEBUFFER, GLFW_FALSE); + glfwWindowHintString(GLFW_WAYLAND_APP_ID, getName()); + glfwWindowHintString(GLFW_X11_CLASS_NAME, getName()); + glfwWindowHintString(GLFW_X11_INSTANCE_NAME, getName()); + + // Create window + identifier = glfwCreateWindow(getSize().getX(), getSize().getY(), getTitle(), NULL, NULL); + if (identifier == NULL) + throw new WindowCreationFailureException(); + + // Own context + //glfwMakeContextCurrent(identifier); + + // Set swap interval based on V-Sync mode setting + //glfwSwapInterval(RenderingSubsystemConfiguration.getInstance().getVsyncMode() == VsyncMode.ON ? 1 : 0); + + // Create callbacks + keyCallback = GLFWKeyCallback.create(new KeyCallback(this)); + mouseButtonCallback = GLFWMouseButtonCallback.create(new MouseButtonCallback(this)); + + // Set callback + glfwSetKeyCallback(identifier, keyCallback); + glfwSetMouseButtonCallback(identifier, mouseButtonCallback); + + // Update the window state + setIcons(getIcons()); + setSize(getSize()); + setMinimumSize(getMinimumSize()); + setMaximumSize(getMaximumSize()); + setWindowMode(getWindowMode()); + + // Initialize bgfx + initBgfx(); + } + + /** + * Initializes bgfx. + * + * @since v1-alpha9 + */ + private void initBgfx() { + try (MemoryStack stack = stackPush()) { + Logger.verb("Initializing bgfx"); + + // Initialize BGFXInit struct + Logger.diag("Initializing BGFXInit struct"); + BGFXInit init = BGFXInit.calloc(stack); + bgfx_init_ctor(init); + + // Set initial resolution + Logger.diag("Setting initial resolution"); + init + .resolution(it -> it + .width(size.getX()) + .height(size.getY()) + .reset(BGFX_RESET_VSYNC)); + + // Determine platform to render for + Logger.diag("Setting platform"); + switch (glfwGetPlatform()) { + case GLFW_PLATFORM_X11 -> init + .platformData() + .ndt(GLFWNativeX11.glfwGetX11Display()) + .nwh(GLFWNativeX11.glfwGetX11Window(identifier)); + case GLFW_PLATFORM_WAYLAND -> init + .platformData() + .ndt(GLFWNativeWayland.glfwGetWaylandDisplay()) + .nwh(GLFWNativeWayland.glfwGetWaylandWindow(identifier)); + case GLFW_PLATFORM_WIN32 -> init + .platformData() + .nwh(GLFWNativeWin32.glfwGetWin32Window(identifier)); + case GLFW_PLATFORM_COCOA -> init + .platformData() + .nwh(GLFWNativeCocoa.glfwGetCocoaWindow(identifier)); + case GLFW_PLATFORM_NULL -> {} + default -> Logger.crash("Invalid GLFW platform \"" + glfwGetPlatform() + "\""); + } + + // Initialize bgfx + Logger.diag("Invoking bgfx_init"); + if (!bgfx_init(init)) + Logger.crash("Unable to initialize bgfx"); + + bgfx_set_debug(BGFX_DEBUG_TEXT); + bgfx_set_view_rect(0, 0, 0, size.getX(), size.getY()); + bgfx_touch(0); + } catch (UnsatisfiedLinkError error) { + Logger.crash("Failed to load LWJGL native libraries", error); + } + } /** * Updates the state of this window. @@ -542,10 +608,59 @@ public abstract class Window implements AutoCloseable { * Do not call this method manually or you * may cause unintended side effects. * - * @throws Exception thrown by implementing method - * @since v1-alpha2 + * @throws NotOnMainThreadException if not running on the main thread + * @since v1-alpha9 */ - public abstract void updateState() throws Exception; + public void updateState() throws NotOnMainThreadException { + // Ensure the window is not terminated + if (isTerminated()) + return; + + // Ensure running on the main thread + if (!Miscellaneous.onMainThread()) + throw new NotOnMainThreadException(); + + // Update window mode + if (Miscellaneous.getBooleanizedInteger(glfwGetWindowAttrib(identifier, GLFW_ICONIFIED))) + setWindowMode(WindowMode.MINIMIZED); + else if (Miscellaneous.getBooleanizedInteger(glfwGetWindowAttrib(identifier, GLFW_MAXIMIZED))) + setWindowMode(WindowMode.MAXIMIZED); + else if (Miscellaneous.getBooleanizedInteger(glfwGetWindowAttrib(identifier, GLFW_VISIBLE))) + setWindowMode(WindowMode.WINDOWED); + else if (Miscellaneous.getBooleanizedInteger(glfwGetWindowAttrib(identifier, GLFW_VISIBLE))) + setWindowMode(WindowMode.HIDDEN); + + // Update monitor + if (!getMonitor().isConnected()) { + Monitor newMonitor = null; + + for (Monitor monitor : Monitor.getMonitors()) + if (monitor.isConnected()) + newMonitor = monitor; + + if (newMonitor == null) + Logger.crash("Unable to set a new target monitor for window " + getUniqueIdentifier() + " as no monitors are connected to the system"); + + setMonitor(Objects.requireNonNull(newMonitor)); + } + + // Update vectors + try (MemoryStack stack = stackPush()) { + IntBuffer width = stack.mallocInt(2); + IntBuffer height = stack.mallocInt(2); + + glfwGetWindowSize(identifier, width, height); + setSize(new Vec2i(width.get(), height.get())); + + glfwGetWindowPos(identifier, width, height); + setPosition(new Vec2i(width.get(), height.get())); + } + + // Update booleans + setResizable(Miscellaneous.getBooleanizedInteger(glfwGetWindowAttrib(identifier, GLFW_RESIZABLE))); + setOnTop(Miscellaneous.getBooleanizedInteger(glfwGetWindowAttrib(identifier, GLFW_FLOATING))); + setTransparent(Miscellaneous.getBooleanizedInteger(glfwGetWindowAttrib(identifier, GLFW_TRANSPARENT_FRAMEBUFFER))); + } /** * Renders this window. @@ -553,52 +668,96 @@ public abstract class Window implements AutoCloseable { * Do not call this method manually or you * may cause unintended side effects. * - * @throws Exception thrown by implementing method - * @since v1-alpha2 + * @throws NotOnMainThreadException if not running on the main thread + * @since v1-alpha9 */ - public abstract void render() throws Exception; + public void render() throws NotOnMainThreadException { + // Ensure running on the main thread + if (!Miscellaneous.onMainThread()) + throw new NotOnMainThreadException(); - /** - * Alias for {@link #terminate()}. - * - * @see #terminate() - * @since v1-alpha2 - */ - public final void close() { - terminate(); + // Ensure the window is not terminated + if (isTerminated()) + return; + // Ensure rendering is enabled + if (!isRendering()) + return; + + glfwSwapBuffers(identifier); } /** * Terminates the window, making it unable to be interacted with. * - * @since v1-alpha2 + * @since v1-alpha9 */ - public abstract void terminate(); + public void close() throws NotOnMainThreadException { + // Ensure running on the main thread + if (!Miscellaneous.onMainThread()) + throw new NotOnMainThreadException(); + + closeInternal(); + terminated = true; + } + + /** + * Terminates the window without affecting it's state. + * For internal use only. + * + * @throws NotOnMainThreadException if not running on the main thread + * @since v1-alpha9 + */ + private void closeInternal() { + // Terminate bgfx + bgfx_shutdown(); + + // Destroy the window + Callbacks.glfwFreeCallbacks(identifier); + glfwDestroyWindow(identifier); + } /** * Returns if the user, window manager or * compositor send a request for the window to close. * * @return {@code true} if a window closure has been requested - * @since v1-alpha2 + * @since v1-alpha9 */ - public abstract boolean isClosureRequested(); + public boolean isClosureRequested() { + // Ensure the window is not terminated + if (isTerminated()) + return false; + + return glfwWindowShouldClose(identifier); + } /** * Returns if the window is currently focused. * * @return {@code true} if focused, {@code false} otherwise - * @since v1-alpha2 + * @since v1-alpha9 */ - public abstract boolean isFocused(); + public boolean isFocused() { + // Ensure the window is not terminated + if (isTerminated()) + return false; + + return Miscellaneous.getTristatedInteger(glfwGetWindowAttrib(identifier, GLFW_FOCUSED)).toBoolean(); + } /** * Will cause the window to be focused immediately, even * without any user input. * - * @since v1-alpha2 + * @since v1-alpha9 */ - public abstract void focus(); + public void focus() { + // Ensure the window is not terminated + if (isTerminated()) + return; + + glfwFocusWindow(identifier); + } /** * Will request user attention. @@ -608,14 +767,308 @@ public abstract class Window implements AutoCloseable { * ignored, or will cause the icon in some bar * or dock flash or blink. * - * @since v1-alpha2 + * @since v1-alpha9 */ - public abstract void requestAttention(); + public void requestAttention() { + // Ensure the window is not terminated + if (isTerminated()) + return; + glfwRequestWindowAttention(identifier); + } + + // -----> Setters & getters + + /** + * Sets the name of this window. + *

+ * Window names should: + *

+ *

+ * On some platforms this may be used for window identification. + * A prime example of this is X11 and Wayland, where window + * managers and compositors can use this information to identify + * windows and customize them. + * + * @param name new name + * @since v1-alpha9 + */ + public void setName(@NotNull String name) { + // Ensure the window is not terminated + if (isTerminated()) + return; + + this.name = name; + initializeWindow(); + } + + /** + * Sets the window title. + * + * @param title new title + * @since v1-alpha9 + */ + public void setTitle(@NotNull String title) { + // Ensure the window is not terminated + if (isTerminated()) + return; + + this.title = title; + glfwSetWindowTitle(identifier, title); + } + + /** + * Sets file paths to window + * icons in the PNG format. + * + * @param icons new file paths to icons + * @since v1-alpha9 + */ + @ApiStatus.Experimental + public void setIcons(@NotNull Path @Nullable [] icons) { + // Ensure the window is not terminated + if (isTerminated()) + return; + + this.icons = icons; + if (icons != null) + try (GLFWImage.Buffer iconsBuffer = GLFWImage.malloc(icons.length)) { + Logger.warn("GlfwWindow#setIcons is experimental and may cause engine or JVM crashes. Here be dragons!"); + Logger.diag("icons.length = " + icons.length); + + List iconBuffers = new ArrayList<>(); + IntBuffer width = memAllocInt(1); + IntBuffer height = memAllocInt(1); + IntBuffer channels = memAllocInt(1); + + for (Path filepath : icons) { + Logger.diag("iterating icons » " + iconBuffers.size() + " » " + filepath); + // Load icon + Logger.diag("loading icon"); + iconBuffers.add(STBImage.stbi_load(filepath.toAbsolutePath().toString(), width, height, channels, 4)); + + if (iconBuffers.getLast() == null) { + Logger.warn("Icon " + iconsBuffer.position() + " could not be loaded" + (STBImage.stbi_failure_reason() == null ? "" : ": " + STBImage.stbi_failure_reason())); + continue; + } + + // Save into 'iconsBuffer' + Logger.diag("saving into buffer"); + iconsBuffer + .position(iconsBuffer.position() + 1) + .width(width.get(0)) + .height(height.get(0)) + .pixels(iconBuffers.getLast()); + } + Logger.diag("out of iteration"); + + // Set icons + Logger.diag("setting position"); + iconsBuffer.position(0); + Logger.diag("setting icons"); + Logger.flush(); + glfwSetWindowIcon(identifier, iconsBuffer); + + // Free icons + Logger.diag("freeing icons"); + for (ByteBuffer buffer : iconBuffers) + if (buffer != null) { + Logger.diag("freeing buffer"); + STBImage.stbi_image_free(buffer); + } else + Logger.diag("skipping null buffer"); + } + } + + /** + * Sets the window size. + * + * @param size new window size + * @since v1-alpha9 + */ + public void setSize(@NotNull Vec2i size) { + // Ensure the window is not terminated + if (isTerminated()) + return; + + this.size = size; + glfwSetWindowSize(identifier, size.getX(), size.getY()); + } + + /** + * Sets the minimum window size. + *

+ * If set to {@code -1}, will enforce no minimum window size. + * + * @param minimumSize new minimum size + * @since v1-alpha9 + */ + public void setMinimumSize(@NotNull Vec2i minimumSize) { + // Ensure the window is not terminated + if (isTerminated()) + return; + + this.minimumSize = minimumSize; + glfwSetWindowSizeLimits(identifier, minimumSize.getX(), minimumSize.getY(), getMaximumSize().getX(), getMaximumSize().getY()); + } + + /** + * Sets the maximum window size. + *

+ * If set to {@code -1}, will enforce no maximum window size. + * + * @param maximumSize new maximum size + * @since v1-alpha9 + */ + public void setMaximumSize(@NotNull Vec2i maximumSize) { + // Ensure the window is not terminated + if (isTerminated()) + return; + + this.maximumSize = maximumSize; + glfwSetWindowSizeLimits(identifier, getMinimumSize().getX(), getMinimumSize().getY(), maximumSize.getX(), maximumSize.getY()); + } + + /** + * Sets the window position. + * + * @param position new position + * @since v1-alpha9 + */ + public void setPosition(@NotNull Vec2i position) { + // Ensure the window is not terminated + if (isTerminated()) + return; + + this.position = position; + glfwSetWindowSize(identifier, position.getX(), position.getY()); + } + + /** + * Sets the window mode. + * + * @param windowMode new mode + * @since v1-alpha9 + */ + public void setWindowMode(@NotNull WindowMode windowMode) { + // Ensure the window is not terminated + if (isTerminated()) + return; + + this.windowMode = windowMode; + switch (windowMode) { + case HIDDEN -> glfwHideWindow(identifier); + case WINDOWED -> { + glfwShowWindow(identifier); + glfwRestoreWindow(identifier); + } + case MINIMIZED -> { + glfwShowWindow(identifier); + glfwIconifyWindow(identifier); + } + case MAXIMIZED -> { + glfwShowWindow(identifier); + glfwRestoreWindow(identifier); + glfwMaximizeWindow(identifier); + } + case BORDERLESS_FULLSCREEN -> { + glfwShowWindow(identifier); + glfwRestoreWindow(identifier); + // TODO + } + case EXCLUSIVE_FULLSCREEN -> { + glfwShowWindow(identifier); + glfwRestoreWindow(identifier); + // TODO + } + } + } + + /** + * Sets if the window is resizable. + * + * @param resizable new resizable flag state + * @since v1-alpha9 + */ + public void setResizable(boolean resizable) { + // Ensure the window is not terminated + if (isTerminated()) + return; + + this.resizable = resizable; + } + + /** + * Sets if the window should be rendered without any decorations. + * + * @param borderless new borderless flag state + * @since v1-alpha9 + */ + public void setBorderless(boolean borderless) { + // Ensure the window is not terminated + if (isTerminated()) + return; + + this.borderless = borderless; + } + + /** + * Sets if the window can be focused. + * + * @param focusable new focusable flag state + * @since v1-alpha9 + */ + public void setFocusable(boolean focusable) { + // Ensure the window is not terminated + if (isTerminated()) + return; + + this.focusable = focusable; + } + + /** + * Sets if the window is displayed over regular windows. + * + * @param onTop new on top flag state + * @since v1-alpha9 + */ + public void setOnTop(boolean onTop) { + // Ensure the window is not terminated + if (isTerminated()) + return; + + this.onTop = onTop; + } + + /** + * Sets if the window can be transparent. + *

+ * Availability depends on the windowing API, compositor or + * window manager and potentially system settings. + * + * @param transparent new transparency flag state + * @since v1-alpha9 + */ + public void setTransparent(boolean transparent) { + // Ensure the window is not terminated + if (isTerminated()) + return; + + this.transparent = transparent; + initializeWindow(); + } + + // -----> Builder inner class /** * Provides an API for building {@link Window}s more easily. * - * @since v1-alpha2 + * @since v1-alpha9 */ @SuppressWarnings({ "unused" }) public static final class Builder { @@ -623,7 +1076,7 @@ public abstract class Window implements AutoCloseable { * Contains the window name. * * @see Window#name - * @since v1-alpha2 + * @since v1-alpha9 */ private @Nullable String name = null; @@ -631,7 +1084,7 @@ public abstract class Window implements AutoCloseable { * Contains the window title. * * @see Window#title - * @since v1-alpha2 + * @since v1-alpha9 */ private @Nullable String title = null; @@ -639,7 +1092,7 @@ public abstract class Window implements AutoCloseable { * Contains the window icons in the PNG format. * * @see Window#icons - * @since v1-alpha6 + * @since v1-alpha9 */ private @NotNull Path @Nullable [] icons = null; @@ -647,7 +1100,7 @@ public abstract class Window implements AutoCloseable { * Contains the window size. * * @see Window#size - * @since v1-alpha2 + * @since v1-alpha9 */ private @Nullable Vec2i size = null; @@ -655,7 +1108,7 @@ public abstract class Window implements AutoCloseable { * Contains the minimum window size. * * @see Window#minimumSize - * @since v1-alpha2 + * @since v1-alpha9 */ private @Nullable Vec2i minimumSize = null; @@ -663,7 +1116,7 @@ public abstract class Window implements AutoCloseable { * Contains the maximum window size. * * @see Window#maximumSize - * @since v1-alpha2 + * @since v1-alpha9 */ private @Nullable Vec2i maximumSize = null; @@ -671,7 +1124,7 @@ public abstract class Window implements AutoCloseable { * Contains the window position. * * @see Window#position - * @since v1-alpha2 + * @since v1-alpha9 */ private @Nullable Vec2i position = null; @@ -679,7 +1132,7 @@ public abstract class Window implements AutoCloseable { * Contains the window mode. * * @see Window#windowMode - * @since v1-alpha2 + * @since v1-alpha9 */ private @Nullable WindowMode windowMode = null; @@ -687,7 +1140,7 @@ public abstract class Window implements AutoCloseable { * Contains the target monitor. * * @see Window#monitor - * @since v1-alpha2 + * @since v1-alpha9 */ private @Nullable Monitor monitor = null; @@ -695,7 +1148,7 @@ public abstract class Window implements AutoCloseable { * Contains the resizable flag. * * @see Window#resizable - * @since v1-alpha2 + * @since v1-alpha9 */ private @NotNull Tristate resizable = Tristate.UNSET; @@ -703,7 +1156,7 @@ public abstract class Window implements AutoCloseable { * Contains the borderless flag. * * @see Window#borderless - * @since v1-alpha2 + * @since v1-alpha9 */ private @NotNull Tristate borderless = Tristate.UNSET; @@ -711,7 +1164,7 @@ public abstract class Window implements AutoCloseable { * Contains the focusable flag. * * @see Window#focusable - * @since v1-alpha2 + * @since v1-alpha9 */ private @NotNull Tristate focusable = Tristate.UNSET; @@ -719,7 +1172,7 @@ public abstract class Window implements AutoCloseable { * Contains the on top flag. * * @see Window#onTop - * @since v1-alpha2 + * @since v1-alpha9 */ private @NotNull Tristate onTop = Tristate.UNSET; @@ -727,7 +1180,7 @@ public abstract class Window implements AutoCloseable { * Contains the transparency flag. * * @see Window#transparent - * @since v1-alpha2 + * @since v1-alpha9 */ private @NotNull Tristate transparent = Tristate.UNSET; @@ -735,26 +1188,30 @@ public abstract class Window implements AutoCloseable { * Contains the rendering flag. * * @see Window#rendering - * @since v1-alpha2 + * @since v1-alpha9 */ private @NotNull Tristate rendering = Tristate.UNSET; /** * Constructs this class. * - * @since v1-alpha2 + * @since v1-alpha9 */ public Builder() {} /** * Builds a new {@link Window} instance. * - * @throws IllegalStateException if {@link #title}, {@link #size} or {@link #position} is unset - * @throws Exception thrown when creating a new {@link Window} instance fails - * @return {@link Window} instance - * @since v1-alpha2 + * @throws IllegalStateException if {@link #title}, {@link #size} or {@link #position} is unset + * @throws NotOnMainThreadException if not running on the main thread + * @return {@link Window} instance or {@code null} if another window is already initialized + * @since v1-alpha9 */ - public @NotNull Window build() throws Exception { + public @Nullable Window build() throws NotOnMainThreadException { + // Check if another window already exists + if (!getWindows().isEmpty()) + return null; + // Booleanized tristates with default values boolean resizableBoolean = true; boolean borderlessBoolean = false; @@ -798,9 +1255,7 @@ public abstract class Window implements AutoCloseable { renderingBoolean = false; // Create new Window instance - return WindowingSubsystem.getInstance().getApi().getInternalApi().getWindowClass() - .getDeclaredConstructor(String.class, String.class, Path[].class, Vec2i.class, Vec2i.class, Vec2i.class, Vec2i.class, WindowMode.class, Monitor.class, Boolean.TYPE, Boolean.TYPE, Boolean.TYPE, Boolean.TYPE, Boolean.TYPE, Boolean.TYPE) - .newInstance(name, title, icons, size, minimumSize, maximumSize, position, windowMode, monitor, resizableBoolean, borderlessBoolean, focusableBoolean, onTopBoolean, transparentBoolean, renderingBoolean); + return new Window(name, title, icons, size, minimumSize, maximumSize, position, windowMode, monitor, resizableBoolean, borderlessBoolean, focusableBoolean, onTopBoolean, transparentBoolean, renderingBoolean); } /** @@ -808,7 +1263,7 @@ public abstract class Window implements AutoCloseable { * * @return window name * @see Window#name - * @since v1-alpha2 + * @since v1-alpha9 */ public @Nullable String getName() { return name; @@ -819,7 +1274,7 @@ public abstract class Window implements AutoCloseable { * * @return window title * @see Window#title - * @since v1-alpha2 + * @since v1-alpha9 */ public @Nullable String getTitle() { return title; @@ -831,7 +1286,7 @@ public abstract class Window implements AutoCloseable { * * @return file paths to icons * @see Window#icons - * @since v1-alpha6 + * @since v1-alpha9 */ public @NotNull Path @Nullable [] getIcons() { return icons; @@ -842,7 +1297,7 @@ public abstract class Window implements AutoCloseable { * * @return window size * @see Window#size - * @since v1-alpha2 + * @since v1-alpha9 */ public @Nullable Vec2i getSize() { return size; @@ -853,7 +1308,7 @@ public abstract class Window implements AutoCloseable { * * @return minimum window size * @see Window#minimumSize - * @since v1-alpha2 + * @since v1-alpha9 */ public @Nullable Vec2i getMinimumSize() { return minimumSize; @@ -864,7 +1319,7 @@ public abstract class Window implements AutoCloseable { * * @return maximum window size * @see Window#maximumSize - * @since v1-alpha2 + * @since v1-alpha9 */ public @Nullable Vec2i getMaximumSize() { return maximumSize; @@ -875,7 +1330,7 @@ public abstract class Window implements AutoCloseable { * * @return window position * @see Window#position - * @since v1-alpha2 + * @since v1-alpha9 */ public @Nullable Vec2i getPosition() { return position; @@ -886,7 +1341,7 @@ public abstract class Window implements AutoCloseable { * * @return window mode * @see Window#windowMode - * @since v1-alpha2 + * @since v1-alpha9 */ public @Nullable WindowMode getWindowMode() { return windowMode; @@ -897,7 +1352,7 @@ public abstract class Window implements AutoCloseable { * * @return target monitor * @see Window#monitor - * @since v1-alpha2 + * @since v1-alpha9 */ public @Nullable Monitor getMonitor() { return monitor; @@ -908,7 +1363,7 @@ public abstract class Window implements AutoCloseable { * * @return resizable flag state * @see Window#resizable - * @since v1-alpha2 + * @since v1-alpha9 */ public @NotNull Tristate getResizable() { return resizable; @@ -919,7 +1374,7 @@ public abstract class Window implements AutoCloseable { * * @return borderless flag state * @see Window#borderless - * @since v1-alpha2 + * @since v1-alpha9 */ public @NotNull Tristate getBorderless() { return borderless; @@ -930,7 +1385,7 @@ public abstract class Window implements AutoCloseable { * * @return focusable flag state * @see Window#focusable - * @since v1-alpha2 + * @since v1-alpha9 */ public @NotNull Tristate getFocusable() { return focusable; @@ -941,7 +1396,7 @@ public abstract class Window implements AutoCloseable { * * @return on top flag state * @see Window#onTop - * @since v1-alpha2 + * @since v1-alpha9 */ public @NotNull Tristate getOnTop() { return onTop; @@ -952,7 +1407,7 @@ public abstract class Window implements AutoCloseable { * * @return transparency flag state * @see Window#transparent - * @since v1-alpha2 + * @since v1-alpha9 */ public @NotNull Tristate getTransparent() { return transparent; @@ -963,7 +1418,7 @@ public abstract class Window implements AutoCloseable { * * @return rendering flag state * @see Window#rendering - * @since v1-alpha2 + * @since v1-alpha9 */ public @NotNull Tristate getRendering() { return rendering; @@ -975,7 +1430,7 @@ public abstract class Window implements AutoCloseable { * @param name new window name * @return builder instance * @see Window#name - * @since v1-alpha2 + * @since v1-alpha9 */ public @NotNull Builder setName(@Nullable String name) { this.name = name; @@ -988,7 +1443,7 @@ public abstract class Window implements AutoCloseable { * @param title new window title * @return builder instance * @see Window#title - * @since v1-alpha2 + * @since v1-alpha9 */ public @NotNull Builder setTitle(@Nullable String title) { this.title = title; @@ -1002,7 +1457,7 @@ public abstract class Window implements AutoCloseable { * @param icons new file paths to icons * @return builder instance * @see Window#icons - * @since v1-alpha6 + * @since v1-alpha9 */ public @NotNull Builder setIcons(@NotNull Path @Nullable [] icons) { this.icons = icons; @@ -1015,7 +1470,7 @@ public abstract class Window implements AutoCloseable { * @param size new window size * @return builder instance * @see Window#size - * @since v1-alpha2 + * @since v1-alpha9 */ public @NotNull Builder setSize(@Nullable Vec2i size) { this.size = size; @@ -1028,7 +1483,7 @@ public abstract class Window implements AutoCloseable { * @param minimumSize new minimum window size * @return builder instance * @see Window#minimumSize - * @since v1-alpha2 + * @since v1-alpha9 */ public @NotNull Builder setMinimumSize(@Nullable Vec2i minimumSize) { this.minimumSize = minimumSize; @@ -1041,7 +1496,7 @@ public abstract class Window implements AutoCloseable { * @param maximumSize new maximum window size * @return builder instance * @see Window#maximumSize - * @since v1-alpha2 + * @since v1-alpha9 */ public @NotNull Builder setMaximumSize(@Nullable Vec2i maximumSize) { this.maximumSize = maximumSize; @@ -1054,7 +1509,7 @@ public abstract class Window implements AutoCloseable { * @param position new window position * @return builder instance * @see Window#position - * @since v1-alpha2 + * @since v1-alpha9 */ public @NotNull Builder setPosition(@Nullable Vec2i position) { this.position = position; @@ -1067,7 +1522,7 @@ public abstract class Window implements AutoCloseable { * @param windowMode new window mode * @return builder instance * @see Window#windowMode - * @since v1-alpha2 + * @since v1-alpha9 */ public @NotNull Builder setWindowMode(@Nullable WindowMode windowMode) { this.windowMode = windowMode; @@ -1080,7 +1535,7 @@ public abstract class Window implements AutoCloseable { * @param monitor new target monitor * @return builder instance * @see Window#monitor - * @since v1-alpha6 + * @since v1-alpha9 */ public synchronized @NotNull Builder setMonitor(@Nullable Monitor monitor) { this.monitor = monitor; @@ -1093,7 +1548,7 @@ public abstract class Window implements AutoCloseable { * @param resizable new resizable flag state * @return builder instance * @see Window#resizable - * @since v1-alpha2 + * @since v1-alpha9 */ public @NotNull Builder setResizable(@NotNull Tristate resizable) { this.resizable = resizable; @@ -1106,7 +1561,7 @@ public abstract class Window implements AutoCloseable { * @param borderless new borderless flag state * @return builder instance * @see Window#borderless - * @since v1-alpha2 + * @since v1-alpha9 */ public @NotNull Builder setBorderless(@NotNull Tristate borderless) { this.borderless = borderless; @@ -1119,7 +1574,7 @@ public abstract class Window implements AutoCloseable { * @param focusable new focusable flag state * @return builder instance * @see Window#focusable - * @since v1-alpha2 + * @since v1-alpha9 */ public @NotNull Builder setFocusable(@NotNull Tristate focusable) { this.focusable = focusable; @@ -1132,7 +1587,7 @@ public abstract class Window implements AutoCloseable { * @param onTop new on top flag state * @return builder instance * @see Window#onTop - * @since v1-alpha2 + * @since v1-alpha9 */ public @NotNull Builder setOnTop(@NotNull Tristate onTop) { this.onTop = onTop; @@ -1145,7 +1600,7 @@ public abstract class Window implements AutoCloseable { * @param transparent new transparency flag state * @return builder instance * @see Window#transparent - * @since v1-alpha2 + * @since v1-alpha9 */ public @NotNull Builder setTransparent(@NotNull Tristate transparent) { this.transparent = transparent; @@ -1158,7 +1613,7 @@ public abstract class Window implements AutoCloseable { * @param rendering new rendering flag state * @return builder instance * @see Window#rendering - * @since v1-alpha2 + * @since v1-alpha9 */ public @NotNull Builder setRendering(@NotNull Tristate rendering) { this.rendering = rendering; diff --git a/windowing/src/main/java/de/staropensource/engine/windowing/type/input/Key.java b/rendering/src/main/java/de/staropensource/engine/rendering/type/input/Key.java similarity index 76% rename from windowing/src/main/java/de/staropensource/engine/windowing/type/input/Key.java rename to rendering/src/main/java/de/staropensource/engine/rendering/type/input/Key.java index d06cafc4..80fab581 100644 --- a/windowing/src/main/java/de/staropensource/engine/windowing/type/input/Key.java +++ b/rendering/src/main/java/de/staropensource/engine/rendering/type/input/Key.java @@ -17,590 +17,590 @@ * along with this program. If not, see . */ -package de.staropensource.engine.windowing.type.input; +package de.staropensource.engine.rendering.type.input; /** * Contains a list of keys which can be recognized by the engine. * - * @since v1-alpha2 + * @since v1-alpha9 */ public enum Key { /** * An unknown key. * - * @since v1-alpha2 + * @since v1-alpha9 */ UNKNOWN_KEY, /** * An unknown mouse button. * - * @since v1-alpha2 + * @since v1-alpha9 */ - UNKNOWN_MOUSE, + UNKNOWN_MOUSE_BUTTON, /** * The left mouse button. * - * @since v1-alpha2 + * @since v1-alpha9 */ MOUSE_LEFT, /** * The middle mouse button. * - * @since v1-alpha2 + * @since v1-alpha9 */ MOUSE_MIDDLE, /** * The right mouse button. * - * @since v1-alpha2 + * @since v1-alpha9 */ MOUSE_RIGHT, /** * The {@code ALT} modifier key. * - * @since v1-alpha2 + * @since v1-alpha9 */ ALT, /** * The {@code '} key. * - * @since v1-alpha2 + * @since v1-alpha9 */ APOSTROPHE, /** * The {@code DOWN} arrow key. * - * @since v1-alpha2 + * @since v1-alpha9 */ ARROW_DOWN, /** * The {@code LEFT} arrow key. * - * @since v1-alpha2 + * @since v1-alpha9 */ ARROW_LEFT, /** * The {@code RIGHT} arrow key. * - * @since v1-alpha2 + * @since v1-alpha9 */ ARROW_RIGHT, /** * The {@code UP} arrow key. * - * @since v1-alpha2 + * @since v1-alpha9 */ ARROW_UP, /** * The {@code \} key. * - * @since v1-alpha2 + * @since v1-alpha9 */ BACKSLASH, /** * The {@code BACKSPACE} key. * - * @since v1-alpha2 + * @since v1-alpha9 */ BACKSPACE, /** * The left {@code [} key. * - * @since v1-alpha2 + * @since v1-alpha9 */ BRACKET_LEFT, /** * The right {@code ]} key. * - * @since v1-alpha2 + * @since v1-alpha9 */ BRACKET_RIGHT, /** * THE {@code CAPSLOCK} KEY. * - * @since v1-alpha2 + * @since v1-alpha9 */ CAPS_LOCK, /** * The {@code ,} key. * - * @since v1-alpha2 + * @since v1-alpha9 */ COMMA, /** * The left {@code CTRL} modifier key. * - * @since v1-alpha2 + * @since v1-alpha9 */ CONTROL_LEFT, /** * The right {@code CTRL} modifier key. * - * @since v1-alpha2 + * @since v1-alpha9 */ CONTROL_RIGHT, /** * The {@code DEL} key. * - * @since v1-alpha2 + * @since v1-alpha9 */ DELETE, /** * The {@code END} key. * - * @since v1-alpha2 + * @since v1-alpha9 */ END, /** * The {@code ENTER} key. * - * @since v1-alpha2 + * @since v1-alpha9 */ ENTER, /** * The {@code =} key. * - * @since v1-alpha2 + * @since v1-alpha9 */ EQUAL, /** * The {@code ESC} key. * - * @since v1-alpha2 + * @since v1-alpha9 */ ESCAPE, /** * The {@code F1} key. * - * @since v1-alpha2 + * @since v1-alpha9 */ FUNCTION_1, /** * The {@code F2} key. * - * @since v1-alpha2 + * @since v1-alpha9 */ FUNCTION_2, /** * The {@code F3} key. * - * @since v1-alpha2 + * @since v1-alpha9 */ FUNCTION_3, /** * The {@code F4} key. * - * @since v1-alpha2 + * @since v1-alpha9 */ FUNCTION_4, /** * The {@code F5} key. * - * @since v1-alpha2 + * @since v1-alpha9 */ FUNCTION_5, /** * The {@code F6} key. * - * @since v1-alpha2 + * @since v1-alpha9 */ FUNCTION_6, /** * The {@code F7} key. * - * @since v1-alpha2 + * @since v1-alpha9 */ FUNCTION_7, /** * The {@code F8} key. * - * @since v1-alpha2 + * @since v1-alpha9 */ FUNCTION_8, /** * The {@code F9} key. * - * @since v1-alpha2 + * @since v1-alpha9 */ FUNCTION_9, /** * The {@code F10} key. * - * @since v1-alpha2 + * @since v1-alpha9 */ FUNCTION_10, /** * The {@code F11} key. * - * @since v1-alpha2 + * @since v1-alpha9 */ FUNCTION_11, /** * The {@code F12} key. * - * @since v1-alpha2 + * @since v1-alpha9 */ FUNCTION_12, /** * The {@code F13} key. * - * @since v1-alpha2 + * @since v1-alpha9 */ FUNCTION_13, /** * The {@code F14} key. * - * @since v1-alpha2 + * @since v1-alpha9 */ FUNCTION_14, /** * The {@code F15} key. * - * @since v1-alpha2 + * @since v1-alpha9 */ FUNCTION_15, /** * The {@code F16} key. * - * @since v1-alpha2 + * @since v1-alpha9 */ FUNCTION_16, /** * The {@code F17} key. * - * @since v1-alpha2 + * @since v1-alpha9 */ FUNCTION_17, /** * The {@code F18} key. * - * @since v1-alpha2 + * @since v1-alpha9 */ FUNCTION_18, /** * The {@code F19} key. * - * @since v1-alpha2 + * @since v1-alpha9 */ FUNCTION_19, /** * The {@code F20} key. * - * @since v1-alpha2 + * @since v1-alpha9 */ FUNCTION_20, /** * The {@code F21} key. * - * @since v1-alpha2 + * @since v1-alpha9 */ FUNCTION_21, /** * The {@code F22} key. * - * @since v1-alpha2 + * @since v1-alpha9 */ FUNCTION_22, /** * The {@code F23} key. * - * @since v1-alpha2 + * @since v1-alpha9 */ FUNCTION_23, /** * The {@code F24} key. * - * @since v1-alpha2 + * @since v1-alpha9 */ FUNCTION_24, /** * The {@code F25} key. * - * @since v1-alpha2 + * @since v1-alpha9 */ FUNCTION_25, /** * The {@code `} key. * - * @since v1-alpha2 + * @since v1-alpha9 */ GRAVE, /** * The {@code HOME} key. * - * @since v1-alpha2 + * @since v1-alpha9 */ HOME, /** * THe {@code INS} key. * - * @since v1-alpha2 + * @since v1-alpha9 */ INSERT, /** * The {@code +} key on your keypad. * - * @since v1-alpha2 + * @since v1-alpha9 */ KEYPAD_ADD, /** * The {@code -} key on your keypad. * - * @since v1-alpha2 + * @since v1-alpha9 */ KEYPAD_DECIMAL, /** * The {@code /} key on your keypad. * - * @since v1-alpha2 + * @since v1-alpha9 */ KEYPAD_DIVIDE, /** * The {@code ENTER} key on your keypad. * - * @since v1-alpha2 + * @since v1-alpha9 */ KEYPAD_ENTER, /** * The {@code =} key on your keypad. * - * @since v1-alpha2 + * @since v1-alpha9 */ KEYPAD_EQUAL, /** * The {@code *} key on your keypad. * - * @since v1-alpha2 + * @since v1-alpha9 */ KEYPAD_MULTIPLY, /** * The number {@code 0} key on your keypad. * - * @since v1-alpha2 + * @since v1-alpha9 */ KEYPAD_NUMBER_0, /** * The number {@code 1} key on your keypad. * - * @since v1-alpha2 + * @since v1-alpha9 */ KEYPAD_NUMBER_1, /** * The number {@code 2} key on your keypad. * - * @since v1-alpha2 + * @since v1-alpha9 */ KEYPAD_NUMBER_2, /** * The number {@code 3} key on your keypad. * - * @since v1-alpha2 + * @since v1-alpha9 */ KEYPAD_NUMBER_3, /** * The number {@code 4} key on your keypad. * - * @since v1-alpha2 + * @since v1-alpha9 */ KEYPAD_NUMBER_4, /** * The number {@code 5} key on your keypad. * - * @since v1-alpha2 + * @since v1-alpha9 */ KEYPAD_NUMBER_5, /** * The number {@code 6} key on your keypad. * - * @since v1-alpha2 + * @since v1-alpha9 */ KEYPAD_NUMBER_6, /** * The number {@code 7} key on your keypad. * - * @since v1-alpha2 + * @since v1-alpha9 */ KEYPAD_NUMBER_7, /** * The number {@code 8} key on your keypad. * - * @since v1-alpha2 + * @since v1-alpha9 */ KEYPAD_NUMBER_8, /** * The number {@code 9} key on your keypad. * - * @since v1-alpha2 + * @since v1-alpha9 */ KEYPAD_NUMBER_9, /** * The {@code -} key on your keypad. * - * @since v1-alpha2 + * @since v1-alpha9 */ KEYPAD_SUBTRACT, /** * The letter {@code A} key. * - * @since v1-alpha2 + * @since v1-alpha9 */ LETTER_A, /** * The letter {@code B} key. * - * @since v1-alpha2 + * @since v1-alpha9 */ LETTER_B, /** * The letter {@code C} key. * - * @since v1-alpha2 + * @since v1-alpha9 */ LETTER_C, /** * The letter {@code D} key. * - * @since v1-alpha2 + * @since v1-alpha9 */ LETTER_D, /** * The letter {@code E} key. * - * @since v1-alpha2 + * @since v1-alpha9 */ LETTER_E, /** * The letter {@code F} key. * - * @since v1-alpha2 + * @since v1-alpha9 */ LETTER_F, /** * The letter {@code G} key. * - * @since v1-alpha2 + * @since v1-alpha9 */ LETTER_G, /** * The letter {@code H} key. * - * @since v1-alpha2 + * @since v1-alpha9 */ LETTER_H, /** * The letter {@code I} key. * - * @since v1-alpha2 + * @since v1-alpha9 */ LETTER_I, /** * The letter {@code J} key. * - * @since v1-alpha2 + * @since v1-alpha9 */ LETTER_J, /** * The letter {@code K} key. * - * @since v1-alpha2 + * @since v1-alpha9 */ LETTER_K, /** * The letter {@code L} key. * - * @since v1-alpha2 + * @since v1-alpha9 */ LETTER_L, /** * The letter {@code M} key. * - * @since v1-alpha2 + * @since v1-alpha9 */ LETTER_M, /** * The letter {@code N} key. * - * @since v1-alpha2 + * @since v1-alpha9 */ LETTER_N, /** * The letter {@code O} key. * - * @since v1-alpha2 + * @since v1-alpha9 */ LETTER_O, /** * The letter {@code P} key. * - * @since v1-alpha2 + * @since v1-alpha9 */ LETTER_P, /** * The letter {@code Q} key. * - * @since v1-alpha2 + * @since v1-alpha9 */ LETTER_Q, /** * The letter {@code R} key. * - * @since v1-alpha2 + * @since v1-alpha9 */ LETTER_R, /** * The letter {@code S} key. * - * @since v1-alpha2 + * @since v1-alpha9 */ LETTER_S, /** * The letter {@code T} key. * - * @since v1-alpha2 + * @since v1-alpha9 */ LETTER_T, /** * The letter {@code U} key. * - * @since v1-alpha2 + * @since v1-alpha9 */ LETTER_U, /** * The letter {@code V} key. * - * @since v1-alpha2 + * @since v1-alpha9 */ LETTER_V, /** * The letter {@code W} key. * - * @since v1-alpha2 + * @since v1-alpha9 */ LETTER_W, /** * The letter {@code X} key. * - * @since v1-alpha2 + * @since v1-alpha9 */ LETTER_X, /** * The letter {@code Y} key. * - * @since v1-alpha2 + * @since v1-alpha9 */ LETTER_Y, /** * The letter {@code Z} key. * - * @since v1-alpha2 + * @since v1-alpha9 */ LETTER_Z, /** * The {@code MENU} key, which brings up the right click menu. * - * @since v1-alpha2 + * @since v1-alpha9 */ MENU, /** @@ -608,151 +608,151 @@ public enum Key { *

* Windows users will recognize this key as the Windows key. * - * @since v1-alpha2 + * @since v1-alpha9 */ META, /** * The {@code -} key. * - * @since v1-alpha2 + * @since v1-alpha9 */ MINUS, /** * The number {@code 0}. * - * @since v1-alpha2 + * @since v1-alpha9 */ NUMBER_0, /** * The number {@code 1}. * - * @since v1-alpha2 + * @since v1-alpha9 */ NUMBER_1, /** * The number {@code 2}. * - * @since v1-alpha2 + * @since v1-alpha9 */ NUMBER_2, /** * The number {@code 3}. * - * @since v1-alpha2 + * @since v1-alpha9 */ NUMBER_3, /** * The number {@code 4}. * - * @since v1-alpha2 + * @since v1-alpha9 */ NUMBER_4, /** * The number {@code 5}. * - * @since v1-alpha2 + * @since v1-alpha9 */ NUMBER_5, /** * The number {@code 6}. * - * @since v1-alpha2 + * @since v1-alpha9 */ NUMBER_6, /** * The number {@code 7}. * - * @since v1-alpha2 + * @since v1-alpha9 */ NUMBER_7, /** * The number {@code 8}. * - * @since v1-alpha2 + * @since v1-alpha9 */ NUMBER_8, /** * The number {@code 9}. * - * @since v1-alpha2 + * @since v1-alpha9 */ NUMBER_9, /** * The {@code NUM} key. * - * @since v1-alpha2 + * @since v1-alpha9 */ NUM_LOCK, /** * The {@code PAGE DOWN} key. * - * @since v1-alpha2 + * @since v1-alpha9 */ PAGE_DOWN, /** * The {@code PAGE UP} key. * - * @since v1-alpha2 + * @since v1-alpha9 */ PAGE_UP, /** * The {@code PAUSE} key. * - * @since v1-alpha2 + * @since v1-alpha9 */ PAUSE, /** * The {@code .} key. * - * @since v1-alpha2 + * @since v1-alpha9 */ PERIOD, /** * The {@code PRINT} key. * - * @since v1-alpha2 + * @since v1-alpha9 */ PRINT, /** * The {@code SCROLL} key. * - * @since v1-alpha2 + * @since v1-alpha9 */ SCROLL_LOCK, /** * The {@code ;} key. * - * @since v1-alpha2 + * @since v1-alpha9 */ SEMICOLON, /** * The left {@code SHIFT} modifier key. * - * @since v1-alpha2 + * @since v1-alpha9 */ SHIFT_LEFT, /** * The right {@code SHIFT} modifier key. * - * @since v1-alpha2 + * @since v1-alpha9 */ SHIFT_RIGHT, /** * The {@code /} key. * - * @since v1-alpha2 + * @since v1-alpha9 */ SLASH, /** * The {@code ENTER} key. * - * @since v1-alpha2 + * @since v1-alpha9 */ SPACE, /** * The {@code TAB} key. * - * @since v1-alpha2 + * @since v1-alpha9 */ TAB, } diff --git a/windowing/src/main/java/de/staropensource/engine/windowing/type/input/KeyState.java b/rendering/src/main/java/de/staropensource/engine/rendering/type/input/KeyState.java similarity index 89% rename from windowing/src/main/java/de/staropensource/engine/windowing/type/input/KeyState.java rename to rendering/src/main/java/de/staropensource/engine/rendering/type/input/KeyState.java index 5a2a6fca..d5c981b7 100644 --- a/windowing/src/main/java/de/staropensource/engine/windowing/type/input/KeyState.java +++ b/rendering/src/main/java/de/staropensource/engine/rendering/type/input/KeyState.java @@ -17,26 +17,26 @@ * along with this program. If not, see . */ -package de.staropensource.engine.windowing.type.input; +package de.staropensource.engine.rendering.type.input; /** * Contains in which state a key is. * - * @since v1-alpha2 + * @since v1-alpha9 */ @SuppressWarnings({ "unused" }) public enum KeyState { /** * Indicates that a key is pressed. * - * @since v1-alpha2 + * @since v1-alpha9 */ PRESSED, /** * Indicates that a key is released. * - * @since v1-alpha2 + * @since v1-alpha9 */ RELEASED, } diff --git a/windowing/src/main/java/de/staropensource/engine/windowing/type/input/package-info.java b/rendering/src/main/java/de/staropensource/engine/rendering/type/input/package-info.java similarity index 92% rename from windowing/src/main/java/de/staropensource/engine/windowing/type/input/package-info.java rename to rendering/src/main/java/de/staropensource/engine/rendering/type/input/package-info.java index adfb042d..c8da5c5a 100644 --- a/windowing/src/main/java/de/staropensource/engine/windowing/type/input/package-info.java +++ b/rendering/src/main/java/de/staropensource/engine/rendering/type/input/package-info.java @@ -20,6 +20,6 @@ /** * Data types related to input. * - * @since v1-alpha2 + * @since v1-alpha9 */ -package de.staropensource.engine.windowing.type.input; +package de.staropensource.engine.rendering.type.input; diff --git a/windowing/src/main/java/de/staropensource/engine/windowing/type/package-info.java b/rendering/src/main/java/de/staropensource/engine/rendering/type/package-info.java similarity index 92% rename from windowing/src/main/java/de/staropensource/engine/windowing/type/package-info.java rename to rendering/src/main/java/de/staropensource/engine/rendering/type/package-info.java index 99ed26d9..3b4574d7 100644 --- a/windowing/src/main/java/de/staropensource/engine/windowing/type/package-info.java +++ b/rendering/src/main/java/de/staropensource/engine/rendering/type/package-info.java @@ -20,6 +20,6 @@ /** * Data types in form of enums and classes. * - * @since v1-alpha1 + * @since v1-alpha9 */ -package de.staropensource.engine.windowing.type; +package de.staropensource.engine.rendering.type; diff --git a/windowing/glfw/src/main/java/de/staropensource/engine/windowing/glfw/type/GlfwPlatform.java b/rendering/src/main/java/de/staropensource/engine/rendering/type/window/RenderingPlatform.java similarity index 77% rename from windowing/glfw/src/main/java/de/staropensource/engine/windowing/glfw/type/GlfwPlatform.java rename to rendering/src/main/java/de/staropensource/engine/rendering/type/window/RenderingPlatform.java index 32c95a19..529ff57c 100644 --- a/windowing/glfw/src/main/java/de/staropensource/engine/windowing/glfw/type/GlfwPlatform.java +++ b/rendering/src/main/java/de/staropensource/engine/rendering/type/window/RenderingPlatform.java @@ -17,53 +17,53 @@ * along with this program. If not, see . */ -package de.staropensource.engine.windowing.glfw.type; +package de.staropensource.engine.rendering.type.window; /** - * Contains all available platforms which GLFW can be initialized with. + * Represents all available platforms. * - * @since v1-alpha2 + * @since v1-alpha9 */ -public enum GlfwPlatform { +public enum RenderingPlatform { /** - * Allows GLFW to autodetect the platform to use. + * Allows the subsystem to autodetect the platform to use. * - * @since v1-alpha2 + * @since v1-alpha9 */ ANY, /** * Prefer initializing with the Wayland platform. * - * @since v1-alpha2 + * @since v1-alpha9 */ WAYLAND, /** * Prefer initializing with the X11 platform. * - * @since v1-alpha2 + * @since v1-alpha9 */ X11, /** * Prefer initializing with the Win32 platform. * - * @since v1-alpha2 + * @since v1-alpha9 */ WIN32, /** * Prefer initializing with the Cocoa platform. * - * @since v1-alpha2 + * @since v1-alpha9 */ COCOA, /** * Prefer initializing without any platform. * - * @since v1-alpha2 + * @since v1-alpha9 */ NONE } diff --git a/windowing/src/main/java/de/staropensource/engine/windowing/type/window/VsyncMode.java b/rendering/src/main/java/de/staropensource/engine/rendering/type/window/VsyncMode.java similarity index 77% rename from windowing/src/main/java/de/staropensource/engine/windowing/type/window/VsyncMode.java rename to rendering/src/main/java/de/staropensource/engine/rendering/type/window/VsyncMode.java index ea69bd0b..9c09c9ef 100644 --- a/windowing/src/main/java/de/staropensource/engine/windowing/type/window/VsyncMode.java +++ b/rendering/src/main/java/de/staropensource/engine/rendering/type/window/VsyncMode.java @@ -17,29 +17,30 @@ * along with this program. If not, see . */ -package de.staropensource.engine.windowing.type.window; +package de.staropensource.engine.rendering.type.window; -import de.staropensource.engine.windowing.WindowingSubsystemConfiguration; +import de.staropensource.engine.rendering.RenderingSubsystemConfiguration; /** * Controls how V-Sync operates. * - * @since v1-alpha1 + * @since v1-alpha9 */ public enum VsyncMode { /** * Disables V-Sync. The frame rate will be uncapped and will allow * for processing an unlimited amount of frames (if not limited by - * {@link WindowingSubsystemConfiguration#maximumFramesPerSecond}). + * {@link RenderingSubsystemConfiguration#maximumFramesPerSecond}). * - * @since v1-alpha1 + * @since v1-alpha9 */ OFF, /** - * Enables V-Sync and will cap the window's frame rate at the refresh rate of the target monitor. + * Enables V-Sync and will cap the window's frame rate + * at the refresh rate of the target monitor. * - * @since v1-alpha1 + * @since v1-alpha9 */ ON } diff --git a/windowing/src/main/java/de/staropensource/engine/windowing/type/window/WindowMode.java b/rendering/src/main/java/de/staropensource/engine/rendering/type/window/WindowMode.java similarity index 75% rename from windowing/src/main/java/de/staropensource/engine/windowing/type/window/WindowMode.java rename to rendering/src/main/java/de/staropensource/engine/rendering/type/window/WindowMode.java index f5670266..5276ccdd 100644 --- a/windowing/src/main/java/de/staropensource/engine/windowing/type/window/WindowMode.java +++ b/rendering/src/main/java/de/staropensource/engine/rendering/type/window/WindowMode.java @@ -17,18 +17,18 @@ * along with this program. If not, see . */ -package de.staropensource.engine.windowing.type.window; +package de.staropensource.engine.rendering.type.window; /** * Contains how a window should be displayed. * - * @since v1-alpha1 + * @since v1-alpha9 */ public enum WindowMode { /** * Marks the window as hidden, making it invisible and unable to be interacted with. * - * @since v1-alpha2 + * @since v1-alpha9 */ HIDDEN, @@ -36,7 +36,7 @@ public enum WindowMode { * Marks the window as windowed, which * will allow the user to drag around the window freely. * - * @since v1-alpha1 + * @since v1-alpha9 */ WINDOWED, @@ -45,7 +45,7 @@ public enum WindowMode { * summoned back into {@link #WINDOWED} mode by the user * by (for example) clicking an icon or {@code ALT+TAB}-ing. * - * @since v1-alpha2 + * @since v1-alpha9 */ MINIMIZED, @@ -53,7 +53,7 @@ public enum WindowMode { * Same as {@link #WINDOWED}, but will make the window occupy * most of the screen space, except for windows/bars/docks. * - * @since v1-alpha2 + * @since v1-alpha9 */ MAXIMIZED, @@ -61,20 +61,25 @@ public enum WindowMode { * Makes the window will have the same * size as the monitor it is currently on. * - * @since v1-alpha1 + * @since v1-alpha9 */ BORDERLESS_FULLSCREEN, /** - * Makes the window occupy the entire monitor it is currently on - * without allowing other windows to occupy the same space. + * Makes the window occupy the entire + * monitor it is currently on without + * allowing other windows to occupy + * the same space. *

- * This will increase rendering throughput as the window manager - * or compositor does not need to care about other windows occupying - * the same monitor. Use (and recommend) this mode if you/your users + * This will increase rendering + * throughput as the window manager + * or compositor does not need to + * care about other windows occupying + * the same monitor. Use (and recommend) + * this mode if you/your users * want more frames per second. * - * @since v1-alpha1 + * @since v1-alpha9 */ EXCLUSIVE_FULLSCREEN } diff --git a/windowing/src/main/java/de/staropensource/engine/windowing/type/window/package-info.java b/rendering/src/main/java/de/staropensource/engine/rendering/type/window/package-info.java similarity index 92% rename from windowing/src/main/java/de/staropensource/engine/windowing/type/window/package-info.java rename to rendering/src/main/java/de/staropensource/engine/rendering/type/window/package-info.java index 35f6245c..732b6dcb 100644 --- a/windowing/src/main/java/de/staropensource/engine/windowing/type/window/package-info.java +++ b/rendering/src/main/java/de/staropensource/engine/rendering/type/window/package-info.java @@ -20,6 +20,6 @@ /** * Data types related to windows. * - * @since v1-alpha1 + * @since v1-alpha9 */ -package de.staropensource.engine.windowing.type.window; +package de.staropensource.engine.rendering.type.window; diff --git a/rendering/src/main/java/module-info.java b/rendering/src/main/java/module-info.java new file mode 100644 index 00000000..63fb1c7a --- /dev/null +++ b/rendering/src/main/java/module-info.java @@ -0,0 +1,33 @@ +/** + * The {@code rendering} subsystem, responsible for + * initializing and managing windows and rendering APIs. + * + * @since v1-alpha9 + */ +module sosengine.rendering { + // Dependencies + // -> Engine + requires transitive sosengine.base; + // -> Libraries + requires transitive static lombok; + requires transitive org.jetbrains.annotations; + requires org.lwjgl.stb; + requires org.lwjgl.glfw; + requires org.lwjgl.bgfx; + + // API access + exports de.staropensource.engine.rendering; + exports de.staropensource.engine.rendering.event; + exports de.staropensource.engine.rendering.exception; + exports de.staropensource.engine.rendering.type; + exports de.staropensource.engine.rendering.type.input; + exports de.staropensource.engine.rendering.type.window; + + // Reflection access + opens de.staropensource.engine.rendering; + opens de.staropensource.engine.rendering.event; + opens de.staropensource.engine.rendering.exception; + opens de.staropensource.engine.rendering.type; + opens de.staropensource.engine.rendering.type.input; + opens de.staropensource.engine.rendering.type.window; +} diff --git a/windowing/src/main/javadoc/overview.html b/rendering/src/main/javadoc/overview.html similarity index 100% rename from windowing/src/main/javadoc/overview.html rename to rendering/src/main/javadoc/overview.html diff --git a/windowing/src/main/javadoc/theme.css b/rendering/src/main/javadoc/theme.css similarity index 100% rename from windowing/src/main/javadoc/theme.css rename to rendering/src/main/javadoc/theme.css diff --git a/settings.gradle b/settings.gradle index 9dfbd03a..47f07ace 100644 --- a/settings.gradle +++ b/settings.gradle @@ -17,13 +17,12 @@ * along with this program. If not, see . */ -rootProject.setName("sosengine") +rootProject.setName("sos!engine") include("base") include("testing") include("ansi") include("slf4j-compat") include("notification") -include("windowing") -include("windowing:glfw") +include("rendering") include("testapp") diff --git a/testapp/build.gradle b/testapp/build.gradle index 1f36e778..f58d0945 100644 --- a/testapp/build.gradle +++ b/testapp/build.gradle @@ -39,10 +39,9 @@ dependencies { // Project implementation(project(":base")) - implementation(project(":windowing")) + implementation(project(":rendering")) runtimeOnly(project(":ansi")) runtimeOnly(project(":slf4j-compat")) - runtimeOnly(project(":windowing:glfw")) } // Fix delombok task diff --git a/testapp/src/main/java/de/staropensource/engine/testapp/Main.java b/testapp/src/main/java/de/staropensource/engine/testapp/Main.java index e6cc213d..a56f8ecd 100644 --- a/testapp/src/main/java/de/staropensource/engine/testapp/Main.java +++ b/testapp/src/main/java/de/staropensource/engine/testapp/Main.java @@ -26,11 +26,11 @@ import de.staropensource.engine.base.implementable.helper.EventHelper; import de.staropensource.engine.base.logging.Logger; import de.staropensource.engine.base.type.vector.Vec2i; import de.staropensource.engine.base.utility.Miscellaneous; -import de.staropensource.engine.windowing.WindowingSubsystem; -import de.staropensource.engine.windowing.event.InputEvent; -import de.staropensource.engine.windowing.implementable.Window; -import de.staropensource.engine.windowing.type.input.Key; -import de.staropensource.engine.windowing.type.input.KeyState; +import de.staropensource.engine.rendering.RenderingSubsystem; +import de.staropensource.engine.rendering.event.InputEvent; +import de.staropensource.engine.rendering.type.Window; +import de.staropensource.engine.rendering.type.input.Key; +import de.staropensource.engine.rendering.type.input.KeyState; import lombok.Getter; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -119,10 +119,6 @@ public final class Main { // Say hello to the world! Logger.info("Hello world!"); - // Choose windowing API to use - if (!WindowingSubsystem.getInstance().setApi()) - Logger.crash("No windowing API is compatible"); - // Create window Window window; try { @@ -139,12 +135,13 @@ public final class Main { return; } + if (window == null) + Logger.crash("'window' is null"); + // Render loop - LinkedHashMap<@NotNull Window, @NotNull Throwable> renderLoopFailures = WindowingSubsystem + LinkedHashMap<@NotNull Window, @NotNull Throwable> renderLoopFailures = RenderingSubsystem .getInstance() - .getApi() - .getManagement() - .runRenderLoopContinuously(() -> { + .runRenderLoop(() -> { if (shutdown || window.isClosureRequested()) Engine.getInstance().shutdown(); }); diff --git a/testapp/src/main/java/module-info.java b/testapp/src/main/java/module-info.java index c0093155..6251ef07 100644 --- a/testapp/src/main/java/module-info.java +++ b/testapp/src/main/java/module-info.java @@ -7,5 +7,5 @@ open module sosengine.testapp { // Dependencies // -> Engine - requires sosengine.windowing; + requires sosengine.rendering; } diff --git a/windowing/build.gradle b/windowing/build.gradle deleted file mode 100644 index 3b0408e9..00000000 --- a/windowing/build.gradle +++ /dev/null @@ -1,109 +0,0 @@ -/* - * STAROPENSOURCE ENGINE SOURCE FILE - * Copyright (c) 2024 The StarOpenSource Engine Authors - * Licensed under the GNU Affero General Public License v3 - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as - * published by the Free Software Foundation, either version 3 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see . - */ - -// Plugins -plugins { - id("java") - id("io.freefair.lombok") version("${pluginLombok}") - id("maven-publish") -} - -// Dependencies -dependencies { - // Lombok - compileOnly("org.projectlombok:lombok:${dependencyLombok}") - annotationProcessor("org.projectlombok:lombok:${dependencyLombok}") - - // JetBrains Annotations - compileOnly("org.jetbrains:annotations:${dependencyJetbrainsAnnotations}") - - // Project - implementation(project(":base")) -} - -// Javadoc configuration -javadoc { - outputs.upToDateWhen { false } // Force task execution - dependsOn(delombok) // Make sure the source is delomboked first - - javadoc { - setClasspath(files(project.sourceSets.main.compileClasspath)) // Include dependencies - - options { - if (new File(projectDir, "src/main/javadoc/theme.css").exists()) - stylesheetFile = new File(projectDir, "src/main/javadoc/theme.css") // Theming is cool :3 - setMemberLevel(JavadocMemberLevel.PUBLIC) // Only display public stuff - setOverview("src/main/javadoc/overview.html") // We want a custom overview page to greet the visitor - setLocale("en_US") // 你好 - addStringOption("Xwerror", "-quiet") // Fail build on warning - - setJFlags([ - "-Duser.language=en_US" // See above - ]) - } - } -} - -// Include javadoc and source jar during publishing -java { - withJavadocJar() - withSourcesJar() -} - -// Build publishing configuration -// Note: You can safely ignore any errors or warnings thrown by your IDE here -publishing { - repositories { - maven { - name = "staropensource" - url = uri("https://mvn.staropensource.de/engine") - credentials(org.gradle.api.credentials.PasswordCredentials) - authentication { - //noinspection GroovyAssignabilityCheck - basic (BasicAuthentication) - } - } - } - publications { - //noinspection GroovyAssignabilityCheck - maven (MavenPublication) { - groupId = group - artifactId = project.getName() - version = version - //noinspection GroovyAssignabilityCheck - from components.java - } - } -} - -// Fix delombok task -delombok.doFirst { - File target = file("${project.projectDir}/src/main/module-info.java") - File source = file("${project.projectDir}/src/main/java/module-info.java") - - target.delete() - source.renameTo(target) -} -delombok.doLast { - File target = file("${project.projectDir}/src/main/java/module-info.java") - File source = file("${project.projectDir}/src/main/module-info.java") - - target.delete() - source.renameTo(target) -} diff --git a/windowing/glfw/README.md b/windowing/glfw/README.md deleted file mode 100644 index 82d50dc1..00000000 --- a/windowing/glfw/README.md +++ /dev/null @@ -1,2 +0,0 @@ -# The `glfw` subsystem -This subsystem provides a Windowing API using [LWJGL](https://lwjgl.org)'s [GLFW](https://glfw.org) bindings. diff --git a/windowing/glfw/gradle b/windowing/glfw/gradle deleted file mode 120000 index 1ce6c4c1..00000000 --- a/windowing/glfw/gradle +++ /dev/null @@ -1 +0,0 @@ -../../gradle \ No newline at end of file diff --git a/windowing/glfw/gradlew b/windowing/glfw/gradlew deleted file mode 120000 index 343e0d2c..00000000 --- a/windowing/glfw/gradlew +++ /dev/null @@ -1 +0,0 @@ -../../gradlew \ No newline at end of file diff --git a/windowing/glfw/gradlew.bat b/windowing/glfw/gradlew.bat deleted file mode 120000 index cb5a9464..00000000 --- a/windowing/glfw/gradlew.bat +++ /dev/null @@ -1 +0,0 @@ -../../gradlew.bat \ No newline at end of file diff --git a/windowing/glfw/src/main/java/de/staropensource/engine/windowing/glfw/GlfwSubsystem.java b/windowing/glfw/src/main/java/de/staropensource/engine/windowing/glfw/GlfwSubsystem.java deleted file mode 100644 index 6d1327cf..00000000 --- a/windowing/glfw/src/main/java/de/staropensource/engine/windowing/glfw/GlfwSubsystem.java +++ /dev/null @@ -1,218 +0,0 @@ -/* - * STAROPENSOURCE ENGINE SOURCE FILE - * Copyright (c) 2024 The StarOpenSource Engine Authors - * Licensed under the GNU Affero General Public License v3 - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as - * published by the Free Software Foundation, either version 3 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see . - */ - -package de.staropensource.engine.windowing.glfw; - -import de.staropensource.engine.base.annotation.EngineSubsystem; -import de.staropensource.engine.base.logging.Logger; -import de.staropensource.engine.base.utility.information.EngineInformation; -import de.staropensource.engine.base.implementation.versioning.StarOpenSourceVersioningSystem; -import de.staropensource.engine.base.type.DependencyVector; -import de.staropensource.engine.base.utility.Miscellaneous; -import de.staropensource.engine.windowing.WindowingSubsystem; -import de.staropensource.engine.windowing.implementable.api.ApiClass; -import de.staropensource.engine.windowing.implementable.api.ApiInternalClass; -import de.staropensource.engine.windowing.implementable.api.ApiManagementClass; -import de.staropensource.engine.windowing.event.WindowingErrorEvent; -import de.staropensource.engine.windowing.exception.NotOnMainThreadException; -import de.staropensource.engine.windowing.glfw.implementation.GlfwInternalClass; -import de.staropensource.engine.windowing.glfw.implementation.GlfwManagementClass; -import lombok.Getter; -import org.jetbrains.annotations.NotNull; -import org.lwjgl.glfw.GLFWErrorCallback; -import org.lwjgl.glfw.GLFWErrorCallbackI; - -import java.util.HashSet; -import java.util.Locale; -import java.util.Set; - -import static org.lwjgl.glfw.GLFW.*; - -/** - * The main class of the GLFW subsystem. - * - * @since v1-alpha2 - */ -@EngineSubsystem -@SuppressWarnings({ "JavadocDeclaration" }) -public final class GlfwSubsystem extends ApiClass { - /** - * Contains the class instance. - * - * @since v1-alpha0 - * -- GETTER -- - * Returns the class instance. - * - * @return class instance unless the subsystem is uninitialized - * @since v1-alpha0 - */ - @Getter - private static GlfwSubsystem instance = null; - - /** - * Contains the internal API class. - * - * @see ApiInternalClass - * @since v1-alpha4 - * -- GETTER -- - * {@inheritDoc} - */ - @Getter - private ApiInternalClass internalApi; - - /** - * Contains the management class. - * - * @see ApiManagementClass - * @since v1-alpha4 - * -- GETTER -- - * {@inheritDoc} - */ - @Getter - private ApiManagementClass management; - - /** - * The {@link GLFWErrorCallback} to use. - *

- * Only declared publicly for freeing during engine shutdown. - * - * @since v1-alpha2 - */ - private GLFWErrorCallback errorCallback = null; - - /** - * Initializes this subsystem. - * - * @since v1-alpha2 - */ - public GlfwSubsystem() { - // Check if subsystem has already initialized - if (instance == null) - instance = this; - else - Logger.crash("The subsystem tried to initialize twice"); - } - - /** {@inheritDoc} */ - @Override - public void initializeSubsystem() { - // Initialize configuration - new GlfwSubsystemConfiguration(); - - // Register API - WindowingSubsystem.getInstance().registerApi(this); - } - - /** {@inheritDoc} */ - @Override - public void initializeApi() { - Logger.verb("Initializing GLFW"); - try { - if (!Miscellaneous.onMainThread()) { - Logger.crash("Unable to initialize GLFW on a non-main thread", new NotOnMainThreadException(), true); - return; - } - - // Set error callback - errorCallback = GLFWErrorCallback.create(new GLFWErrorCallbackI() { - /** - * {@inheritDoc} - */ - @Override - public void invoke(int error, long description) { - new WindowingErrorEvent().callEvent(description + " (" + error + ")"); - } - }).set(); - - // Set init hints - switch (GlfwSubsystemConfiguration.getInstance().getPlatform()) { - case ANY -> glfwInitHint(GLFW_PLATFORM, GLFW_ANY_PLATFORM); - case WAYLAND -> tryPlatform(GLFW_PLATFORM_WAYLAND); - case X11 -> tryPlatform(GLFW_PLATFORM_X11); - case WIN32 -> tryPlatform(GLFW_PLATFORM_WIN32); - case COCOA -> tryPlatform(GLFW_PLATFORM_COCOA); - case NONE -> glfwInitHint(GLFW_PLATFORM, GLFW_PLATFORM_NULL); - } - glfwInitHint(GLFW_WAYLAND_LIBDECOR, GlfwSubsystemConfiguration.getInstance().isDisableLibdecor() ? GLFW_WAYLAND_DISABLE_LIBDECOR : GLFW_WAYLAND_PREFER_LIBDECOR); - - // Initialize GLFW - if (!glfwInit()) - Logger.crash("Failed to initialize GLFW"); - - // Initialize classes - internalApi = new GlfwInternalClass(); - management = new GlfwManagementClass(); - } catch (UnsatisfiedLinkError error) { - Logger.crash("Failed to load LWJGL native libraries", error); - } - } - - /** {@inheritDoc} */ - @Override - public void shutdownApi() { - Logger.verb("Terminating GLFW"); - - errorCallback.free(); - - if (Miscellaneous.onMainThread()) - glfwTerminate(); - else - Logger.crash("Unable to terminate GLFW on a non-main thread. Did you call Engine#shutdown or Logger#crash from another thread?", new NotOnMainThreadException(), true); - } - - /** {@inheritDoc} */ - @Override - public @NotNull String getName() { - return getApiName().toLowerCase(Locale.ROOT); - } - - /** {@inheritDoc} */ - @Override - public String getApiName() { - return "GLFW"; - } - - /** {@inheritDoc} */ - @Override - public @NotNull DependencyVector getDependencyVector() { - Set<@NotNull String> dependencies = new HashSet<>(); - dependencies.add("windowing"); - - return new DependencyVector.Builder() - .setIdentifier(getName()) - .setVersioningSystem(StarOpenSourceVersioningSystem.class) - .setVersion(EngineInformation.getVersioningString()) - .setDependencies(dependencies) - .build(); - } - - /** - * Checks if the specified platform is compatible, - * and if so, specifies it as the platform to use. - * - * @param platform platform to try - * @since v1-alpha2 - */ - private void tryPlatform(int platform) { - if (glfwPlatformSupported(platform)) - glfwInitHint(GLFW_PLATFORM, platform); - else - glfwInitHint(GLFW_PLATFORM, GLFW_ANY_PLATFORM); - } -} diff --git a/windowing/glfw/src/main/java/de/staropensource/engine/windowing/glfw/GlfwSubsystemConfiguration.java b/windowing/glfw/src/main/java/de/staropensource/engine/windowing/glfw/GlfwSubsystemConfiguration.java deleted file mode 100644 index abbaa540..00000000 --- a/windowing/glfw/src/main/java/de/staropensource/engine/windowing/glfw/GlfwSubsystemConfiguration.java +++ /dev/null @@ -1,139 +0,0 @@ -/* - * STAROPENSOURCE ENGINE SOURCE FILE - * Copyright (c) 2024 The StarOpenSource Engine Authors - * Licensed under the GNU Affero General Public License v3 - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as - * published by the Free Software Foundation, either version 3 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see . - */ - -package de.staropensource.engine.windowing.glfw; - -import de.staropensource.engine.base.implementable.Configuration; -import de.staropensource.engine.base.logging.Logger; -import de.staropensource.engine.base.utility.PropertiesReader; -import de.staropensource.engine.windowing.glfw.type.GlfwPlatform; -import lombok.Getter; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; - -/** - * Provides the GLFW subsystem configuration. - * - * @since v1-alpha2 - */ -@Getter -@SuppressWarnings({ "JavadocDeclaration" }) -public final class GlfwSubsystemConfiguration extends Configuration { - /** - * Contains the class instance. - * - * @since v1-alpha2 - * -- GETTER -- - * Returns the class instance. - * - * @return class instance unless {@link GlfwSubsystem} is uninitialized - * @since v1-alpha2 - */ - @Getter - private static GlfwSubsystemConfiguration instance; - - /** - * Defines prefix properties must begin with. - * - * @since v1-alpha2 - * -- GETTER -- - * Returns prefix properties must begin with. - * - * @return property group - * @since v1-alpha2 - */ - private final @NotNull String group = "sosengine.windowing.glfw."; - - /** - * Contains the platform GLFW will try to initialize with. - * - * @since v1-alpha2 - * -- GETTER -- - * Gets the value for {@link #platform}. - * - * @return variable value - * @see #platform - * @since v1-alpha2 - */ - private GlfwPlatform platform; - - /** - * If {@code true}, will disable support for - * libdecor. - *

- * Only affects the {@link GlfwPlatform#WAYLAND} platform. - * - * @since v1-alpha2 - * -- GETTER -- - * Gets the value for {@link #disableLibdecor}. - * - * @return variable value - * @see #disableLibdecor - * @since v1-alpha2 - */ - private boolean disableLibdecor; - - /** - * Creates and initializes an instance of this class. - * - * @see GlfwSubsystem - * @since v1-alpha6 - */ - GlfwSubsystemConfiguration() { - instance = this; - - loadDefaultConfiguration(); - } - - /** {@inheritDoc} */ - @Override - protected void matchProperty(@NotNull PropertiesReader parser, @NotNull String property) { - switch (property) { - case "platform" -> { - try { - platform = GlfwPlatform.valueOf(parser.getString(group + property).toUpperCase()); - } catch (IllegalArgumentException ignored) { - Logger.error("Platform " + parser.getString(group + property) + " is not valid"); - } - } - case "disableLibdecor" -> disableLibdecor = parser.getBoolean(group + property); - } - } - - /** {@inheritDoc} */ - @Override - protected void processSettings(@NotNull PropertiesReader parser) {} - - /** {@inheritDoc} */ - @Override - public void loadDefaultConfiguration() { - platform = GlfwPlatform.ANY; - disableLibdecor = false; - } - - /** {@inheritDoc} */ - @Override - public @Nullable Object getSetting(@NotNull String setting) { - return switch (setting) { - case "platform" -> platform; - case "disableLibdecor" -> disableLibdecor; - default -> null; - }; - } -} diff --git a/windowing/glfw/src/main/java/de/staropensource/engine/windowing/glfw/implementable/package-info.java b/windowing/glfw/src/main/java/de/staropensource/engine/windowing/glfw/implementable/package-info.java deleted file mode 100644 index 83c5ac78..00000000 --- a/windowing/glfw/src/main/java/de/staropensource/engine/windowing/glfw/implementable/package-info.java +++ /dev/null @@ -1,25 +0,0 @@ -/* - * STAROPENSOURCE ENGINE SOURCE FILE - * Copyright (c) 2024 The StarOpenSource Engine Authors - * Licensed under the GNU Affero General Public License v3 - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as - * published by the Free Software Foundation, either version 3 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see . - */ - -/** - * Interfaces and abstract classes which can be used for implementing classes. - * - * @since v1-alpha6 - */ -package de.staropensource.engine.windowing.glfw.implementable; diff --git a/windowing/glfw/src/main/java/de/staropensource/engine/windowing/glfw/implementation/GlfwInternalClass.java b/windowing/glfw/src/main/java/de/staropensource/engine/windowing/glfw/implementation/GlfwInternalClass.java deleted file mode 100644 index e995166d..00000000 --- a/windowing/glfw/src/main/java/de/staropensource/engine/windowing/glfw/implementation/GlfwInternalClass.java +++ /dev/null @@ -1,82 +0,0 @@ -/* - * STAROPENSOURCE ENGINE SOURCE FILE - * Copyright (c) 2024 The StarOpenSource Engine Authors - * Licensed under the GNU Affero General Public License v3 - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as - * published by the Free Software Foundation, either version 3 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see . - */ - -package de.staropensource.engine.windowing.glfw.implementation; - -import de.staropensource.engine.windowing.implementable.Monitor; -import de.staropensource.engine.windowing.implementable.api.ApiInternalClass; -import de.staropensource.engine.windowing.exception.NoMonitorsFoundException; -import lombok.Getter; -import lombok.Setter; -import org.jetbrains.annotations.NotNull; -import org.lwjgl.PointerBuffer; - -import java.util.LinkedHashSet; - -import static org.lwjgl.glfw.GLFW.glfwGetMonitors; - -/** - * The internal API class for GLFW-powered windowing APIs. - * - * @since v1-alpha2 - */ -@Getter -@Setter -@SuppressWarnings({ "JavadocDeclaration" }) -public final class GlfwInternalClass implements ApiInternalClass { - /** - * Contains a class which extends the {@link GlfwWindow} class. - * - * @since v1-alpha4 - * -- GETTER -- - * {@inheritDoc} - * -- SETTER -- - * Sets a class which extends the {@link GlfwWindow} class. - * - * @param windowClass new window class - * @since v1-alpha4 - */ - private @NotNull Class windowClass = GlfwWindow.class; - - /** - * Creates and initializes an instance of this class. - * - * @since v1-alpha2 - */ - public GlfwInternalClass() {} - - /** - * Returns all connected monitors. - * - * @return connected monitors - * @since v1-alpha2 - */ - @Override - public @NotNull LinkedHashSet<@NotNull Monitor> getMonitors() throws NoMonitorsFoundException { - PointerBuffer monitors = glfwGetMonitors(); - LinkedHashSet<@NotNull Monitor> output = new LinkedHashSet<>(); - if (monitors == null) - throw new NoMonitorsFoundException(); - - while (monitors.hasRemaining()) - output.add(new GlfwMonitor(monitors.get())); - - return output; - } -} diff --git a/windowing/glfw/src/main/java/de/staropensource/engine/windowing/glfw/implementation/GlfwManagementClass.java b/windowing/glfw/src/main/java/de/staropensource/engine/windowing/glfw/implementation/GlfwManagementClass.java deleted file mode 100644 index 9399ac95..00000000 --- a/windowing/glfw/src/main/java/de/staropensource/engine/windowing/glfw/implementation/GlfwManagementClass.java +++ /dev/null @@ -1,92 +0,0 @@ -/* - * STAROPENSOURCE ENGINE SOURCE FILE - * Copyright (c) 2024 The StarOpenSource Engine Authors - * Licensed under the GNU Affero General Public License v3 - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as - * published by the Free Software Foundation, either version 3 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see . - */ - -package de.staropensource.engine.windowing.glfw.implementation; - -import de.staropensource.engine.base.logging.Logger; -import de.staropensource.engine.base.utility.Miscellaneous; -import de.staropensource.engine.windowing.implementable.api.ApiManagementClass; -import de.staropensource.engine.windowing.implementable.Window; -import de.staropensource.engine.windowing.exception.NotOnMainThreadException; -import lombok.Getter; -import org.jetbrains.annotations.NotNull; - -import java.util.*; - -import static org.lwjgl.glfw.GLFW.*; - -/** - * The abstract management class for GLFW-powered windowing APIs. - * - * @since v1-alpha2 - */ -@Getter -public final class GlfwManagementClass extends ApiManagementClass { - /** - * Creates and initializes an instance of this class. - * - * @since v1-alpha2 - */ - public GlfwManagementClass() {} - - /** {@inheritDoc} */ - @Override - public boolean mustRunOnMainThread() { - return true; - } - - /** {@inheritDoc} */ - @Override - public @NotNull LinkedHashMap<@NotNull Window, @NotNull Throwable> runRenderLoop() { - // Ensure running on the main thread - if (!Miscellaneous.onMainThread()) - throw new NotOnMainThreadException(); - - LinkedHashMap<@NotNull Window, @NotNull Throwable> throwables = new LinkedHashMap<>(); - - // Update and render all windows - for (Window window : Window.getWindows()) { - if (!window.isRendering()) - continue; - - try { - window.updateState(); - window.render(); - } catch (Throwable throwable) { - Logger.error("Rendering window " + window + " failed: Threw throwable " + throwable.getClass().getName() + (throwable.getMessage() == null ? "" : ": " + throwable.getMessage())); - throwables.put(window, throwable); - } - } - - // Poll for events - glfwPollEvents(); - - return throwables; - } - - /** {@inheritDoc} */ - @Override - public @NotNull LinkedHashMap<@NotNull Window, @NotNull Throwable> runRenderLoopContinuously(@NotNull Runnable frameCode) { - // Ensure running on the main thread - if (!Miscellaneous.onMainThread()) - throw new NotOnMainThreadException(); - - return super.runRenderLoopContinuously(frameCode); - } -} diff --git a/windowing/glfw/src/main/java/de/staropensource/engine/windowing/glfw/implementation/GlfwMonitor.java b/windowing/glfw/src/main/java/de/staropensource/engine/windowing/glfw/implementation/GlfwMonitor.java deleted file mode 100644 index 81f54802..00000000 --- a/windowing/glfw/src/main/java/de/staropensource/engine/windowing/glfw/implementation/GlfwMonitor.java +++ /dev/null @@ -1,118 +0,0 @@ -/* - * STAROPENSOURCE ENGINE SOURCE FILE - * Copyright (c) 2024 The StarOpenSource Engine Authors - * Licensed under the GNU Affero General Public License v3 - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as - * published by the Free Software Foundation, either version 3 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see . - */ - -package de.staropensource.engine.windowing.glfw.implementation; - -import de.staropensource.engine.base.type.vector.Vec2i; -import de.staropensource.engine.windowing.implementable.Monitor; -import de.staropensource.engine.windowing.exception.InvalidMonitorException; -import lombok.SneakyThrows; -import org.jetbrains.annotations.NotNull; -import org.lwjgl.glfw.GLFWVidMode; - -import java.util.Objects; - -import static org.lwjgl.glfw.GLFW.*; - -/** - * Represents a monitor. A GLFW-powered monitor. Wait... aren't monitors powered by... power? - * - * @since v1-alpha2 - */ -@SuppressWarnings({ "JavadocDeclaration" }) -public final class GlfwMonitor extends Monitor { - /** - * Contains the {@link #identifier} as a long. - * - * @since v1-alpha2 - * -- GETTER -- - * Returns the monitor identifier as a long. - * - * @return monitor identifier as a long - * @since v1-alpha2 - */ - private final long identifierLong; - - /** - * Creates and initializes an instance of this class. - * - * @param identifier glfw monitor pointer - * @since v1-alpha2 - */ - @SneakyThrows - public GlfwMonitor(long identifier) throws InvalidMonitorException { - // Set identifier - setIdentifier(String.valueOf(identifier)); - identifierLong = identifier; - - // Check if connected - checkConnected(); - } - - /** {@inheritDoc} */ - @SneakyThrows - public void checkConnected() throws InvalidMonitorException { - super.checkConnected(); - } - - /** {@inheritDoc} */ - @Override - public boolean isConnected() { - return glfwGetMonitorName(identifierLong) != null; - } - - /** - * Returns the monitor name. - * - * @return monitor name - * @since v1-alpha2 - */ - @Override - public @NotNull String getName() throws InvalidMonitorException { - checkConnected(); - return Objects.requireNonNull(glfwGetMonitorName(identifierLong)); - } - - /** - * Returns the monitor size. - * - * @return monitor size - * @since v1-alpha2 - */ - @Override - public @NotNull Vec2i getSize() throws InvalidMonitorException { - checkConnected(); - - GLFWVidMode videoMode = Objects.requireNonNull(glfwGetVideoMode(identifierLong)); - - return new Vec2i(videoMode.width(), videoMode.height()); - } - - /** - * Returns the monitor refresh rate. - * - * @return monitor refresh rate - * @since v1-alpha2 - */ - @Override - public short getRefreshRate() throws InvalidMonitorException { - checkConnected(); - return (short) Objects.requireNonNull(glfwGetVideoMode(identifierLong)).refreshRate(); - } -} diff --git a/windowing/glfw/src/main/java/de/staropensource/engine/windowing/glfw/implementation/GlfwWindow.java b/windowing/glfw/src/main/java/de/staropensource/engine/windowing/glfw/implementation/GlfwWindow.java deleted file mode 100644 index 5ffa1f8c..00000000 --- a/windowing/glfw/src/main/java/de/staropensource/engine/windowing/glfw/implementation/GlfwWindow.java +++ /dev/null @@ -1,566 +0,0 @@ -/* - * STAROPENSOURCE ENGINE SOURCE FILE - * Copyright (c) 2024 The StarOpenSource Engine Authors - * Licensed under the GNU Affero General Public License v3 - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as - * published by the Free Software Foundation, either version 3 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see . - */ - -package de.staropensource.engine.windowing.glfw.implementation; - -import de.staropensource.engine.base.logging.Logger; -import de.staropensource.engine.base.type.vector.Vec2i; -import de.staropensource.engine.base.utility.Miscellaneous; -import de.staropensource.engine.windowing.WindowingSubsystemConfiguration; -import de.staropensource.engine.windowing.event.InputEvent; -import de.staropensource.engine.windowing.event.RenderingErrorEvent; -import de.staropensource.engine.windowing.exception.NotOnMainThreadException; -import de.staropensource.engine.windowing.exception.WindowCreationFailureException; -import de.staropensource.engine.windowing.glfw.callback.KeyCallback; -import de.staropensource.engine.windowing.glfw.callback.MouseButtonCallback; -import de.staropensource.engine.windowing.implementable.Monitor; -import de.staropensource.engine.windowing.implementable.Window; -import de.staropensource.engine.windowing.type.window.VsyncMode; -import de.staropensource.engine.windowing.type.window.WindowMode; -import lombok.Getter; -import lombok.Setter; -import org.jetbrains.annotations.ApiStatus; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; -import org.lwjgl.glfw.GLFWImage; -import org.lwjgl.glfw.GLFWKeyCallback; -import org.lwjgl.glfw.GLFWMouseButtonCallback; -import org.lwjgl.stb.STBImage; -import org.lwjgl.system.MemoryStack; -import org.lwjgl.system.MemoryUtil; - -import java.nio.ByteBuffer; -import java.nio.IntBuffer; -import java.nio.file.Path; -import java.util.ArrayList; -import java.util.List; -import java.util.Objects; - -import static org.lwjgl.glfw.GLFW.*; - -/** - * Abstract class for implementing GLFW-powered windows in a windowing API. - * - * @since v1-alpha2 - */ -@SuppressWarnings({ "JavadocDeclaration" }) -public final class GlfwWindow extends Window { - /** - * Contains the {@link #identifier} used by GLFW. - * - * @since v1-alpha2 - * -- GETTER -- - * Returns the window identifier used by GLFW. - * - * @return GLFW identifier - * @since v1-alpha2 - */ - @Getter - private long identifierLong; - - /** - * Contains the code to execute in {@link #render()}. - * - * @since v1-alpha8 - * -- GETTER -- - * Returns the code to execute in {@link #render()}. - * - * @return rendering code - * @since v1-alpha8 - * -- SETTER -- - * Sets the code to execute in {@link #render()} - * - * @param renderCode new rendering code - * @since v1-alpha8 - */ - @Getter - @Setter - private @NotNull Runnable renderCode = () -> glfwSwapBuffers(identifierLong); - - /** - * Contains the {@link GLFWKeyCallback} used for emitting {@link InputEvent}s. - * - * @since v1-alpha2 - */ - private GLFWKeyCallback keyCallback; - - /** - * Contains the {@link GLFWMouseButtonCallback} used for emitting {@link InputEvent}s. - * - * @since v1-alpha2 - */ - private GLFWMouseButtonCallback mouseButtonCallback; - - // ------------------------------------------------ [ Window (de)initialization ] ------------------------------------------------ // - /** - * Creates and initializes an instance of this class. - * - * @param name name - * @param title title - * @param icons icons - * @param size size - * @param minimumSize minimum size - * @param maximumSize maximum size - * @param position position - * @param windowMode window mode - * @param monitor monitor - * @param resizable resizable flag - * @param borderless borderless flag - * @param focusable focusable flag - * @param onTop on top flag - * @param transparent transparency flag - * @param rendering rendering flag - * @throws Exception stuff thrown by the {@link #initializeWindow()} and {@link #render()} methods of the implementing windowing API - * @since v1-alpha2 - */ - public GlfwWindow(@NotNull String name, @NotNull String title, @NotNull Path @Nullable [] icons, @NotNull Vec2i size, @NotNull Vec2i minimumSize, @NotNull Vec2i maximumSize, @NotNull Vec2i position, @NotNull WindowMode windowMode, @NotNull Monitor monitor, boolean resizable, boolean borderless, boolean focusable, boolean onTop, boolean transparent, boolean rendering) throws Exception { - super(name, title, icons, size, minimumSize, maximumSize, position, windowMode, monitor, resizable, borderless, focusable, onTop, transparent, rendering); - } - - /** {@inheritDoc} */ - @Override - protected void initializeWindow() { - createGlfwWindow(); - } - - /** - * (Re-)Creates the associated GLFW window. - * - * @since v1-alpha2 - */ - public void createGlfwWindow() throws WindowCreationFailureException { - // Ensure running on the main thread - if (!Miscellaneous.onMainThread()) - throw new NotOnMainThreadException(); - - // Get current focus and destroy existing window - boolean focused = true; - if (getIdentifier() != null) { - focused = isFocused(); - closeGlfwWindow(); - } - - // Set window hints - glfwWindowHint(GLFW_VISIBLE, GLFW_FALSE); // The window's visibility is later changed in setWindowState, this is just for setting up the window - glfwWindowHint(GLFW_POSITION_X, getPosition().getX()); - glfwWindowHint(GLFW_POSITION_Y, getPosition().getY()); - glfwWindowHint(GLFW_CENTER_CURSOR, 0); - glfwWindowHint(GLFW_FOCUSED, Miscellaneous.getIntegerizedBoolean(focused)); - glfwWindowHint(GLFW_TRANSPARENT_FRAMEBUFFER, Miscellaneous.getIntegerizedBoolean(isTransparent())); - glfwWindowHint(GLFW_CLIENT_API, GLFW_NO_API); - glfwWindowHint(GLFW_COCOA_RETINA_FRAMEBUFFER, GLFW_FALSE); - glfwWindowHintString(GLFW_WAYLAND_APP_ID, getName()); - glfwWindowHintString(GLFW_X11_CLASS_NAME, getName()); - glfwWindowHintString(GLFW_X11_INSTANCE_NAME, getName()); - - // Create window - long identifier = glfwCreateWindow(getSize().getX(), getSize().getY(), getTitle(), MemoryUtil.NULL, MemoryUtil.NULL); - if (identifier == MemoryUtil.NULL) { - new RenderingErrorEvent().callEvent("Unable to create window: Identifier is null"); - throw new WindowCreationFailureException(); - } - - // Set identifier - identifierLong = identifier; - setIdentifier(String.valueOf(identifier)); - - // Own context - ownContext(); - - // Set swap interval based on V-Sync mode setting - glfwSwapInterval(WindowingSubsystemConfiguration.getInstance().getVsyncMode() == VsyncMode.ON ? 1 : 0); - - // Create callbacks - keyCallback = GLFWKeyCallback.create(new KeyCallback(this)); - mouseButtonCallback = GLFWMouseButtonCallback.create(new MouseButtonCallback(this)); - - // Set callback - glfwSetKeyCallback(identifierLong, keyCallback); - glfwSetMouseButtonCallback(identifier, mouseButtonCallback); - - // Update the window state - setIcons(getIcons()); - setSize(getSize()); - setMinimumSize(getMinimumSize()); - setMaximumSize(getMaximumSize()); - setWindowMode(getWindowMode()); - } - - /** - * Closes the associated GLFW window. - * - * @since v1-alpha2 - */ - public void closeGlfwWindow() throws WindowCreationFailureException { - // Ensure running on the main thread - if (!Miscellaneous.onMainThread()) - throw new NotOnMainThreadException(); - - // Close callbacks - keyCallback.close(); - mouseButtonCallback.close(); - - // Destroy the window - glfwDestroyWindow(identifierLong); - } - - /** {@inheritDoc} */ - public void terminate() { - setTerminated(true); - closeGlfwWindow(); - } - - // ------------------------------------------------ [ State updates ] ------------------------------------------------ // - /** - * Updates the window state. - * - * @since v1-alpha2 - */ - @Override - public void updateState() { - // Ensure the window is not terminated - if (isTerminated()) - return; - - // Ensure running on the main thread - if (!Miscellaneous.onMainThread()) - throw new NotOnMainThreadException(); - - // Update window mode - if (Miscellaneous.getBooleanizedInteger(glfwGetWindowAttrib(identifierLong, GLFW_ICONIFIED))) - super.setWindowMode(WindowMode.MINIMIZED); - else if (Miscellaneous.getBooleanizedInteger(glfwGetWindowAttrib(identifierLong, GLFW_MAXIMIZED))) - super.setWindowMode(WindowMode.MAXIMIZED); - else if (Miscellaneous.getBooleanizedInteger(glfwGetWindowAttrib(identifierLong, GLFW_VISIBLE))) - super.setWindowMode(WindowMode.WINDOWED); - else if (Miscellaneous.getBooleanizedInteger(glfwGetWindowAttrib(identifierLong, GLFW_VISIBLE))) - super.setWindowMode(WindowMode.HIDDEN); - - // Update monitor - if (!getMonitor().isConnected()) { - Monitor newMonitor = null; - - for (Monitor monitor : Monitor.getMonitors()) - if (monitor.isConnected()) - newMonitor = monitor; - - if (newMonitor == null) - Logger.crash("Unable to set a new target monitor for window " + getUniqueIdentifier() + " as no monitors are connected to the system"); - - setMonitor(Objects.requireNonNull(newMonitor)); - } - - // Update vectors - try (MemoryStack stack = MemoryStack.stackPush()) { - IntBuffer width = stack.mallocInt(2); - IntBuffer height = stack.mallocInt(2); - - glfwGetWindowSize(identifierLong, width, height); - super.setSize(new Vec2i(width.get(), height.get())); - - glfwGetWindowPos(identifierLong, width, height); - super.setPosition(new Vec2i(width.get(), height.get())); - } - - // Update booleans - super.setResizable(Miscellaneous.getBooleanizedInteger(glfwGetWindowAttrib(identifierLong, GLFW_RESIZABLE))); - super.setOnTop(Miscellaneous.getBooleanizedInteger(glfwGetWindowAttrib(identifierLong, GLFW_FLOATING))); - super.setTransparent(Miscellaneous.getBooleanizedInteger(glfwGetWindowAttrib(identifierLong, GLFW_TRANSPARENT_FRAMEBUFFER))); - } - - // ------------------------------------------------ [ Rendering ] ------------------------------------------------ // - /** {@inheritDoc} */ - @Override - public void render() throws NotOnMainThreadException { - // Ensure the window is not terminated - if (isTerminated()) - return; - // Ensure rendering is enabled - if (!isRendering()) - return; - - // Ensure running on the main thread - if (!Miscellaneous.onMainThread()) - throw new NotOnMainThreadException(); - - renderCode.run(); - } - - // ------------------------------------------------ [ GLFW handling ] ------------------------------------------------ // - /** - * Updates the OpenGL context. - * - * @since v1-alpha2 - */ - public void ownContext() { - glfwMakeContextCurrent(identifierLong); - } - - // ------------------------------------------------ [ Information/Action methods ] ------------------------------------------------ // - /** {@inheritDoc} */ - @Override - public boolean isClosureRequested() { - // Ensure the window is not terminated - if (isTerminated()) - return false; - - return glfwWindowShouldClose(identifierLong); - } - - /** {@inheritDoc} */ - @Override - public boolean isFocused() { - // Ensure the window is not terminated - if (isTerminated()) - return false; - - return Miscellaneous.getTristatedInteger(glfwGetWindowAttrib(identifierLong, GLFW_FOCUSED)).toBoolean(); - } - - /** {@inheritDoc} */ - public void focus() { - // Ensure the window is not terminated - if (isTerminated()) - return; - - glfwFocusWindow(identifierLong); - } - - /** {@inheritDoc} */ - public void requestAttention() { - // Ensure the window is not terminated - if (isTerminated()) - return; - - glfwRequestWindowAttention(identifierLong); - } - - // ------------------------------------------------ [ Setter overrides ] ------------------------------------------------ // - - /** {@inheritDoc} */ - @Override - public void setName(@NotNull String name) { - // Ensure the window is not terminated - if (isTerminated()) - return; - - super.setName(name); - createGlfwWindow(); - } - - /** {@inheritDoc} */ - @Override - public void setTitle(@NotNull String title) { - // Ensure the window is not terminated - if (isTerminated()) - return; - - super.setTitle(title); - glfwSetWindowTitle(identifierLong, title); - } - - /** {@inheritDoc} */ - @ApiStatus.Experimental - @Override - public void setIcons(@NotNull Path @Nullable [] icons) { - // Ensure the window is not terminated - if (isTerminated()) - return; - - this.icons = icons; - if (icons != null) - try (GLFWImage.Buffer iconsBuffer = GLFWImage.malloc(icons.length)) { - Logger.warn("GlfwWindow#setIcons is experimental and may cause engine or JVM crashes. Here be dragons!"); - Logger.diag("icons.length = " + icons.length); - - List iconBuffers = new ArrayList<>(); - IntBuffer width = MemoryUtil.memAllocInt(1); - IntBuffer height = MemoryUtil.memAllocInt(1); - IntBuffer channels = MemoryUtil.memAllocInt(1); - - for (Path filepath : icons) { - Logger.diag("iterating icons » " + iconBuffers.size() + " » " + filepath); - // Load icon - Logger.diag("loading icon"); - iconBuffers.add(STBImage.stbi_load(filepath.toAbsolutePath().toString(), width, height, channels, 4)); - - if (iconBuffers.getLast() == null) { - Logger.warn("Icon " + iconsBuffer.position() + " could not be loaded" + (STBImage.stbi_failure_reason() == null ? "" : ": " + STBImage.stbi_failure_reason())); - continue; - } - - // Save into 'iconsBuffer' - Logger.diag("saving into buffer"); - iconsBuffer - .position(iconsBuffer.position() + 1) - .width(width.get(0)) - .height(height.get(0)) - .pixels(iconBuffers.getLast()); - } - Logger.diag("out of iteration"); - - // Set icons - Logger.diag("setting position"); - iconsBuffer.position(0); - Logger.diag("setting icons"); - Logger.flush(); - glfwSetWindowIcon(identifierLong, iconsBuffer); - - // Free icons - Logger.diag("freeing icons"); - for (ByteBuffer buffer : iconBuffers) - if (buffer != null) { - Logger.diag("freeing buffer"); - STBImage.stbi_image_free(buffer); - } else - Logger.diag("skipping null buffer"); - } - } - - /** {@inheritDoc} */ - @Override - public void setSize(@NotNull Vec2i size) { - // Ensure the window is not terminated - if (isTerminated()) - return; - - super.setSize(size); - glfwSetWindowSize(identifierLong, size.getX(), size.getY()); - } - - /** {@inheritDoc} */ - @Override - public void setMinimumSize(@NotNull Vec2i minimumSize) { - // Ensure the window is not terminated - if (isTerminated()) - return; - - super.setMinimumSize(minimumSize); - glfwSetWindowSizeLimits(identifierLong, minimumSize.getX(), minimumSize.getY(), getMaximumSize().getX(), getMaximumSize().getY()); - } - - /** {@inheritDoc} */ - @Override - public void setMaximumSize(@NotNull Vec2i maximumSize) { - // Ensure the window is not terminated - if (isTerminated()) - return; - - super.setMaximumSize(maximumSize); - glfwSetWindowSizeLimits(identifierLong, getMinimumSize().getX(), getMinimumSize().getY(), maximumSize.getX(), maximumSize.getY()); - } - - /** {@inheritDoc} */ - @Override - public void setPosition(@NotNull Vec2i position) { - // Ensure the window is not terminated - if (isTerminated()) - return; - - super.setPosition(position); - glfwSetWindowSize(identifierLong, position.getX(), position.getY()); - } - - /** {@inheritDoc} */ - @Override - public void setWindowMode(@NotNull WindowMode windowMode) { - // Ensure the window is not terminated - if (isTerminated()) - return; - - super.setWindowMode(windowMode); - switch (windowMode) { - case HIDDEN -> glfwHideWindow(identifierLong); - case WINDOWED -> { - glfwShowWindow(identifierLong); - glfwRestoreWindow(identifierLong); - } - case MINIMIZED -> { - glfwShowWindow(identifierLong); - glfwIconifyWindow(identifierLong); - } - case MAXIMIZED -> { - glfwShowWindow(identifierLong); - glfwRestoreWindow(identifierLong); - glfwMaximizeWindow(identifierLong); - } - case BORDERLESS_FULLSCREEN -> { - glfwShowWindow(identifierLong); - glfwRestoreWindow(identifierLong); - // TODO - } - case EXCLUSIVE_FULLSCREEN -> { - glfwShowWindow(identifierLong); - glfwRestoreWindow(identifierLong); - // TODO - } - } - } - - /** {@inheritDoc} */ - @Override - public void setResizable(boolean resizable) { - // Ensure the window is not terminated - if (isTerminated()) - return; - - super.setResizable(resizable); - } - - /** {@inheritDoc} */ - @Override - public void setBorderless(boolean borderless) { - // Ensure the window is not terminated - if (isTerminated()) - return; - - super.setBorderless(borderless); - } - - /** {@inheritDoc} */ - @Override - public void setFocusable(boolean focusable) { - // Ensure the window is not terminated - if (isTerminated()) - return; - - super.setFocusable(focusable); - } - - /** {@inheritDoc} */ - @Override - public void setOnTop(boolean onTop) { - // Ensure the window is not terminated - if (isTerminated()) - return; - - super.setOnTop(onTop); - } - - /** {@inheritDoc} */ - @Override - public void setTransparent(boolean transparent) { - // Ensure the window is not terminated - if (isTerminated()) - return; - - super.setTransparent(transparent); - createGlfwWindow(); - } -} diff --git a/windowing/glfw/src/main/java/de/staropensource/engine/windowing/glfw/implementation/package-info.java b/windowing/glfw/src/main/java/de/staropensource/engine/windowing/glfw/implementation/package-info.java deleted file mode 100644 index 01ffac46..00000000 --- a/windowing/glfw/src/main/java/de/staropensource/engine/windowing/glfw/implementation/package-info.java +++ /dev/null @@ -1,25 +0,0 @@ -/* - * STAROPENSOURCE ENGINE SOURCE FILE - * Copyright (c) 2024 The StarOpenSource Engine Authors - * Licensed under the GNU Affero General Public License v3 - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as - * published by the Free Software Foundation, either version 3 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see . - */ - -/** - * Implementations for various interfaces and abstract classes. - * - * @since v1-alpha6 - */ -package de.staropensource.engine.windowing.glfw.implementation; diff --git a/windowing/glfw/src/main/java/de/staropensource/engine/windowing/glfw/package-info.java b/windowing/glfw/src/main/java/de/staropensource/engine/windowing/glfw/package-info.java deleted file mode 100644 index bd6ac93f..00000000 --- a/windowing/glfw/src/main/java/de/staropensource/engine/windowing/glfw/package-info.java +++ /dev/null @@ -1,25 +0,0 @@ -/* - * STAROPENSOURCE ENGINE SOURCE FILE - * Copyright (c) 2024 The StarOpenSource Engine Authors - * Licensed under the GNU Affero General Public License v3 - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as - * published by the Free Software Foundation, either version 3 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see . - */ - -/** - * Code of the GLFW subsystem. - * - * @since v1-alpha2 - */ -package de.staropensource.engine.windowing.glfw; diff --git a/windowing/glfw/src/main/java/de/staropensource/engine/windowing/glfw/type/package-info.java b/windowing/glfw/src/main/java/de/staropensource/engine/windowing/glfw/type/package-info.java deleted file mode 100644 index 0131a440..00000000 --- a/windowing/glfw/src/main/java/de/staropensource/engine/windowing/glfw/type/package-info.java +++ /dev/null @@ -1,25 +0,0 @@ -/* - * STAROPENSOURCE ENGINE SOURCE FILE - * Copyright (c) 2024 The StarOpenSource Engine Authors - * Licensed under the GNU Affero General Public License v3 - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as - * published by the Free Software Foundation, either version 3 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see . - */ - -/** - * Data types in form of enums and classes. - * - * @since v1-alpha2 - */ -package de.staropensource.engine.windowing.glfw.type; diff --git a/windowing/glfw/src/main/java/module-info.java b/windowing/glfw/src/main/java/module-info.java deleted file mode 100644 index f87153bd..00000000 --- a/windowing/glfw/src/main/java/module-info.java +++ /dev/null @@ -1,25 +0,0 @@ -/** - * The {@code glfw} subsystem and windowing API, which makes it - * possible to create {@link Window} using the GLFW library. - * - * @since v1-alpha4 - */ -module sosengine.windowing.glfw { - // Dependencies - // -> Engine - requires transitive sosengine.base; - requires transitive sosengine.windowing; - // -> Libraries - requires transitive static lombok; - requires transitive org.jetbrains.annotations; - requires org.lwjgl.glfw; - requires org.lwjgl.stb; - - // API access - exports de.staropensource.engine.windowing.glfw; - exports de.staropensource.engine.windowing.glfw.implementation; - - // Reflection access - opens de.staropensource.engine.windowing.glfw; - opens de.staropensource.engine.windowing.glfw.implementation; -} diff --git a/windowing/glfw/src/main/javadoc/overview.html b/windowing/glfw/src/main/javadoc/overview.html deleted file mode 100644 index 7d320504..00000000 --- a/windowing/glfw/src/main/javadoc/overview.html +++ /dev/null @@ -1,24 +0,0 @@ - - - -

Welcome to the sos!engine API documentation!
- You are currently in the documentation for the glfw subsystem, allowing Graphics APIs to easily implement window and monitor support.

-

This subsystem does not provide any utility for your application, as it's meant to be used by Graphics APIs and just implements interfaces and classes from the graphics subsystem.

- diff --git a/windowing/glfw/src/main/javadoc/theme.css b/windowing/glfw/src/main/javadoc/theme.css deleted file mode 120000 index bccac6b3..00000000 --- a/windowing/glfw/src/main/javadoc/theme.css +++ /dev/null @@ -1 +0,0 @@ -../../../../../src/main/javadoc/theme.css \ No newline at end of file diff --git a/windowing/src/main/java/de/staropensource/engine/windowing/WindowingSubsystem.java b/windowing/src/main/java/de/staropensource/engine/windowing/WindowingSubsystem.java deleted file mode 100644 index f07f9611..00000000 --- a/windowing/src/main/java/de/staropensource/engine/windowing/WindowingSubsystem.java +++ /dev/null @@ -1,235 +0,0 @@ -/* - * STAROPENSOURCE ENGINE SOURCE FILE - * Copyright (c) 2024 The StarOpenSource Engine Authors - * Licensed under the GNU Affero General Public License v3 - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as - * published by the Free Software Foundation, either version 3 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see . - */ - -package de.staropensource.engine.windowing; - -import de.staropensource.engine.base.annotation.EngineSubsystem; -import de.staropensource.engine.base.annotation.EventListener; -import de.staropensource.engine.base.implementable.SubsystemClass; -import de.staropensource.engine.base.implementable.helper.EventHelper; -import de.staropensource.engine.base.logging.Logger; -import de.staropensource.engine.base.utility.information.EngineInformation; -import de.staropensource.engine.base.implementation.versioning.StarOpenSourceVersioningSystem; -import de.staropensource.engine.base.event.InternalEngineShutdownEvent; -import de.staropensource.engine.base.type.DependencyVector; -import de.staropensource.engine.base.utility.Miscellaneous; -import de.staropensource.engine.windowing.implementable.api.ApiClass; -import de.staropensource.engine.windowing.event.InputEvent; -import de.staropensource.engine.windowing.event.RenderingErrorEvent; -import de.staropensource.engine.windowing.event.WindowingErrorEvent; -import de.staropensource.engine.windowing.event.WindowingShutdownEvent; -import lombok.Getter; -import org.jetbrains.annotations.NotNull; - -import java.util.HashMap; -import java.util.Map; - -/** - * Main class of the {@code windowing} subsystem. - * - * @since v1-alpha0 - */ -@EngineSubsystem -@SuppressWarnings({ "JavadocDeclaration" }) -public final class WindowingSubsystem extends SubsystemClass { - /** - * Contains the class instance. - * - * @since v1-alpha0 - * -- GETTER -- - * Returns the class instance. - * - * @return class instance unless the subsystem is uninitialized - * @since v1-alpha0 - */ - @Getter - private static WindowingSubsystem instance = null; - - /** - * Contains a list of all registered windowing APIs. - * - * @see ApiClass - * @since v1-alpha0 - * -- GETTER -- - * Returns a list of all registered windowing APIs. - * - * @return list of all registered windowing APIs - * @see ApiClass - * @since v1-alpha0 - */ - @Getter - private final @NotNull Map<@NotNull String, @NotNull ApiClass> registeredApis = new HashMap<>(); - - /** - * Contains a reference to the active windowing API main class. - * - * @see ApiClass - * @since v1-alpha0 - * -- GETTER -- - * Returns a reference to the active windowing API main class. - * - * @return windowing API main class reference - * @see ApiClass - * @since v1-alpha0 - */ - @Getter - private ApiClass api = null; - - /** - * Initializes this subsystem. - * - * @since v1-alpha0 - */ - public WindowingSubsystem() { - // Only allow one instance - if (instance == null) - instance = this; - else - Logger.crash("Only one instance of this class is allowed, use getInstance() instead of creating a new instance"); - } - - /** {@inheritDoc} */ - @Override - public @NotNull String getName() { - return "windowing"; - } - - /** {@inheritDoc} */ - @Override - public void initializeSubsystem() { - // Initialize WindowingSubsystemConfiguration and load it - new WindowingSubsystemConfiguration().loadConfiguration(); - - // Precompute event listeners - cacheEvents(); - - // Warn about subsystem and API instability - Logger.warn("The windowing subsystem is experimental. Subsystem and API stability are not guaranteed."); - } - - /** - * Caches all windowing subsystem events. - * - * @since v1-alpha0 - */ - public static void cacheEvents() { - EventHelper.cacheEvent(RenderingErrorEvent.class); - EventHelper.cacheEvent(WindowingShutdownEvent.class); - EventHelper.cacheEvent(WindowingErrorEvent.class); - EventHelper.cacheEvent(InputEvent.class); - } - - /** {@inheritDoc} */ - @Override - public @NotNull DependencyVector getDependencyVector() { - return new DependencyVector.Builder() - .setIdentifier(getName()) - .setVersioningSystem(StarOpenSourceVersioningSystem.class) - .setVersion(EngineInformation.getVersioningString()) - .build(); - } - - /** - * Shuts the subsystem down. - * - * @since v1-alpha0 - */ - @EventListener(event = InternalEngineShutdownEvent.class) - @SuppressWarnings({ "unused" }) - protected static void shutdownSubsystem() { - Logger.verb("Shutting down"); - - long shutdownTime = Miscellaneous.measureExecutionTime(() -> { - new WindowingShutdownEvent().callEvent(); - - if (instance.api != null) - instance.api.shutdownApi(); - }); - - Logger.info("Shut down in " + shutdownTime + "ms"); - } - - /** - * Registers a windowing API. - * - * @param mainClass main class of the windowing API - * @since v1-alpha4 - */ - public void registerApi(@NotNull ApiClass mainClass) { - Logger.verb("Registering windowing API " + mainClass.getApiName() + " (" + mainClass.getClass().getName() + ")"); - - Object[] output = Miscellaneous.getMapValues(registeredApis, mainClass).toArray(); - - if (output.length == 0 || output[0] == null) - registeredApis.put(mainClass.getApiName(), mainClass); - } - - /** - * Chooses a windowing API to use automatically based on hardware support. - * - * @return if a compatible windowing API has been chosen - * @see #setApi(String) - * @since v1-alpha4 - */ - public boolean setApi() { - Logger.verb("Choosing a windowing API"); - - if (registeredApis.isEmpty()) - return false; - - // Initialize first API in list. - api = registeredApis.get(registeredApis.keySet().toArray(new String[0])[0]); - try { - Logger.diag("Initializing windowing API \"" + api.getApiName() + "\""); - Logger.diag("Initialized windowing API \"" + api.getApiName() + "\" in " + Miscellaneous.measureExecutionTime(() -> api.initializeApi()) + "ms"); - } catch (Throwable throwable) { - Logger.crash("Windowing API \"" + api.getApiName() + "\" failed to initialize", throwable, true); - throw throwable; - } - - return true; - } - - /** - * Sets the windowing API to use. - * - * @param name name of the windowing API - * @return if the windowing API has been found - * @see #setApi() - * @since v1-alpha4 - */ - @SuppressWarnings({ "unused" }) - public boolean setApi(@NotNull String name) { - if (!registeredApis.containsKey(name)) - return false; - - Logger.verb("Setting windowing API " + name); - - if (api == null) - api = registeredApis.get(name); - else - Logger.crash("Unable to set windowing API: windowing API " + api.getApiName() + " already registered"); - - // Initialize API - Logger.diag("Initializing windowing API " + api.getApiName()); - Logger.diag("Initialized windowing API " + api.getApiName() + " in " + Miscellaneous.measureExecutionTime(() -> api.initializeApi()) + "ms"); - - return true; - } -} diff --git a/windowing/src/main/java/de/staropensource/engine/windowing/WindowingSubsystemConfiguration.java b/windowing/src/main/java/de/staropensource/engine/windowing/WindowingSubsystemConfiguration.java deleted file mode 100644 index 6a73a3f5..00000000 --- a/windowing/src/main/java/de/staropensource/engine/windowing/WindowingSubsystemConfiguration.java +++ /dev/null @@ -1,246 +0,0 @@ -/* - * STAROPENSOURCE ENGINE SOURCE FILE - * Copyright (c) 2024 The StarOpenSource Engine Authors - * Licensed under the GNU Affero General Public License v3 - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as - * published by the Free Software Foundation, either version 3 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see . - */ - -package de.staropensource.engine.windowing; - -import de.staropensource.engine.base.implementable.Configuration; -import de.staropensource.engine.base.logging.Logger; -import de.staropensource.engine.base.utility.PropertiesReader; -import de.staropensource.engine.windowing.event.RenderingErrorEvent; -import de.staropensource.engine.windowing.event.WindowingErrorEvent; -import de.staropensource.engine.windowing.implementable.api.ApiManagementClass; -import de.staropensource.engine.windowing.type.window.VsyncMode; -import lombok.Getter; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; - -/** - * Provides the configuration of the windowing subsystem. - * - * @since v1-alpha0 - */ -@Getter -@SuppressWarnings({ "JavadocDeclaration" }) -public final class WindowingSubsystemConfiguration extends Configuration { - /** - * Contains the class instance. - * - * @since v1-alpha0 - * -- GETTER -- - * Returns the class instance. - * - * @return class instance unless {@link WindowingSubsystem} is uninitialized - * @since v1-alpha0 - */ - @Getter - private static WindowingSubsystemConfiguration instance; - - /** - * Defines the group every property must start with to be recognized as a subsystem configuration setting. - * - * @since v1-alpha0 - * -- GETTER -- - * Returns the group that every property must start with to be recognized as a subsystem configuration setting. - * - * @return property group - * @since v1-alpha0 - */ - @Getter - public final @NotNull String group = "sosengine.windowing."; - - /** - * If enabled, allows for unintentional behaviour and excess logging. - * Unless you want to debug or work on a sensitive part of the subsystem, don't enable this! - * - * @since v1-alpha0 - * -- GETTER -- - * Gets the value for {@link #debug}. - * - * @return variable value - * @see WindowingSubsystemConfiguration#debug - * @since v1-alpha0 - */ - private boolean debug; - - /** - * If enabled, will log all keys being pressed or released. - * - * @since v1-alpha2 - * -- GETTER -- - * Gets the value for {@link #debugInput}. - * - * @return variable value - * @see WindowingSubsystemConfiguration#debugInput - * @since v1-alpha2 - */ - private boolean debugInput; - - /** - * If enabled, will log the delta time average - * and FPS count to the console every second. - *

- * Is applied during rendering thread startup - * and will not be applied after. - * - * @since v1-alpha2 - * -- GETTER -- - * Gets the value for {@link #debugFrames}. - * - * @return variable value - * @see #debugFrames - * @since v1-alpha2 - */ - private boolean debugFrames; - - /** - * Causes windowing errors will be logged, if enabled. - * - * @see WindowingErrorEvent - * @since v1-alpha4 - * -- GETTER -- - * Gets the value for {@link #errorWindowingFailure}. - * - * @return variable value - * @see WindowingSubsystemConfiguration#errorWindowingFailure - * @since v1-alpha4 - */ - private boolean errorWindowingFailure; - - /** - * Causes rendering errors will be logged, if enabled. - * - * @see RenderingErrorEvent - * @since v1-alpha4 - * -- GETTER -- - * Gets the value for {@link #errorRenderingFailure}. - * - * @return variable value - * @see WindowingSubsystemConfiguration#errorRenderingFailure - * @since v1-alpha4 - */ - private boolean errorRenderingFailure; - - /** - * Contains how many frames can be rendered per second. - *

- * This setting determines if and how V-Sync will operate, which - * (if enabled) tries to synchronize the frame rate to the monitor's - * refresh rate. See {@link VsyncMode} for more information. - * - * @since v1-alpha2 - * -- GETTER -- - * Gets the value for {@link #vsyncMode}. - * - * @return variable value - * @see #vsyncMode - * @since v1-alpha2 - */ - private VsyncMode vsyncMode; - - /** - * Contains how many frames can be rendered per second. - *

- * This value will have no effect on windows with V-Sync enabled. - * Set to {@code 0} for no limit. - * - * @since v1-alpha2 - * -- GETTER -- - * Gets the value for {@link #maximumFramesPerSecond}. - * - * @return variable value - * @see #maximumFramesPerSecond - * @since v1-alpha2 - */ - private int maximumFramesPerSecond; - - /** - * Creates and initializes an instance of this class. - * - * @see WindowingSubsystem - * @since v1-alpha6 - */ - WindowingSubsystemConfiguration() { - instance = this; - - loadDefaultConfiguration(); - } - - /** {@inheritDoc} */ - @Override - protected void matchProperty(@NotNull PropertiesReader parser, @NotNull String property) { - switch (property) { - case "debug" -> debug = parser.getBoolean(group + property); - case "debugInput" -> debugInput = parser.getBoolean(group + property); - case "debugFrames" -> debugFrames = parser.getBoolean(group + property); - - case "errorWindowingFailure" -> errorWindowingFailure = parser.getBoolean(group + property); - case "errorRenderingFailure" -> errorRenderingFailure = parser.getBoolean(group + property); - - case "vsyncMode" -> { - try { - vsyncMode = VsyncMode.valueOf(parser.getString(group + property).toUpperCase()); - } catch (IllegalArgumentException exception) { - Logger.error("V-Sync mode " + parser.getString(group + property) + " is not valid"); - } - } - case "maximumFramesPerSecond" -> maximumFramesPerSecond = parser.getInteger(group + property, true); - } - } - - /** {@inheritDoc} */ - @Override - protected void processSettings(@NotNull PropertiesReader parser) { - // Disable all debug options if 'debug' is disabled - if (!debug) { - debugInput = false; - debugFrames = false; - } - } - - /** {@inheritDoc} */ - @Override - public void loadDefaultConfiguration() { - debug = false; - debugInput = false; - debugFrames = false; - - errorWindowingFailure = true; - errorRenderingFailure = true; - - vsyncMode = VsyncMode.ON; - maximumFramesPerSecond = 60; - } - - /** {@inheritDoc} */ - @Override - public @Nullable Object getSetting(@NotNull String setting) { - switch (setting) { - case "debug" -> { return debug; } - case "debugInput" -> { return debugInput; } - case "debugFrames" -> { return debugFrames; } - - case "errorWindowingFailure" -> { return errorWindowingFailure; } - case "errorRenderingFailure" -> { return errorRenderingFailure; } - - case "vsyncMode" -> { return vsyncMode; } - case "maximumFramesPerSecond" -> { return maximumFramesPerSecond; } - default -> { return null; } - } - } -} diff --git a/windowing/src/main/java/de/staropensource/engine/windowing/event/WindowingErrorEvent.java b/windowing/src/main/java/de/staropensource/engine/windowing/event/WindowingErrorEvent.java deleted file mode 100644 index 9c593162..00000000 --- a/windowing/src/main/java/de/staropensource/engine/windowing/event/WindowingErrorEvent.java +++ /dev/null @@ -1,58 +0,0 @@ -/* - * STAROPENSOURCE ENGINE SOURCE FILE - * Copyright (c) 2024 The StarOpenSource Engine Authors - * Licensed under the GNU Affero General Public License v3 - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as - * published by the Free Software Foundation, either version 3 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see . - */ - -package de.staropensource.engine.windowing.event; - -import de.staropensource.engine.base.implementable.Event; -import de.staropensource.engine.base.implementable.helper.EventHelper; -import org.jetbrains.annotations.NotNull; - -/** - * Called when an error occurs in the windowing API. - * - * @since v1-alpha0 - */ -public final class WindowingErrorEvent implements Event { - /** - * Creates and initializes an instance of this event. - * - * @since v1-alpha0 - */ - public WindowingErrorEvent() {} - - /** - * {@inheritDoc} - * - * @deprecated use the {@code callEvent} method with arguments - * @see #callEvent(String) - */ - @Deprecated - @Override - public void callEvent() {} - - /** - * Emits the event and calls all event listeners. - * - * @param error error description - * @since v1-alpha0 - */ - public void callEvent(@NotNull String error) { - EventHelper.invokeAnnotatedMethods(getClass(), error); - } -} diff --git a/windowing/src/main/java/de/staropensource/engine/windowing/event/WindowingShutdownEvent.java b/windowing/src/main/java/de/staropensource/engine/windowing/event/WindowingShutdownEvent.java deleted file mode 100644 index eecf3b04..00000000 --- a/windowing/src/main/java/de/staropensource/engine/windowing/event/WindowingShutdownEvent.java +++ /dev/null @@ -1,44 +0,0 @@ -/* - * STAROPENSOURCE ENGINE SOURCE FILE - * Copyright (c) 2024 The StarOpenSource Engine Authors - * Licensed under the GNU Affero General Public License v3 - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as - * published by the Free Software Foundation, either version 3 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see . - */ - -package de.staropensource.engine.windowing.event; - -import de.staropensource.engine.base.implementable.Event; -import de.staropensource.engine.base.implementable.helper.EventHelper; - -/** - * Called when the windowing API shuts down. - * - * @since v1-alpha0 - */ -public final class WindowingShutdownEvent implements Event { - /** - * Creates and initializes an instance of this event. - * - * @since v1-alpha0 - */ - public WindowingShutdownEvent() {} - - - /** {@inheritDoc} */ - @Override - public void callEvent() { - EventHelper.invokeAnnotatedMethods(getClass()); - } -} diff --git a/windowing/src/main/java/de/staropensource/engine/windowing/implementable/api/ApiClass.java b/windowing/src/main/java/de/staropensource/engine/windowing/implementable/api/ApiClass.java deleted file mode 100644 index 5d41fc9f..00000000 --- a/windowing/src/main/java/de/staropensource/engine/windowing/implementable/api/ApiClass.java +++ /dev/null @@ -1,84 +0,0 @@ -/* - * STAROPENSOURCE ENGINE SOURCE FILE - * Copyright (c) 2024 The StarOpenSource Engine Authors - * Licensed under the GNU Affero General Public License v3 - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as - * published by the Free Software Foundation, either version 3 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see . - */ - -package de.staropensource.engine.windowing.implementable.api; - -import de.staropensource.engine.base.Engine; -import de.staropensource.engine.base.implementable.SubsystemClass; -import org.jetbrains.annotations.NotNull; - -/** - * Abstract class for building windowing API main classes. - * - * @since v1-alpha0 - */ -public abstract class ApiClass extends SubsystemClass { - /** - * Creates and initializes an instance of this abstract class. - * - * @since v1-alpha2 - */ - public ApiClass() {} - - /** - * Initializes the windowing API. - * - * @since v1-alpha0 - */ - public abstract void initializeApi(); - - /** - * Shuts the windowing API down. - *

- * Called when the engine shuts down. - * - * @see Engine#shutdown() - * @see Engine#shutdown(int) - * @since v1-alpha0 - */ - public abstract void shutdownApi(); - - /** - * Returns the name of the windowing API. - * - * @return windowing API name - * @since v1-alpha0 - */ - public abstract String getApiName(); - - /** - * Returns the windowing API's internal API access class. - * - * @return a {@link ApiInternalClass} - * @see ApiInternalClass - * @since v1-alpha2 - */ - @NotNull - public abstract ApiInternalClass getInternalApi(); - - /** - * Returns the windowing API's management class. - * - * @return a {@link ApiManagementClass} - * @see ApiManagementClass - * @since v1-alpha0 - */ - @NotNull - public abstract ApiManagementClass getManagement(); -} diff --git a/windowing/src/main/java/de/staropensource/engine/windowing/implementable/api/ApiInternalClass.java b/windowing/src/main/java/de/staropensource/engine/windowing/implementable/api/ApiInternalClass.java deleted file mode 100644 index 622cfd5d..00000000 --- a/windowing/src/main/java/de/staropensource/engine/windowing/implementable/api/ApiInternalClass.java +++ /dev/null @@ -1,54 +0,0 @@ -/* - * STAROPENSOURCE ENGINE SOURCE FILE - * Copyright (c) 2024 The StarOpenSource Engine Authors - * Licensed under the GNU Affero General Public License v3 - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as - * published by the Free Software Foundation, either version 3 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see . - */ - -package de.staropensource.engine.windowing.implementable.api; - -import de.staropensource.engine.windowing.implementable.Monitor; -import de.staropensource.engine.windowing.implementable.Window; -import de.staropensource.engine.windowing.exception.NoMonitorsFoundException; -import org.jetbrains.annotations.NotNull; - -import java.util.LinkedHashSet; - -/** - * Interface for internal API access classes. - * These are used exclusively by the windowing - * subsystem's code. - * - * @since v1-alpha2 - */ -public interface ApiInternalClass { - /** - * Returns the {@link Window} class of the windowing API. - * - * @return {@link Window} class - * @since v1-alpha2 - */ - @NotNull - Class getWindowClass(); - - /** - * Returns all connected monitors. - * - * @return connected monitors - * @since v1-alpha2 - */ - @NotNull - LinkedHashSet<@NotNull Monitor> getMonitors() throws NoMonitorsFoundException; -} diff --git a/windowing/src/main/java/de/staropensource/engine/windowing/implementable/api/ApiManagementClass.java b/windowing/src/main/java/de/staropensource/engine/windowing/implementable/api/ApiManagementClass.java deleted file mode 100644 index 451a765f..00000000 --- a/windowing/src/main/java/de/staropensource/engine/windowing/implementable/api/ApiManagementClass.java +++ /dev/null @@ -1,125 +0,0 @@ -/* - * STAROPENSOURCE ENGINE SOURCE FILE - * Copyright (c) 2024 The StarOpenSource Engine Authors - * Licensed under the GNU Affero General Public License v3 - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as - * published by the Free Software Foundation, either version 3 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see . - */ - -package de.staropensource.engine.windowing.implementable.api; - -import de.staropensource.engine.base.logging.Logger; -import de.staropensource.engine.base.utility.Math; -import de.staropensource.engine.base.utility.Miscellaneous; -import de.staropensource.engine.windowing.WindowingSubsystemConfiguration; -import de.staropensource.engine.windowing.implementable.Window; -import de.staropensource.engine.windowing.type.window.VsyncMode; -import org.jetbrains.annotations.NotNull; - -import java.util.LinkedHashMap; -import java.util.LinkedList; -import java.util.concurrent.atomic.AtomicReference; - -/** - * Interface for building windowing API management classes. - * These are used for interfacing with the windowing API directly. - * - * @since v1-alpha0 - */ -public abstract class ApiManagementClass { - /** - * Creates and initializes an instance of this abstract class. - * - * @since v1-alpha2 - */ - public ApiManagementClass() {} - - /** - * Returns if this windowing API must be interacted with on the main thread. - * - * @return {@code true} if windowing API must be interacted with on the main thread, {@code false} otherwise - * @since v1-alpha2 - */ - public abstract boolean mustRunOnMainThread(); - - /** - * Runs the render loop once. - * To run the render loop continuously, see {@link #runRenderLoopContinuously(Runnable)}. - * - * @return map of windows and their thrown throwables - * @since v1-alpha2 - */ - public abstract LinkedHashMap<@NotNull Window, @NotNull Throwable> runRenderLoop(); - - /** - * Runs the render loop for ever. - * To run the render loop only once, see {@link #runRenderLoop()}. - *

- * Immediately returns with when a {@link #runRenderLoop()} call fails. - * - * @param frameCode code that should be invoked on during a frame. will be counted to frame time - * @return see {@link #runRenderLoop()} - * @since v1-alpha2 - */ - public LinkedHashMap<@NotNull Window, @NotNull Throwable> runRenderLoopContinuously(@NotNull Runnable frameCode) { - // Define variables - AtomicReference> output = new AtomicReference<>(new LinkedHashMap<>()); // runRenderLoop output - long renderTime; // Amount of time spent rendering - long sleepDuration; // Time spent sleeping the thread - LinkedList splitDeltaTime = new LinkedList<>(); // Used for calculating the delta time (render time average over one second) - long reportDuration = System.currentTimeMillis() + 1000; // Used for determining when to report frame count and delta time - double deltaTime; // Contains the average render time over one second (delta time) - - // Check if delta time and frame count shall be printed to console. - // Unless this code is ran 292 billion years into the future, - // this should sufficiently disable the reporting feature. - if (!WindowingSubsystemConfiguration.getInstance().isDebugFrames()) - reportDuration = Long.MAX_VALUE; - - // Run while the 'output' is empty - while (output.get().isEmpty()) { - renderTime = Miscellaneous.measureExecutionTime(() -> { - output.set(runRenderLoop()); - frameCode.run(); - }); - - if (WindowingSubsystemConfiguration.getInstance().getVsyncMode() != VsyncMode.OFF) - // V-Sync is enabled, no need for manual busy waiting - sleepDuration = 0L; - else - // Calculate amount of time the thread should spend sleeping - sleepDuration = (long) (1d / WindowingSubsystemConfiguration.getInstance().getMaximumFramesPerSecond() * 1000d) - renderTime; - // Add render and sleep time to list used for calculating the delta time value - splitDeltaTime.add(renderTime + sleepDuration); - - // Busy wait unless V-Sync is enabled - if (WindowingSubsystemConfiguration.getInstance().getVsyncMode() == VsyncMode.OFF && WindowingSubsystemConfiguration.getInstance().getMaximumFramesPerSecond() >= 1) { - sleepDuration += System.currentTimeMillis(); - while (System.currentTimeMillis() < sleepDuration) - Thread.onSpinWait(); - } - - // Calculate delta time and frame count every second - if (System.currentTimeMillis() >= reportDuration) { - deltaTime = Math.getMeanLong(splitDeltaTime); // Calculate delta time - Logger.diag("Delta time average: " + deltaTime + " | Frames/s: " + 1000 / deltaTime); // Print delta time and frame count to console - - reportDuration = System.currentTimeMillis() + 1000; // Update 'reportDuration' - splitDeltaTime.clear(); // Clear 'splitDeltaTime' list - } - } - - return output.get(); - } -} diff --git a/windowing/src/main/java/de/staropensource/engine/windowing/implementable/api/package-info.java b/windowing/src/main/java/de/staropensource/engine/windowing/implementable/api/package-info.java deleted file mode 100644 index 18c7a940..00000000 --- a/windowing/src/main/java/de/staropensource/engine/windowing/implementable/api/package-info.java +++ /dev/null @@ -1,25 +0,0 @@ -/* - * STAROPENSOURCE ENGINE SOURCE FILE - * Copyright (c) 2024 The StarOpenSource Engine Authors - * Licensed under the GNU Affero General Public License v3 - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as - * published by the Free Software Foundation, either version 3 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see . - */ - -/** - * Contains classes starting with {@code Api*}. - * - * @since v1-alpha2 - */ -package de.staropensource.engine.windowing.implementable.api; diff --git a/windowing/src/main/java/de/staropensource/engine/windowing/implementable/package-info.java b/windowing/src/main/java/de/staropensource/engine/windowing/implementable/package-info.java deleted file mode 100644 index 8bea7f8b..00000000 --- a/windowing/src/main/java/de/staropensource/engine/windowing/implementable/package-info.java +++ /dev/null @@ -1,27 +0,0 @@ -/* - * STAROPENSOURCE ENGINE SOURCE FILE - * Copyright (c) 2024 The StarOpenSource Engine Authors - * Licensed under the GNU Affero General Public License v3 - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as - * published by the Free Software Foundation, either version 3 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see . - */ - -/** - * Interfaces and abstract classes which can be used for implementing classes. - *

- * These are not to be confused with data types. See {@link de.staropensource.engine.windowing.type}. - * - * @since v1-alpha0 - */ -package de.staropensource.engine.windowing.implementable; diff --git a/windowing/src/main/java/module-info.java b/windowing/src/main/java/module-info.java deleted file mode 100644 index fe95734d..00000000 --- a/windowing/src/main/java/module-info.java +++ /dev/null @@ -1,32 +0,0 @@ -/** - * The {@code windowing} subsystem, which provides abstractions and - * APIs, which allow the creation and management of windows. - * - * @since v1-alpha4 - */ -module sosengine.windowing { - // Dependencies - // -> Engine - requires transitive sosengine.base; - // -> Libraries - requires transitive static lombok; - requires transitive org.jetbrains.annotations; - - // API access - exports de.staropensource.engine.windowing; - exports de.staropensource.engine.windowing.implementable; - exports de.staropensource.engine.windowing.implementable.api; - exports de.staropensource.engine.windowing.event; - exports de.staropensource.engine.windowing.exception; - exports de.staropensource.engine.windowing.type.input; - exports de.staropensource.engine.windowing.type.window; - - // Reflection access - opens de.staropensource.engine.windowing; - opens de.staropensource.engine.windowing.implementable; - opens de.staropensource.engine.windowing.implementable.api; - opens de.staropensource.engine.windowing.event; - opens de.staropensource.engine.windowing.exception; - opens de.staropensource.engine.windowing.type.input; - opens de.staropensource.engine.windowing.type.window; -}