Fix updateState, add terminate methods

This commit is contained in:
JeremyStar™ 2024-07-25 04:13:33 +02:00
parent 6c0244053b
commit eea7fce13c
Signed by: JeremyStarTM
GPG key ID: E366BAEF67E4704D
4 changed files with 192 additions and 30 deletions

View file

@ -32,8 +32,11 @@ import de.staropensource.sosengine.graphics.types.window.VsyncMode;
import de.staropensource.sosengine.graphics.types.window.WindowMode; import de.staropensource.sosengine.graphics.types.window.WindowMode;
import lombok.Getter; import lombok.Getter;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.lwjgl.system.MemoryStack;
import org.lwjgl.system.MemoryUtil; import org.lwjgl.system.MemoryUtil;
import java.nio.IntBuffer;
import static org.lwjgl.glfw.GLFW.*; import static org.lwjgl.glfw.GLFW.*;
/** /**
@ -57,8 +60,8 @@ public abstract class GlfwWindow extends Window {
*/ */
private long identifierLong; private long identifierLong;
// ------------------------------------------------ [ Window initialization ] ------------------------------------------------ //
/** /**
// ------------------------------------------------ [ Window (de)initialization ] ------------------------------------------------ //
* Creates a new window. * Creates a new window.
* *
* @param name name * @param name name
@ -85,10 +88,6 @@ public abstract class GlfwWindow extends Window {
/** {@inheritDoc} */ /** {@inheritDoc} */
@Override @Override
protected void initializeWindow() throws Throwable { protected void initializeWindow() throws Throwable {
// Ensure running on the main thread
if (!Miscellaneous.onMainThread())
throw new NotOnMainThreadException();
createGlfwWindow(); // Create the GLFW window createGlfwWindow(); // Create the GLFW window
initializeGlfwWindow(); // Call GLFW window initialization method initializeGlfwWindow(); // Call GLFW window initialization method
} }
@ -102,22 +101,25 @@ public abstract class GlfwWindow extends Window {
protected abstract void initializeGlfwWindow() throws Throwable; protected abstract void initializeGlfwWindow() throws Throwable;
/** /**
* (Re-)Creates the GLFW window. * (Re-)Creates the associated GLFW window.
* *
* @since v1-alpha2 * @since v1-alpha2
*/ */
public void createGlfwWindow() throws WindowCreationFailureException { public void createGlfwWindow() throws WindowCreationFailureException {
// Get current focus // Ensure running on the main thread
boolean focused = true; if (!Miscellaneous.onMainThread())
throw new NotOnMainThreadException();
// Destroy existing window // Get current focus and destroy existing window
boolean focused = true;
if (getIdentifier() != null) { if (getIdentifier() != null) {
focused = isFocused(); focused = isFocused();
glfwDestroyWindow(identifierLong); closeGlfwWindow();
} }
// Set window hints // Set window hints
setWindowHints(); setWindowHints();
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_X, getPosition().getX());
glfwWindowHint(GLFW_POSITION_Y, getPosition().getY()); glfwWindowHint(GLFW_POSITION_Y, getPosition().getY());
glfwWindowHint(GLFW_CENTER_CURSOR, 0); glfwWindowHint(GLFW_CENTER_CURSOR, 0);
@ -152,6 +154,23 @@ public abstract class GlfwWindow extends Window {
setWindowMode(getWindowMode()); 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();
// Destroy the window
glfwDestroyWindow(identifierLong);
}
/** /**
* Sets window hints. * Sets window hints.
* *
@ -159,6 +178,12 @@ public abstract class GlfwWindow extends Window {
*/ */
public abstract void setWindowHints(); public abstract void setWindowHints();
/** {@inheritDoc} */
public void terminate() {
setTerminated(true);
closeGlfwWindow();
}
// ------------------------------------------------ [ State updates ] ------------------------------------------------ // // ------------------------------------------------ [ State updates ] ------------------------------------------------ //
/** /**
* Updates the window state. * Updates the window state.
@ -167,6 +192,10 @@ public abstract class GlfwWindow extends Window {
*/ */
@Override @Override
public void updateState() { public void updateState() {
// Ensure the window is not terminated
if (isTerminated())
return;
// Ensure running on the main thread // Ensure running on the main thread
if (!Miscellaneous.onMainThread()) if (!Miscellaneous.onMainThread())
throw new NotOnMainThreadException(); throw new NotOnMainThreadException();
@ -177,23 +206,16 @@ public abstract class GlfwWindow extends Window {
// Set swap interval based on isDisallowTearing setting // Set swap interval based on isDisallowTearing setting
glfwSwapInterval(Miscellaneous.getIntegerizedBoolean(GraphicsSubsystemConfiguration.getInstance().isDisallowTearing())); glfwSwapInterval(Miscellaneous.getIntegerizedBoolean(GraphicsSubsystemConfiguration.getInstance().isDisallowTearing()));
/* try (MemoryStack stack = MemoryStack.stackPush()) {
// Initialize IntBuffers, used for 'size' and 'position' IntBuffer width = stack.mallocInt(2);
IntBuffer width = MemoryUtil.memAllocInt(1); IntBuffer height = stack.mallocInt(2);
IntBuffer height = MemoryUtil.memAllocInt(1);
// Update window size glfwGetWindowSize(identifierLong, width, height);
glfwGetFramebufferSize(identifierLong, width, height); super.setSize(new Vec2i(width.get(), height.get()));
super.setSize(new Vec2i(width.get(0), height.get(0)));
// Clear IntBuffers
width.clear();
height.clear();
// Update window position
glfwGetWindowPos(identifierLong, width, height); glfwGetWindowPos(identifierLong, width, height);
super.setPosition(new Vec2i(width.get(0), height.get(0))); super.setPosition(new Vec2i(width.get(), height.get()));
*/ }
// Update window mode // Update window mode
if (Miscellaneous.getBooleanizedInteger(glfwGetWindowAttrib(identifierLong, GLFW_ICONIFIED))) if (Miscellaneous.getBooleanizedInteger(glfwGetWindowAttrib(identifierLong, GLFW_ICONIFIED)))
@ -226,6 +248,10 @@ public abstract class GlfwWindow extends Window {
/** {@inheritDoc} */ /** {@inheritDoc} */
@Override @Override
public void render() throws NotOnMainThreadException { public void render() throws NotOnMainThreadException {
// Ensure the window is not terminated
if (isTerminated())
return;
// Ensure running on the main thread // Ensure running on the main thread
if (!Miscellaneous.onMainThread()) if (!Miscellaneous.onMainThread())
throw new NotOnMainThreadException(); throw new NotOnMainThreadException();
@ -248,22 +274,38 @@ public abstract class GlfwWindow extends Window {
/** {@inheritDoc} */ /** {@inheritDoc} */
@Override @Override
public boolean isClosureRequested() { public boolean isClosureRequested() {
// Ensure the window is not terminated
if (isTerminated())
return false;
return glfwWindowShouldClose(identifierLong); return glfwWindowShouldClose(identifierLong);
} }
/** {@inheritDoc} */ /** {@inheritDoc} */
@Override @Override
public boolean isFocused() { public boolean isFocused() {
// Ensure the window is not terminated
if (isTerminated())
return false;
return Tristate.toBoolean(Miscellaneous.getTristatedInteger(glfwGetWindowAttrib(identifierLong, GLFW_FOCUSED))); return Tristate.toBoolean(Miscellaneous.getTristatedInteger(glfwGetWindowAttrib(identifierLong, GLFW_FOCUSED)));
} }
/** {@inheritDoc} */ /** {@inheritDoc} */
public void focus() { public void focus() {
// Ensure the window is not terminated
if (isTerminated())
return;
glfwFocusWindow(identifierLong); glfwFocusWindow(identifierLong);
} }
/** {@inheritDoc} */ /** {@inheritDoc} */
public void requestAttention() { public void requestAttention() {
// Ensure the window is not terminated
if (isTerminated())
return;
glfwRequestWindowAttention(identifierLong); glfwRequestWindowAttention(identifierLong);
} }
@ -272,6 +314,10 @@ public abstract class GlfwWindow extends Window {
/** {@inheritDoc} */ /** {@inheritDoc} */
@Override @Override
public void setName(@NotNull String name) { public void setName(@NotNull String name) {
// Ensure the window is not terminated
if (isTerminated())
return;
super.setName(name); super.setName(name);
createGlfwWindow(); createGlfwWindow();
} }
@ -279,6 +325,10 @@ public abstract class GlfwWindow extends Window {
/** {@inheritDoc} */ /** {@inheritDoc} */
@Override @Override
public void setTitle(@NotNull String title) { public void setTitle(@NotNull String title) {
// Ensure the window is not terminated
if (isTerminated())
return;
super.setTitle(title); super.setTitle(title);
glfwSetWindowTitle(identifierLong, title); glfwSetWindowTitle(identifierLong, title);
} }
@ -286,6 +336,10 @@ public abstract class GlfwWindow extends Window {
/** {@inheritDoc} */ /** {@inheritDoc} */
@Override @Override
public void setSize(@NotNull Vec2i size) { public void setSize(@NotNull Vec2i size) {
// Ensure the window is not terminated
if (isTerminated())
return;
super.setSize(size); super.setSize(size);
glfwSetWindowSize(identifierLong, size.getX(), size.getY()); glfwSetWindowSize(identifierLong, size.getX(), size.getY());
} }
@ -293,6 +347,10 @@ public abstract class GlfwWindow extends Window {
/** {@inheritDoc} */ /** {@inheritDoc} */
@Override @Override
public void setMinimumSize(@NotNull Vec2i minimumSize) { public void setMinimumSize(@NotNull Vec2i minimumSize) {
// Ensure the window is not terminated
if (isTerminated())
return;
super.setMinimumSize(minimumSize); super.setMinimumSize(minimumSize);
glfwSetWindowSizeLimits(identifierLong, minimumSize.getX(), minimumSize.getY(), getMaximumSize().getX(), getMaximumSize().getY()); glfwSetWindowSizeLimits(identifierLong, minimumSize.getX(), minimumSize.getY(), getMaximumSize().getX(), getMaximumSize().getY());
} }
@ -300,6 +358,10 @@ public abstract class GlfwWindow extends Window {
/** {@inheritDoc} */ /** {@inheritDoc} */
@Override @Override
public void setMaximumSize(@NotNull Vec2i maximumSize) { public void setMaximumSize(@NotNull Vec2i maximumSize) {
// Ensure the window is not terminated
if (isTerminated())
return;
super.setMaximumSize(maximumSize); super.setMaximumSize(maximumSize);
glfwSetWindowSizeLimits(identifierLong, getMinimumSize().getX(), getMinimumSize().getY(), maximumSize.getX(), maximumSize.getY()); glfwSetWindowSizeLimits(identifierLong, getMinimumSize().getX(), getMinimumSize().getY(), maximumSize.getX(), maximumSize.getY());
} }
@ -307,6 +369,10 @@ public abstract class GlfwWindow extends Window {
/** {@inheritDoc} */ /** {@inheritDoc} */
@Override @Override
public void setPosition(@NotNull Vec2i position) { public void setPosition(@NotNull Vec2i position) {
// Ensure the window is not terminated
if (isTerminated())
return;
super.setPosition(position); super.setPosition(position);
glfwSetWindowSize(identifierLong, position.getX(), position.getY()); glfwSetWindowSize(identifierLong, position.getX(), position.getY());
} }
@ -314,6 +380,10 @@ public abstract class GlfwWindow extends Window {
/** {@inheritDoc} */ /** {@inheritDoc} */
@Override @Override
public void setWindowMode(@NotNull WindowMode windowMode) { public void setWindowMode(@NotNull WindowMode windowMode) {
// Ensure the window is not terminated
if (isTerminated())
return;
super.setWindowMode(windowMode); super.setWindowMode(windowMode);
switch (windowMode) { switch (windowMode) {
case HIDDEN -> glfwHideWindow(identifierLong); case HIDDEN -> glfwHideWindow(identifierLong);
@ -346,30 +416,50 @@ public abstract class GlfwWindow extends Window {
/** {@inheritDoc} */ /** {@inheritDoc} */
@Override @Override
public void setResizable(boolean resizable) { public void setResizable(boolean resizable) {
// Ensure the window is not terminated
if (isTerminated())
return;
super.setResizable(resizable); super.setResizable(resizable);
} }
/** {@inheritDoc} */ /** {@inheritDoc} */
@Override @Override
public void setBorderless(boolean borderless) { public void setBorderless(boolean borderless) {
// Ensure the window is not terminated
if (isTerminated())
return;
super.setBorderless(borderless); super.setBorderless(borderless);
} }
/** {@inheritDoc} */ /** {@inheritDoc} */
@Override @Override
public void setFocusable(boolean focusable) { public void setFocusable(boolean focusable) {
// Ensure the window is not terminated
if (isTerminated())
return;
super.setFocusable(focusable); super.setFocusable(focusable);
} }
/** {@inheritDoc} */ /** {@inheritDoc} */
@Override @Override
public void setOnTop(boolean onTop) { public void setOnTop(boolean onTop) {
// Ensure the window is not terminated
if (isTerminated())
return;
super.setOnTop(onTop); super.setOnTop(onTop);
} }
/** {@inheritDoc} */ /** {@inheritDoc} */
@Override @Override
public void setTransparent(boolean transparent) { public void setTransparent(boolean transparent) {
// Ensure the window is not terminated
if (isTerminated())
return;
super.setTransparent(transparent); super.setTransparent(transparent);
createGlfwWindow(); createGlfwWindow();
} }

View file

@ -89,6 +89,10 @@ public class OpenGlWindow extends GlfwWindow {
@NotNull @NotNull
@Override @Override
public Vec2i getSizeWithDecorations() { public Vec2i getSizeWithDecorations() {
// Ensure the window is not terminated
if (isTerminated())
return new Vec2i(-1, -1);
return getSize(); return getSize();
} }
@ -96,6 +100,10 @@ public class OpenGlWindow extends GlfwWindow {
@NotNull @NotNull
@Override @Override
public Vec2i getPositionWithDecorations() { public Vec2i getPositionWithDecorations() {
// Ensure the window is not terminated
if (isTerminated())
return new Vec2i(-1, -1);
return getPosition(); return getPosition();
} }
} }

View file

@ -51,7 +51,7 @@ import java.util.Set;
// TODO monitors // TODO monitors
@Getter @Getter
@SuppressWarnings({ "unused", "JavadocDeclaration", "JavadocBlankLines" }) @SuppressWarnings({ "unused", "JavadocDeclaration", "JavadocBlankLines" })
public abstract class Window { public abstract class Window implements AutoCloseable {
/** /**
* A set of all active windows. * A set of all active windows.
* *
@ -76,6 +76,26 @@ public abstract class Window {
@Getter(value = AccessLevel.PROTECTED) @Getter(value = AccessLevel.PROTECTED)
private final LoggerInstance logger = new LoggerInstance(new LogIssuer(getClass(), CodePart.ENGINE)); private final LoggerInstance logger = new LoggerInstance(new LogIssuer(getClass(), CodePart.ENGINE));
/**
* Determines if this window can be interacted with or not.
*
* @since v1-alpha2
*
* -- GETTER --
* Returns if this window can be interacted with or not.
*
* @return closed flag state
* @since v1-alpha2
*
* -- SETTER --
* Sets if this window can be interacted with or not.
*
* @param closed new closed flag state
* @since v1-alpha2
*/
@Setter(AccessLevel.PROTECTED)
private boolean terminated;
/** /**
* Contains the window identifier. * Contains the window identifier.
* *
@ -499,7 +519,7 @@ public abstract class Window {
* @since v1-alpha2 * @since v1-alpha2
*/ */
public Window(@NotNull String name, @NotNull String title, @NotNull Vec2i size, @NotNull Vec2i minimumSize, @NotNull Vec2i maximumSize, @NotNull Vec2i position, @NotNull WindowMode windowMode, @NotNull VsyncMode vsyncMode, boolean resizable, boolean borderless, boolean focusable, boolean onTop, boolean transparent, boolean rendering) throws UnexpectedThrowableException { public Window(@NotNull String name, @NotNull String title, @NotNull Vec2i size, @NotNull Vec2i minimumSize, @NotNull Vec2i maximumSize, @NotNull Vec2i position, @NotNull WindowMode windowMode, @NotNull VsyncMode vsyncMode, boolean resizable, boolean borderless, boolean focusable, boolean onTop, boolean transparent, boolean rendering) throws UnexpectedThrowableException {
logger.diag("Creating new window with properties: title=\"" + title + "\" size=" + size + " position=" + position + " windowMode=" + windowMode + " vsyncMode=" + vsyncMode + " resizable=" + resizable + " borderless=" + borderless + " focusable=" + focusable + " onTop=" + onTop + " transparent=" + transparent + " rendering=" + rendering); logger.diag("Creating new window with properties: name=\"" + name + "\" title=\"" + title + "\" size=" + size + " minimumSize=" + minimumSize + " maximumSize=" + maximumSize + " position=" + position + " windowMode=" + windowMode + " vsyncMode=" + vsyncMode + " resizable=" + resizable + " borderless=" + borderless + " focusable=" + focusable + " onTop=" + onTop + " transparent=" + transparent + " rendering=" + rendering);
// Initialize variables // Initialize variables
this.name = name; this.name = name;
@ -548,6 +568,9 @@ public abstract class Window {
* <p> * <p>
* Do not call this method manually or you * Do not call this method manually or you
* may cause unintended side effects. * may cause unintended side effects.
*
* @throws Throwable thrown by implementing method
* @since v1-alpha2
*/ */
public abstract void updateState() throws Throwable; public abstract void updateState() throws Throwable;
@ -556,9 +579,29 @@ public abstract class Window {
* <p> * <p>
* Do not call this method manually or you * Do not call this method manually or you
* may cause unintended side effects. * may cause unintended side effects.
*
* @throws Throwable thrown by implementing method
* @since v1-alpha2
*/ */
public abstract void render() throws Throwable; public abstract void render() throws Throwable;
/**
* Alias for {@link #terminate()}.
*
* @see #terminate()
* @since v1-alpha2
*/
public void close() {
terminate();
}
/**
* Terminates the window, making it unable to be interacted with.
*
* @since v1-alpha2
*/
public abstract void terminate();
/** /**
* Returns the window size including decorations (e.g. title bar). * Returns the window size including decorations (e.g. title bar).
* *

View file

@ -116,8 +116,9 @@ public class Main {
ApiManagementClass management = api.getManagement(); ApiManagementClass management = api.getManagement();
// Create window // Create window
Window window;
try { try {
Window window = new Window.Builder() window = new Window.Builder()
.setName("sosengine-testapp") .setName("sosengine-testapp")
.setTitle("test application window") .setTitle("test application window")
.setSize(new Vec2i(960, 540)) .setSize(new Vec2i(960, 540))
@ -125,13 +126,33 @@ public class Main {
.build(); .build();
} catch (Throwable throwable) { } catch (Throwable throwable) {
logger.crash("Window.Builder#build() failed", throwable); logger.crash("Window.Builder#build() failed", throwable);
return;
}
// Sleep for 2.5 seconds
logger.diag("Sleeping for 2.5s");
try {
Thread.sleep(2500);
} catch (InterruptedException exception) {
logger.crash("Was unable to sleep for 2500ms", exception);
}
// Update state and render window
try {
logger.diag("Updating state");
window.updateState();
logger.diag("Rendering");
window.render();
} catch (Throwable throwable) {
logger.crash("Window updating or rendering failed", throwable);
} }
// Sleep for five seconds // Sleep for five seconds
logger.diag("Sleeping for 2.5s");
try { try {
Thread.sleep(5000); Thread.sleep(2500);
} catch (InterruptedException exception) { } catch (InterruptedException exception) {
logger.crash("Was unable to sleep for 5000ms", exception); logger.crash("Was unable to sleep for 2500ms", exception);
} }
// Shutdown // Shutdown