From 68e0a793aa9316460a4072ed0b6a943821077929 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Przemys=C5=82aw=20Pluta?= Date: Sat, 13 Mar 2021 11:22:48 +0100 Subject: [PATCH] Add support for key event handling in GUI --- .../base/api/game/context/Context.java | 3 --- .../base/api/game/gui/base/BaseWidget.java | 7 +++++++ .../base/api/game/gui/base/GUI.java | 3 ++- .../base/api/game/gui/base/Widget.java | 3 ++- .../api/game/gui/component/BaseContainer.java | 13 +++++++++++++ .../base/api/game/gui/window/BaseWindow.java | 6 ++++++ .../game/gui/window/DefaultWindowManager.java | 14 ++++++++++++++ .../api/game/gui/window/WindowManager.java | 2 ++ .../base/api/game/input/Input.java | 6 ++---- .../base/api/game/input/KeyEventHandler.java | 5 +++++ .../resources/java_templates/game_runner.ftl | 4 ++++ .../resources/java_templates/map_handler.ftl | 3 ++- .../engine/context/model/DefaultContext.java | 6 ------ .../base/engine/gui/render/NanoVGGUI.java | 6 ++++++ .../base/engine/gui/widget/ScreenWidget.java | 6 ++++++ .../base/engine/logic/DefaultGameLogic.java | 5 +---- .../base/engine/ui/model/GLFWInput.java | 18 ++++++++---------- 17 files changed, 80 insertions(+), 30 deletions(-) create mode 100644 api/src/main/java/com/bartlomiejpluta/base/api/game/input/KeyEventHandler.java diff --git a/api/src/main/java/com/bartlomiejpluta/base/api/game/context/Context.java b/api/src/main/java/com/bartlomiejpluta/base/api/game/context/Context.java index 36c15375..1d448db2 100644 --- a/api/src/main/java/com/bartlomiejpluta/base/api/game/context/Context.java +++ b/api/src/main/java/com/bartlomiejpluta/base/api/game/context/Context.java @@ -5,7 +5,6 @@ import com.bartlomiejpluta.base.api.game.entity.Entity; import com.bartlomiejpluta.base.api.game.gui.base.GUI; import com.bartlomiejpluta.base.api.game.image.Image; import com.bartlomiejpluta.base.api.game.input.Input; -import com.bartlomiejpluta.base.api.game.input.KeyEvent; import com.bartlomiejpluta.base.api.game.runner.GameRunner; import com.bartlomiejpluta.base.api.game.screen.Screen; import com.bartlomiejpluta.base.api.internal.gc.Disposable; @@ -46,6 +45,4 @@ public interface Context extends Updatable, Renderable, Disposable { void init(Screen screen, Input input, Camera camera); void input(Input input); - - void handleKeyEvent(KeyEvent event); } diff --git a/api/src/main/java/com/bartlomiejpluta/base/api/game/gui/base/BaseWidget.java b/api/src/main/java/com/bartlomiejpluta/base/api/game/gui/base/BaseWidget.java index c06d71a9..b9da5d80 100644 --- a/api/src/main/java/com/bartlomiejpluta/base/api/game/gui/base/BaseWidget.java +++ b/api/src/main/java/com/bartlomiejpluta/base/api/game/gui/base/BaseWidget.java @@ -1,5 +1,7 @@ package com.bartlomiejpluta.base.api.game.gui.base; +import com.bartlomiejpluta.base.api.game.input.KeyEvent; + public abstract class BaseWidget implements Widget { protected Widget parent; @@ -271,4 +273,9 @@ public abstract class BaseWidget implements Widget { public float getPaddingLeft() { return paddingLeft; } + + @Override + public void handleKeyEvent(KeyEvent event) { + // Designed to be overridden if needed so + } } diff --git a/api/src/main/java/com/bartlomiejpluta/base/api/game/gui/base/GUI.java b/api/src/main/java/com/bartlomiejpluta/base/api/game/gui/base/GUI.java index bf5a7a51..11191351 100644 --- a/api/src/main/java/com/bartlomiejpluta/base/api/game/gui/base/GUI.java +++ b/api/src/main/java/com/bartlomiejpluta/base/api/game/gui/base/GUI.java @@ -1,9 +1,10 @@ package com.bartlomiejpluta.base.api.game.gui.base; +import com.bartlomiejpluta.base.api.game.input.KeyEventHandler; import com.bartlomiejpluta.base.api.internal.gc.Disposable; import com.bartlomiejpluta.base.api.internal.render.Renderable; -public interface GUI extends Renderable, Disposable { +public interface GUI extends Renderable, Disposable, KeyEventHandler { int ALIGN_LEFT = 1 << 0; int ALIGN_CENTER = 1 << 1; int ALIGN_RIGHT = 1 << 2; diff --git a/api/src/main/java/com/bartlomiejpluta/base/api/game/gui/base/Widget.java b/api/src/main/java/com/bartlomiejpluta/base/api/game/gui/base/Widget.java index 103ac055..034d22cb 100644 --- a/api/src/main/java/com/bartlomiejpluta/base/api/game/gui/base/Widget.java +++ b/api/src/main/java/com/bartlomiejpluta/base/api/game/gui/base/Widget.java @@ -1,8 +1,9 @@ package com.bartlomiejpluta.base.api.game.gui.base; +import com.bartlomiejpluta.base.api.game.input.KeyEventHandler; import com.bartlomiejpluta.base.api.game.screen.Screen; -public interface Widget { +public interface Widget extends KeyEventHandler { Widget getParent(); void setParent(Widget parent); diff --git a/api/src/main/java/com/bartlomiejpluta/base/api/game/gui/component/BaseContainer.java b/api/src/main/java/com/bartlomiejpluta/base/api/game/gui/component/BaseContainer.java index 9a45ee5d..289c9195 100644 --- a/api/src/main/java/com/bartlomiejpluta/base/api/game/gui/component/BaseContainer.java +++ b/api/src/main/java/com/bartlomiejpluta/base/api/game/gui/component/BaseContainer.java @@ -1,5 +1,7 @@ package com.bartlomiejpluta.base.api.game.gui.component; +import com.bartlomiejpluta.base.api.game.input.KeyEvent; + import java.util.LinkedList; import java.util.List; @@ -63,4 +65,15 @@ public abstract class BaseContainer extends BaseComponent implements Container { return childrenHeight; } + + @Override + public void handleKeyEvent(KeyEvent event) { + for (var child : children) { + if (!event.isConsumed()) { + return; + } + + child.handleKeyEvent(event); + } + } } diff --git a/api/src/main/java/com/bartlomiejpluta/base/api/game/gui/window/BaseWindow.java b/api/src/main/java/com/bartlomiejpluta/base/api/game/gui/window/BaseWindow.java index c0517482..fe8f6ab8 100644 --- a/api/src/main/java/com/bartlomiejpluta/base/api/game/gui/window/BaseWindow.java +++ b/api/src/main/java/com/bartlomiejpluta/base/api/game/gui/window/BaseWindow.java @@ -2,6 +2,7 @@ package com.bartlomiejpluta.base.api.game.gui.window; import com.bartlomiejpluta.base.api.game.gui.base.BaseWidget; import com.bartlomiejpluta.base.api.game.gui.component.Component; +import com.bartlomiejpluta.base.api.game.input.KeyEvent; public abstract class BaseWindow extends BaseWidget implements Window { protected Component content; @@ -36,4 +37,9 @@ public abstract class BaseWindow extends BaseWidget implements Window { public void onClose(WindowManager manager) { // do nothing } + + @Override + public void handleKeyEvent(KeyEvent event) { + content.handleKeyEvent(event); + } } diff --git a/api/src/main/java/com/bartlomiejpluta/base/api/game/gui/window/DefaultWindowManager.java b/api/src/main/java/com/bartlomiejpluta/base/api/game/gui/window/DefaultWindowManager.java index 0fc840e8..c3123593 100644 --- a/api/src/main/java/com/bartlomiejpluta/base/api/game/gui/window/DefaultWindowManager.java +++ b/api/src/main/java/com/bartlomiejpluta/base/api/game/gui/window/DefaultWindowManager.java @@ -3,6 +3,7 @@ package com.bartlomiejpluta.base.api.game.gui.window; import com.bartlomiejpluta.base.api.game.gui.base.BaseWidget; import com.bartlomiejpluta.base.api.game.gui.base.GUI; import com.bartlomiejpluta.base.api.game.gui.base.SizeMode; +import com.bartlomiejpluta.base.api.game.input.KeyEvent; import com.bartlomiejpluta.base.api.game.screen.Screen; import java.util.Deque; @@ -68,6 +69,11 @@ public class DefaultWindowManager extends BaseWidget implements WindowManager { window.onClose(this); } + @Override + public int size() { + return windows.size(); + } + @Override public void draw(Screen screen, GUI gui) { switch (displayMode) { @@ -86,6 +92,14 @@ public class DefaultWindowManager extends BaseWidget implements WindowManager { } } + @Override + public void handleKeyEvent(KeyEvent event) { + var topWindow = windows.peekFirst(); + if (topWindow != null) { + topWindow.handleKeyEvent(event); + } + } + private void drawWindow(Screen screen, Window window, GUI gui) { switch (window.getWindowPosition()) { case TOP -> window.setPosition( diff --git a/api/src/main/java/com/bartlomiejpluta/base/api/game/gui/window/WindowManager.java b/api/src/main/java/com/bartlomiejpluta/base/api/game/gui/window/WindowManager.java index 8b1132aa..f7e7f39e 100644 --- a/api/src/main/java/com/bartlomiejpluta/base/api/game/gui/window/WindowManager.java +++ b/api/src/main/java/com/bartlomiejpluta/base/api/game/gui/window/WindowManager.java @@ -8,4 +8,6 @@ public interface WindowManager extends Widget { void open(Window window); void close(); + + int size(); } diff --git a/api/src/main/java/com/bartlomiejpluta/base/api/game/input/Input.java b/api/src/main/java/com/bartlomiejpluta/base/api/game/input/Input.java index 192729dd..356e3bfa 100644 --- a/api/src/main/java/com/bartlomiejpluta/base/api/game/input/Input.java +++ b/api/src/main/java/com/bartlomiejpluta/base/api/game/input/Input.java @@ -1,11 +1,9 @@ package com.bartlomiejpluta.base.api.game.input; -import java.util.function.Consumer; - public interface Input { boolean isKeyPressed(Key key); - void addKeyEventHandler(Consumer handler); + void addKeyEventHandler(KeyEventHandler handler); - void removeKeyEventHandler(Consumer handler); + void removeKeyEventHandler(KeyEventHandler handler); } diff --git a/api/src/main/java/com/bartlomiejpluta/base/api/game/input/KeyEventHandler.java b/api/src/main/java/com/bartlomiejpluta/base/api/game/input/KeyEventHandler.java new file mode 100644 index 00000000..f0fb16a1 --- /dev/null +++ b/api/src/main/java/com/bartlomiejpluta/base/api/game/input/KeyEventHandler.java @@ -0,0 +1,5 @@ +package com.bartlomiejpluta.base.api.game.input; + +public interface KeyEventHandler { + void handleKeyEvent(KeyEvent event); +} diff --git a/editor/src/main/resources/java_templates/game_runner.ftl b/editor/src/main/resources/java_templates/game_runner.ftl index 34c6bdf5..60159c28 100644 --- a/editor/src/main/resources/java_templates/game_runner.ftl +++ b/editor/src/main/resources/java_templates/game_runner.ftl @@ -4,6 +4,7 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.bartlomiejpluta.base.api.game.context.Context; +import com.bartlomiejpluta.base.api.game.input.Input; import com.bartlomiejpluta.base.api.game.screen.Screen; import com.bartlomiejpluta.base.api.game.runner.GameRunner; @@ -12,6 +13,9 @@ public class ${className} implements GameRunner { @Override public void init(Context context) { + // Resume engine, because it is initially paused + context.resume(); + log.info("The game runner is not implemented yet..."); throw new RuntimeException("Not implemented yet"); } diff --git a/editor/src/main/resources/java_templates/map_handler.ftl b/editor/src/main/resources/java_templates/map_handler.ftl index 188f3adb..cf918d48 100644 --- a/editor/src/main/resources/java_templates/map_handler.ftl +++ b/editor/src/main/resources/java_templates/map_handler.ftl @@ -1,6 +1,7 @@ package ${package}; import com.bartlomiejpluta.base.api.game.context.Context; +import com.bartlomiejpluta.base.api.game.input.Input; import com.bartlomiejpluta.base.api.game.map.model.GameMap; import com.bartlomiejpluta.base.api.game.map.handler.MapHandler; import com.bartlomiejpluta.base.api.game.screen.Screen; @@ -18,7 +19,7 @@ public class ${className} implements MapHandler { } @Override - public void input(Screen screen) { + public void input(Input input) { } diff --git a/engine/src/main/java/com/bartlomiejpluta/base/engine/context/model/DefaultContext.java b/engine/src/main/java/com/bartlomiejpluta/base/engine/context/model/DefaultContext.java index 4b856ce5..e9847d8d 100644 --- a/engine/src/main/java/com/bartlomiejpluta/base/engine/context/model/DefaultContext.java +++ b/engine/src/main/java/com/bartlomiejpluta/base/engine/context/model/DefaultContext.java @@ -6,7 +6,6 @@ import com.bartlomiejpluta.base.api.game.entity.Entity; import com.bartlomiejpluta.base.api.game.gui.base.GUI; import com.bartlomiejpluta.base.api.game.image.Image; import com.bartlomiejpluta.base.api.game.input.Input; -import com.bartlomiejpluta.base.api.game.input.KeyEvent; import com.bartlomiejpluta.base.api.game.map.handler.MapHandler; import com.bartlomiejpluta.base.api.game.runner.GameRunner; import com.bartlomiejpluta.base.api.game.screen.Screen; @@ -137,11 +136,6 @@ public class DefaultContext implements Context { return engine.togglePaused(); } - @Override - public void handleKeyEvent(KeyEvent event) { - // TODO - } - @Override public void input(Input input) { gameRunner.input(input); diff --git a/engine/src/main/java/com/bartlomiejpluta/base/engine/gui/render/NanoVGGUI.java b/engine/src/main/java/com/bartlomiejpluta/base/engine/gui/render/NanoVGGUI.java index 1df53f19..4d41dfec 100644 --- a/engine/src/main/java/com/bartlomiejpluta/base/engine/gui/render/NanoVGGUI.java +++ b/engine/src/main/java/com/bartlomiejpluta/base/engine/gui/render/NanoVGGUI.java @@ -5,6 +5,7 @@ import com.bartlomiejpluta.base.api.game.gui.base.GUI; import com.bartlomiejpluta.base.api.game.gui.base.LineCap; import com.bartlomiejpluta.base.api.game.gui.base.Widget; import com.bartlomiejpluta.base.api.game.gui.base.WindingDirection; +import com.bartlomiejpluta.base.api.game.input.KeyEvent; import com.bartlomiejpluta.base.api.game.screen.Screen; import com.bartlomiejpluta.base.api.internal.render.ShaderManager; import com.bartlomiejpluta.base.engine.error.AppException; @@ -245,6 +246,11 @@ public class NanoVGGUI implements GUI { nvgScissor(context, x, y, width, height); } + @Override + public void handleKeyEvent(KeyEvent event) { + screenWidget.handleKeyEvent(event); + } + @Override public void dispose() { fillColor.free(); diff --git a/engine/src/main/java/com/bartlomiejpluta/base/engine/gui/widget/ScreenWidget.java b/engine/src/main/java/com/bartlomiejpluta/base/engine/gui/widget/ScreenWidget.java index 4e3ee620..98f4f804 100644 --- a/engine/src/main/java/com/bartlomiejpluta/base/engine/gui/widget/ScreenWidget.java +++ b/engine/src/main/java/com/bartlomiejpluta/base/engine/gui/widget/ScreenWidget.java @@ -3,6 +3,7 @@ package com.bartlomiejpluta.base.engine.gui.widget; import com.bartlomiejpluta.base.api.game.gui.base.GUI; import com.bartlomiejpluta.base.api.game.gui.base.SizeMode; import com.bartlomiejpluta.base.api.game.gui.base.Widget; +import com.bartlomiejpluta.base.api.game.input.KeyEvent; import com.bartlomiejpluta.base.api.game.screen.Screen; import lombok.Getter; import lombok.RequiredArgsConstructor; @@ -231,6 +232,11 @@ public class ScreenWidget implements Widget { return 0; } + @Override + public void handleKeyEvent(KeyEvent event) { + root.handleKeyEvent(event); + } + @Override public void draw(Screen screen, GUI gui) { if (root != null) { diff --git a/engine/src/main/java/com/bartlomiejpluta/base/engine/logic/DefaultGameLogic.java b/engine/src/main/java/com/bartlomiejpluta/base/engine/logic/DefaultGameLogic.java index 20445278..fd198a28 100644 --- a/engine/src/main/java/com/bartlomiejpluta/base/engine/logic/DefaultGameLogic.java +++ b/engine/src/main/java/com/bartlomiejpluta/base/engine/logic/DefaultGameLogic.java @@ -33,13 +33,10 @@ public class DefaultGameLogic implements GameLogic { camera = new DefaultCamera(); log.info("Initializing input model"); - var input = new GLFWInput(screen); - input.init(context); + input = new GLFWInput(screen).init(); log.info("Initializing game context"); context.init(screen, input, camera); - - this.input = input; } @Override diff --git a/engine/src/main/java/com/bartlomiejpluta/base/engine/ui/model/GLFWInput.java b/engine/src/main/java/com/bartlomiejpluta/base/engine/ui/model/GLFWInput.java index e2321d1a..392079ef 100644 --- a/engine/src/main/java/com/bartlomiejpluta/base/engine/ui/model/GLFWInput.java +++ b/engine/src/main/java/com/bartlomiejpluta/base/engine/ui/model/GLFWInput.java @@ -1,9 +1,8 @@ package com.bartlomiejpluta.base.engine.ui.model; -import com.bartlomiejpluta.base.api.game.context.Context; import com.bartlomiejpluta.base.api.game.input.Input; import com.bartlomiejpluta.base.api.game.input.Key; -import com.bartlomiejpluta.base.api.game.input.KeyEvent; +import com.bartlomiejpluta.base.api.game.input.KeyEventHandler; import com.bartlomiejpluta.base.api.game.screen.Screen; import com.bartlomiejpluta.base.engine.ui.event.GLFWKeyEvent; import lombok.NonNull; @@ -11,7 +10,6 @@ import lombok.extern.slf4j.Slf4j; import java.util.Deque; import java.util.LinkedList; -import java.util.function.Consumer; import static com.bartlomiejpluta.base.engine.ui.event.GLFWKeyEvent.glfwCode; import static org.lwjgl.glfw.GLFW.*; @@ -19,27 +17,27 @@ import static org.lwjgl.glfw.GLFW.*; @Slf4j public class GLFWInput implements Input { private final long windowHandle; - private final Deque> keyEventHandlers = new LinkedList<>(); + private final Deque keyEventHandlers = new LinkedList<>(); public GLFWInput(@NonNull Screen screen) { this.windowHandle = screen.getID(); } - public void init(Context context) { + public GLFWInput init() { log.info("Registering key callback"); glfwSetKeyCallback(windowHandle, (window, key, scancode, action, mods) -> { var event = GLFWKeyEvent.of(key, action); - context.handleKeyEvent(event); - for (var handler : keyEventHandlers) { if (event.isConsumed()) { return; } - handler.accept(event); + handler.handleKeyEvent(event); } }); + + return this; } @Override @@ -48,12 +46,12 @@ public class GLFWInput implements Input { } @Override - public void addKeyEventHandler(Consumer handler) { + public void addKeyEventHandler(KeyEventHandler handler) { keyEventHandlers.addLast(handler); } @Override - public void removeKeyEventHandler(Consumer handler) { + public void removeKeyEventHandler(KeyEventHandler handler) { keyEventHandlers.remove(handler); } }