Added ThreadSensitive, InputBus cleanup

This commit is contained in:
493msi 2020-09-24 02:34:33 +02:00
parent 9c06c47ffc
commit 93ef85f804
7 changed files with 106 additions and 84 deletions

View File

@ -13,6 +13,9 @@
* Renamed `VertexArray#getVertexAttribs` to `VertexArray#getVertexAttributes` * Renamed `VertexArray#getVertexAttribs` to `VertexArray#getVertexAttributes`
* `[PlutoCore]` Made `PlutoApplication.StartupConfig` fields private, options * `[PlutoCore]` Made `PlutoApplication.StartupConfig` fields private, options
can now only be modified only through public setters can now only be modified only through public setters
* `[PlutoLib]` Added the `ThreadSensitive` annotation
* `[PlutoCore]` Refactored `InputBus` and added several convenience methods
* `[PlutoCore]` Refactored input callbacks
## 20.2.0.0-alpha.1 ## 20.2.0.0-alpha.1
* `[PlutoLib#cz.tefek.pluto.io.logger]` Refactored the Logger subsystem * `[PlutoLib#cz.tefek.pluto.io.logger]` Refactored the Logger subsystem

View File

@ -2,156 +2,157 @@ package cz.tefek.pluto.engine.input;
import org.lwjgl.glfw.GLFW; import org.lwjgl.glfw.GLFW;
import javax.annotation.concurrent.ThreadSafe; import cz.tefek.pluto.annotation.ThreadSensitive;
import cz.tefek.pluto.engine.display.Display; import cz.tefek.pluto.engine.display.Display;
@ThreadSafe @ThreadSensitive(localContexts = true)
public class InputBus public class InputBus
{ {
private static ThreadLocal<KeyboardInputCallback> keyboard = new ThreadLocal<>(); private static final ThreadLocal<InputBus> INSTANCE = new ThreadLocal<>();
private static ThreadLocal<MouseButtonCallback> mouseButton = new ThreadLocal<>();
private static ThreadLocal<CursorPositionCallback> cursorPosition = new ThreadLocal<>(); private final KeyboardInputCallback keyboard = new KeyboardInputCallback();
private static ThreadLocal<ScrollInputCallback> scroll = new ThreadLocal<>(); private final MouseButtonCallback mouseButton = new MouseButtonCallback();
private static ThreadLocal<KeyboardCharInput> charInput = new ThreadLocal<>(); private final CursorPositionCallback cursorPosition = new CursorPositionCallback();
private final ScrollInputCallback scroll = new ScrollInputCallback();
private final KeyboardCharInput charInput = new KeyboardCharInput();
private InputBus()
{
}
public static void init(Display display) public static void init(Display display)
{ {
keyboard.set(new KeyboardInputCallback()); var instance = new InputBus();
GLFW.glfwSetKeyCallback(display.getWindowPointer(), keyboard.get());
mouseButton.set(new MouseButtonCallback());
GLFW.glfwSetMouseButtonCallback(display.getWindowPointer(), mouseButton.get());
cursorPosition.set(new CursorPositionCallback());
GLFW.glfwSetCursorPosCallback(display.getWindowPointer(), cursorPosition.get());
scroll.set(new ScrollInputCallback());
GLFW.glfwSetScrollCallback(display.getWindowPointer(), scroll.get());
charInput.set(new KeyboardCharInput());
GLFW.glfwSetCharCallback(display.getWindowPointer(), charInput.get());
GLFW.glfwSetKeyCallback(display.getWindowPointer(), instance.keyboard);
GLFW.glfwSetMouseButtonCallback(display.getWindowPointer(), instance.mouseButton);
GLFW.glfwSetCursorPosCallback(display.getWindowPointer(), instance.cursorPosition);
GLFW.glfwSetScrollCallback(display.getWindowPointer(), instance.scroll);
GLFW.glfwSetCharCallback(display.getWindowPointer(), instance.charInput);
} }
public static void destroy() public static void destroy()
{ {
scroll.get().free(); var instance = INSTANCE.get();
scroll.remove();
mouseButton.get().free(); instance.scroll.free();
mouseButton.remove(); instance.mouseButton.free();
instance.keyboard.free();
keyboard.get().free(); instance.cursorPosition.free();
keyboard.remove(); instance.charInput.free();
cursorPosition.get().free();
cursorPosition.remove();
charInput.get().free();
charInput.remove();
} }
public static KeyboardInputCallback keyboard() public static KeyboardInputCallback keyboard()
{ {
return keyboard.get(); return INSTANCE.get().keyboard;
} }
public static MouseButtonCallback mouseButtons() public static MouseButtonCallback mouseButtons()
{ {
return mouseButton.get(); return INSTANCE.get().mouseButton;
} }
public static ScrollInputCallback scroll() public static ScrollInputCallback scroll()
{ {
return scroll.get(); return INSTANCE.get().scroll;
} }
public static CursorPositionCallback cursorPosition() public static CursorPositionCallback cursorPosition()
{ {
return cursorPosition.get(); return INSTANCE.get().cursorPosition;
}
public static KeyboardCharInput charInput()
{
return INSTANCE.get().charInput;
} }
public static void resetStates() public static void resetStates()
{ {
keyboard.get().resetPressed(); var instance = INSTANCE.get();
mouseButton.get().reset();
scroll.get().reset(); instance.keyboard.resetPressed();
cursorPosition.get().reset(); instance.mouseButton.reset();
charInput.get().reset(); instance.scroll.reset();
instance.cursorPosition.reset();
instance.charInput.reset();
} }
@ThreadSensitive(localContexts = true)
public static class Mouse public static class Mouse
{ {
public static boolean clicked(int button) public static boolean clicked(int button)
{ {
var mb = mouseButton.get(); return INSTANCE.get().mouseButton.buttonClicked[button];
return mb.buttonClicked[button];
} }
public static boolean released(int button) public static boolean released(int button)
{ {
var mb = mouseButton.get(); return INSTANCE.get().mouseButton.buttonReleased[button];
return mb.buttonReleased[button];
} }
public static boolean isButtonDown(int button) public static boolean isButtonDown(int button)
{ {
var mb = mouseButton.get(); return INSTANCE.get().mouseButton.buttonDown[button];
return mb.buttonDown[button];
} }
public static double getX() public static double getX()
{ {
return cursorPosition.get().getX(); return INSTANCE.get().cursorPosition.getX();
} }
public static double getY() public static double getY()
{ {
return cursorPosition.get().getY(); return INSTANCE.get().cursorPosition.getY();
}
public static boolean isInside(int x1, int y1, int x2, int y2)
{
return INSTANCE.get().cursorPosition.isInside(x1, y1, x2, y2);
} }
public static double getDX() public static double getDX()
{ {
return cursorPosition.get().getDeltaX(); return INSTANCE.get().cursorPosition.getDeltaX();
} }
public static double getDY() public static double getDY()
{ {
return cursorPosition.get().getDeltaY(); return INSTANCE.get().cursorPosition.getDeltaY();
} }
public static double getScrollX() public static double getScrollX()
{ {
return scroll.get().getXScroll(); return INSTANCE.get().scroll.getXScroll();
} }
public static double getScrollY() public static double getScrollY()
{ {
return scroll.get().getYScroll(); return INSTANCE.get().scroll.getYScroll();
} }
} }
@ThreadSensitive(localContexts = true)
public static class Keyboard public static class Keyboard
{ {
public static boolean pressed(int key) public static boolean pressed(int key)
{ {
return keyboard.get().hasBeenPressed(key); return INSTANCE.get().keyboard.hasBeenPressed(key);
} }
public static boolean released(int key) public static boolean released(int key)
{ {
return keyboard.get().hasBeenReleased(key); return INSTANCE.get().keyboard.hasBeenReleased(key);
} }
public static boolean isKeyDown(int key) public static boolean isKeyDown(int key)
{ {
return keyboard.get().isKeyDown(key); return INSTANCE.get().keyboard.isKeyDown(key);
} }
public static String getTypedText() public static String getTypedText()
{ {
return charInput.get().getTypedText(); return INSTANCE.get().charInput.getTypedText();
} }
} }
} }

