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

View file

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

View file

@ -51,7 +51,7 @@ import java.util.Set;
// TODO monitors
@Getter
@SuppressWarnings({ "unused", "JavadocDeclaration", "JavadocBlankLines" })
public abstract class Window {
public abstract class Window implements AutoCloseable {
/**
* A set of all active windows.
*
@ -76,6 +76,26 @@ public abstract class Window {
@Getter(value = AccessLevel.PROTECTED)
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.
*
@ -499,7 +519,7 @@ public abstract class Window {
* @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 {
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
this.name = name;
@ -548,6 +568,9 @@ public abstract class Window {
* <p>
* Do not call this method manually or you
* may cause unintended side effects.
*
* @throws Throwable thrown by implementing method
* @since v1-alpha2
*/
public abstract void updateState() throws Throwable;
@ -556,9 +579,29 @@ public abstract class Window {
* <p>
* Do not call this method manually or you
* may cause unintended side effects.
*
* @throws Throwable thrown by implementing method
* @since v1-alpha2
*/
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).
*

View file

@ -116,8 +116,9 @@ public class Main {
ApiManagementClass management = api.getManagement();
// Create window
Window window;
try {
Window window = new Window.Builder()
window = new Window.Builder()
.setName("sosengine-testapp")
.setTitle("test application window")
.setSize(new Vec2i(960, 540))
@ -125,13 +126,33 @@ public class Main {
.build();
} catch (Throwable 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
logger.diag("Sleeping for 2.5s");
try {
Thread.sleep(5000);
Thread.sleep(2500);
} catch (InterruptedException exception) {
logger.crash("Was unable to sleep for 5000ms", exception);
logger.crash("Was unable to sleep for 2500ms", exception);
}
// Shutdown