From 099eec4fe4d6c07e962465abbc69f1320dcaff1f Mon Sep 17 00:00:00 2001 From: Speiger Date: Sun, 2 Jun 2024 00:47:22 +0200 Subject: [PATCH] More work on the engine. - Added: Animation Features (Delays/reverse playing/etc) - Added: Joystick can now work when no window is focused (per window setting) - Changed: BitUtil functions to with better names. --- .../speiger/src/coreengine/NewInputTest.java | 1 - .../speiger/src/coreengine/math/BitUtil.java | 36 ++++++++----------- .../src/coreengine/math/MathUtils.java | 12 +++---- .../src/coreengine/math/ShapeUtil.java | 2 +- .../math/collision2d/I2DCollision.java | 2 +- .../rendering/gui/animation/GuiAnimation.java | 2 +- .../rendering/gui/animation/IAction.java | 35 +++++++++++++++++- .../rendering/input/devices/Joystick.java | 24 +++++++++++-- .../textures/base/TextureMetadata.java | 4 +-- .../textures/custom/DynamicTexture.java | 2 +- .../texturesOld/normal/DynamicTexture.java | 4 +-- 11 files changed, 84 insertions(+), 40 deletions(-) diff --git a/src/main/java/speiger/src/coreengine/NewInputTest.java b/src/main/java/speiger/src/coreengine/NewInputTest.java index 6c9155f..d6a08a6 100644 --- a/src/main/java/speiger/src/coreengine/NewInputTest.java +++ b/src/main/java/speiger/src/coreengine/NewInputTest.java @@ -29,7 +29,6 @@ public class NewInputTest { manager.addDevices(Mouse.INSTANCE, Keyboard.INSTANCE, Joystick.INSTANCE, FileDrop.INSTANCE); Window window = manager.builder().title("Testing Engine").build(); window.visible(true); - //TODO implement window close requests while(!window.shouldClose()) { GLFW.glfwPollEvents(); window.beginFrame(); diff --git a/src/main/java/speiger/src/coreengine/math/BitUtil.java b/src/main/java/speiger/src/coreengine/math/BitUtil.java index a94e374..c58386d 100644 --- a/src/main/java/speiger/src/coreengine/math/BitUtil.java +++ b/src/main/java/speiger/src/coreengine/math/BitUtil.java @@ -1,42 +1,36 @@ package speiger.src.coreengine.math; -import speiger.src.coreengine.math.vector.ints.Vec2i; - public class BitUtil { - public static long toLong(long firstShort, long secondShort) { - return (firstShort << 32) | (secondShort & 0xFFFFFFFFL); + public static long toLong(long key, long value) { + return (key << 32L) | (value & 0xFFFFFFFFL); } - public static int toFirstInt(long value) { + public static int intKey(long value) { return (int)((value >> 32) & 0xFFFFFFFFL); } - public static int toSecondInt(long value) { - return (int)(value & 0xFFFFFFFFL); + public static int intValue(long value) { + return (int)(value & 0xFFFFFFFFL); + } + + public static long intAdd(long source, long key, long value) { + return toLong(key + intKey(source), value + intValue(source)); } - public static long addToLong(long value, long x, long z) { - return ((x + toFirstInt(value)) & 0xFFFFFFFFL) << 32 | (((z + toSecondInt(value)) & 0xFFFFFFFFL)); + public static int toInt(int key, int value) { + return (key & 0xFFFF) << 16 | (value & 0xFFFF); } - public static int toInt(int firstShort, int secondShort) { - return (firstShort & 0xFFFF) << 16 | (secondShort & 0xFFFF); - } - - public static int toFirstShort(int value) { + public static int shortKey(int value) { return (short)(value >> 16 & 0xFFFF); } - public static int toSecondShort(int value) { + public static int shortValue(int value) { return (short)(value & 0xFFFF); } - public static int addToInt(int value, int x, int z) { - return ((x + toFirstShort(value)) & 0xFFFF) << 16 | ((z + toSecondShort(value)) & 0xFFFF); - } - - public static int addToInt(int value, Vec2i offset) { - return ((offset.x() + toFirstShort(value)) & 0xFFFF) << 16 | ((offset.y() + toSecondShort(value)) & 0xFFFF); + public static int shortAdd(int source, int key, int value) { + return toInt(key + shortKey(source), value + shortValue(source)); } public static int pack_2_10_10_10_int_rev(float x, float y, float z, float w) { diff --git a/src/main/java/speiger/src/coreengine/math/MathUtils.java b/src/main/java/speiger/src/coreengine/math/MathUtils.java index eede175..c4e62a8 100644 --- a/src/main/java/speiger/src/coreengine/math/MathUtils.java +++ b/src/main/java/speiger/src/coreengine/math/MathUtils.java @@ -48,27 +48,27 @@ public class MathUtils { } public static byte sign(byte value) { - return value > 0 ? 1 : (value < 0 ? -1 : (byte)0); + return (byte)Integer.signum(value); } public static short sign(short value) { - return value > 0 ? 1 : (value < 0 ? -1 : (short)0); + return (short)Integer.signum(value); } public static int sign(int value) { - return value > 0 ? 1 : (value < 0 ? -1 : 0); + return Integer.signum(value); } public static long sign(long value) { - return value > 0 ? 1 : (value < 0 ? -1 : 0); + return Long.signum(value); } public static float sign(float value) { - return value > 0 ? 1F : (value < 0 ? -1F : 0F); + return Math.signum(value); } public static double sign(double value) { - return value > 0 ? 1D : (value < 0 ? -1D : 0D); + return Math.signum(value); } public static int sub(int key, int value) { diff --git a/src/main/java/speiger/src/coreengine/math/ShapeUtil.java b/src/main/java/speiger/src/coreengine/math/ShapeUtil.java index 7f2bfee..4beffe4 100644 --- a/src/main/java/speiger/src/coreengine/math/ShapeUtil.java +++ b/src/main/java/speiger/src/coreengine/math/ShapeUtil.java @@ -4,7 +4,7 @@ import speiger.src.coreengine.math.vector.ints.Vec2i; public class ShapeUtil { public static boolean isInCircle(int position, int radius, int testX, int testZ) { - return isInCircle(BitUtil.toFirstShort(position), BitUtil.toSecondShort(position), radius, testX, testZ); + return isInCircle(BitUtil.shortKey(position), BitUtil.shortValue(position), radius, testX, testZ); } public static boolean isInCircle(Vec2i position, int radius, int testX, int testZ) { diff --git a/src/main/java/speiger/src/coreengine/math/collision2d/I2DCollision.java b/src/main/java/speiger/src/coreengine/math/collision2d/I2DCollision.java index 7f41120..4a4bb7c 100644 --- a/src/main/java/speiger/src/coreengine/math/collision2d/I2DCollision.java +++ b/src/main/java/speiger/src/coreengine/math/collision2d/I2DCollision.java @@ -6,7 +6,7 @@ import speiger.src.coreengine.math.vector.ints.Vec2i; public interface I2DCollision extends Iterable { public default boolean isMixedCollision() {return false;} - public default boolean isColliding(int position){return isColliding(BitUtil.toFirstShort(position), BitUtil.toSecondShort(position));} + public default boolean isColliding(int position){return isColliding(BitUtil.shortKey(position), BitUtil.shortValue(position));} public default boolean isColliding(Vec2i pos){return isColliding(pos.x(), pos.y());} public boolean isColliding(int x, int y); } diff --git a/src/main/java/speiger/src/coreengine/rendering/gui/animation/GuiAnimation.java b/src/main/java/speiger/src/coreengine/rendering/gui/animation/GuiAnimation.java index 0d58032..5beaea5 100644 --- a/src/main/java/speiger/src/coreengine/rendering/gui/animation/GuiAnimation.java +++ b/src/main/java/speiger/src/coreengine/rendering/gui/animation/GuiAnimation.java @@ -26,7 +26,7 @@ public class GuiAnimation { public void apply(GuiComponent owner, float progress) { for(Entry entry : Object2ObjectMaps.fastIterable(actions)) { IAction action = entry.getValue(); - action.apply(entry.getKey(), Math.min(progress, action.duration())); + action.apply(entry.getKey(), owner, Math.min(progress, action.duration())); } } diff --git a/src/main/java/speiger/src/coreengine/rendering/gui/animation/IAction.java b/src/main/java/speiger/src/coreengine/rendering/gui/animation/IAction.java index a1b62ec..0ee0662 100644 --- a/src/main/java/speiger/src/coreengine/rendering/gui/animation/IAction.java +++ b/src/main/java/speiger/src/coreengine/rendering/gui/animation/IAction.java @@ -1,8 +1,41 @@ package speiger.src.coreengine.rendering.gui.animation; import speiger.src.coreengine.rendering.gui.animation.GuiAnimation.Target; +import speiger.src.coreengine.rendering.gui.components.base.GuiComponent; public interface IAction { public float duration(); - public void apply(Target target, float progress); + public void apply(Target target, GuiComponent component, float progress); + public default IAction withPreDelay(float delay) { return this instanceof PreDelayedAction delayed ? new PreDelayedAction(delayed.action(), delay + delayed.delay()) : new PreDelayedAction(this, delay); } + public default IAction withPostDelay(float delay) { return this instanceof PostDelayedAction delayed ? new PostDelayedAction(delayed.action(), delay + delayed.delay()) : new PostDelayedAction(this, delay); } + public default IAction reverse() { return this instanceof ReversedAction reversed ? reversed.action() : new ReversedAction(this); } + + public record PreDelayedAction(IAction action, float delay) implements IAction { + @Override + public float duration() { return delay + action.duration(); } + @Override + public void apply(Target target, GuiComponent component, float progress) { + action.apply(target, component, Math.max(progress - delay, 0F)); + } + } + + public record PostDelayedAction(IAction action, float delay) implements IAction { + @Override + public float duration() { return action.duration() + delay; } + @Override + public void apply(Target target, GuiComponent component, float progress) { + action.apply(target, component, Math.min(progress, action.duration())); + } + } + + public record ReversedAction(IAction action) implements IAction { + @Override + public float duration() { return action.duration(); } + @Override + public void apply(Target target, GuiComponent component, float progress) { + action.apply(target, component, action.duration() - progress); + } + } + + } \ No newline at end of file diff --git a/src/main/java/speiger/src/coreengine/rendering/input/devices/Joystick.java b/src/main/java/speiger/src/coreengine/rendering/input/devices/Joystick.java index 91b4702..9f01bd6 100644 --- a/src/main/java/speiger/src/coreengine/rendering/input/devices/Joystick.java +++ b/src/main/java/speiger/src/coreengine/rendering/input/devices/Joystick.java @@ -14,6 +14,8 @@ import speiger.src.collections.ints.maps.interfaces.Int2ObjectMap; import speiger.src.collections.ints.sets.IntLinkedOpenHashSet; import speiger.src.collections.ints.sets.IntSet; import speiger.src.collections.longs.collections.LongIterator; +import speiger.src.collections.longs.sets.LongOpenHashSet; +import speiger.src.collections.longs.sets.LongSet; import speiger.src.coreengine.rendering.input.devices.Joystick.JoyStickData; import speiger.src.coreengine.rendering.input.devices.Joystick.JoyStickTask; import speiger.src.coreengine.rendering.input.events.JoystickEvent; @@ -24,6 +26,7 @@ public class Joystick extends AbstractDevice { public static final Joystick INSTANCE = new Joystick(); WindowManager manager; IntSet presentJoysticks = new IntLinkedOpenHashSet(); + LongSet alwaysProcessInputs = new LongOpenHashSet(); public void init(WindowManager manager, EventBus bus) { this.manager = manager; @@ -31,7 +34,7 @@ public class Joystick extends AbstractDevice { manager.addCallback(this::plugin, GLFW::glfwSetJoystickCallback); for(int i = 0,m=GLFW.GLFW_JOYSTICK_LAST;i<=m;i++) { if(GLFW.glfwJoystickPresent(i)) { - presentJoysticks.add(i); + plugin(i, GLFW.GLFW_CONNECTED); } } } @@ -39,6 +42,15 @@ public class Joystick extends AbstractDevice { @Override public void init(EventBus bus) { throw new UnsupportedOperationException("Use init(WindowManager, EventBus) instead"); } + public void setWindowAlwaysProcessInputs(long windowId, boolean value) { + if(value) alwaysProcessInputs.add(windowId); + else alwaysProcessInputs.remove(windowId); + } + + public boolean isWindowAlwaysProcessingInputs(long windowId) { + return alwaysProcessInputs.contains(windowId); + } + private void plugin(int jid, int event) { if(event == GLFW.GLFW_CONNECTED) presentJoysticks.add(jid); else presentJoysticks.remove(jid); @@ -51,14 +63,14 @@ public class Joystick extends AbstractDevice { @Override public void reset(long windowId) {} @Override - protected JoyStickData createData(long windowId) { return new JoyStickData(); } + protected JoyStickData createData(long windowId) { return new JoyStickData(presentJoysticks); } @Override protected void process(JoyStickTask task) { task.process(this); } @Override public void processInput(long windowId) { super.processInput(windowId); - if(manager.getActiveWindow() != windowId) return; + if(manager.getActiveWindow() != windowId && !alwaysProcessInputs.contains(windowId)) return; JoyStickData data = get(windowId); if(data == null) return; for(IntIterator iter = presentJoysticks.iterator();iter.hasNext();) { @@ -97,6 +109,12 @@ public class Joystick extends AbstractDevice { public static class JoyStickData { Int2ObjectMap data = new Int2ObjectOpenHashMap<>(); + + public JoyStickData(IntSet knownJoysticks) { + for(IntIterator iter = knownJoysticks.iterator();iter.hasNext();) { + data.put(iter.nextInt(), new ButtonData()); + } + } } public static class ButtonData { diff --git a/src/main/java/speiger/src/coreengine/rendering/textures/base/TextureMetadata.java b/src/main/java/speiger/src/coreengine/rendering/textures/base/TextureMetadata.java index 5b62bd7..3698f6a 100644 --- a/src/main/java/speiger/src/coreengine/rendering/textures/base/TextureMetadata.java +++ b/src/main/java/speiger/src/coreengine/rendering/textures/base/TextureMetadata.java @@ -23,7 +23,7 @@ public class TextureMetadata { public void applyArguments(int texture) { for(int i = 0,m=arguments.size();i values = iter.next(); int key = values.getIntKey(); - int chunkX = BitUtil.toFirstShort(key) * 16; - int chunkZ = BitUtil.toSecondShort(key) * 16; + int chunkX = BitUtil.shortKey(key) * 16; + int chunkZ = BitUtil.shortValue(key) * 16; int width = 0; int height = 0; for(IntIterator subIt = values.getValue().iterator();subIt.hasNext();)