View File

@ -4,7 +4,7 @@ import org.lwjgl.glfw.GLFWCharCallback;
public class KeyboardCharInput extends GLFWCharCallback public class KeyboardCharInput extends GLFWCharCallback
{ {
private StringBuilder typedText = new StringBuilder(); private final StringBuilder typedText = new StringBuilder();
@Override @Override
public void invoke(long window, int codepoint) public void invoke(long window, int codepoint)

View File

@ -1,16 +1,16 @@
package cz.tefek.pluto.engine.input; package cz.tefek.pluto.engine.input;
import static org.lwjgl.glfw.GLFW.GLFW_PRESS; import org.lwjgl.glfw.GLFWKeyCallback;
import static org.lwjgl.glfw.GLFW.GLFW_RELEASE;
import java.util.HashSet; import java.util.HashSet;
import java.util.Set; import java.util.Set;
import org.lwjgl.glfw.GLFWKeyCallback; import static org.lwjgl.glfw.GLFW.GLFW_PRESS;
import static org.lwjgl.glfw.GLFW.GLFW_RELEASE;
public class KeyboardInputCallback extends GLFWKeyCallback public class KeyboardInputCallback extends GLFWKeyCallback
{ {
private Set<Integer> keyPressed = new HashSet<>(); private final Set<Integer> keyPressed = new HashSet<>();
private Set<Integer> keyDown = new HashSet<>(); private Set<Integer> keyDown = new HashSet<>();
private Set<Integer> keyReleased = new HashSet<>(); private Set<Integer> keyReleased = new HashSet<>();

View File

@ -3,6 +3,8 @@ package cz.tefek.pluto.engine.input;
import org.lwjgl.glfw.GLFW; import org.lwjgl.glfw.GLFW;
import org.lwjgl.glfw.GLFWMouseButtonCallback; import org.lwjgl.glfw.GLFWMouseButtonCallback;
import java.util.Arrays;
public class MouseButtonCallback extends GLFWMouseButtonCallback public class MouseButtonCallback extends GLFWMouseButtonCallback
{ {
public boolean[] buttonClicked = new boolean[32]; public boolean[] buttonClicked = new boolean[32];
@ -19,15 +21,8 @@ public class MouseButtonCallback extends GLFWMouseButtonCallback
public void reset() public void reset()
{ {
for (int i = 0; i < this.buttonClicked.length; i++) Arrays.fill(this.buttonClicked, false);
{ Arrays.fill(this.buttonReleased, false);
this.buttonClicked[i] = false;
}
for (int i = 0; i < this.buttonClicked.length; i++)
{
this.buttonReleased[i] = false;
}
} }
} }

View File

@ -29,18 +29,8 @@ public class ScrollInputCallback extends GLFWScrollCallback
return yScroll; return yScroll;
} }
public void setYScroll(double yScroll)
{
this.yScroll = yScroll;
}
public double getXScroll() public double getXScroll()
{ {
return xScroll; return xScroll;
} }
public void setXScroll(double xScroll)
{
this.xScroll = xScroll;
}
} }

View File

@ -0,0 +1,33 @@
package cz.tefek.pluto.annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* <p>
* Marks a type as a thread-sensitive unit. Accesses from other threads
* other than the original one may result in undesirable behaviour (see below for exceptions).
* </p>
*
* <p>
* Types can opt in to set the {@link ThreadSensitive#localContexts} field to <tt>true</tt>,
* committing to support per-thread local contexts.
* </p>
*
* @author 493msi
*
* @since 20.2.0.0-alpha.2
*/
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.SOURCE)
public @interface ThreadSensitive
{
/**
* When <tt>true</tt>, the annotated type commits to support thread-local contexts.
*
* @since 20.2.0.0-alpha.2
* */
boolean localContexts() default false;
}