Compare commits
No commits in common. "develop" and "v1-alpha8" have entirely different histories.
71 changed files with 3067 additions and 1901 deletions
3
.gitignore
vendored
3
.gitignore
vendored
|
@ -42,6 +42,3 @@ bin/
|
|||
|
||||
### Mac OS ###
|
||||
.DS_Store
|
||||
|
||||
### Java ###
|
||||
hs_err_pid*.log
|
||||
|
|
|
@ -19,11 +19,8 @@
|
|||
|
||||
package de.staropensource.engine.base;
|
||||
|
||||
import de.staropensource.engine.base.annotation.EngineSubsystem;
|
||||
import de.staropensource.engine.base.event.LogEvent;
|
||||
import de.staropensource.engine.base.implementable.Configuration;
|
||||
import de.staropensource.engine.base.implementable.ShortcodeParser;
|
||||
import de.staropensource.engine.base.implementable.SubsystemClass;
|
||||
import de.staropensource.engine.base.logging.Logger;
|
||||
import de.staropensource.engine.base.logging.backend.async.LoggingThread;
|
||||
import de.staropensource.engine.base.type.EngineState;
|
||||
|
@ -69,11 +66,11 @@ public final class EngineConfiguration extends Configuration {
|
|||
private static EngineConfiguration instance;
|
||||
|
||||
/**
|
||||
* Contains the configuration prefix.
|
||||
* Contains prefix properties must begin with.
|
||||
*
|
||||
* @since v1-alpha0
|
||||
* -- GETTER --
|
||||
* Returns the configuration prefix.
|
||||
* Returns prefix properties must begin with.
|
||||
*
|
||||
* @return property group
|
||||
* @since v1-alpha0
|
||||
|
@ -82,196 +79,132 @@ public final class EngineConfiguration extends Configuration {
|
|||
|
||||
|
||||
/**
|
||||
* 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}.
|
||||
* If enabled, allows for unintentional behaviour
|
||||
* and excess logging. Unless you want to debug or work
|
||||
* on a sensitive part of the engine, don't enable this!
|
||||
*
|
||||
* @since v1-alpha0
|
||||
* -- 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}.
|
||||
* Gets the value for {@link #debug}.
|
||||
*
|
||||
* @return debugging enabled?
|
||||
* @return variable value
|
||||
* @see #debug
|
||||
* @since v1-alpha0
|
||||
*/
|
||||
private boolean debug;
|
||||
|
||||
/**
|
||||
* Contains whether or not to log
|
||||
* events being emitted.
|
||||
* <p>
|
||||
* This will cause all events to
|
||||
* be logged, with the exception
|
||||
* of the {@link LogEvent}.
|
||||
* If enabled, all called events will be logged.
|
||||
*
|
||||
* @since v1-alpha0
|
||||
* -- GETTER --
|
||||
* Returns whether or not to log
|
||||
* events being emitted.
|
||||
* <p>
|
||||
* This will cause all events to
|
||||
* be logged, with the exception
|
||||
* of the {@link LogEvent}.
|
||||
* Gets the value for {@link #debugEvents}.
|
||||
*
|
||||
* @return detailed event logging enabled?
|
||||
* @return variable value
|
||||
* @see #debugEvents
|
||||
* @since v1-alpha0
|
||||
*/
|
||||
private boolean debugEvents;
|
||||
|
||||
|
||||
/**
|
||||
* Contains whether or not to automatically discover
|
||||
* and initialize any class extending {@link SubsystemClass}
|
||||
* whilst being annotated with {@link EngineSubsystem}.
|
||||
* If enabled, will try to automatically initialize every
|
||||
* subsystem found though reflection.
|
||||
* <p>
|
||||
* This mechanism may fail in certain situations, where
|
||||
* manual subsystem initialization may be desired. Make
|
||||
* sure to disable this setting before engine startup
|
||||
* and then initialize all subsystems manually.
|
||||
* This however may fail in certain situation, where manual
|
||||
* subsystem initialization may be required. For this reason,
|
||||
* this can be turned off before the engine initializes. Please
|
||||
* note though that dependency resolution between subsystems
|
||||
* won't be performed, be careful when initializing subsystems manually.
|
||||
*
|
||||
* @see Engine
|
||||
* @since v1-alpha5
|
||||
* @since v1-alpha2
|
||||
* -- GETTER --
|
||||
* Returns whether or not to automatically discover
|
||||
* and initialize any class extending {@link SubsystemClass}
|
||||
* whilst being annotated with {@link EngineSubsystem}.
|
||||
* <p>
|
||||
* This mechanism may fail in certain situations, where
|
||||
* manual subsystem initialization may be desired. Make
|
||||
* sure to disable this setting before engine startup
|
||||
* and then initialize all subsystems manually.
|
||||
* Gets the value for {@link #initialPerformSubsystemInitialization}.
|
||||
*
|
||||
* @return automatically discover and initialize subsystems?
|
||||
* @return variable value
|
||||
* @see #initialPerformSubsystemInitialization
|
||||
* @since v1-alpha5
|
||||
*/
|
||||
private boolean initialPerformSubsystemInitialization;
|
||||
|
||||
/**
|
||||
* Contains a set of class names to try to load
|
||||
* and initialize as subsystems. Will only take effect
|
||||
* if {@link #initialPerformSubsystemInitialization} is
|
||||
* turned off.
|
||||
* Will try to load the specified classes as subsystems,
|
||||
* if reflective classpath scanning is disabled.
|
||||
*
|
||||
* @since v1-alpha5
|
||||
* -- GETTER --
|
||||
* Returns a set of class names to try to load
|
||||
* and initialize as subsystems. Will only take effect
|
||||
* if {@link #getInitialIncludeSubsystemClasses()} is
|
||||
* turned off.
|
||||
* Gets the value for {@link #initialIncludeSubsystemClasses}.
|
||||
*
|
||||
* @return set of class names to try and initialize as subsystems
|
||||
* @return variable value
|
||||
* @see #initialIncludeSubsystemClasses
|
||||
* @since v1-alpha5
|
||||
*/
|
||||
private Set<@NotNull String> initialIncludeSubsystemClasses;
|
||||
|
||||
|
||||
/**
|
||||
* Contains whether or not to complain about invalid
|
||||
* shortcodes.
|
||||
* <p>
|
||||
* Requires the active log level to be set at least
|
||||
* to {@link LogLevel#SILENT_WARNING} to have effect.
|
||||
* If enabled, will cause {@link ShortcodeParser} to print
|
||||
* invalid shortcodes as {@link LogLevel#SILENT_WARNING}s.
|
||||
*
|
||||
* @see ShortcodeParser
|
||||
* @see #logLevel
|
||||
* @since v1-alpha0
|
||||
* -- GETTER --
|
||||
* Returns whether or not to complain about invalid
|
||||
* shortcodes.
|
||||
* <p>
|
||||
* Requires the active log level to be set at least
|
||||
* to {@link LogLevel#SILENT_WARNING} to have effect.
|
||||
* Gets the value for {@link #errorShortcodeParser}.
|
||||
*
|
||||
* @return complain about invalid shortcodes?
|
||||
* @see #getLogLevel()
|
||||
* @return variable value
|
||||
* @see #errorShortcodeParser
|
||||
* @since v1-alpha0
|
||||
*/
|
||||
private boolean errorShortcodeParser;
|
||||
|
||||
|
||||
/**
|
||||
* Contains if to log asynchronously.
|
||||
* <p>
|
||||
* If enabled, will cause a logging thread
|
||||
* to spawn. All log messages will be queued
|
||||
* and printed after a set delay
|
||||
* ({@link #logPollingSpeed}).
|
||||
* Highly recommended to keep enabled, or
|
||||
* the performance of your application will
|
||||
* very likely suffer.
|
||||
* If enabled, will makes the {@link Logger} work asynchronous,
|
||||
* in a separate platform thread. Don't disable unless you want
|
||||
* your application to run <b>extremely</b> slowly.
|
||||
*
|
||||
* @see #logPollingSpeed
|
||||
* @see Thread
|
||||
* @since v1-alpha0
|
||||
* -- GETTER --
|
||||
* Returns if to log asynchronously.
|
||||
* <p>
|
||||
* If enabled, will cause a logging thread
|
||||
* to spawn. All log messages will be queued
|
||||
* and printed after a set delay
|
||||
* ({@link #getLogPollingSpeed()}).
|
||||
* Highly recommended to keep enabled, or
|
||||
* the performance of your application will
|
||||
* very likely suffer.
|
||||
* Gets the value for {@link #optimizeLogging}.
|
||||
*
|
||||
* @return log asynchronously?
|
||||
* @see #getLogPollingSpeed()
|
||||
* @return variable value
|
||||
* @see #optimizeLogging
|
||||
* @since v1-alpha0
|
||||
*/
|
||||
private boolean optimizeLogging;
|
||||
|
||||
/**
|
||||
* Contains whether or not to emit events
|
||||
* asynchronously.
|
||||
* <p>
|
||||
* This will cause a
|
||||
* <a href="https://openjdk.org/jeps/444">VirtualThread</a>
|
||||
* to spawn every time an event is emitted.
|
||||
* If enabled, will make all events asynchronous,
|
||||
* in separate virtual threads. Don't disable unless you
|
||||
* want your application to run slower.
|
||||
*
|
||||
* @see VirtualThread
|
||||
* @since v1-alpha0
|
||||
* -- GETTER --
|
||||
* Contains whether or not to emit events
|
||||
* asynchronously.
|
||||
* <p>
|
||||
* This will cause a
|
||||
* <a href="https://openjdk.org/jeps/444">VirtualThread</a>
|
||||
* to spawn every time an event is emitted.
|
||||
* Gets the value for {@link #optimizeEvents}.
|
||||
*
|
||||
* @return emit events asynchronously?
|
||||
* @return variable value
|
||||
* @see #optimizeEvents
|
||||
* @since v1-alpha0
|
||||
*/
|
||||
private boolean optimizeEvents;
|
||||
|
||||
|
||||
/**
|
||||
* Contains the minimum allowed log level.
|
||||
* <p>
|
||||
* The priority list is as follows (from high to low priority):
|
||||
* <ul>
|
||||
* <li>{@link LogLevel#CRASH}</li>
|
||||
* <li>{@link LogLevel#ERROR}</li>
|
||||
* <li>{@link LogLevel#WARNING}</li>
|
||||
* <li>{@link LogLevel#INFORMATIONAL}</li>
|
||||
* <li>{@link LogLevel#SILENT_WARNING}</li>
|
||||
* <li>{@link LogLevel#VERBOSE}</li>
|
||||
* <li>{@link LogLevel#DIAGNOSTIC}</li>
|
||||
* </ul>
|
||||
* Contains which logger levels are allowed
|
||||
* by setting the minimum logger level.
|
||||
*
|
||||
* @see Logger
|
||||
* @since v1-alpha0
|
||||
* -- GETTER --
|
||||
* Returns the minimum allowed log level.
|
||||
* <p>
|
||||
* The priority list is as follows (from high to low priority):
|
||||
* <ul>
|
||||
* <li>{@link LogLevel#CRASH}</li>
|
||||
* <li>{@link LogLevel#ERROR}</li>
|
||||
* <li>{@link LogLevel#WARNING}</li>
|
||||
* <li>{@link LogLevel#INFORMATIONAL}</li>
|
||||
* <li>{@link LogLevel#SILENT_WARNING}</li>
|
||||
* <li>{@link LogLevel#VERBOSE}</li>
|
||||
* <li>{@link LogLevel#DIAGNOSTIC}</li>
|
||||
* </ul>
|
||||
* Gets the value for {@link #logLevel}.
|
||||
*
|
||||
* @return minimum allowed log level
|
||||
* @return variable value
|
||||
* @see #logLevel
|
||||
* @since v1-alpha0
|
||||
*/
|
||||
private LogLevel logLevel;
|
||||
|
@ -293,118 +226,75 @@ public final class EngineConfiguration extends Configuration {
|
|||
* <li><code>lineNumber</code></li>
|
||||
* </ul>
|
||||
*
|
||||
* @see Logger
|
||||
* @since v1-alpha8
|
||||
* -- GETTER --
|
||||
* Returns a comma-separated list of optional
|
||||
* features to add to the final log output.
|
||||
* <p>
|
||||
* Available features (in order of appearance):
|
||||
* <ul>
|
||||
* <li><code>formatting</code></li>
|
||||
* <li><code>runtime</code></li>
|
||||
* <li><code>date</code></li>
|
||||
* <li><code>time</code></li>
|
||||
* <li><code>shortIssuerClass</code></li>
|
||||
* <li><code>moduleName</code></li>
|
||||
* <li><code>moduleVersion</code> (requires <code>moduleName</code>)</li>
|
||||
* <li><code>methodName</code></li>
|
||||
* <li><code>lineNumber</code></li>
|
||||
* </ul>
|
||||
* Gets the value for {@link #logFeatures}
|
||||
*
|
||||
* @return optional features to enable
|
||||
* @return variable value
|
||||
* @see #logFeatures
|
||||
* @since v1-alpha8
|
||||
*/
|
||||
private Set<@NotNull String> logFeatures;
|
||||
|
||||
/**
|
||||
* Contains how fast the logging thread will
|
||||
* poll for queued messages in milliseconds.
|
||||
* This also causes messages to be buffered.
|
||||
* poll for queued messages. This also causes
|
||||
* messages to be buffered.
|
||||
* <p>
|
||||
* Only applies if {@code optimizeLogging} is turned on.
|
||||
* Values below {@code 1} will poll for queued messages
|
||||
* as fast as it can. This however has pretty much no
|
||||
* benefit. Leave it at {@code 5}, it works quite well.
|
||||
* Values below {@code 1} will poll for queued
|
||||
* messages as fast as it can. This however has pretty much
|
||||
* no benefit. Leave it at {@code 5}, it works quite well.
|
||||
*
|
||||
* @see #optimizeLogging
|
||||
* @since v1-alpha4
|
||||
* -- GETTER --
|
||||
* Contains how fast the logging thread will
|
||||
* poll for queued messages, in milliseconds.
|
||||
* This also causes messages to be buffered.
|
||||
* <p>
|
||||
* Only applies if {@code optimizeLogging} is turned on.
|
||||
* Values below {@code 1} will poll for queued messages
|
||||
* as fast as it can. This however has pretty much no
|
||||
* benefit. Leave it at {@code 5}, it works quite well.
|
||||
* Gets the value for {@link #logPollingSpeed}.
|
||||
*
|
||||
* @return logging thread polling speed in milliseconds
|
||||
* @see #isOptimizeLogging()
|
||||
* @return variable value
|
||||
* @see #logPollingSpeed
|
||||
* @since v1-alpha4
|
||||
*/
|
||||
private int logPollingSpeed;
|
||||
|
||||
/**
|
||||
* Contains whether or not to forcefully write
|
||||
* to the standard output instead of the
|
||||
* standard error stream.
|
||||
* <p>
|
||||
* This only applies to the {@link LogLevel#ERROR} and
|
||||
* {@link LogLevel#CRASH} log levels, as these use
|
||||
* the standard error stream by default.
|
||||
* If enabled, will force sos!engine's logging infrastructure to use
|
||||
* <a href="https://www.man7.org/linux/man-pages/man3/stderr.3.html">the standard output</a>
|
||||
* instead of <a href="https://www.man7.org/linux/man-pages/man3/stderr.3.html">the standard error</a>
|
||||
* for logging the {@code ERROR} and {@code CRASH} log levels.
|
||||
*
|
||||
* @see <a href="https://man7.org/linux/man-pages/man3/stderr.3.html">man page about standard streams</a>
|
||||
* @since v1-alpha0
|
||||
* -- GETTER --
|
||||
* Contains whether or not to forcefully write
|
||||
* to the standard output instead of the
|
||||
* standard error stream.
|
||||
* <p>
|
||||
* This only applies to the {@link LogLevel#ERROR} and
|
||||
* {@link LogLevel#CRASH} log levels, as these use
|
||||
* the standard error stream by default.
|
||||
* Gets the value for {@link #logForceStandardOutput}.
|
||||
*
|
||||
* @return force use stdout?
|
||||
* @see <a href="https://man7.org/linux/man-pages/man3/stderr.3.html">man page about standard streams</a>
|
||||
* @return variable value
|
||||
* @see #logForceStandardOutput
|
||||
* @since v1-alpha0
|
||||
*/
|
||||
private boolean logForceStandardOutput;
|
||||
|
||||
|
||||
/**
|
||||
* Contains if to truncate the full path
|
||||
* of a class when invoking using their
|
||||
* {@link #toString()} method.
|
||||
* Will truncate the path of types when using
|
||||
* their {@code toString} method.
|
||||
* <p>
|
||||
* Here's an example: Lets say that you have a
|
||||
* {@link Vec2f} instance and want to convert
|
||||
* it to a String. You can do that by using
|
||||
* {@link Vec2f}'s {@link Vec2f#toString()}
|
||||
* method. With this flag disabled it will
|
||||
* return
|
||||
* {@code de.staropensource.engine.base.types.vectors.}{@link Vec2i}{@code (x=64 y=64)}.
|
||||
* With this flag enabled however the method will return
|
||||
* Here's an example: Lets say that you
|
||||
* have a {@link Vec2f} and to convert it
|
||||
* to a String, which you can do with
|
||||
* {@link Vec2f#toString()}. With this flag
|
||||
* disabled it would return
|
||||
* {@code de.staropensource.engine.base.types.vectors.}{@link Vec2i}{@code (x=64 y=64)},
|
||||
* with it however it would just return
|
||||
* {@link Vec2i}{@code (x=64 y=64)},
|
||||
* which is much smaller.
|
||||
*
|
||||
* @since v1-alpha2
|
||||
* -- GETTER --
|
||||
* Returns if to truncate the full path
|
||||
* of a class when invoking using their
|
||||
* {@link #toString()} method.
|
||||
* <p>
|
||||
* Here's an example: Lets say that you have a
|
||||
* {@link Vec2f} instance and want to convert
|
||||
* it to a String. You can do that by using
|
||||
* {@link Vec2f}'s {@link Vec2f#toString()}
|
||||
* method. With this flag disabled it will
|
||||
* return
|
||||
* {@code de.staropensource.engine.base.types.vectors.}{@link Vec2i}{@code (x=64 y=64)}.
|
||||
* With this flag enabled however the method will return
|
||||
* {@link Vec2i}{@code (x=64 y=64)},
|
||||
* which is much smaller.
|
||||
* Gets the value for {@link #hideFullTypePath}.
|
||||
*
|
||||
* @return truncate class paths?
|
||||
* @return variable value
|
||||
* @see #hideFullTypePath
|
||||
* @since v1-alpha2
|
||||
*/
|
||||
private boolean hideFullTypePath;
|
||||
|
|
|
@ -30,7 +30,8 @@ tasks.register("javadocAll", Javadoc) {
|
|||
":base",
|
||||
":ansi",
|
||||
":slf4j-compat",
|
||||
":rendering",
|
||||
":windowing",
|
||||
":windowing:glfw",
|
||||
":notification",
|
||||
]
|
||||
|
||||
|
|
|
@ -78,7 +78,7 @@ This avoids unnecessary bloat, having too many dependencies in your project whil
|
|||
size and memory footprint of your project.
|
||||
|
||||
## Official subsystems
|
||||
Besides the `base` engine, there are two stable subsystem and two experimental subsystems.
|
||||
Besides the `base` engine, there are two stable subsystem and three experimental subsystems.
|
||||
|
||||
There may be other subsystems out there. Please note though that they are not maintained
|
||||
by the StarOpenSource Project directly and are not automatically updated with the engine.
|
||||
|
@ -86,7 +86,8 @@ by the StarOpenSource Project directly and are not automatically updated with th
|
|||
- [`ansi`](https://git.staropensource.de/StarOpenSource/Engine/src/branch/develop/ansi): Provides an ANSI logger and a ShortcodeParserSkeleton implementation for all your terminal formatting needs
|
||||
- [`slf4j-compat`](https://git.staropensource.de/StarOpenSource/Engine/src/branch/develop/slf4j-compat): Provides a [SLF4J](https://slf4j.org/) compatibility logger for redirecting all log calls to the engine's logging system
|
||||
### Experimental
|
||||
- [`rendering`](https://git.staropensource.de/StarOpenSource/Engine/src/branch/develop/rendering): Provides an API for creating, managing and rendering windows
|
||||
- [`windowing`](https://git.staropensource.de/StarOpenSource/Engine/src/branch/develop/windowing): Provides abstract APIs for creating and managing windows as well as monitors
|
||||
- [`windowing-glfw`](https://git.staropensource.de/StarOpenSource/Engine/src/branch/develop/windowing/glfw): Windowing API; allows using [GLFW](https://glfw.org) for creating windows
|
||||
- [`notification`](https://git.staropensource.de/StarOpenSource/Engine/src/branch/develop/notification): Provides an API for sending and receiving notifications inside a program
|
||||
|
||||
## API documentation
|
||||
|
|
|
@ -15,11 +15,11 @@
|
|||
"typecheck": "tsc"
|
||||
},
|
||||
"dependencies": {
|
||||
"@docusaurus/core": "3.6.1",
|
||||
"@docusaurus/plugin-client-redirects": "^3.6.1",
|
||||
"@docusaurus/plugin-content-docs": "^3.6.1",
|
||||
"@docusaurus/plugin-sitemap": "^3.6.1",
|
||||
"@docusaurus/preset-classic": "3.6.1",
|
||||
"@docusaurus/core": "3.6.0",
|
||||
"@docusaurus/plugin-client-redirects": "^3.6.0",
|
||||
"@docusaurus/plugin-content-docs": "^3.6.0",
|
||||
"@docusaurus/plugin-sitemap": "^3.6.0",
|
||||
"@docusaurus/preset-classic": "3.6.0",
|
||||
"@mdx-js/react": "^3.0.1",
|
||||
"clsx": "^2.1.0",
|
||||
"prism-react-renderer": "^2.3.1",
|
||||
|
@ -27,9 +27,9 @@
|
|||
"react-dom": "^18.2.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@docusaurus/module-type-aliases": "3.6.1",
|
||||
"@docusaurus/tsconfig": "3.6.1",
|
||||
"@docusaurus/types": "3.6.1",
|
||||
"@docusaurus/module-type-aliases": "3.6.0",
|
||||
"@docusaurus/tsconfig": "3.6.0",
|
||||
"@docusaurus/types": "3.6.0",
|
||||
"@types/node": "^20.12.5",
|
||||
"typescript": "~5.4.4"
|
||||
},
|
||||
|
|
|
@ -21,7 +21,7 @@
|
|||
versioningCodename=Sugarcookie
|
||||
versioningVersion=1
|
||||
versioningType=alpha
|
||||
versioningTyperelease=9
|
||||
versioningTyperelease=8
|
||||
versioningFork=
|
||||
|
||||
# Java
|
||||
|
|
|
@ -1,323 +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 <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
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.
|
||||
* <p>
|
||||
* 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.
|
||||
* <p>
|
||||
* 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<LinkedHashMap<@NotNull Window, @NotNull Throwable>> output = new AtomicReference<>(new LinkedHashMap<>()); // runRenderLoop output
|
||||
long renderTime; // Amount of time spent rendering
|
||||
long sleepDuration; // Time spent sleeping the thread
|
||||
LinkedList<Long> 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);
|
||||
}
|
||||
}
|
|
@ -1,311 +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 <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
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.
|
||||
* <p>
|
||||
* 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.
|
||||
* <p>
|
||||
* 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
|
||||
* <a href="https://gitlab.freedesktop.org/libdecor/libdecor">libdecor</a>.
|
||||
* <p>
|
||||
* Only affects the {@link RenderingPlatform#WAYLAND} platform.
|
||||
*
|
||||
* @since v1-alpha9
|
||||
* -- GETTER --
|
||||
* Returns whether or not to disable support for
|
||||
* <a href="https://gitlab.freedesktop.org/libdecor/libdecor">libdecor</a>.
|
||||
* <p>
|
||||
* 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.
|
||||
* <p>
|
||||
* 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.
|
||||
* <p>
|
||||
* 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.
|
||||
* <p>
|
||||
* 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.
|
||||
* <p>
|
||||
* 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.
|
||||
* <p>
|
||||
* 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.
|
||||
* <p>
|
||||
* 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; }
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,33 +0,0 @@
|
|||
/**
|
||||
* 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;
|
||||
}
|
|
@ -17,12 +17,13 @@
|
|||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
rootProject.setName("sos!engine")
|
||||
rootProject.setName("sosengine")
|
||||
|
||||
include("base")
|
||||
include("testing")
|
||||
include("ansi")
|
||||
include("slf4j-compat")
|
||||
include("notification")
|
||||
include("rendering")
|
||||
include("windowing")
|
||||
include("windowing:glfw")
|
||||
include("testapp")
|
||||
|
|
|
@ -39,9 +39,10 @@ dependencies {
|
|||
|
||||
// Project
|
||||
implementation(project(":base"))
|
||||
implementation(project(":rendering"))
|
||||
implementation(project(":windowing"))
|
||||
runtimeOnly(project(":ansi"))
|
||||
runtimeOnly(project(":slf4j-compat"))
|
||||
runtimeOnly(project(":windowing:glfw"))
|
||||
}
|
||||
|
||||
// Fix delombok task
|
||||
|
|
|
@ -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.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 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 lombok.Getter;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
@ -119,6 +119,10 @@ 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 {
|
||||
|
@ -135,13 +139,12 @@ public final class Main {
|
|||
return;
|
||||
}
|
||||
|
||||
if (window == null)
|
||||
Logger.crash("'window' is null");
|
||||
|
||||
// Render loop
|
||||
LinkedHashMap<@NotNull Window, @NotNull Throwable> renderLoopFailures = RenderingSubsystem
|
||||
LinkedHashMap<@NotNull Window, @NotNull Throwable> renderLoopFailures = WindowingSubsystem
|
||||
.getInstance()
|
||||
.runRenderLoop(() -> {
|
||||
.getApi()
|
||||
.getManagement()
|
||||
.runRenderLoopContinuously(() -> {
|
||||
if (shutdown || window.isClosureRequested())
|
||||
Engine.getInstance().shutdown();
|
||||
});
|
||||
|
|
|
@ -7,5 +7,5 @@
|
|||
open module sosengine.testapp {
|
||||
// Dependencies
|
||||
// -> Engine
|
||||
requires sosengine.rendering;
|
||||
requires sosengine.windowing;
|
||||
}
|
||||
|
|
109
windowing/build.gradle
Normal file
109
windowing/build.gradle
Normal file
|
@ -0,0 +1,109 @@
|
|||
/*
|
||||
* 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 <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
// 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)
|
||||
}
|
2
windowing/glfw/README.md
Normal file
2
windowing/glfw/README.md
Normal file
|
@ -0,0 +1,2 @@
|
|||
# The `glfw` subsystem
|
||||
This subsystem provides a Windowing API using [LWJGL](https://lwjgl.org)'s [GLFW](https://glfw.org) bindings.
|
|
@ -61,17 +61,16 @@ dependencies {
|
|||
// LWJGL
|
||||
implementation(platform("org.lwjgl:lwjgl-bom:${dependencyLwjgl}"))
|
||||
implementation("org.lwjgl:lwjgl")
|
||||
implementation("org.lwjgl:lwjgl-stb")
|
||||
implementation("org.lwjgl:lwjgl-glfw")
|
||||
implementation("org.lwjgl:lwjgl-bgfx")
|
||||
implementation("org.lwjgl:lwjgl-stb")
|
||||
runtimeOnly("org.lwjgl:lwjgl::${dependencyLwjglNatives}")
|
||||
runtimeOnly("org.lwjgl:lwjgl-stb::${dependencyLwjglNatives}")
|
||||
runtimeOnly("org.lwjgl:lwjgl-glfw::${dependencyLwjglNatives}")
|
||||
runtimeOnly("org.lwjgl:lwjgl-bgfx::${dependencyLwjglNatives}")
|
||||
runtimeOnly("org.lwjgl:lwjgl-stb::${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
|
||||
|
@ -97,6 +96,26 @@ javadoc {
|
|||
}
|
||||
}
|
||||
|
||||
// Unit testing configuration
|
||||
test {
|
||||
useJUnitPlatform()
|
||||
|
||||
// Pass test configuration to test VMs
|
||||
Map<String, String> 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()
|
1
windowing/glfw/gradle
Symbolic link
1
windowing/glfw/gradle
Symbolic link
|
@ -0,0 +1 @@
|
|||
../../gradle
|
1
windowing/glfw/gradlew
vendored
Symbolic link
1
windowing/glfw/gradlew
vendored
Symbolic link
|
@ -0,0 +1 @@
|
|||
../../gradlew
|
1
windowing/glfw/gradlew.bat
vendored
Symbolic link
1
windowing/glfw/gradlew.bat
vendored
Symbolic link
|
@ -0,0 +1 @@
|
|||
../../gradlew.bat
|
|
@ -0,0 +1,218 @@
|
|||
/*
|
||||
* 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 <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
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.
|
||||
* <p>
|
||||
* 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);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,139 @@
|
|||
/*
|
||||
* 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 <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
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
|
||||
* <a href="https://gitlab.freedesktop.org/libdecor/libdecor">libdecor</a>.
|
||||
* <p>
|
||||
* 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;
|
||||
};
|
||||
}
|
||||
}
|
|
@ -17,13 +17,13 @@
|
|||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package de.staropensource.engine.rendering.callback;
|
||||
package de.staropensource.engine.windowing.glfw.callback;
|
||||
|
||||
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 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 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-alpha9
|
||||
* @since v1-alpha2
|
||||
*/
|
||||
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-alpha9
|
||||
* @since v1-alpha2
|
||||
*/
|
||||
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-alpha9
|
||||
* @since v1-alpha2
|
||||
*/
|
||||
public KeyCallback(@NotNull Window window) {
|
||||
super(window);
|
|
@ -17,12 +17,13 @@
|
|||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package de.staropensource.engine.rendering.callback;
|
||||
package de.staropensource.engine.windowing.glfw.callback;
|
||||
|
||||
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 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 org.jetbrains.annotations.NotNull;
|
||||
import org.lwjgl.glfw.GLFWMouseButtonCallbackI;
|
||||
|
||||
|
@ -31,7 +32,7 @@ import static org.lwjgl.glfw.GLFW.*;
|
|||
/**
|
||||
* A {@link GLFWMouseButtonCallbackI} implementation, which forward them to {@link InputEvent}.
|
||||
*
|
||||
* @since v1-alpha9
|
||||
* @since v1-alpha2
|
||||
*/
|
||||
public final class MouseButtonCallback extends WindowCallback implements GLFWMouseButtonCallbackI {
|
||||
/**
|
||||
|
@ -39,7 +40,7 @@ public final class MouseButtonCallback extends WindowCallback implements GLFWMou
|
|||
* and making too many allocations, which would potentially decrease
|
||||
* performance.
|
||||
*
|
||||
* @since v1-alpha9
|
||||
* @since v1-alpha2
|
||||
*/
|
||||
private static final InputEvent event = new InputEvent();
|
||||
|
||||
|
@ -47,7 +48,7 @@ public final class MouseButtonCallback extends WindowCallback implements GLFWMou
|
|||
* Creates and initializes an instance of this class.
|
||||
*
|
||||
* @param window {@link Window} class
|
||||
* @since v1-alpha9
|
||||
* @since v1-alpha2
|
||||
*/
|
||||
public MouseButtonCallback(@NotNull Window window) {
|
||||
super(window);
|
||||
|
@ -71,7 +72,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_BUTTON;
|
||||
GLFW_MOUSE_BUTTON_8 -> Key.UNKNOWN_MOUSE;
|
||||
default -> throw new IllegalStateException("Mouse button " + key + " is invalid");
|
||||
},
|
||||
// Key state
|
|
@ -20,6 +20,6 @@
|
|||
/**
|
||||
* Callbacks, which emit {@link de.staropensource.engine.base.implementable.Event}s.
|
||||
*
|
||||
* @since v1-alpha9
|
||||
* @since v1-alpha2
|
||||
*/
|
||||
package de.staropensource.engine.rendering.callback;
|
||||
package de.staropensource.engine.windowing.glfw.callback;
|
|
@ -17,9 +17,9 @@
|
|||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package de.staropensource.engine.rendering.callback;
|
||||
package de.staropensource.engine.windowing.glfw.implementable;
|
||||
|
||||
import de.staropensource.engine.rendering.type.Window;
|
||||
import de.staropensource.engine.windowing.implementable.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-alpha9
|
||||
* @since v1-alpha2
|
||||
*/
|
||||
@Getter
|
||||
@SuppressWarnings({ "JavadocDeclaration" })
|
||||
|
@ -36,13 +36,13 @@ public class WindowCallback {
|
|||
* Refers to the {@link Window} instance
|
||||
* this callback is tied to.
|
||||
*
|
||||
* @since v1-alpha9
|
||||
* @since v1-alpha2
|
||||
* -- GETTER --
|
||||
* Returns the {@link Window} instance
|
||||
* this callback is tied to.
|
||||
*
|
||||
* @return attached {@link Window} instance
|
||||
* @since v1-alpha9
|
||||
* @since v1-alpha2
|
||||
*/
|
||||
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-alpha9
|
||||
* @since v1-alpha2
|
||||
*/
|
||||
public WindowCallback(@NotNull Window window) {
|
||||
this.attachedWindow = window;
|
|
@ -0,0 +1,25 @@
|
|||
/*
|
||||
* 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 <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Interfaces and abstract classes which can be used for implementing classes.
|
||||
*
|
||||
* @since v1-alpha6
|
||||
*/
|
||||
package de.staropensource.engine.windowing.glfw.implementable;
|
|
@ -0,0 +1,82 @@
|
|||
/*
|
||||
* 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 <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
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<? extends GlfwWindow> 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;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,92 @@
|
|||
/*
|
||||
* 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 <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,118 @@
|
|||
/*
|
||||
* 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 <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
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();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,566 @@
|
|||
/*
|
||||
* 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 <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
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<ByteBuffer> 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();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,25 @@
|
|||
/*
|
||||
* 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 <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Implementations for various interfaces and abstract classes.
|
||||
*
|
||||
* @since v1-alpha6
|
||||
*/
|
||||
package de.staropensource.engine.windowing.glfw.implementation;
|
|
@ -0,0 +1,25 @@
|
|||
/*
|
||||
* 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 <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Code of the GLFW subsystem.
|
||||
*
|
||||
* @since v1-alpha2
|
||||
*/
|
||||
package de.staropensource.engine.windowing.glfw;
|
|
@ -17,53 +17,53 @@
|
|||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package de.staropensource.engine.rendering.type.window;
|
||||
package de.staropensource.engine.windowing.glfw.type;
|
||||
|
||||
/**
|
||||
* Represents all available platforms.
|
||||
* Contains all available platforms which GLFW can be initialized with.
|
||||
*
|
||||
* @since v1-alpha9
|
||||
* @since v1-alpha2
|
||||
*/
|
||||
public enum RenderingPlatform {
|
||||
public enum GlfwPlatform {
|
||||
/**
|
||||
* Allows the subsystem to autodetect the platform to use.
|
||||
* Allows GLFW to autodetect the platform to use.
|
||||
*
|
||||
* @since v1-alpha9
|
||||
* @since v1-alpha2
|
||||
*/
|
||||
ANY,
|
||||
|
||||
/**
|
||||
* Prefer initializing with the Wayland platform.
|
||||
*
|
||||
* @since v1-alpha9
|
||||
* @since v1-alpha2
|
||||
*/
|
||||
WAYLAND,
|
||||
|
||||
/**
|
||||
* Prefer initializing with the X11 platform.
|
||||
*
|
||||
* @since v1-alpha9
|
||||
* @since v1-alpha2
|
||||
*/
|
||||
X11,
|
||||
|
||||
/**
|
||||
* Prefer initializing with the Win32 platform.
|
||||
*
|
||||
* @since v1-alpha9
|
||||
* @since v1-alpha2
|
||||
*/
|
||||
WIN32,
|
||||
|
||||
/**
|
||||
* Prefer initializing with the Cocoa platform.
|
||||
*
|
||||
* @since v1-alpha9
|
||||
* @since v1-alpha2
|
||||
*/
|
||||
COCOA,
|
||||
|
||||
/**
|
||||
* Prefer initializing without any platform.
|
||||
*
|
||||
* @since v1-alpha9
|
||||
* @since v1-alpha2
|
||||
*/
|
||||
NONE
|
||||
}
|
|
@ -0,0 +1,25 @@
|
|||
/*
|
||||
* 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 <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Data types in form of enums and classes.
|
||||
*
|
||||
* @since v1-alpha2
|
||||
*/
|
||||
package de.staropensource.engine.windowing.glfw.type;
|
25
windowing/glfw/src/main/java/module-info.java
Normal file
25
windowing/glfw/src/main/java/module-info.java
Normal file
|
@ -0,0 +1,25 @@
|
|||
/**
|
||||
* 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;
|
||||
}
|
24
windowing/glfw/src/main/javadoc/overview.html
Normal file
24
windowing/glfw/src/main/javadoc/overview.html
Normal file
|
@ -0,0 +1,24 @@
|
|||
<!--
|
||||
~ 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 <https://www.gnu.org/licenses/>.
|
||||
-->
|
||||
|
||||
<body>
|
||||
<p>Welcome to the sos!engine API documentation!<br/>
|
||||
You are currently in the documentation for the <b>glfw</b> subsystem, allowing Graphics APIs to easily implement window and monitor support.</p>
|
||||
<p>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 <b>graphics</b> subsystem.</p>
|
||||
</body>
|
1
windowing/glfw/src/main/javadoc/theme.css
Symbolic link
1
windowing/glfw/src/main/javadoc/theme.css
Symbolic link
|
@ -0,0 +1 @@
|
|||
../../../../../src/main/javadoc/theme.css
|
0
rendering/gradlew → windowing/gradlew
vendored
0
rendering/gradlew → windowing/gradlew
vendored
|
@ -0,0 +1,235 @@
|
|||
/*
|
||||
* 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 <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,246 @@
|
|||
/*
|
||||
* 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 <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
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.
|
||||
* <p>
|
||||
* 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.
|
||||
* <p>
|
||||
* 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.
|
||||
* <p>
|
||||
* 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; }
|
||||
}
|
||||
}
|
||||
}
|
|
@ -17,28 +17,28 @@
|
|||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package de.staropensource.engine.rendering.event;
|
||||
package de.staropensource.engine.windowing.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.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 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 org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
/**
|
||||
* Called when a key or button is pressed.
|
||||
*
|
||||
* @since v1-alpha9
|
||||
* @since v1-alpha2
|
||||
*/
|
||||
public final class InputEvent implements Event {
|
||||
/**
|
||||
* Creates and initializes an instance of this event.
|
||||
*
|
||||
* @since v1-alpha9
|
||||
* @since v1-alpha2
|
||||
*/
|
||||
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-alpha9
|
||||
* @since v1-alpha0
|
||||
*/
|
||||
public void callEvent(@Nullable Window window, @NotNull Key key, @NotNull KeyState state) {
|
||||
if (RenderingSubsystemConfiguration.getInstance().isDebugInput())
|
||||
if (WindowingSubsystemConfiguration.getInstance().isDebugInput())
|
||||
Logger.diag("Got input event: window=" + (window == null ? "\\<null>" : window.getUniqueIdentifier()) + " key=" + key.name() + " state=" + state.name());
|
||||
|
||||
EventHelper.invokeAnnotatedMethods(getClass(), window, key, state);
|
|
@ -17,30 +17,29 @@
|
|||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package de.staropensource.engine.rendering.event;
|
||||
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;
|
||||
|
||||
/**
|
||||
* Emitted when a rendering error occurs.
|
||||
* Called when an error occurs in the renderer API (e.g. OpenGL, Vulkan).
|
||||
*
|
||||
* @since v1-alpha9
|
||||
* @since v1-alpha0
|
||||
*/
|
||||
public final class RenderingErrorEvent implements Event {
|
||||
/**
|
||||
* Creates and initializes an instance of this event.
|
||||
*
|
||||
* @since v1-alpha9
|
||||
* @since v1-alpha0
|
||||
*/
|
||||
public RenderingErrorEvent() {}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* @deprecated use the {@code callEvent} method with arguments
|
||||
* @see #callEvent(String)
|
||||
* @see #callEvent(String)
|
||||
*/
|
||||
@Deprecated
|
||||
@Override
|
||||
|
@ -50,7 +49,7 @@ public final class RenderingErrorEvent implements Event {
|
|||
* Emits the event and calls all event listeners.
|
||||
*
|
||||
* @param error error description
|
||||
* @since v1-alpha9
|
||||
* @since v1-alpha0
|
||||
*/
|
||||
public void callEvent(@NotNull String error) {
|
||||
EventHelper.invokeAnnotatedMethods(getClass(), error);
|
|
@ -0,0 +1,58 @@
|
|||
/*
|
||||
* 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 <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,44 @@
|
|||
/*
|
||||
* 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 <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
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());
|
||||
}
|
||||
}
|
|
@ -20,6 +20,6 @@
|
|||
/**
|
||||
* Events. There's nothing more to say.
|
||||
*
|
||||
* @since v1-alpha9
|
||||
* @since v1-alpha0
|
||||
*/
|
||||
package de.staropensource.engine.rendering.event;
|
||||
package de.staropensource.engine.windowing.event;
|
|
@ -17,18 +17,18 @@
|
|||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package de.staropensource.engine.rendering.exception;
|
||||
package de.staropensource.engine.windowing.exception;
|
||||
|
||||
/**
|
||||
* Thrown when the specified monitor does not exist.
|
||||
*
|
||||
* @since v1-alpha9
|
||||
* @since v1-alpha2
|
||||
*/
|
||||
public final class InvalidMonitorException extends RuntimeException {
|
||||
/**
|
||||
* Creates and initializes an instance of this exception.
|
||||
*
|
||||
* @since v1-alpha9
|
||||
* @since v1-alpha2
|
||||
*/
|
||||
public InvalidMonitorException() {}
|
||||
}
|
|
@ -17,18 +17,18 @@
|
|||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package de.staropensource.engine.rendering.exception;
|
||||
package de.staropensource.engine.windowing.exception;
|
||||
|
||||
/**
|
||||
* Thrown when trying to access one or more monitors but none are found.
|
||||
*
|
||||
* @since v1-alpha9
|
||||
* @since v1-alpha2
|
||||
*/
|
||||
public final class NoMonitorsFoundException extends RuntimeException {
|
||||
/**
|
||||
* Creates and initializes an instance of this exception.
|
||||
*
|
||||
* @since v1-alpha9
|
||||
* @since v1-alpha2
|
||||
*/
|
||||
public NoMonitorsFoundException() {}
|
||||
}
|
|
@ -17,18 +17,18 @@
|
|||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package de.staropensource.engine.rendering.exception;
|
||||
package de.staropensource.engine.windowing.exception;
|
||||
|
||||
/**
|
||||
* Thrown when trying to communicate with a windowing API over a non-main thread.
|
||||
*
|
||||
* @since v1-alpha9
|
||||
* @since v1-alpha2
|
||||
*/
|
||||
public final class NotOnMainThreadException extends RuntimeException {
|
||||
/**
|
||||
* Creates and initializes an instance of this exception.
|
||||
*
|
||||
* @since v1-alpha9
|
||||
* @since v1-alpha2
|
||||
*/
|
||||
public NotOnMainThreadException() {}
|
||||
}
|
|
@ -17,21 +17,21 @@
|
|||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package de.staropensource.engine.rendering.exception;
|
||||
package de.staropensource.engine.windowing.exception;
|
||||
|
||||
import de.staropensource.engine.rendering.type.Window;
|
||||
import de.staropensource.engine.windowing.implementable.Window;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
/**
|
||||
* Thrown when a {@link Window} cannot be created.
|
||||
*
|
||||
* @since v1-alpha9
|
||||
* @since v1-alpha2
|
||||
*/
|
||||
public final class WindowCreationFailureException extends RuntimeException {
|
||||
/**
|
||||
* Creates and initializes an instance of this exception.
|
||||
*
|
||||
* @since v1-alpha9
|
||||
* @since v1-alpha2
|
||||
*/
|
||||
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-alpha9
|
||||
* @since v1-alpha2
|
||||
*/
|
||||
public WindowCreationFailureException(@NotNull String message) {
|
||||
super(message);
|
|
@ -23,6 +23,6 @@
|
|||
* These aren't meant for the windowing subsystem,
|
||||
* but instead for windowing APIs, which may throw them.
|
||||
*
|
||||
* @since v1-alpha9
|
||||
* @since v1-alpha2
|
||||
*/
|
||||
package de.staropensource.engine.rendering.exception;
|
||||
package de.staropensource.engine.windowing.exception;
|
|
@ -17,45 +17,43 @@
|
|||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package de.staropensource.engine.rendering.type;
|
||||
package de.staropensource.engine.windowing.implementable;
|
||||
|
||||
import de.staropensource.engine.base.type.vector.Vec2i;
|
||||
import de.staropensource.engine.rendering.exception.InvalidMonitorException;
|
||||
import de.staropensource.engine.rendering.exception.NoMonitorsFoundException;
|
||||
import de.staropensource.engine.windowing.WindowingSubsystem;
|
||||
import de.staropensource.engine.windowing.exception.InvalidMonitorException;
|
||||
import de.staropensource.engine.windowing.exception.NoMonitorsFoundException;
|
||||
import lombok.AccessLevel;
|
||||
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.
|
||||
* <p>
|
||||
* Note that monitors stop working unannounced when disconnected,
|
||||
* call {@link #isConnected()} before using to avoid unexpected behaviour.
|
||||
*
|
||||
* @since v1-alpha9
|
||||
* @since v1-alpha2
|
||||
*/
|
||||
@SuppressWarnings({ "JavadocDeclaration" })
|
||||
public final class Monitor {
|
||||
public abstract class Monitor {
|
||||
/**
|
||||
* Contains the unique identifier.
|
||||
* <p>
|
||||
* This identifier is unique to every monitor and does not change during runtime.
|
||||
*
|
||||
* @since v1-alpha9
|
||||
* @since v1-alpha2
|
||||
* -- GETTER --
|
||||
* Returns the unique identifier.
|
||||
* <p>
|
||||
* This identifier is unique to every monitor and does not change during runtime.
|
||||
*
|
||||
* @return unique identifier
|
||||
* @since v1-alpha9
|
||||
* @since v1-alpha2
|
||||
*/
|
||||
@Getter
|
||||
private final UUID uniqueIdentifier = UUID.randomUUID();
|
||||
|
@ -65,59 +63,47 @@ public final class Monitor {
|
|||
* <p>
|
||||
* This identifier is used by the windowing API to refer to a monitor and may change during runtime.
|
||||
*
|
||||
* @since v1-alpha9
|
||||
* @since v1-alpha1
|
||||
* -- GETTER --
|
||||
* Returns the monitor identifier.
|
||||
* <p>
|
||||
* This identifier is used by the windowing API to refer to a monitor and may change during runtime.
|
||||
*
|
||||
* @return monitor identifier
|
||||
* @since v1-alpha9
|
||||
* @since v1-alpha2
|
||||
* -- SETTER --
|
||||
* Sets the monitor identifier.
|
||||
* <p>
|
||||
* 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-alpha9
|
||||
* @since v1-alpha2
|
||||
*/
|
||||
private final long identifier;
|
||||
@Setter(AccessLevel.PROTECTED)
|
||||
private String identifier = null;
|
||||
|
||||
/**
|
||||
* Creates and initializes an instance of this abstract class.
|
||||
*
|
||||
* @throws InvalidMonitorException if the monitor isn't connected
|
||||
* @since v1-alpha9
|
||||
* @since v1-alpha2
|
||||
*/
|
||||
public Monitor(long identifier) throws InvalidMonitorException {
|
||||
this.identifier = identifier;
|
||||
|
||||
checkConnected();
|
||||
}
|
||||
public Monitor() {}
|
||||
|
||||
/**
|
||||
* Returns a set of all connected monitors.
|
||||
* Returns all connected monitors.
|
||||
*
|
||||
* @return connected monitors
|
||||
* @since v1-alpha9
|
||||
* @since v1-alpha2
|
||||
*/
|
||||
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;
|
||||
return WindowingSubsystem.getInstance().getApi().getInternalApi().getMonitors();
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if this monitor is actually connected.
|
||||
* Checks if the monitor is actually connected.
|
||||
* If not, throws an {@link InvalidMonitorException}.
|
||||
*
|
||||
* @since v1-alpha9
|
||||
* @since v1-alpha2
|
||||
*/
|
||||
public void checkConnected() throws InvalidMonitorException, NoMonitorsFoundException {
|
||||
if (!isConnected())
|
||||
|
@ -125,48 +111,34 @@ public final class Monitor {
|
|||
}
|
||||
|
||||
/**
|
||||
* Checks if this monitor is connected.
|
||||
* Checks if the monitor is connected or not.
|
||||
*
|
||||
* @return connection status
|
||||
* @since v1-alpha9
|
||||
* @since v1-alpha2
|
||||
*/
|
||||
public boolean isConnected() throws NoMonitorsFoundException {
|
||||
return glfwGetMonitorName(identifier) != null;
|
||||
}
|
||||
public abstract boolean isConnected() throws NoMonitorsFoundException;
|
||||
|
||||
/**
|
||||
* Returns the name of this monitor.
|
||||
* Returns the monitor name.
|
||||
*
|
||||
* @return monitor name
|
||||
* @since v1-alpha9
|
||||
* @since v1-alpha2
|
||||
*/
|
||||
public @NotNull String getName() throws InvalidMonitorException, NoMonitorsFoundException {
|
||||
checkConnected();
|
||||
return Objects.requireNonNull(glfwGetMonitorName(identifier));
|
||||
}
|
||||
public abstract @NotNull String getName() throws InvalidMonitorException, NoMonitorsFoundException;
|
||||
|
||||
/**
|
||||
* Returns size of this monitor.
|
||||
* Returns the monitor size.
|
||||
*
|
||||
* @return monitor size
|
||||
* @since v1-alpha9
|
||||
* @since v1-alpha2
|
||||
*/
|
||||
public @NotNull Vec2i getSize() throws InvalidMonitorException, NoMonitorsFoundException {
|
||||
checkConnected();
|
||||
|
||||
GLFWVidMode videoMode = Objects.requireNonNull(glfwGetVideoMode(identifier));
|
||||
|
||||
return new Vec2i(videoMode.width(), videoMode.height());
|
||||
}
|
||||
public abstract @NotNull Vec2i getSize() throws InvalidMonitorException, NoMonitorsFoundException;
|
||||
|
||||
/**
|
||||
* Returns refresh rate of this monitor in hertz.
|
||||
* Returns the monitor refresh rate.
|
||||
*
|
||||
* @return monitor refresh rate
|
||||
* @since v1-alpha9
|
||||
* @since v1-alpha2
|
||||
*/
|
||||
public short getRefreshRate() throws InvalidMonitorException, NoMonitorsFoundException {
|
||||
checkConnected();
|
||||
return (short) Objects.requireNonNull(glfwGetVideoMode(identifier)).refreshRate();
|
||||
}
|
||||
public abstract short getRefreshRate() throws InvalidMonitorException, NoMonitorsFoundException;
|
||||
}
|
File diff suppressed because it is too large
Load diff
|
@ -0,0 +1,84 @@
|
|||
/*
|
||||
* 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 <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
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.
|
||||
* <p>
|
||||
* 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();
|
||||
}
|
|
@ -0,0 +1,54 @@
|
|||
/*
|
||||
* 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 <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
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<? extends Window> getWindowClass();
|
||||
|
||||
/**
|
||||
* Returns all connected monitors.
|
||||
*
|
||||
* @return connected monitors
|
||||
* @since v1-alpha2
|
||||
*/
|
||||
@NotNull
|
||||
LinkedHashSet<@NotNull Monitor> getMonitors() throws NoMonitorsFoundException;
|
||||
}
|
|
@ -0,0 +1,125 @@
|
|||
/*
|
||||
* 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 <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
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 <b>once</b>.
|
||||
* 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 <b>for ever</b>.
|
||||
* To run the render loop only once, see {@link #runRenderLoop()}.
|
||||
* <p>
|
||||
* 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<LinkedHashMap<@NotNull Window, @NotNull Throwable>> output = new AtomicReference<>(new LinkedHashMap<>()); // runRenderLoop output
|
||||
long renderTime; // Amount of time spent rendering
|
||||
long sleepDuration; // Time spent sleeping the thread
|
||||
LinkedList<Long> 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();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,25 @@
|
|||
/*
|
||||
* 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 <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Contains classes starting with {@code Api*}.
|
||||
*
|
||||
* @since v1-alpha2
|
||||
*/
|
||||
package de.staropensource.engine.windowing.implementable.api;
|
|
@ -0,0 +1,27 @@
|
|||
/*
|
||||
* 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 <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Interfaces and abstract classes which can be used for implementing classes.
|
||||
* <p>
|
||||
* 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;
|
|
@ -20,6 +20,6 @@
|
|||
/**
|
||||
* Code of the windowing subsystem.
|
||||
*
|
||||
* @since v1-alpha9
|
||||
* @since v1-alpha0
|
||||
*/
|
||||
package de.staropensource.engine.rendering;
|
||||
package de.staropensource.engine.windowing;
|
|
@ -17,590 +17,590 @@
|
|||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package de.staropensource.engine.rendering.type.input;
|
||||
package de.staropensource.engine.windowing.type.input;
|
||||
|
||||
/**
|
||||
* Contains a list of keys which can be recognized by the engine.
|
||||
*
|
||||
* @since v1-alpha9
|
||||
* @since v1-alpha2
|
||||
*/
|
||||
public enum Key {
|
||||
/**
|
||||
* An unknown key.
|
||||
*
|
||||
* @since v1-alpha9
|
||||
* @since v1-alpha2
|
||||
*/
|
||||
UNKNOWN_KEY,
|
||||
/**
|
||||
* An unknown mouse button.
|
||||
*
|
||||
* @since v1-alpha9
|
||||
* @since v1-alpha2
|
||||
*/
|
||||
UNKNOWN_MOUSE_BUTTON,
|
||||
UNKNOWN_MOUSE,
|
||||
|
||||
/**
|
||||
* The left mouse button.
|
||||
*
|
||||
* @since v1-alpha9
|
||||
* @since v1-alpha2
|
||||
*/
|
||||
MOUSE_LEFT,
|
||||
/**
|
||||
* The middle mouse button.
|
||||
*
|
||||
* @since v1-alpha9
|
||||
* @since v1-alpha2
|
||||
*/
|
||||
MOUSE_MIDDLE,
|
||||
/**
|
||||
* The right mouse button.
|
||||
*
|
||||
* @since v1-alpha9
|
||||
* @since v1-alpha2
|
||||
*/
|
||||
MOUSE_RIGHT,
|
||||
|
||||
/**
|
||||
* The {@code ALT} modifier key.
|
||||
*
|
||||
* @since v1-alpha9
|
||||
* @since v1-alpha2
|
||||
*/
|
||||
ALT,
|
||||
/**
|
||||
* The {@code '} key.
|
||||
*
|
||||
* @since v1-alpha9
|
||||
* @since v1-alpha2
|
||||
*/
|
||||
APOSTROPHE,
|
||||
/**
|
||||
* The {@code DOWN} arrow key.
|
||||
*
|
||||
* @since v1-alpha9
|
||||
* @since v1-alpha2
|
||||
*/
|
||||
ARROW_DOWN,
|
||||
/**
|
||||
* The {@code LEFT} arrow key.
|
||||
*
|
||||
* @since v1-alpha9
|
||||
* @since v1-alpha2
|
||||
*/
|
||||
ARROW_LEFT,
|
||||
/**
|
||||
* The {@code RIGHT} arrow key.
|
||||
*
|
||||
* @since v1-alpha9
|
||||
* @since v1-alpha2
|
||||
*/
|
||||
ARROW_RIGHT,
|
||||
/**
|
||||
* The {@code UP} arrow key.
|
||||
*
|
||||
* @since v1-alpha9
|
||||
* @since v1-alpha2
|
||||
*/
|
||||
ARROW_UP,
|
||||
/**
|
||||
* The {@code \} key.
|
||||
*
|
||||
* @since v1-alpha9
|
||||
* @since v1-alpha2
|
||||
*/
|
||||
BACKSLASH,
|
||||
/**
|
||||
* The {@code BACKSPACE} key.
|
||||
*
|
||||
* @since v1-alpha9
|
||||
* @since v1-alpha2
|
||||
*/
|
||||
BACKSPACE,
|
||||
/**
|
||||
* The left {@code [} key.
|
||||
*
|
||||
* @since v1-alpha9
|
||||
* @since v1-alpha2
|
||||
*/
|
||||
BRACKET_LEFT,
|
||||
/**
|
||||
* The right {@code ]} key.
|
||||
*
|
||||
* @since v1-alpha9
|
||||
* @since v1-alpha2
|
||||
*/
|
||||
BRACKET_RIGHT,
|
||||
/**
|
||||
* THE {@code CAPSLOCK} KEY.
|
||||
*
|
||||
* @since v1-alpha9
|
||||
* @since v1-alpha2
|
||||
*/
|
||||
CAPS_LOCK,
|
||||
/**
|
||||
* The {@code ,} key.
|
||||
*
|
||||
* @since v1-alpha9
|
||||
* @since v1-alpha2
|
||||
*/
|
||||
COMMA,
|
||||
/**
|
||||
* The left {@code CTRL} modifier key.
|
||||
*
|
||||
* @since v1-alpha9
|
||||
* @since v1-alpha2
|
||||
*/
|
||||
CONTROL_LEFT,
|
||||
/**
|
||||
* The right {@code CTRL} modifier key.
|
||||
*
|
||||
* @since v1-alpha9
|
||||
* @since v1-alpha2
|
||||
*/
|
||||
CONTROL_RIGHT,
|
||||
/**
|
||||
* The {@code DEL} key.
|
||||
*
|
||||
* @since v1-alpha9
|
||||
* @since v1-alpha2
|
||||
*/
|
||||
DELETE,
|
||||
/**
|
||||
* The {@code END} key.
|
||||
*
|
||||
* @since v1-alpha9
|
||||
* @since v1-alpha2
|
||||
*/
|
||||
END,
|
||||
/**
|
||||
* The {@code ENTER} key.
|
||||
*
|
||||
* @since v1-alpha9
|
||||
* @since v1-alpha2
|
||||
*/
|
||||
ENTER,
|
||||
/**
|
||||
* The {@code =} key.
|
||||
*
|
||||
* @since v1-alpha9
|
||||
* @since v1-alpha2
|
||||
*/
|
||||
EQUAL,
|
||||
/**
|
||||
* The {@code ESC} key.
|
||||
*
|
||||
* @since v1-alpha9
|
||||
* @since v1-alpha2
|
||||
*/
|
||||
ESCAPE,
|
||||
/**
|
||||
* The {@code F1} key.
|
||||
*
|
||||
* @since v1-alpha9
|
||||
* @since v1-alpha2
|
||||
*/
|
||||
FUNCTION_1,
|
||||
/**
|
||||
* The {@code F2} key.
|
||||
*
|
||||
* @since v1-alpha9
|
||||
* @since v1-alpha2
|
||||
*/
|
||||
FUNCTION_2,
|
||||
/**
|
||||
* The {@code F3} key.
|
||||
*
|
||||
* @since v1-alpha9
|
||||
* @since v1-alpha2
|
||||
*/
|
||||
FUNCTION_3,
|
||||
/**
|
||||
* The {@code F4} key.
|
||||
*
|
||||
* @since v1-alpha9
|
||||
* @since v1-alpha2
|
||||
*/
|
||||
FUNCTION_4,
|
||||
/**
|
||||
* The {@code F5} key.
|
||||
*
|
||||
* @since v1-alpha9
|
||||
* @since v1-alpha2
|
||||
*/
|
||||
FUNCTION_5,
|
||||
/**
|
||||
* The {@code F6} key.
|
||||
*
|
||||
* @since v1-alpha9
|
||||
* @since v1-alpha2
|
||||
*/
|
||||
FUNCTION_6,
|
||||
/**
|
||||
* The {@code F7} key.
|
||||
*
|
||||
* @since v1-alpha9
|
||||
* @since v1-alpha2
|
||||
*/
|
||||
FUNCTION_7,
|
||||
/**
|
||||
* The {@code F8} key.
|
||||
*
|
||||
* @since v1-alpha9
|
||||
* @since v1-alpha2
|
||||
*/
|
||||
FUNCTION_8,
|
||||
/**
|
||||
* The {@code F9} key.
|
||||
*
|
||||
* @since v1-alpha9
|
||||
* @since v1-alpha2
|
||||
*/
|
||||
FUNCTION_9,
|
||||
/**
|
||||
* The {@code F10} key.
|
||||
*
|
||||
* @since v1-alpha9
|
||||
* @since v1-alpha2
|
||||
*/
|
||||
FUNCTION_10,
|
||||
/**
|
||||
* The {@code F11} key.
|
||||
*
|
||||
* @since v1-alpha9
|
||||
* @since v1-alpha2
|
||||
*/
|
||||
FUNCTION_11,
|
||||
/**
|
||||
* The {@code F12} key.
|
||||
*
|
||||
* @since v1-alpha9
|
||||
* @since v1-alpha2
|
||||
*/
|
||||
FUNCTION_12,
|
||||
/**
|
||||
* The {@code F13} key.
|
||||
*
|
||||
* @since v1-alpha9
|
||||
* @since v1-alpha2
|
||||
*/
|
||||
FUNCTION_13,
|
||||
/**
|
||||
* The {@code F14} key.
|
||||
*
|
||||
* @since v1-alpha9
|
||||
* @since v1-alpha2
|
||||
*/
|
||||
FUNCTION_14,
|
||||
/**
|
||||
* The {@code F15} key.
|
||||
*
|
||||
* @since v1-alpha9
|
||||
* @since v1-alpha2
|
||||
*/
|
||||
FUNCTION_15,
|
||||
/**
|
||||
* The {@code F16} key.
|
||||
*
|
||||
* @since v1-alpha9
|
||||
* @since v1-alpha2
|
||||
*/
|
||||
FUNCTION_16,
|
||||
/**
|
||||
* The {@code F17} key.
|
||||
*
|
||||
* @since v1-alpha9
|
||||
* @since v1-alpha2
|
||||
*/
|
||||
FUNCTION_17,
|
||||
/**
|
||||
* The {@code F18} key.
|
||||
*
|
||||
* @since v1-alpha9
|
||||
* @since v1-alpha2
|
||||
*/
|
||||
FUNCTION_18,
|
||||
/**
|
||||
* The {@code F19} key.
|
||||
*
|
||||
* @since v1-alpha9
|
||||
* @since v1-alpha2
|
||||
*/
|
||||
FUNCTION_19,
|
||||
/**
|
||||
* The {@code F20} key.
|
||||
*
|
||||
* @since v1-alpha9
|
||||
* @since v1-alpha2
|
||||
*/
|
||||
FUNCTION_20,
|
||||
/**
|
||||
* The {@code F21} key.
|
||||
*
|
||||
* @since v1-alpha9
|
||||
* @since v1-alpha2
|
||||
*/
|
||||
FUNCTION_21,
|
||||
/**
|
||||
* The {@code F22} key.
|
||||
*
|
||||
* @since v1-alpha9
|
||||
* @since v1-alpha2
|
||||
*/
|
||||
FUNCTION_22,
|
||||
/**
|
||||
* The {@code F23} key.
|
||||
*
|
||||
* @since v1-alpha9
|
||||
* @since v1-alpha2
|
||||
*/
|
||||
FUNCTION_23,
|
||||
/**
|
||||
* The {@code F24} key.
|
||||
*
|
||||
* @since v1-alpha9
|
||||
* @since v1-alpha2
|
||||
*/
|
||||
FUNCTION_24,
|
||||
/**
|
||||
* The {@code F25} key.
|
||||
*
|
||||
* @since v1-alpha9
|
||||
* @since v1-alpha2
|
||||
*/
|
||||
FUNCTION_25,
|
||||
/**
|
||||
* The {@code `} key.
|
||||
*
|
||||
* @since v1-alpha9
|
||||
* @since v1-alpha2
|
||||
*/
|
||||
GRAVE,
|
||||
/**
|
||||
* The {@code HOME} key.
|
||||
*
|
||||
* @since v1-alpha9
|
||||
* @since v1-alpha2
|
||||
*/
|
||||
HOME,
|
||||
/**
|
||||
* THe {@code INS} key.
|
||||
*
|
||||
* @since v1-alpha9
|
||||
* @since v1-alpha2
|
||||
*/
|
||||
INSERT,
|
||||
/**
|
||||
* The {@code +} key on your keypad.
|
||||
*
|
||||
* @since v1-alpha9
|
||||
* @since v1-alpha2
|
||||
*/
|
||||
KEYPAD_ADD,
|
||||
/**
|
||||
* The {@code -} key on your keypad.
|
||||
*
|
||||
* @since v1-alpha9
|
||||
* @since v1-alpha2
|
||||
*/
|
||||
KEYPAD_DECIMAL,
|
||||
/**
|
||||
* The {@code /} key on your keypad.
|
||||
*
|
||||
* @since v1-alpha9
|
||||
* @since v1-alpha2
|
||||
*/
|
||||
KEYPAD_DIVIDE,
|
||||
/**
|
||||
* The {@code ENTER} key on your keypad.
|
||||
*
|
||||
* @since v1-alpha9
|
||||
* @since v1-alpha2
|
||||
*/
|
||||
KEYPAD_ENTER,
|
||||
/**
|
||||
* The {@code =} key on your keypad.
|
||||
*
|
||||
* @since v1-alpha9
|
||||
* @since v1-alpha2
|
||||
*/
|
||||
KEYPAD_EQUAL,
|
||||
/**
|
||||
* The {@code *} key on your keypad.
|
||||
*
|
||||
* @since v1-alpha9
|
||||
* @since v1-alpha2
|
||||
*/
|
||||
KEYPAD_MULTIPLY,
|
||||
/**
|
||||
* The number {@code 0} key on your keypad.
|
||||
*
|
||||
* @since v1-alpha9
|
||||
* @since v1-alpha2
|
||||
*/
|
||||
KEYPAD_NUMBER_0,
|
||||
/**
|
||||
* The number {@code 1} key on your keypad.
|
||||
*
|
||||
* @since v1-alpha9
|
||||
* @since v1-alpha2
|
||||
*/
|
||||
KEYPAD_NUMBER_1,
|
||||
/**
|
||||
* The number {@code 2} key on your keypad.
|
||||
*
|
||||
* @since v1-alpha9
|
||||
* @since v1-alpha2
|
||||
*/
|
||||
KEYPAD_NUMBER_2,
|
||||
/**
|
||||
* The number {@code 3} key on your keypad.
|
||||
*
|
||||
* @since v1-alpha9
|
||||
* @since v1-alpha2
|
||||
*/
|
||||
KEYPAD_NUMBER_3,
|
||||
/**
|
||||
* The number {@code 4} key on your keypad.
|
||||
*
|
||||
* @since v1-alpha9
|
||||
* @since v1-alpha2
|
||||
*/
|
||||
KEYPAD_NUMBER_4,
|
||||
/**
|
||||
* The number {@code 5} key on your keypad.
|
||||
*
|
||||
* @since v1-alpha9
|
||||
* @since v1-alpha2
|
||||
*/
|
||||
KEYPAD_NUMBER_5,
|
||||
/**
|
||||
* The number {@code 6} key on your keypad.
|
||||
*
|
||||
* @since v1-alpha9
|
||||
* @since v1-alpha2
|
||||
*/
|
||||
KEYPAD_NUMBER_6,
|
||||
/**
|
||||
* The number {@code 7} key on your keypad.
|
||||
*
|
||||
* @since v1-alpha9
|
||||
* @since v1-alpha2
|
||||
*/
|
||||
KEYPAD_NUMBER_7,
|
||||
/**
|
||||
* The number {@code 8} key on your keypad.
|
||||
*
|
||||
* @since v1-alpha9
|
||||
* @since v1-alpha2
|
||||
*/
|
||||
KEYPAD_NUMBER_8,
|
||||
/**
|
||||
* The number {@code 9} key on your keypad.
|
||||
*
|
||||
* @since v1-alpha9
|
||||
* @since v1-alpha2
|
||||
*/
|
||||
KEYPAD_NUMBER_9,
|
||||
/**
|
||||
* The {@code -} key on your keypad.
|
||||
*
|
||||
* @since v1-alpha9
|
||||
* @since v1-alpha2
|
||||
*/
|
||||
KEYPAD_SUBTRACT,
|
||||
/**
|
||||
* The letter {@code A} key.
|
||||
*
|
||||
* @since v1-alpha9
|
||||
* @since v1-alpha2
|
||||
*/
|
||||
LETTER_A,
|
||||
/**
|
||||
* The letter {@code B} key.
|
||||
*
|
||||
* @since v1-alpha9
|
||||
* @since v1-alpha2
|
||||
*/
|
||||
LETTER_B,
|
||||
/**
|
||||
* The letter {@code C} key.
|
||||
*
|
||||
* @since v1-alpha9
|
||||
* @since v1-alpha2
|
||||
*/
|
||||
LETTER_C,
|
||||
/**
|
||||
* The letter {@code D} key.
|
||||
*
|
||||
* @since v1-alpha9
|
||||
* @since v1-alpha2
|
||||
*/
|
||||
LETTER_D,
|
||||
/**
|
||||
* The letter {@code E} key.
|
||||
*
|
||||
* @since v1-alpha9
|
||||
* @since v1-alpha2
|
||||
*/
|
||||
LETTER_E,
|
||||
/**
|
||||
* The letter {@code F} key.
|
||||
*
|
||||
* @since v1-alpha9
|
||||
* @since v1-alpha2
|
||||
*/
|
||||
LETTER_F,
|
||||
/**
|
||||
* The letter {@code G} key.
|
||||
*
|
||||
* @since v1-alpha9
|
||||
* @since v1-alpha2
|
||||
*/
|
||||
LETTER_G,
|
||||
/**
|
||||
* The letter {@code H} key.
|
||||
*
|
||||
* @since v1-alpha9
|
||||
* @since v1-alpha2
|
||||
*/
|
||||
LETTER_H,
|
||||
/**
|
||||
* The letter {@code I} key.
|
||||
*
|
||||
* @since v1-alpha9
|
||||
* @since v1-alpha2
|
||||
*/
|
||||
LETTER_I,
|
||||
/**
|
||||
* The letter {@code J} key.
|
||||
*
|
||||
* @since v1-alpha9
|
||||
* @since v1-alpha2
|
||||
*/
|
||||
LETTER_J,
|
||||
/**
|
||||
* The letter {@code K} key.
|
||||
*
|
||||
* @since v1-alpha9
|
||||
* @since v1-alpha2
|
||||
*/
|
||||
LETTER_K,
|
||||
/**
|
||||
* The letter {@code L} key.
|
||||
*
|
||||
* @since v1-alpha9
|
||||
* @since v1-alpha2
|
||||
*/
|
||||
LETTER_L,
|
||||
/**
|
||||
* The letter {@code M} key.
|
||||
*
|
||||
* @since v1-alpha9
|
||||
* @since v1-alpha2
|
||||
*/
|
||||
LETTER_M,
|
||||
/**
|
||||
* The letter {@code N} key.
|
||||
*
|
||||
* @since v1-alpha9
|
||||
* @since v1-alpha2
|
||||
*/
|
||||
LETTER_N,
|
||||
/**
|
||||
* The letter {@code O} key.
|
||||
*
|
||||
* @since v1-alpha9
|
||||
* @since v1-alpha2
|
||||
*/
|
||||
LETTER_O,
|
||||
/**
|
||||
* The letter {@code P} key.
|
||||
*
|
||||
* @since v1-alpha9
|
||||
* @since v1-alpha2
|
||||
*/
|
||||
LETTER_P,
|
||||
/**
|
||||
* The letter {@code Q} key.
|
||||
*
|
||||
* @since v1-alpha9
|
||||
* @since v1-alpha2
|
||||
*/
|
||||
LETTER_Q,
|
||||
/**
|
||||
* The letter {@code R} key.
|
||||
*
|
||||
* @since v1-alpha9
|
||||
* @since v1-alpha2
|
||||
*/
|
||||
LETTER_R,
|
||||
/**
|
||||
* The letter {@code S} key.
|
||||
*
|
||||
* @since v1-alpha9
|
||||
* @since v1-alpha2
|
||||
*/
|
||||
LETTER_S,
|
||||
/**
|
||||
* The letter {@code T} key.
|
||||
*
|
||||
* @since v1-alpha9
|
||||
* @since v1-alpha2
|
||||
*/
|
||||
LETTER_T,
|
||||
/**
|
||||
* The letter {@code U} key.
|
||||
*
|
||||
* @since v1-alpha9
|
||||
* @since v1-alpha2
|
||||
*/
|
||||
LETTER_U,
|
||||
/**
|
||||
* The letter {@code V} key.
|
||||
*
|
||||
* @since v1-alpha9
|
||||
* @since v1-alpha2
|
||||
*/
|
||||
LETTER_V,
|
||||
/**
|
||||
* The letter {@code W} key.
|
||||
*
|
||||
* @since v1-alpha9
|
||||
* @since v1-alpha2
|
||||
*/
|
||||
LETTER_W,
|
||||
/**
|
||||
* The letter {@code X} key.
|
||||
*
|
||||
* @since v1-alpha9
|
||||
* @since v1-alpha2
|
||||
*/
|
||||
LETTER_X,
|
||||
/**
|
||||
* The letter {@code Y} key.
|
||||
*
|
||||
* @since v1-alpha9
|
||||
* @since v1-alpha2
|
||||
*/
|
||||
LETTER_Y,
|
||||
/**
|
||||
* The letter {@code Z} key.
|
||||
*
|
||||
* @since v1-alpha9
|
||||
* @since v1-alpha2
|
||||
*/
|
||||
LETTER_Z,
|
||||
/**
|
||||
* The {@code MENU} key, which brings up the right click menu.
|
||||
*
|
||||
* @since v1-alpha9
|
||||
* @since v1-alpha2
|
||||
*/
|
||||
MENU,
|
||||
/**
|
||||
|
@ -608,151 +608,151 @@ public enum Key {
|
|||
* <p>
|
||||
* Windows users will recognize this key as the Windows key.
|
||||
*
|
||||
* @since v1-alpha9
|
||||
* @since v1-alpha2
|
||||
*/
|
||||
META,
|
||||
/**
|
||||
* The {@code -} key.
|
||||
*
|
||||
* @since v1-alpha9
|
||||
* @since v1-alpha2
|
||||
*/
|
||||
MINUS,
|
||||
/**
|
||||
* The number {@code 0}.
|
||||
*
|
||||
* @since v1-alpha9
|
||||
* @since v1-alpha2
|
||||
*/
|
||||
NUMBER_0,
|
||||
/**
|
||||
* The number {@code 1}.
|
||||
*
|
||||
* @since v1-alpha9
|
||||
* @since v1-alpha2
|
||||
*/
|
||||
NUMBER_1,
|
||||
/**
|
||||
* The number {@code 2}.
|
||||
*
|
||||
* @since v1-alpha9
|
||||
* @since v1-alpha2
|
||||
*/
|
||||
NUMBER_2,
|
||||
/**
|
||||
* The number {@code 3}.
|
||||
*
|
||||
* @since v1-alpha9
|
||||
* @since v1-alpha2
|
||||
*/
|
||||
NUMBER_3,
|
||||
/**
|
||||
* The number {@code 4}.
|
||||
*
|
||||
* @since v1-alpha9
|
||||
* @since v1-alpha2
|
||||
*/
|
||||
NUMBER_4,
|
||||
/**
|
||||
* The number {@code 5}.
|
||||
*
|
||||
* @since v1-alpha9
|
||||
* @since v1-alpha2
|
||||
*/
|
||||
NUMBER_5,
|
||||
/**
|
||||
* The number {@code 6}.
|
||||
*
|
||||
* @since v1-alpha9
|
||||
* @since v1-alpha2
|
||||
*/
|
||||
NUMBER_6,
|
||||
/**
|
||||
* The number {@code 7}.
|
||||
*
|
||||
* @since v1-alpha9
|
||||
* @since v1-alpha2
|
||||
*/
|
||||
NUMBER_7,
|
||||
/**
|
||||
* The number {@code 8}.
|
||||
*
|
||||
* @since v1-alpha9
|
||||
* @since v1-alpha2
|
||||
*/
|
||||
NUMBER_8,
|
||||
/**
|
||||
* The number {@code 9}.
|
||||
*
|
||||
* @since v1-alpha9
|
||||
* @since v1-alpha2
|
||||
*/
|
||||
NUMBER_9,
|
||||
/**
|
||||
* The {@code NUM} key.
|
||||
*
|
||||
* @since v1-alpha9
|
||||
* @since v1-alpha2
|
||||
*/
|
||||
NUM_LOCK,
|
||||
/**
|
||||
* The {@code PAGE DOWN} key.
|
||||
*
|
||||
* @since v1-alpha9
|
||||
* @since v1-alpha2
|
||||
*/
|
||||
PAGE_DOWN,
|
||||
/**
|
||||
* The {@code PAGE UP} key.
|
||||
*
|
||||
* @since v1-alpha9
|
||||
* @since v1-alpha2
|
||||
*/
|
||||
PAGE_UP,
|
||||
/**
|
||||
* The {@code PAUSE} key.
|
||||
*
|
||||
* @since v1-alpha9
|
||||
* @since v1-alpha2
|
||||
*/
|
||||
PAUSE,
|
||||
/**
|
||||
* The {@code .} key.
|
||||
*
|
||||
* @since v1-alpha9
|
||||
* @since v1-alpha2
|
||||
*/
|
||||
PERIOD,
|
||||
/**
|
||||
* The {@code PRINT} key.
|
||||
*
|
||||
* @since v1-alpha9
|
||||
* @since v1-alpha2
|
||||
*/
|
||||
PRINT,
|
||||
/**
|
||||
* The {@code SCROLL} key.
|
||||
*
|
||||
* @since v1-alpha9
|
||||
* @since v1-alpha2
|
||||
*/
|
||||
SCROLL_LOCK,
|
||||
/**
|
||||
* The {@code ;} key.
|
||||
*
|
||||
* @since v1-alpha9
|
||||
* @since v1-alpha2
|
||||
*/
|
||||
SEMICOLON,
|
||||
/**
|
||||
* The left {@code SHIFT} modifier key.
|
||||
*
|
||||
* @since v1-alpha9
|
||||
* @since v1-alpha2
|
||||
*/
|
||||
SHIFT_LEFT,
|
||||
/**
|
||||
* The right {@code SHIFT} modifier key.
|
||||
*
|
||||
* @since v1-alpha9
|
||||
* @since v1-alpha2
|
||||
*/
|
||||
SHIFT_RIGHT,
|
||||
/**
|
||||
* The {@code /} key.
|
||||
*
|
||||
* @since v1-alpha9
|
||||
* @since v1-alpha2
|
||||
*/
|
||||
SLASH,
|
||||
/**
|
||||
* The {@code ENTER} key.
|
||||
*
|
||||
* @since v1-alpha9
|
||||
* @since v1-alpha2
|
||||
*/
|
||||
SPACE,
|
||||
/**
|
||||
* The {@code TAB} key.
|
||||
*
|
||||
* @since v1-alpha9
|
||||
* @since v1-alpha2
|
||||
*/
|
||||
TAB,
|
||||
}
|
|
@ -17,26 +17,26 @@
|
|||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package de.staropensource.engine.rendering.type.input;
|
||||
package de.staropensource.engine.windowing.type.input;
|
||||
|
||||
/**
|
||||
* Contains in which state a key is.
|
||||
*
|
||||
* @since v1-alpha9
|
||||
* @since v1-alpha2
|
||||
*/
|
||||
@SuppressWarnings({ "unused" })
|
||||
public enum KeyState {
|
||||
/**
|
||||
* Indicates that a key is pressed.
|
||||
*
|
||||
* @since v1-alpha9
|
||||
* @since v1-alpha2
|
||||
*/
|
||||
PRESSED,
|
||||
|
||||
/**
|
||||
* Indicates that a key is released.
|
||||
*
|
||||
* @since v1-alpha9
|
||||
* @since v1-alpha2
|
||||
*/
|
||||
RELEASED,
|
||||
}
|
|
@ -20,6 +20,6 @@
|
|||
/**
|
||||
* Data types related to input.
|
||||
*
|
||||
* @since v1-alpha9
|
||||
* @since v1-alpha2
|
||||
*/
|
||||
package de.staropensource.engine.rendering.type.input;
|
||||
package de.staropensource.engine.windowing.type.input;
|
|
@ -20,6 +20,6 @@
|
|||
/**
|
||||
* Data types in form of enums and classes.
|
||||
*
|
||||
* @since v1-alpha9
|
||||
* @since v1-alpha1
|
||||
*/
|
||||
package de.staropensource.engine.rendering.type;
|
||||
package de.staropensource.engine.windowing.type;
|
|
@ -17,30 +17,29 @@
|
|||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package de.staropensource.engine.rendering.type.window;
|
||||
package de.staropensource.engine.windowing.type.window;
|
||||
|
||||
import de.staropensource.engine.rendering.RenderingSubsystemConfiguration;
|
||||
import de.staropensource.engine.windowing.WindowingSubsystemConfiguration;
|
||||
|
||||
/**
|
||||
* Controls how <a href="https://en.wikipedia.org/wiki/Screen_tearing#Vertical_synchronization">V-Sync</a> operates.
|
||||
*
|
||||
* @since v1-alpha9
|
||||
* @since v1-alpha1
|
||||
*/
|
||||
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 RenderingSubsystemConfiguration#maximumFramesPerSecond}).
|
||||
* {@link WindowingSubsystemConfiguration#maximumFramesPerSecond}).
|
||||
*
|
||||
* @since v1-alpha9
|
||||
* @since v1-alpha1
|
||||
*/
|
||||
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-alpha9
|
||||
* @since v1-alpha1
|
||||
*/
|
||||
ON
|
||||
}
|
|
@ -17,18 +17,18 @@
|
|||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package de.staropensource.engine.rendering.type.window;
|
||||
package de.staropensource.engine.windowing.type.window;
|
||||
|
||||
/**
|
||||
* Contains how a window should be displayed.
|
||||
*
|
||||
* @since v1-alpha9
|
||||
* @since v1-alpha1
|
||||
*/
|
||||
public enum WindowMode {
|
||||
/**
|
||||
* Marks the window as hidden, making it invisible and unable to be interacted with.
|
||||
*
|
||||
* @since v1-alpha9
|
||||
* @since v1-alpha2
|
||||
*/
|
||||
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-alpha9
|
||||
* @since v1-alpha1
|
||||
*/
|
||||
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-alpha9
|
||||
* @since v1-alpha2
|
||||
*/
|
||||
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-alpha9
|
||||
* @since v1-alpha2
|
||||
*/
|
||||
MAXIMIZED,
|
||||
|
||||
|
@ -61,25 +61,20 @@ public enum WindowMode {
|
|||
* Makes the window will have the same
|
||||
* size as the monitor it is currently on.
|
||||
*
|
||||
* @since v1-alpha9
|
||||
* @since v1-alpha1
|
||||
*/
|
||||
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.
|
||||
* <p>
|
||||
* 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-alpha9
|
||||
* @since v1-alpha1
|
||||
*/
|
||||
EXCLUSIVE_FULLSCREEN
|
||||
}
|
|
@ -20,6 +20,6 @@
|
|||
/**
|
||||
* Data types related to windows.
|
||||
*
|
||||
* @since v1-alpha9
|
||||
* @since v1-alpha1
|
||||
*/
|
||||
package de.staropensource.engine.rendering.type.window;
|
||||
package de.staropensource.engine.windowing.type.window;
|
32
windowing/src/main/java/module-info.java
Normal file
32
windowing/src/main/java/module-info.java
Normal file
|
@ -0,0 +1,32 @@
|
|||
/**
|
||||
* 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;
|
||||
}
|
Loading…
Reference in a new issue