aboutsummaryrefslogtreecommitdiff
path: root/core/src/main/java/coffee/liz/abstractionengine
diff options
context:
space:
mode:
Diffstat (limited to 'core/src/main/java/coffee/liz/abstractionengine')
-rw-r--r--core/src/main/java/coffee/liz/abstractionengine/AbstractionEngineGridWorld.java32
-rw-r--r--core/src/main/java/coffee/liz/abstractionengine/app/AbstractionEngineGame.java64
-rw-r--r--core/src/main/java/coffee/liz/abstractionengine/app/Theme.java34
-rw-r--r--core/src/main/java/coffee/liz/abstractionengine/app/actor/Abstraction.java59
-rw-r--r--core/src/main/java/coffee/liz/abstractionengine/app/actor/Button.java176
-rw-r--r--core/src/main/java/coffee/liz/abstractionengine/app/actor/GridBoardActor.java68
-rw-r--r--core/src/main/java/coffee/liz/abstractionengine/app/actor/LifeGridActor.java154
-rw-r--r--core/src/main/java/coffee/liz/abstractionengine/app/actor/Logo.java58
-rw-r--r--core/src/main/java/coffee/liz/abstractionengine/app/actor/Penguin.java160
-rw-r--r--core/src/main/java/coffee/liz/abstractionengine/app/actor/Player.java22
-rw-r--r--core/src/main/java/coffee/liz/abstractionengine/app/actor/Wall.java22
-rw-r--r--core/src/main/java/coffee/liz/abstractionengine/app/config/KeyBinds.java42
-rw-r--r--core/src/main/java/coffee/liz/abstractionengine/app/config/Settings.java16
-rw-r--r--core/src/main/java/coffee/liz/abstractionengine/app/life/CellState.java54
-rw-r--r--core/src/main/java/coffee/liz/abstractionengine/app/life/EntropyAudioSystem.java226
-rw-r--r--core/src/main/java/coffee/liz/abstractionengine/app/life/LifeInput.java4
-rw-r--r--core/src/main/java/coffee/liz/abstractionengine/app/life/LifeSystem.java122
-rw-r--r--core/src/main/java/coffee/liz/abstractionengine/app/screen/GameScreen.java86
-rw-r--r--core/src/main/java/coffee/liz/abstractionengine/app/screen/MainMenu.java228
-rw-r--r--core/src/main/java/coffee/liz/abstractionengine/app/screen/ScrollLogo.java228
-rw-r--r--core/src/main/java/coffee/liz/abstractionengine/app/screen/game/FrameState.java4
-rw-r--r--core/src/main/java/coffee/liz/abstractionengine/app/screen/game/GameScreenWorld.java12
-rw-r--r--core/src/main/java/coffee/liz/abstractionengine/app/screen/game/component/ActorHolder.java (renamed from core/src/main/java/coffee/liz/abstractionengine/app/screen/game/component/GridEntityRef.java)7
-rw-r--r--core/src/main/java/coffee/liz/abstractionengine/app/screen/game/component/ExternalWorldEntityRef.java12
-rw-r--r--core/src/main/java/coffee/liz/abstractionengine/app/screen/game/component/InterpolatedPosition.java18
-rw-r--r--core/src/main/java/coffee/liz/abstractionengine/app/screen/game/system/GameWorldManagementSystem.java100
-rw-r--r--core/src/main/java/coffee/liz/abstractionengine/app/screen/game/system/GridInterpolationSystem.java74
-rw-r--r--core/src/main/java/coffee/liz/abstractionengine/app/screen/game/system/GridWorldBridgeSystem.java119
-rw-r--r--core/src/main/java/coffee/liz/abstractionengine/app/screen/game/system/InputSystem.java104
-rw-r--r--core/src/main/java/coffee/liz/abstractionengine/app/screen/game/system/RenderSystem.java128
-rw-r--r--core/src/main/java/coffee/liz/abstractionengine/app/ui/editor/CursorStyle.java2
-rw-r--r--core/src/main/java/coffee/liz/abstractionengine/app/ui/editor/EditorModifier.java2
-rw-r--r--core/src/main/java/coffee/liz/abstractionengine/app/ui/editor/EditorTextArea.java434
-rw-r--r--core/src/main/java/coffee/liz/abstractionengine/app/ui/editor/InputStrategy.java10
-rw-r--r--core/src/main/java/coffee/liz/abstractionengine/app/ui/editor/KeyEvent.java6
-rw-r--r--core/src/main/java/coffee/liz/abstractionengine/app/ui/editor/LambdaEditor.java94
-rw-r--r--core/src/main/java/coffee/liz/abstractionengine/app/ui/editor/LineNumberMode.java2
-rw-r--r--core/src/main/java/coffee/liz/abstractionengine/app/ui/editor/RenderState.java2
-rw-r--r--core/src/main/java/coffee/liz/abstractionengine/app/ui/editor/vim/EditorBuffer.java18
-rw-r--r--core/src/main/java/coffee/liz/abstractionengine/app/ui/editor/vim/Mode.java2
-rw-r--r--core/src/main/java/coffee/liz/abstractionengine/app/ui/editor/vim/VimConfig.java56
-rw-r--r--core/src/main/java/coffee/liz/abstractionengine/app/ui/editor/vim/VimEngine.java286
-rw-r--r--core/src/main/java/coffee/liz/abstractionengine/app/ui/editor/vim/buffer/TextAreaBuffer.java92
-rw-r--r--core/src/main/java/coffee/liz/abstractionengine/app/ui/editor/vim/context/KeyContext.java1172
-rw-r--r--core/src/main/java/coffee/liz/abstractionengine/app/ui/editor/vim/handler/CommandAction.java2
-rw-r--r--core/src/main/java/coffee/liz/abstractionengine/app/ui/editor/vim/handler/HandleResult.java42
-rw-r--r--core/src/main/java/coffee/liz/abstractionengine/app/ui/editor/vim/handler/InsertModeHandler.java28
-rw-r--r--core/src/main/java/coffee/liz/abstractionengine/app/ui/editor/vim/handler/ModeHandler.java4
-rw-r--r--core/src/main/java/coffee/liz/abstractionengine/app/ui/editor/vim/handler/MotionAction.java2
-rw-r--r--core/src/main/java/coffee/liz/abstractionengine/app/ui/editor/vim/handler/NormalModeHandler.java582
-rw-r--r--core/src/main/java/coffee/liz/abstractionengine/app/ui/editor/vim/handler/SearchModeHandler.java56
-rw-r--r--core/src/main/java/coffee/liz/abstractionengine/app/ui/editor/vim/handler/VisualLineModeHandler.java146
-rw-r--r--core/src/main/java/coffee/liz/abstractionengine/app/ui/editor/vim/handler/VisualModeHandler.java226
-rw-r--r--core/src/main/java/coffee/liz/abstractionengine/app/ui/editor/vim/model/Register.java4
-rw-r--r--core/src/main/java/coffee/liz/abstractionengine/app/ui/editor/vim/model/RegisterType.java2
-rw-r--r--core/src/main/java/coffee/liz/abstractionengine/app/ui/editor/vim/model/UndoManager.java74
-rw-r--r--core/src/main/java/coffee/liz/abstractionengine/app/ui/editor/vim/model/UndoState.java4
-rw-r--r--core/src/main/java/coffee/liz/abstractionengine/app/ui/editor/vim/navigation/TextNavigation.java186
-rw-r--r--core/src/main/java/coffee/liz/abstractionengine/app/ui/editor/vim/search/SearchDirection.java2
-rw-r--r--core/src/main/java/coffee/liz/abstractionengine/app/ui/editor/vim/search/SearchIterator.java96
-rw-r--r--core/src/main/java/coffee/liz/abstractionengine/app/ui/editor/vim/state/ModeState.java18
-rw-r--r--core/src/main/java/coffee/liz/abstractionengine/app/ui/editor/vim/state/NormalState.java2
-rw-r--r--core/src/main/java/coffee/liz/abstractionengine/app/ui/editor/vim/state/PendingOperator.java2
-rw-r--r--core/src/main/java/coffee/liz/abstractionengine/app/ui/editor/vim/state/SearchState.java10
-rw-r--r--core/src/main/java/coffee/liz/abstractionengine/app/ui/editor/vim/state/VisualLineState.java2
-rw-r--r--core/src/main/java/coffee/liz/abstractionengine/app/ui/editor/vim/state/VisualState.java2
-rw-r--r--core/src/main/java/coffee/liz/abstractionengine/app/ui/editor/vim/status/StatusFormatter.java80
-rw-r--r--core/src/main/java/coffee/liz/abstractionengine/app/utils/FontHelper.java36
-rw-r--r--core/src/main/java/coffee/liz/abstractionengine/app/utils/FunctionUtils.java44
-rw-r--r--core/src/main/java/coffee/liz/abstractionengine/app/utils/TimerUtils.java34
-rw-r--r--core/src/main/java/coffee/liz/abstractionengine/entity/EntityFactory.java118
-rw-r--r--core/src/main/java/coffee/liz/abstractionengine/entity/EntityType.java74
-rw-r--r--core/src/main/java/coffee/liz/abstractionengine/entity/EntityTypeGridCollidable.java8
-rw-r--r--core/src/main/java/coffee/liz/abstractionengine/grid/component/GridCollidable.java94
-rw-r--r--core/src/main/java/coffee/liz/abstractionengine/grid/component/GridInputState.java30
-rw-r--r--core/src/main/java/coffee/liz/abstractionengine/grid/component/GridMomentum.java6
-rw-r--r--core/src/main/java/coffee/liz/abstractionengine/grid/component/GridPosition.java2
-rw-r--r--core/src/main/java/coffee/liz/abstractionengine/grid/system/BaseGridIndexSystem.java54
-rw-r--r--core/src/main/java/coffee/liz/abstractionengine/grid/system/GridCollisionPropagatationSystem.java130
-rw-r--r--core/src/main/java/coffee/liz/abstractionengine/grid/system/GridIndexSystem.java6
-rw-r--r--core/src/main/java/coffee/liz/abstractionengine/grid/system/GridMovementSystem.java18
-rw-r--r--core/src/main/java/coffee/liz/abstractionengine/grid/system/GridPhysicsSystem.java26
82 files changed, 3469 insertions, 3394 deletions
diff --git a/core/src/main/java/coffee/liz/abstractionengine/AbstractionEngineGridWorld.java b/core/src/main/java/coffee/liz/abstractionengine/AbstractionEngineGridWorld.java
index c6e7a49..806d05e 100644
--- a/core/src/main/java/coffee/liz/abstractionengine/AbstractionEngineGridWorld.java
+++ b/core/src/main/java/coffee/liz/abstractionengine/AbstractionEngineGridWorld.java
@@ -16,21 +16,21 @@ import java.util.Map;
/** Grid world implementation for the abstraction engine. */
@Log4j2
public class AbstractionEngineGridWorld extends DAGWorld<GridInputState> {
- /** Initialize world with systems and player. */
- public AbstractionEngineGridWorld(final Vec2<Integer> gridDimensions) {
- super(Map.of(GridMovementSystem.class, new GridMovementSystem(), GridPhysicsSystem.class,
- new GridPhysicsSystem(), GridIndexSystem.class, new GridIndexSystem(gridDimensions),
- GridCollisionPropagatationSystem.class, new GridCollisionPropagatationSystem()));
- }
+ /** Initialize world with systems and player. */
+ public AbstractionEngineGridWorld(final Vec2<Integer> gridDimensions) {
+ super(Map.of(GridMovementSystem.class, new GridMovementSystem(), GridPhysicsSystem.class,
+ new GridPhysicsSystem(), GridIndexSystem.class, new GridIndexSystem(gridDimensions),
+ GridCollisionPropagatationSystem.class, new GridCollisionPropagatationSystem()));
+ }
- /**
- * Update world with input state. For now our grid world is a "step function",
- * so we shouldn't (yet) care about the amount of time between steps.
- *
- * @param state
- * the {@link GridInputState}
- */
- public void update(final GridInputState state) {
- update(state, Duration.ZERO);
- }
+ /**
+ * Update world with input state. For now our grid world is a "step function",
+ * so we shouldn't (yet) care about the amount of time between steps.
+ *
+ * @param state
+ * the {@link GridInputState}
+ */
+ public void update(final GridInputState state) {
+ update(state, Duration.ZERO);
+ }
}
diff --git a/core/src/main/java/coffee/liz/abstractionengine/app/AbstractionEngineGame.java b/core/src/main/java/coffee/liz/abstractionengine/app/AbstractionEngineGame.java
index 9aa61ec..d0ba1f3 100644
--- a/core/src/main/java/coffee/liz/abstractionengine/app/AbstractionEngineGame.java
+++ b/core/src/main/java/coffee/liz/abstractionengine/app/AbstractionEngineGame.java
@@ -13,42 +13,42 @@ import com.badlogic.gdx.graphics.glutils.ShapeRenderer;
import com.badlogic.gdx.utils.viewport.FitViewport;
public class AbstractionEngineGame extends Game {
- public static final Vec2<Float> WORLD_SIZE = Vec2f.builder().x(800f).y(800f).build();
+ public static final Vec2<Float> WORLD_SIZE = Vec2f.builder().x(800f).y(800f).build();
- public SpriteBatch batch;
- public BitmapFont font;
- public FitViewport viewport;
- public ShapeRenderer shapeRenderer;
- public Settings settings = Settings.builder().build();
+ public SpriteBatch batch;
+ public BitmapFont font;
+ public FitViewport viewport;
+ public ShapeRenderer shapeRenderer;
+ public Settings settings = Settings.builder().build();
- /**
- * Game initialization hook.
- */
- public void create() {
- viewport = new FitViewport(WORLD_SIZE.getX(), WORLD_SIZE.getY());
- batch = new SpriteBatch();
- shapeRenderer = new ShapeRenderer();
- font = FontHelper.initFont(24, FontHelper.MONO,
- AbstractionEngineGame.WORLD_SIZE.getY() / Gdx.graphics.getHeight());
+ /**
+ * Game initialization hook.
+ */
+ public void create() {
+ viewport = new FitViewport(WORLD_SIZE.getX(), WORLD_SIZE.getY());
+ batch = new SpriteBatch();
+ shapeRenderer = new ShapeRenderer();
+ font = FontHelper.initFont(24, FontHelper.MONO,
+ AbstractionEngineGame.WORLD_SIZE.getY() / Gdx.graphics.getHeight());
- this.setScreen(new ScrollLogo(this));
+ this.setScreen(new ScrollLogo(this));
- viewport.update(Gdx.graphics.getWidth(), Gdx.graphics.getHeight(), true);
- }
+ viewport.update(Gdx.graphics.getWidth(), Gdx.graphics.getHeight(), true);
+ }
- /**
- * Game render hook.
- */
- public void render() {
- super.render();
- }
+ /**
+ * Game render hook.
+ */
+ public void render() {
+ super.render();
+ }
- /**
- * Game cleanup hook.
- */
- public void dispose() {
- batch.dispose();
- font.dispose();
- shapeRenderer.dispose();
- }
+ /**
+ * Game cleanup hook.
+ */
+ public void dispose() {
+ batch.dispose();
+ font.dispose();
+ shapeRenderer.dispose();
+ }
}
diff --git a/core/src/main/java/coffee/liz/abstractionengine/app/Theme.java b/core/src/main/java/coffee/liz/abstractionengine/app/Theme.java
index bc653fd..1d3f449 100644
--- a/core/src/main/java/coffee/liz/abstractionengine/app/Theme.java
+++ b/core/src/main/java/coffee/liz/abstractionengine/app/Theme.java
@@ -4,26 +4,26 @@ import com.badlogic.gdx.graphics.Color;
// TODO: Make this part of the {@link Settings}
public final class Theme {
- public static final Color BG = Color.valueOf("2d2523");
- public static final Color BG_PATTERN = Color.valueOf("241e1c");
- public static final Color SURFACE = Color.valueOf("3b312f");
- public static final Color SURFACE_ALT = Color.valueOf("463a37");
+ public static final Color BG = Color.valueOf("2d2523");
+ public static final Color BG_PATTERN = Color.valueOf("241e1c");
+ public static final Color SURFACE = Color.valueOf("3b312f");
+ public static final Color SURFACE_ALT = Color.valueOf("463a37");
- public static final Color FG = Color.valueOf("f9efea");
- public static final Color MUTED = Color.valueOf("cbb8b1");
+ public static final Color FG = Color.valueOf("f9efea");
+ public static final Color MUTED = Color.valueOf("cbb8b1");
- public static final Color BORDER = Color.valueOf("f1e6e0");
- public static final Color BORDER_LIGHT = Color.valueOf("6e5b57");
- public static final Color BORDER_DARK = Color.valueOf("120d0c");
+ public static final Color BORDER = Color.valueOf("f1e6e0");
+ public static final Color BORDER_LIGHT = Color.valueOf("6e5b57");
+ public static final Color BORDER_DARK = Color.valueOf("120d0c");
- public static final Color PRIMARY = Color.valueOf("f06aa6");
- public static final Color PRIMARY_LIGHT = Color.valueOf("ff97c8");
- public static final Color PRIMARY_DARK = Color.valueOf("d94b8e");
+ public static final Color PRIMARY = Color.valueOf("f06aa6");
+ public static final Color PRIMARY_LIGHT = Color.valueOf("ff97c8");
+ public static final Color PRIMARY_DARK = Color.valueOf("d94b8e");
- public static final Color SECONDARY = Color.valueOf("b69cff");
- public static final Color SECONDARY_LIGHT = Color.valueOf("d7c8ff");
- public static final Color SECONDARY_DARK = Color.valueOf("8f78d6");
+ public static final Color SECONDARY = Color.valueOf("b69cff");
+ public static final Color SECONDARY_LIGHT = Color.valueOf("d7c8ff");
+ public static final Color SECONDARY_DARK = Color.valueOf("8f78d6");
- private Theme() {
- }
+ private Theme() {
+ }
}
diff --git a/core/src/main/java/coffee/liz/abstractionengine/app/actor/Abstraction.java b/core/src/main/java/coffee/liz/abstractionengine/app/actor/Abstraction.java
new file mode 100644
index 0000000..5c964a2
--- /dev/null
+++ b/core/src/main/java/coffee/liz/abstractionengine/app/actor/Abstraction.java
@@ -0,0 +1,59 @@
+package coffee.liz.abstractionengine.app.actor;
+
+import coffee.liz.ecs.math.Vec2;
+import coffee.liz.ecs.math.Vec2i;
+import com.badlogic.gdx.Gdx;
+import com.badlogic.gdx.graphics.Color;
+import com.badlogic.gdx.graphics.Texture;
+import com.badlogic.gdx.graphics.g2d.Animation;
+import com.badlogic.gdx.graphics.g2d.Batch;
+import com.badlogic.gdx.graphics.g2d.TextureRegion;
+import com.badlogic.gdx.scenes.scene2d.Actor;
+import lombok.Getter;
+
+public class Abstraction extends Actor {
+ private static final Vec2<Integer> ABSTRACTION_FRAMES = Vec2i.builder().x(1).y(4).build();
+
+ private final Texture texture;
+ @Getter
+ private final Animation<TextureRegion> animation;
+ private float stateTime = 0f;
+
+ /**
+ * Creates a penguin actor.
+ */
+ public Abstraction() {
+ this.texture = new Texture(Gdx.files.internal("sprites/abstraction.png"));
+ final TextureRegion[][] tmp = TextureRegion.split(texture, texture.getWidth() / ABSTRACTION_FRAMES.getX(),
+ texture.getHeight() / ABSTRACTION_FRAMES.getY());
+ final TextureRegion[] anim = {
+ tmp[0][0],
+ tmp[1][0],
+ tmp[2][0],
+ tmp[3][0]
+ };
+ this.animation = new Animation<>(0.25f, anim);
+ }
+
+ /**
+ * Actor draw hook.
+ *
+ * @param batch
+ * parent batch
+ * @param parentAlpha
+ * parent alpha multiplier
+ */
+ @Override
+ public void draw(final Batch batch, final float parentAlpha) {
+ final TextureRegion frame = this.animation.getKeyFrame(stateTime, true);
+ final Color c = getColor();
+ batch.setColor(c.r, c.g, c.b, c.a * parentAlpha);
+ batch.draw(frame, getX(), getY(), getWidth(), getHeight());
+ }
+
+ @Override
+ public void act(final float delta) {
+ super.act(delta);
+ stateTime += delta;
+ }
+}
diff --git a/core/src/main/java/coffee/liz/abstractionengine/app/actor/Button.java b/core/src/main/java/coffee/liz/abstractionengine/app/actor/Button.java
index a7416b9..271e40f 100644
--- a/core/src/main/java/coffee/liz/abstractionengine/app/actor/Button.java
+++ b/core/src/main/java/coffee/liz/abstractionengine/app/actor/Button.java
@@ -17,110 +17,110 @@ import lombok.Setter;
@RequiredArgsConstructor
public class Button extends Actor {
- private static final float ALPHA = 0.85f;
- private static final float BORDER_WIDTH = 1f;
+ private static final float ALPHA = 0.85f;
+ private static final float BORDER_WIDTH = 1f;
- private final ShapeRenderer shapeRenderer;
- private final BitmapFont font;
- private final String text;
+ private final ShapeRenderer shapeRenderer;
+ private final BitmapFont font;
+ private final String text;
- @Setter
- private Runnable onClick;
+ @Setter
+ private Runnable onClick;
- @Getter
- private boolean hovered = false;
- @Getter
- private boolean pressed = false;
+ @Getter
+ private boolean hovered = false;
+ @Getter
+ private boolean pressed = false;
- private final GlyphLayout layout = new GlyphLayout();
- private final Color bgColor = new Color();
- private final Color borderColor = new Color();
+ private final GlyphLayout layout = new GlyphLayout();
+ private final Color bgColor = new Color();
+ private final Color borderColor = new Color();
- /**
- * Actor draw hook.
- *
- * @param batch
- * parent batch
- * @param parentAlpha
- * parent alpha multiplier
- */
- @Override
- public void draw(final Batch batch, final float parentAlpha) {
- batch.end();
+ /**
+ * Actor draw hook.
+ *
+ * @param batch
+ * parent batch
+ * @param parentAlpha
+ * parent alpha multiplier
+ */
+ @Override
+ public void draw(final Batch batch, final float parentAlpha) {
+ batch.end();
- Gdx.gl.glEnable(GL20.GL_BLEND);
- Gdx.gl.glBlendFunc(GL20.GL_SRC_ALPHA, GL20.GL_ONE_MINUS_SRC_ALPHA);
+ Gdx.gl.glEnable(GL20.GL_BLEND);
+ Gdx.gl.glBlendFunc(GL20.GL_SRC_ALPHA, GL20.GL_ONE_MINUS_SRC_ALPHA);
- shapeRenderer.setProjectionMatrix(batch.getProjectionMatrix());
- shapeRenderer.setTransformMatrix(batch.getTransformMatrix());
+ shapeRenderer.setProjectionMatrix(batch.getProjectionMatrix());
+ shapeRenderer.setTransformMatrix(batch.getTransformMatrix());
- final float effectiveAlpha = parentAlpha * ALPHA * getColor().a;
- computeColors(effectiveAlpha);
+ final float effectiveAlpha = parentAlpha * ALPHA * getColor().a;
+ computeColors(effectiveAlpha);
- shapeRenderer.begin(ShapeRenderer.ShapeType.Filled);
- shapeRenderer.setColor(borderColor);
- shapeRenderer.rect(getX(), getY(), getWidth(), getHeight());
- shapeRenderer.setColor(bgColor);
- shapeRenderer.rect(getX() + BORDER_WIDTH, getY() + BORDER_WIDTH, getWidth() - BORDER_WIDTH * 2,
- getHeight() - BORDER_WIDTH * 2);
- shapeRenderer.end();
+ shapeRenderer.begin(ShapeRenderer.ShapeType.Filled);
+ shapeRenderer.setColor(borderColor);
+ shapeRenderer.rect(getX(), getY(), getWidth(), getHeight());
+ shapeRenderer.setColor(bgColor);
+ shapeRenderer.rect(getX() + BORDER_WIDTH, getY() + BORDER_WIDTH, getWidth() - BORDER_WIDTH * 2,
+ getHeight() - BORDER_WIDTH * 2);
+ shapeRenderer.end();
- Gdx.gl.glDisable(GL20.GL_BLEND);
+ Gdx.gl.glDisable(GL20.GL_BLEND);
- batch.begin();
+ batch.begin();
- layout.setText(font, text);
- final float textX = getX() + (getWidth() - layout.width) / 2f;
- final float textY = getY() + (getHeight() + layout.height) / 2f;
+ layout.setText(font, text);
+ final float textX = getX() + (getWidth() - layout.width) / 2f;
+ final float textY = getY() + (getHeight() + layout.height) / 2f;
- final Color textColor = hovered ? Theme.FG : Theme.MUTED;
- font.setColor(textColor.r, textColor.g, textColor.b, effectiveAlpha);
- font.draw(batch, text, textX, textY);
- }
+ final Color textColor = hovered ? Theme.FG : Theme.MUTED;
+ font.setColor(textColor.r, textColor.g, textColor.b, effectiveAlpha);
+ font.draw(batch, text, textX, textY);
+ }
- private void computeColors(final float alpha) {
- if (hovered) {
- bgColor.set(Theme.SURFACE_ALT).a = alpha;
- borderColor.set(Theme.PRIMARY).a = alpha;
- } else {
- bgColor.set(Theme.SURFACE).a = alpha;
- borderColor.set(Theme.BORDER_LIGHT).a = alpha;
- }
- }
+ private void computeColors(final float alpha) {
+ if (hovered) {
+ bgColor.set(Theme.SURFACE_ALT).a = alpha;
+ borderColor.set(Theme.PRIMARY).a = alpha;
+ } else {
+ bgColor.set(Theme.SURFACE).a = alpha;
+ borderColor.set(Theme.BORDER_LIGHT).a = alpha;
+ }
+ }
- /**
- * Enables input handling for the button.
- */
- public void addButtonListener() {
- addListener(new InputListener() {
- @Override
- public boolean touchDown(final InputEvent event, final float x, final float y, final int pointer,
- final int button) {
- pressed = true;
- return true;
- }
+ /**
+ * Enables input handling for the button.
+ */
+ public void addButtonListener() {
+ addListener(new InputListener() {
+ @Override
+ public boolean touchDown(final InputEvent event, final float x, final float y, final int pointer,
+ final int button) {
+ pressed = true;
+ return true;
+ }
- @Override
- public void touchUp(final InputEvent event, final float x, final float y, final int pointer,
- final int button) {
- if (pressed && hovered && onClick != null) {
- onClick.run();
- }
- pressed = false;
- }
+ @Override
+ public void touchUp(final InputEvent event, final float x, final float y, final int pointer,
+ final int button) {
+ if (pressed && hovered && onClick != null) {
+ onClick.run();
+ }
+ pressed = false;
+ }
- @Override
- public void enter(final InputEvent event, final float x, final float y, final int pointer,
- final Actor fromActor) {
- hovered = true;
- }
+ @Override
+ public void enter(final InputEvent event, final float x, final float y, final int pointer,
+ final Actor fromActor) {
+ hovered = true;
+ }
- @Override
- public void exit(final InputEvent event, final float x, final float y, final int pointer,
- final Actor toActor) {
- hovered = false;
- pressed = false;
- }
- });
- }
+ @Override
+ public void exit(final InputEvent event, final float x, final float y, final int pointer,
+ final Actor toActor) {
+ hovered = false;
+ pressed = false;
+ }
+ });
+ }
}
diff --git a/core/src/main/java/coffee/liz/abstractionengine/app/actor/GridBoardActor.java b/core/src/main/java/coffee/liz/abstractionengine/app/actor/GridBoardActor.java
deleted file mode 100644
index a4317e0..0000000
--- a/core/src/main/java/coffee/liz/abstractionengine/app/actor/GridBoardActor.java
+++ /dev/null
@@ -1,68 +0,0 @@
-package coffee.liz.abstractionengine.app.actor;
-
-import coffee.liz.abstractionengine.app.Theme;
-import coffee.liz.abstractionengine.entity.EntityType;
-import coffee.liz.ecs.math.Mat2;
-import coffee.liz.ecs.math.Vec2;
-import coffee.liz.ecs.math.Vec2f;
-import com.badlogic.gdx.graphics.Color;
-import com.badlogic.gdx.graphics.g2d.Batch;
-import com.badlogic.gdx.graphics.glutils.ShapeRenderer;
-import com.badlogic.gdx.scenes.scene2d.Actor;
-import lombok.RequiredArgsConstructor;
-import lombok.Setter;
-
-import java.util.List;
-
-@RequiredArgsConstructor
-public class GridBoardActor extends Actor {
- private final ShapeRenderer shapeRenderer;
- private final Vec2<Integer> gridSize;
-
- @Setter
- private Vec2<Float> cellSize;
-
- @Setter
- private List<RenderableEntity> entities = List.of();
-
- @Override
- public void draw(final Batch batch, final float parentAlpha) {
- batch.end();
-
- shapeRenderer.setProjectionMatrix(batch.getProjectionMatrix());
- shapeRenderer.setTransformMatrix(batch.getTransformMatrix());
- shapeRenderer.begin(ShapeRenderer.ShapeType.Filled);
-
- if (cellSize != null) {
- final float dotRadius = Math.min(cellSize.getX(), cellSize.getY()) * 0.07f;
- shapeRenderer.setColor(Theme.BORDER);
- Mat2.init(gridSize, pos -> {
- final Vec2<Float> center = pos.floatValue().plus(Vec2f.builder().x(0.5f).y(0.5f).build())
- .scale(cellSize);
- shapeRenderer.circle(center.getX(), center.getY(), dotRadius);
- return center;
- });
- }
-
- for (final RenderableEntity entity : entities) {
- shapeRenderer.setColor(getEntityColor(entity.entityType()));
- shapeRenderer.rect(entity.position().getX(), entity.position().getY(), entity.size().getX(),
- entity.size().getY());
- }
-
- shapeRenderer.end();
- batch.begin();
- }
-
- private static Color getEntityColor(final EntityType type) {
- return switch (type) {
- case WALL -> Theme.MUTED;
- case PLAYER -> Theme.PRIMARY;
- case ABSTRACTION -> Theme.SECONDARY;
- default -> Color.GREEN;
- };
- }
-
- public record RenderableEntity(EntityType entityType, Vec2<Float> position, Vec2<Float> size) {
- }
-}
diff --git a/core/src/main/java/coffee/liz/abstractionengine/app/actor/LifeGridActor.java b/core/src/main/java/coffee/liz/abstractionengine/app/actor/LifeGridActor.java
index ab3fcbb..c4bb5e3 100644
--- a/core/src/main/java/coffee/liz/abstractionengine/app/actor/LifeGridActor.java
+++ b/core/src/main/java/coffee/liz/abstractionengine/app/actor/LifeGridActor.java
@@ -28,92 +28,92 @@ import static com.badlogic.gdx.math.MathUtils.clamp;
@RequiredArgsConstructor
public class LifeGridActor extends Actor {
- private final ShapeRenderer shapeRenderer;
- private final World<LifeInput> world;
- private final Vec2<Integer> gridDimensions;
- private final Settings settings;
- private final Color cellColor = new Color();
+ private final ShapeRenderer shapeRenderer;
+ private final World<LifeInput> world;
+ private final Vec2<Integer> gridDimensions;
+ private final Settings settings;
+ private final Color cellColor = new Color();
- @Setter
- private Viewport viewport;
- @Setter
- private Vec2<Float> parallaxOffset = Vec2f.ZERO;
+ @Setter
+ private Viewport viewport;
+ @Setter
+ private Vec2<Float> parallaxOffset = Vec2f.ZERO;
- /**
- * Actor update hook.
- *
- * @param delta
- * time since last frame
- */
- @Override
- public void act(final float delta) {
- super.act(delta);
- if (viewport == null) {
- return;
- }
+ /**
+ * Actor update hook.
+ *
+ * @param delta
+ * time since last frame
+ */
+ @Override
+ public void act(final float delta) {
+ super.act(delta);
+ if (viewport == null) {
+ return;
+ }
- final Vec2<Float> cellSize = computeCellSize();
- final Set<Vec2<Integer>> forcedAlive = computeForcedAlive(cellSize);
- world.update(new LifeInput(forcedAlive, settings), Duration.ofMillis((int) (delta * 1000)));
- }
+ final Vec2<Float> cellSize = computeCellSize();
+ final Set<Vec2<Integer>> forcedAlive = computeForcedAlive(cellSize);
+ world.update(new LifeInput(forcedAlive, settings), Duration.ofMillis((int) (delta * 1000)));
+ }
- /**
- * Actor draw hook.
- *
- * @param batch
- * parent batch
- * @param parentAlpha
- * parent alpha multiplier
- */
- @Override
- public void draw(final Batch batch, final float parentAlpha) {
- if (viewport == null) {
- return;
- }
- batch.end();
+ /**
+ * Actor draw hook.
+ *
+ * @param batch
+ * parent batch
+ * @param parentAlpha
+ * parent alpha multiplier
+ */
+ @Override
+ public void draw(final Batch batch, final float parentAlpha) {
+ if (viewport == null) {
+ return;
+ }
+ batch.end();
- shapeRenderer.setProjectionMatrix(batch.getProjectionMatrix());
- shapeRenderer.setTransformMatrix(batch.getTransformMatrix());
- shapeRenderer.begin(ShapeRenderer.ShapeType.Filled);
- drawCells(computeCellSize());
- shapeRenderer.end();
+ shapeRenderer.setProjectionMatrix(batch.getProjectionMatrix());
+ shapeRenderer.setTransformMatrix(batch.getTransformMatrix());
+ shapeRenderer.begin(ShapeRenderer.ShapeType.Filled);
+ drawCells(computeCellSize());
+ shapeRenderer.end();
- batch.begin();
- }
+ batch.begin();
+ }
- private Vec2<Float> computeCellSize() {
- return Vec2f.builder().x(viewport.getWorldWidth() / gridDimensions.getX())
- .y(viewport.getWorldHeight() / gridDimensions.getY()).build();
- }
+ private Vec2<Float> computeCellSize() {
+ return Vec2f.builder().x(viewport.getWorldWidth() / gridDimensions.getX())
+ .y(viewport.getWorldHeight() / gridDimensions.getY()).build();
+ }
- private Set<Vec2<Integer>> computeForcedAlive(final Vec2<Float> cellSize) {
- final Vector3 cursorPosition = viewport.unproject(new Vector3(Gdx.input.getX(), Gdx.input.getY(), 0));
- final Vec2<Integer> gridPosition = Vec2f.builder().x(cursorPosition.x).y(cursorPosition.y).build()
- .transform(x -> clamp(x, 0.0f, viewport.getWorldWidth() - 0.001f),
- y -> clamp(y, 0.0f, viewport.getWorldHeight() - 0.001f))
- .scale(cellSize.transform(x -> 1 / x, y -> 1 / y)).intValue();
- return Stream.of(gridPosition)
- .flatMap(pos -> Stream.of(Vec2i.ZERO, Vec2i.EAST, Vec2i.WEST, Vec2i.NORTH, Vec2i.SOUTH).map(pos::plus))
- .collect(Collectors.toSet());
- }
+ private Set<Vec2<Integer>> computeForcedAlive(final Vec2<Float> cellSize) {
+ final Vector3 cursorPosition = viewport.unproject(new Vector3(Gdx.input.getX(), Gdx.input.getY(), 0));
+ final Vec2<Integer> gridPosition = Vec2f.builder().x(cursorPosition.x).y(cursorPosition.y).build()
+ .transform(x -> clamp(x, 0.0f, viewport.getWorldWidth() - 0.001f),
+ y -> clamp(y, 0.0f, viewport.getWorldHeight() - 0.001f))
+ .scale(cellSize.transform(x -> 1 / x, y -> 1 / y)).intValue();
+ return Stream.of(gridPosition)
+ .flatMap(pos -> Stream.of(Vec2i.ZERO, Vec2i.EAST, Vec2i.WEST, Vec2i.NORTH, Vec2i.SOUTH).map(pos::plus))
+ .collect(Collectors.toSet());
+ }
- private void drawCells(final Vec2<Float> cellSize) {
- world.query(Set.of(GridPosition.class, CellState.class)).forEach(entity -> {
- final CellState state = entity.get(CellState.class);
- final Vec2<Integer> gridPos = entity.get(GridPosition.class).getPosition();
- final Vec2<Float> drawPos = gridPos.floatValue().scale(cellSize).plus(parallaxOffset);
+ private void drawCells(final Vec2<Float> cellSize) {
+ world.query(Set.of(GridPosition.class, CellState.class)).forEach(entity -> {
+ final CellState state = entity.get(CellState.class);
+ final Vec2<Integer> gridPos = entity.get(GridPosition.class).getPosition();
+ final Vec2<Float> drawPos = gridPos.floatValue().scale(cellSize).plus(parallaxOffset);
- final float alivePercentage = state.getAlivePercentage();
- if (alivePercentage <= 0.0f) {
- return;
- }
- shapeRenderer.setColor(interpolateColor(alivePercentage));
- shapeRenderer.rect(drawPos.getX(), drawPos.getY(), cellSize.getX(), cellSize.getY());
- });
- }
+ final float alivePercentage = state.getAlivePercentage();
+ if (alivePercentage <= 0.0f) {
+ return;
+ }
+ shapeRenderer.setColor(interpolateColor(alivePercentage));
+ shapeRenderer.rect(drawPos.getX(), drawPos.getY(), cellSize.getX(), cellSize.getY());
+ });
+ }
- private Color interpolateColor(final float alivePercentage) {
- final float interpolation = alivePercentage * alivePercentage * alivePercentage;
- return cellColor.set(Theme.BG_PATTERN).lerp(Theme.FG, interpolation);
- }
+ private Color interpolateColor(final float alivePercentage) {
+ final float interpolation = alivePercentage * alivePercentage * alivePercentage;
+ return cellColor.set(Theme.BG_PATTERN).lerp(Theme.FG, interpolation);
+ }
}
diff --git a/core/src/main/java/coffee/liz/abstractionengine/app/actor/Logo.java b/core/src/main/java/coffee/liz/abstractionengine/app/actor/Logo.java
index e8bf025..80f04cb 100644
--- a/core/src/main/java/coffee/liz/abstractionengine/app/actor/Logo.java
+++ b/core/src/main/java/coffee/liz/abstractionengine/app/actor/Logo.java
@@ -8,36 +8,36 @@ import com.badlogic.gdx.scenes.scene2d.Actor;
import com.badlogic.gdx.utils.Disposable;
public class Logo extends Actor implements Disposable {
- private final Texture texture;
+ private final Texture texture;
- /**
- * Creates a logo actor.
- */
- public Logo() {
- this.texture = new Texture(Gdx.files.internal("sprites/logo.png"));
- setSize(texture.getWidth(), texture.getHeight());
- }
+ /**
+ * Creates a logo actor.
+ */
+ public Logo() {
+ this.texture = new Texture(Gdx.files.internal("sprites/logo.png"));
+ setSize(texture.getWidth(), texture.getHeight());
+ }
- /**
- * Actor draw hook.
- *
- * @param batch
- * parent batch
- * @param parentAlpha
- * parent alpha multiplier
- */
- @Override
- public void draw(final Batch batch, final float parentAlpha) {
- final Color c = getColor();
- batch.setColor(c.r, c.g, c.b, c.a * parentAlpha);
- batch.draw(texture, getX(), getY(), getWidth(), getHeight());
- }
+ /**
+ * Actor draw hook.
+ *
+ * @param batch
+ * parent batch
+ * @param parentAlpha
+ * parent alpha multiplier
+ */
+ @Override
+ public void draw(final Batch batch, final float parentAlpha) {
+ final Color c = getColor();
+ batch.setColor(c.r, c.g, c.b, c.a * parentAlpha);
+ batch.draw(texture, getX(), getY(), getWidth(), getHeight());
+ }
- /**
- * Releases actor resources.
- */
- @Override
- public void dispose() {
- texture.dispose();
- }
+ /**
+ * Releases actor resources.
+ */
+ @Override
+ public void dispose() {
+ texture.dispose();
+ }
}
diff --git a/core/src/main/java/coffee/liz/abstractionengine/app/actor/Penguin.java b/core/src/main/java/coffee/liz/abstractionengine/app/actor/Penguin.java
index 4a557e7..932ac41 100644
--- a/core/src/main/java/coffee/liz/abstractionengine/app/actor/Penguin.java
+++ b/core/src/main/java/coffee/liz/abstractionengine/app/actor/Penguin.java
@@ -13,95 +13,95 @@ import com.badlogic.gdx.utils.Disposable;
import lombok.Getter;
public class Penguin extends Actor implements Disposable {
- private static final Vec2<Integer> PENGUIN_FRAMES = Vec2i.builder().x(8).y(4).build();
+ private static final Vec2<Integer> PENGUIN_FRAMES = Vec2i.builder().x(8).y(4).build();
- private final Texture texture;
- @Getter
- private final Animation<TextureRegion> tobaganning;
- @Getter
- private final Animation<TextureRegion> eepy;
- @Getter
- private final Animation<TextureRegion> eeping;
- private Animation<TextureRegion> currentAnimation;
- private float stateTime = 0f;
+ private final Texture texture;
+ @Getter
+ private final Animation<TextureRegion> tobaganning;
+ @Getter
+ private final Animation<TextureRegion> eepy;
+ @Getter
+ private final Animation<TextureRegion> eeping;
+ private Animation<TextureRegion> currentAnimation;
+ private float stateTime = 0f;
- /**
- * Creates a penguin actor.
- */
- public Penguin() {
- this.texture = new Texture(Gdx.files.internal("sprites/penguins.png"));
- final TextureRegion[][] tmp = TextureRegion.split(texture, texture.getWidth() / PENGUIN_FRAMES.getX(),
- texture.getHeight() / PENGUIN_FRAMES.getY());
+ /**
+ * Creates a penguin actor.
+ */
+ public Penguin() {
+ this.texture = new Texture(Gdx.files.internal("sprites/penguins.png"));
+ final TextureRegion[][] tmp = TextureRegion.split(texture, texture.getWidth() / PENGUIN_FRAMES.getX(),
+ texture.getHeight() / PENGUIN_FRAMES.getY());
- final TextureRegion[] tobaggonTextureRegion = new TextureRegion[2];
- tobaggonTextureRegion[0] = tmp[2][7];
- tobaggonTextureRegion[1] = tmp[3][6];
+ final TextureRegion[] tobaggonTextureRegion = new TextureRegion[2];
+ tobaggonTextureRegion[0] = tmp[2][7];
+ tobaggonTextureRegion[1] = tmp[3][6];
- final TextureRegion[] eepyTextureRegion = new TextureRegion[2];
- eepyTextureRegion[0] = tmp[2][3];
- eepyTextureRegion[1] = tmp[3][3];
+ final TextureRegion[] eepyTextureRegion = new TextureRegion[2];
+ eepyTextureRegion[0] = tmp[2][3];
+ eepyTextureRegion[1] = tmp[3][3];
- final TextureRegion[] eepingTextureRegion = new TextureRegion[2];
- eepingTextureRegion[0] = tmp[0][2];
- eepingTextureRegion[1] = tmp[1][2];
+ final TextureRegion[] eepingTextureRegion = new TextureRegion[2];
+ eepingTextureRegion[0] = tmp[0][2];
+ eepingTextureRegion[1] = tmp[1][2];
- this.tobaganning = new Animation<>(0.25f, tobaggonTextureRegion);
- this.eepy = new Animation<>(0.45f, eepyTextureRegion);
- this.eeping = new Animation<>(0.45f, eepingTextureRegion);
- this.currentAnimation = tobaganning;
- }
+ this.tobaganning = new Animation<>(0.25f, tobaggonTextureRegion);
+ this.eepy = new Animation<>(0.45f, eepyTextureRegion);
+ this.eeping = new Animation<>(0.45f, eepingTextureRegion);
+ this.currentAnimation = tobaganning;
+ }
- /**
- * Actor update hook.
- *
- * @param delta
- * time since last frame
- */
- @Override
- public void act(final float delta) {
- super.act(delta);
- stateTime += delta;
- }
+ /**
+ * Actor update hook.
+ *
+ * @param delta
+ * time since last frame
+ */
+ @Override
+ public void act(final float delta) {
+ super.act(delta);
+ stateTime += delta;
+ }
- /**
- * Actor draw hook.
- *
- * @param batch
- * parent batch
- * @param parentAlpha
- * parent alpha multiplier
- */
- @Override
- public void draw(final Batch batch, final float parentAlpha) {
- final TextureRegion frame = currentAnimation.getKeyFrame(stateTime, true);
- final Color c = getColor();
- batch.setColor(c.r, c.g, c.b, c.a * parentAlpha);
- batch.draw(frame, getX(), getY(), getWidth(), getHeight());
- }
+ /**
+ * Actor draw hook.
+ *
+ * @param batch
+ * parent batch
+ * @param parentAlpha
+ * parent alpha multiplier
+ */
+ @Override
+ public void draw(final Batch batch, final float parentAlpha) {
+ final TextureRegion frame = currentAnimation.getKeyFrame(stateTime, true);
+ final Color c = getColor();
+ batch.setColor(c.r, c.g, c.b, c.a * parentAlpha);
+ batch.draw(frame, getX(), getY(), getWidth(), getHeight());
+ }
- /**
- * Sets the current animation state.
- *
- * @param state
- * new state
- */
- public void setState(final State state) {
- this.currentAnimation = switch (state) {
- case EEPY -> eepy;
- case EEPING -> eeping;
- case TOBAGGON -> tobaganning;
- };
- }
+ /**
+ * Sets the current animation state.
+ *
+ * @param state
+ * new state
+ */
+ public void setState(final State state) {
+ this.currentAnimation = switch (state) {
+ case EEPY -> eepy;
+ case EEPING -> eeping;
+ case TOBAGGON -> tobaganning;
+ };
+ }
- /**
- * Releases actor resources.
- */
- @Override
- public void dispose() {
- texture.dispose();
- }
+ /**
+ * Releases actor resources.
+ */
+ @Override
+ public void dispose() {
+ texture.dispose();
+ }
- public enum State {
- EEPY, EEPING, TOBAGGON
- }
+ public enum State {
+ EEPY, EEPING, TOBAGGON
+ }
}
diff --git a/core/src/main/java/coffee/liz/abstractionengine/app/actor/Player.java b/core/src/main/java/coffee/liz/abstractionengine/app/actor/Player.java
new file mode 100644
index 0000000..fb63b0d
--- /dev/null
+++ b/core/src/main/java/coffee/liz/abstractionengine/app/actor/Player.java
@@ -0,0 +1,22 @@
+package coffee.liz.abstractionengine.app.actor;
+
+import com.badlogic.gdx.graphics.g2d.Batch;
+import com.badlogic.gdx.scenes.scene2d.Actor;
+import com.badlogic.gdx.scenes.scene2d.InputListener;
+import com.badlogic.gdx.scenes.scene2d.Stage;
+
+import lombok.AllArgsConstructor;
+
+@AllArgsConstructor
+public class Player extends Actor {
+ private Stage stage;
+
+ public Player() {
+ addListener(new InputListener());
+ }
+
+ @Override
+ public void draw(final Batch batch, final float parentAlpha) {
+ // batch.
+ }
+}
diff --git a/core/src/main/java/coffee/liz/abstractionengine/app/actor/Wall.java b/core/src/main/java/coffee/liz/abstractionengine/app/actor/Wall.java
new file mode 100644
index 0000000..2848a8e
--- /dev/null
+++ b/core/src/main/java/coffee/liz/abstractionengine/app/actor/Wall.java
@@ -0,0 +1,22 @@
+package coffee.liz.abstractionengine.app.actor;
+
+import com.badlogic.gdx.Gdx;
+import com.badlogic.gdx.graphics.Color;
+import com.badlogic.gdx.graphics.Texture;
+import com.badlogic.gdx.graphics.g2d.Batch;
+import com.badlogic.gdx.scenes.scene2d.Actor;
+
+public class Wall extends Actor {
+ private final Texture texture;
+
+ public Wall() {
+ this.texture = new Texture(Gdx.files.internal("sprites/wall.png"));
+ }
+
+ @Override
+ public void draw(final Batch batch, final float parentAlpha) {
+ final Color c = getColor();
+ batch.setColor(c.r, c.g, c.b, c.a * parentAlpha);
+ batch.draw(texture, getX(), getY(), getWidth(), getHeight());
+ }
+}
diff --git a/core/src/main/java/coffee/liz/abstractionengine/app/config/KeyBinds.java b/core/src/main/java/coffee/liz/abstractionengine/app/config/KeyBinds.java
index 598e1a8..06ae70d 100644
--- a/core/src/main/java/coffee/liz/abstractionengine/app/config/KeyBinds.java
+++ b/core/src/main/java/coffee/liz/abstractionengine/app/config/KeyBinds.java
@@ -17,27 +17,27 @@ import java.util.function.Predicate;
@RequiredArgsConstructor
@Getter
public class KeyBinds {
- @Builder.Default
- private Set<Integer> moveUpKeys = Set.of(Input.Keys.K, Input.Keys.UP, Input.Keys.W);
- @Builder.Default
- private Set<Integer> moveDownKeys = Set.of(Input.Keys.J, Input.Keys.DOWN, Input.Keys.S);
- @Builder.Default
- private Set<Integer> moveLeftKeys = Set.of(Input.Keys.H, Input.Keys.LEFT, Input.Keys.A);
- @Builder.Default
- private Set<Integer> moveRightKeys = Set.of(Input.Keys.L, Input.Keys.RIGHT, Input.Keys.D);
+ @Builder.Default
+ private Set<Integer> moveUpKeys = Set.of(Input.Keys.K, Input.Keys.UP, Input.Keys.W);
+ @Builder.Default
+ private Set<Integer> moveDownKeys = Set.of(Input.Keys.J, Input.Keys.DOWN, Input.Keys.S);
+ @Builder.Default
+ private Set<Integer> moveLeftKeys = Set.of(Input.Keys.H, Input.Keys.LEFT, Input.Keys.A);
+ @Builder.Default
+ private Set<Integer> moveRightKeys = Set.of(Input.Keys.L, Input.Keys.RIGHT, Input.Keys.D);
- public Set<Action> filterActiveActions(final Predicate<Integer> isDown) {
- final Set<Action> actions = new HashSet<>();
- Map.of(moveUpKeys, Action.MOVE_UP, moveDownKeys, Action.MOVE_DOWN, moveRightKeys, Action.MOVE_RIGHT,
- moveLeftKeys, Action.MOVE_LEFT).forEach((keys, action) -> {
- if (keys.stream().anyMatch(isDown)) {
- actions.add(action);
- }
- });
- return actions;
- }
+ public Set<Action> filterActiveActions(final Predicate<Integer> isDown) {
+ final Set<Action> actions = new HashSet<>();
+ Map.of(moveUpKeys, Action.MOVE_UP, moveDownKeys, Action.MOVE_DOWN, moveRightKeys, Action.MOVE_RIGHT,
+ moveLeftKeys, Action.MOVE_LEFT).forEach((keys, action) -> {
+ if (keys.stream().anyMatch(isDown)) {
+ actions.add(action);
+ }
+ });
+ return actions;
+ }
- public enum Action {
- MOVE_UP, MOVE_LEFT, MOVE_DOWN, MOVE_RIGHT;
- }
+ public enum Action {
+ MOVE_UP, MOVE_LEFT, MOVE_DOWN, MOVE_RIGHT;
+ }
}
diff --git a/core/src/main/java/coffee/liz/abstractionengine/app/config/Settings.java b/core/src/main/java/coffee/liz/abstractionengine/app/config/Settings.java
index dd09c21..7662700 100644
--- a/core/src/main/java/coffee/liz/abstractionengine/app/config/Settings.java
+++ b/core/src/main/java/coffee/liz/abstractionengine/app/config/Settings.java
@@ -8,13 +8,13 @@ import lombok.Getter;
@AllArgsConstructor
@Getter
public class Settings {
- @Builder.Default
- private boolean skipIntro = true;
- @Builder.Default
- private boolean playMusic = true;
- @Builder.Default
- private boolean vimMode = true;
+ @Builder.Default
+ private boolean skipIntro = true;
+ @Builder.Default
+ private boolean playMusic = true;
+ @Builder.Default
+ private boolean vimMode = true;
- @Builder.Default
- private KeyBinds keyBinds = KeyBinds.builder().build();
+ @Builder.Default
+ private KeyBinds keyBinds = KeyBinds.builder().build();
}
diff --git a/core/src/main/java/coffee/liz/abstractionengine/app/life/CellState.java b/core/src/main/java/coffee/liz/abstractionengine/app/life/CellState.java
index 025cde0..bd07629 100644
--- a/core/src/main/java/coffee/liz/abstractionengine/app/life/CellState.java
+++ b/core/src/main/java/coffee/liz/abstractionengine/app/life/CellState.java
@@ -5,36 +5,36 @@ import lombok.Getter;
@Getter
public class CellState implements Component {
- private static final float EPS = 1.0e-4f;
+ private static final float EPS = 1.0e-4f;
- public static final CellState LIVE = new CellState(1.0f);
- public static final CellState DEAD = new CellState(0.0f);
+ public static final CellState LIVE = new CellState(1.0f);
+ public static final CellState DEAD = new CellState(0.0f);
- private final float alivePercentage;
+ private final float alivePercentage;
- /**
- * Creates a cell state with a normalized alive percentage.
- *
- * @param alivePercentage
- * alive value in the range [0, 1]
- */
- public CellState(final float alivePercentage) {
- this.alivePercentage = clamp(alivePercentage);
- }
+ /**
+ * Creates a cell state with a normalized alive percentage.
+ *
+ * @param alivePercentage
+ * alive value in the range [0, 1]
+ */
+ public CellState(final float alivePercentage) {
+ this.alivePercentage = clamp(alivePercentage);
+ }
- /**
- * Returns true when the cell is considered alive.
- *
- * @return whether the cell is alive
- */
- public boolean isAlive() {
- return alivePercentage >= (1.0f - EPS);
- }
+ /**
+ * Returns true when the cell is considered alive.
+ *
+ * @return whether the cell is alive
+ */
+ public boolean isAlive() {
+ return alivePercentage >= (1.0f - EPS);
+ }
- private static float clamp(final float value) {
- if (value <= 0.0f) {
- return 0.0f;
- }
- return Math.min(value, 1.0f);
- }
+ private static float clamp(final float value) {
+ if (value <= 0.0f) {
+ return 0.0f;
+ }
+ return Math.min(value, 1.0f);
+ }
}
diff --git a/core/src/main/java/coffee/liz/abstractionengine/app/life/EntropyAudioSystem.java b/core/src/main/java/coffee/liz/abstractionengine/app/life/EntropyAudioSystem.java
index b57db71..5660ff3 100644
--- a/core/src/main/java/coffee/liz/abstractionengine/app/life/EntropyAudioSystem.java
+++ b/core/src/main/java/coffee/liz/abstractionengine/app/life/EntropyAudioSystem.java
@@ -17,142 +17,142 @@ import java.util.Set;
import java.util.stream.IntStream;
public class EntropyAudioSystem implements System<LifeInput> {
- private static final int SAMPLE_RATE = 44100;
- private static final int CHUNKS_X = 4;
- private static final int CHUNKS_Y = 4;
- private static final int NUM_CHUNKS = CHUNKS_X * CHUNKS_Y;
- private static final Duration AUDIO_THREAD_TIMEOUT = Duration.ofMillis(20);
+ private static final int SAMPLE_RATE = 44100;
+ private static final int CHUNKS_X = 4;
+ private static final int CHUNKS_Y = 4;
+ private static final int NUM_CHUNKS = CHUNKS_X * CHUNKS_Y;
+ private static final Duration AUDIO_THREAD_TIMEOUT = Duration.ofMillis(20);
- private static final int[] PENTATONIC_INTERVALS = {0, 3, 5, 7, 10};
- private static final float BASE_FREQUENCY = 110f;
- private static final float[] FREQUENCIES = new float[NUM_CHUNKS];
- static {
- for (int i = 0; i < NUM_CHUNKS; i++) {
- final int octave = i / PENTATONIC_INTERVALS.length;
- final int degree = i % PENTATONIC_INTERVALS.length;
- final int semitones = octave * 12 + PENTATONIC_INTERVALS[degree];
- FREQUENCIES[i] = BASE_FREQUENCY * (float) Math.pow(2.0, semitones / 12.0);
- }
- }
+ private static final int[] PENTATONIC_INTERVALS = {0, 3, 5, 7, 10};
+ private static final float BASE_FREQUENCY = 110f;
+ private static final float[] FREQUENCIES = new float[NUM_CHUNKS];
+ static {
+ for (int i = 0; i < NUM_CHUNKS; i++) {
+ final int octave = i / PENTATONIC_INTERVALS.length;
+ final int degree = i % PENTATONIC_INTERVALS.length;
+ final int semitones = octave * 12 + PENTATONIC_INTERVALS[degree];
+ FREQUENCIES[i] = BASE_FREQUENCY * (float) Math.pow(2.0, semitones / 12.0);
+ }
+ }
- private static final float MIN_PULSE_RATE = 1.0f;
- private static final float MAX_PULSE_RATE = 8.0f;
- private static final float MASTER_VOLUME = 0.15f;
- private static final float SMOOTHING_FACTOR = 0.0005f;
+ private static final float MIN_PULSE_RATE = 1.0f;
+ private static final float MAX_PULSE_RATE = 8.0f;
+ private static final float MASTER_VOLUME = 0.15f;
+ private static final float SMOOTHING_FACTOR = 0.0005f;
- private final AudioDevice device = Gdx.audio.newAudioDevice(SAMPLE_RATE, true);
- private final float[] targetEntropies = new float[NUM_CHUNKS];
- private final float[] smoothedEntropies = new float[NUM_CHUNKS];
- private final float[] phases = new float[NUM_CHUNKS];
- private final float[] pulsePhases = new float[NUM_CHUNKS];
+ private final AudioDevice device = Gdx.audio.newAudioDevice(SAMPLE_RATE, true);
+ private final float[] targetEntropies = new float[NUM_CHUNKS];
+ private final float[] smoothedEntropies = new float[NUM_CHUNKS];
+ private final float[] phases = new float[NUM_CHUNKS];
+ private final float[] pulsePhases = new float[NUM_CHUNKS];
- private final Thread audioThread;
- private volatile boolean running = true;
+ private final Thread audioThread;
+ private volatile boolean running = true;
- public EntropyAudioSystem() {
- audioThread = new Thread(this::audioLoop, "EntropyAudio");
- audioThread.setDaemon(true);
- }
+ public EntropyAudioSystem() {
+ audioThread = new Thread(this::audioLoop, "EntropyAudio");
+ audioThread.setDaemon(true);
+ }
- @Override
- public Collection<Class<? extends System<LifeInput>>> getDependencies() {
- return Set.of(LifeSystem.class);
- }
+ @Override
+ public Collection<Class<? extends System<LifeInput>>> getDependencies() {
+ return Set.of(LifeSystem.class);
+ }
- @Override
- public void update(final World<LifeInput> world, final LifeInput state, final Duration dt) {
- if (!state.getGameInstructions().isPlayMusic()) {
- running = false;
- return;
- }
+ @Override
+ public void update(final World<LifeInput> world, final LifeInput state, final Duration dt) {
+ if (!state.getGameInstructions().isPlayMusic()) {
+ running = false;
+ return;
+ }
- if (!audioThread.isAlive()) {
- audioThread.start();
- running = true;
- }
+ if (!audioThread.isAlive()) {
+ audioThread.start();
+ running = true;
+ }
- final LifeSystem lifeSystem = world.getSystem(LifeSystem.class);
- final Vec2<Integer> gridDimensions = lifeSystem.getDimensions();
- final List<List<Set<Entity>>> rows = lifeSystem.getRows();
+ final LifeSystem lifeSystem = world.getSystem(LifeSystem.class);
+ final Vec2<Integer> gridDimensions = lifeSystem.getDimensions();
+ final List<List<Set<Entity>>> rows = lifeSystem.getRows();
- final Vec2<Integer> chunkDimensions = Vec2i.builder().x(gridDimensions.getX() / CHUNKS_X)
- .y(gridDimensions.getY() / CHUNKS_Y).build();
+ final Vec2<Integer> chunkDimensions = Vec2i.builder().x(gridDimensions.getX() / CHUNKS_X)
+ .y(gridDimensions.getY() / CHUNKS_Y).build();
- for (int cy = 0; cy < CHUNKS_Y; cy++) {
- for (int cx = 0; cx < CHUNKS_X; cx++) {
- final int chunkIndex = cy * CHUNKS_X + cx;
- final Vec2<Integer> chunk = Vec2i.builder().x(cx).y(cy).build();
- final Vec2<Integer> bottomLeft = chunkDimensions.scale(chunk);
- final Vec2<Integer> topRight = bottomLeft.plus(chunkDimensions);
+ for (int cy = 0; cy < CHUNKS_Y; cy++) {
+ for (int cx = 0; cx < CHUNKS_X; cx++) {
+ final int chunkIndex = cy * CHUNKS_X + cx;
+ final Vec2<Integer> chunk = Vec2i.builder().x(cx).y(cy).build();
+ final Vec2<Integer> bottomLeft = chunkDimensions.scale(chunk);
+ final Vec2<Integer> topRight = bottomLeft.plus(chunkDimensions);
- final long alive = IntStream.range(bottomLeft.getY(), topRight.getY())
- .mapToLong(y -> IntStream.range(bottomLeft.getX(), topRight.getX()).mapToLong(
- x -> rows.get(y).get(x).stream().filter(e -> e.get(CellState.class).isAlive()).count())
- .sum())
- .sum();
- targetEntropies[chunkIndex] = computeShannonEntropy(
- alive / (float) (chunkDimensions.getY() * chunkDimensions.getX()));
- }
- }
- }
+ final long alive = IntStream.range(bottomLeft.getY(), topRight.getY())
+ .mapToLong(y -> IntStream.range(bottomLeft.getX(), topRight.getX()).mapToLong(
+ x -> rows.get(y).get(x).stream().filter(e -> e.get(CellState.class).isAlive()).count())
+ .sum())
+ .sum();
+ targetEntropies[chunkIndex] = computeShannonEntropy(
+ alive / (float) (chunkDimensions.getY() * chunkDimensions.getX()));
+ }
+ }
+ }
- private float computeShannonEntropy(final float p) {
- if (p <= 0.0f || p >= 1.0f) {
- return 0.0f;
- }
+ private float computeShannonEntropy(final float p) {
+ if (p <= 0.0f || p >= 1.0f) {
+ return 0.0f;
+ }
- final float entropy = -p * MathUtils.log2(p) - (1 - p) * MathUtils.log2(1 - p);
- return MathUtils.clamp(entropy, 0f, 1f);
- }
+ final float entropy = -p * MathUtils.log2(p) - (1 - p) * MathUtils.log2(1 - p);
+ return MathUtils.clamp(entropy, 0f, 1f);
+ }
- private void audioLoop() {
- final int bufferSize = 2048;
- final float[] buffer = new float[bufferSize];
- final float dtPerSample = 1.0f / SAMPLE_RATE;
+ private void audioLoop() {
+ final int bufferSize = 2048;
+ final float[] buffer = new float[bufferSize];
+ final float dtPerSample = 1.0f / SAMPLE_RATE;
- while (running) {
- for (int i = 0; i < bufferSize; i++) {
- float sample = 0.0f;
+ while (running) {
+ for (int i = 0; i < bufferSize; i++) {
+ float sample = 0.0f;
- for (int c = 0; c < NUM_CHUNKS; c++) {
- final float target = targetEntropies[c];
- smoothedEntropies[c] += (target - smoothedEntropies[c]) * SMOOTHING_FACTOR;
- final float entropy = smoothedEntropies[c];
+ for (int c = 0; c < NUM_CHUNKS; c++) {
+ final float target = targetEntropies[c];
+ smoothedEntropies[c] += (target - smoothedEntropies[c]) * SMOOTHING_FACTOR;
+ final float entropy = smoothedEntropies[c];
- if (entropy < 0.01f) {
- continue;
- }
+ if (entropy < 0.01f) {
+ continue;
+ }
- final float frequency = FREQUENCIES[c];
- final float pulseRate = MIN_PULSE_RATE + entropy * (MAX_PULSE_RATE - MIN_PULSE_RATE);
- final float volume = entropy * MASTER_VOLUME;
+ final float frequency = FREQUENCIES[c];
+ final float pulseRate = MIN_PULSE_RATE + entropy * (MAX_PULSE_RATE - MIN_PULSE_RATE);
+ final float volume = entropy * MASTER_VOLUME;
- phases[c] += frequency * dtPerSample;
- if (phases[c] > 1.0f) {
- phases[c] -= 1.0f;
- }
+ phases[c] += frequency * dtPerSample;
+ if (phases[c] > 1.0f) {
+ phases[c] -= 1.0f;
+ }
- pulsePhases[c] += pulseRate * dtPerSample;
- if (pulsePhases[c] > 1.0f) {
- pulsePhases[c] -= 1.0f;
- }
+ pulsePhases[c] += pulseRate * dtPerSample;
+ if (pulsePhases[c] > 1.0f) {
+ pulsePhases[c] -= 1.0f;
+ }
- final float wave = (float) Math.sin(phases[c] * 2 * Math.PI);
- final float pulse = 0.5f + 0.5f * (float) Math.sin(pulsePhases[c] * 2 * Math.PI);
- sample += wave * volume * pulse;
- }
+ final float wave = (float) Math.sin(phases[c] * 2 * Math.PI);
+ final float pulse = 0.5f + 0.5f * (float) Math.sin(pulsePhases[c] * 2 * Math.PI);
+ sample += wave * volume * pulse;
+ }
- buffer[i] = Math.max(-1.0f, Math.min(1.0f, sample));
- }
+ buffer[i] = Math.max(-1.0f, Math.min(1.0f, sample));
+ }
- device.writeSamples(buffer, 0, bufferSize);
- }
- }
+ device.writeSamples(buffer, 0, bufferSize);
+ }
+ }
- @Override
- public void close() {
- running = false;
- FunctionUtils.wrapCheckedException(() -> audioThread.join(AUDIO_THREAD_TIMEOUT));
- device.dispose();
- }
+ @Override
+ public void close() {
+ running = false;
+ FunctionUtils.wrapCheckedException(() -> audioThread.join(AUDIO_THREAD_TIMEOUT));
+ device.dispose();
+ }
}
diff --git a/core/src/main/java/coffee/liz/abstractionengine/app/life/LifeInput.java b/core/src/main/java/coffee/liz/abstractionengine/app/life/LifeInput.java
index 36a1276..4007274 100644
--- a/core/src/main/java/coffee/liz/abstractionengine/app/life/LifeInput.java
+++ b/core/src/main/java/coffee/liz/abstractionengine/app/life/LifeInput.java
@@ -10,6 +10,6 @@ import java.util.Set;
@RequiredArgsConstructor
@Data
public class LifeInput {
- private final Set<Vec2<Integer>> forceAliveCells;
- private final Settings gameInstructions;
+ private final Set<Vec2<Integer>> forceAliveCells;
+ private final Settings gameInstructions;
}
diff --git a/core/src/main/java/coffee/liz/abstractionengine/app/life/LifeSystem.java b/core/src/main/java/coffee/liz/abstractionengine/app/life/LifeSystem.java
index aea42c9..dcb6fb9 100644
--- a/core/src/main/java/coffee/liz/abstractionengine/app/life/LifeSystem.java
+++ b/core/src/main/java/coffee/liz/abstractionengine/app/life/LifeSystem.java
@@ -12,74 +12,74 @@ import java.util.Set;
/** Conway's game of life */
public class LifeSystem extends BaseGridIndexSystem<LifeInput> {
- public final static int MAX_DECAY_STEPS = 12;
- private final static float DECAY_STEP = 1.0f / MAX_DECAY_STEPS;
- private final static Vec2<Integer> CONVOLUTION_RADIUS = Vec2i.builder().x(1).y(1).build();
+ public final static int MAX_DECAY_STEPS = 12;
+ private final static float DECAY_STEP = 1.0f / MAX_DECAY_STEPS;
+ private final static Vec2<Integer> CONVOLUTION_RADIUS = Vec2i.builder().x(1).y(1).build();
- private final static Duration BETWEEN_UPDATES = Duration.ofMillis(200);
+ private final static Duration BETWEEN_UPDATES = Duration.ofMillis(200);
- private Duration sinceUpdate = Duration.ZERO;
+ private Duration sinceUpdate = Duration.ZERO;
- /**
- * Creates a life system.
- *
- * @param dimensions
- * grid size
- */
- public LifeSystem(final Vec2<Integer> dimensions) {
- super(dimensions);
- }
+ /**
+ * Creates a life system.
+ *
+ * @param dimensions
+ * grid size
+ */
+ public LifeSystem(final Vec2<Integer> dimensions) {
+ super(dimensions);
+ }
- /**
- * Advances the simulation.
- *
- * @param world
- * world to update
- * @param state
- * input state for this tick
- * @param dt
- * time step
- */
- @Override
- public void update(final World<LifeInput> world, final LifeInput state, final Duration dt) {
- super.update(world, state, dt);
+ /**
+ * Advances the simulation.
+ *
+ * @param world
+ * world to update
+ * @param state
+ * input state for this tick
+ * @param dt
+ * time step
+ */
+ @Override
+ public void update(final World<LifeInput> world, final LifeInput state, final Duration dt) {
+ super.update(world, state, dt);
- sinceUpdate = sinceUpdate.plus(dt);
- if (BETWEEN_UPDATES.compareTo(sinceUpdate) <= 0) {
- Mat2.convolveTorus(this.rows, CONVOLUTION_RADIUS, () -> 0, (entities, rel, prev) -> {
- if (rel.equals(Vec2i.ZERO)) {
- return prev;
- }
- return entities.stream().findFirst().map(entity -> entity.get(CellState.class))
- .map(cellState -> prev + (cellState.isAlive() ? 1 : 0)).orElse(prev);
- }, (entities, neighboringAliveCells) -> entities.stream().findFirst().map(entity -> {
- final CellState cellState = entity.get(CellState.class);
- final float decay = cellState.getAlivePercentage();
+ sinceUpdate = sinceUpdate.plus(dt);
+ if (BETWEEN_UPDATES.compareTo(sinceUpdate) <= 0) {
+ Mat2.convolveTorus(this.rows, CONVOLUTION_RADIUS, () -> 0, (entities, rel, prev) -> {
+ if (rel.equals(Vec2i.ZERO)) {
+ return prev;
+ }
+ return entities.stream().findFirst().map(entity -> entity.get(CellState.class))
+ .map(cellState -> prev + (cellState.isAlive() ? 1 : 0)).orElse(prev);
+ }, (entities, neighboringAliveCells) -> entities.stream().findFirst().map(entity -> {
+ final CellState cellState = entity.get(CellState.class);
+ final float decay = cellState.getAlivePercentage();
- final boolean alive = cellState.isAlive();
- final boolean diesNow = alive && (neighboringAliveCells < 2 || neighboringAliveCells > 3);
- final boolean spawnsNow = !alive && neighboringAliveCells == 3;
- final boolean stillAlive = alive && !diesNow;
+ final boolean alive = cellState.isAlive();
+ final boolean diesNow = alive && (neighboringAliveCells < 2 || neighboringAliveCells > 3);
+ final boolean spawnsNow = !alive && neighboringAliveCells == 3;
+ final boolean stillAlive = alive && !diesNow;
- final CellState nextState;
- if (spawnsNow || stillAlive) {
- nextState = CellState.LIVE;
- } else {
- nextState = new CellState(decay - DECAY_STEP);
- }
+ final CellState nextState;
+ if (spawnsNow || stillAlive) {
+ nextState = CellState.LIVE;
+ } else {
+ nextState = new CellState(decay - DECAY_STEP);
+ }
- entity.add(nextState);
- return entity;
- }));
- sinceUpdate = Duration.ZERO;
- }
+ entity.add(nextState);
+ return entity;
+ }));
+ sinceUpdate = Duration.ZERO;
+ }
- state.getForceAliveCells().forEach(cell -> {
- if (!inBounds(cell)) {
- return;
- }
- final Set<Entity> entities = rows.get(cell.getY()).get(cell.getX());
- entities.forEach(e -> e.add(CellState.LIVE));
- });
- }
+ state.getForceAliveCells().forEach(cell -> {
+ if (!inBounds(cell)) {
+ return;
+ }
+ final Set<Entity> entities = rows.get(cell.getY()).get(cell.getX());
+ entities.forEach(e -> e.add(CellState.LIVE));
+ });
+ }
}
diff --git a/core/src/main/java/coffee/liz/abstractionengine/app/screen/GameScreen.java b/core/src/main/java/coffee/liz/abstractionengine/app/screen/GameScreen.java
index cbdf51a..70bb973 100644
--- a/core/src/main/java/coffee/liz/abstractionengine/app/screen/GameScreen.java
+++ b/core/src/main/java/coffee/liz/abstractionengine/app/screen/GameScreen.java
@@ -3,7 +3,7 @@ package coffee.liz.abstractionengine.app.screen;
import coffee.liz.abstractionengine.app.AbstractionEngineGame;
import coffee.liz.abstractionengine.app.screen.game.FrameState;
import coffee.liz.abstractionengine.app.screen.game.GameScreenWorld;
-import coffee.liz.abstractionengine.app.screen.game.system.GameWorldManagementSystem;
+import coffee.liz.abstractionengine.app.screen.game.system.GridWorldBridgeSystem;
import coffee.liz.abstractionengine.app.screen.game.system.RenderSystem;
import coffee.liz.abstractionengine.app.utils.FunctionUtils;
import coffee.liz.ecs.math.Vec2;
@@ -17,54 +17,54 @@ import java.time.Duration;
@RequiredArgsConstructor
public class GameScreen implements Screen {
- private final AbstractionEngineGame game;
- private static final Vec2<Integer> GAME_GRID_SIZE = Vec2i.builder().x(20).y(20).build();
+ private final AbstractionEngineGame game;
+ private static final Vec2<Integer> GAME_GRID_SIZE = Vec2i.builder().x(20).y(20).build();
- private GameScreenWorld outerWorld;
- private FitViewport viewport;
- private RenderSystem renderSystem;
+ private GameScreenWorld outerWorld;
+ private FitViewport viewport;
+ private RenderSystem renderSystem;
- @Override
- public void show() {
- viewport = new FitViewport(AbstractionEngineGame.WORLD_SIZE.getX(), AbstractionEngineGame.WORLD_SIZE.getY());
- outerWorld = new GameScreenWorld(GAME_GRID_SIZE, viewport, game.settings);
- outerWorld.getSystem(GameWorldManagementSystem.class).populateLevel();
- renderSystem = outerWorld.getSystem(RenderSystem.class);
- Gdx.input.setInputProcessor(renderSystem.getInputProcessor());
- viewport.update(Gdx.graphics.getWidth(), Gdx.graphics.getHeight(), true);
- renderSystem.resize(Gdx.graphics.getWidth(), Gdx.graphics.getHeight());
- render(0);
- }
+ @Override
+ public void show() {
+ viewport = new FitViewport(AbstractionEngineGame.WORLD_SIZE.getX(), AbstractionEngineGame.WORLD_SIZE.getY());
+ outerWorld = new GameScreenWorld(GAME_GRID_SIZE, viewport, game.settings);
+ outerWorld.getSystem(GridWorldBridgeSystem.class).initLevel();
+ renderSystem = outerWorld.getSystem(RenderSystem.class);
+ Gdx.input.setInputProcessor(renderSystem.getInputProcessor());
+ viewport.update(Gdx.graphics.getWidth(), Gdx.graphics.getHeight(), true);
+ renderSystem.resize(Gdx.graphics.getWidth(), Gdx.graphics.getHeight());
+ render(0);
+ }
- @Override
- public void render(final float delta) {
- viewport.apply();
- final FrameState state = FrameState.builder().settings(game.settings).isKeyPressed(Gdx.input::isKeyPressed)
- .build();
- outerWorld.update(state, Duration.ofMillis((long) (delta * 1000)));
- }
+ @Override
+ public void render(final float delta) {
+ viewport.apply();
+ final FrameState state = FrameState.builder().settings(game.settings).isKeyPressed(Gdx.input::isKeyPressed)
+ .build();
+ outerWorld.update(state, Duration.ofMillis((long) (delta * 1000)));
+ }
- @Override
- public void resize(final int width, final int height) {
- viewport.update(width, height, true);
- renderSystem.resize(width, height);
- }
+ @Override
+ public void resize(final int width, final int height) {
+ viewport.update(width, height, true);
+ renderSystem.resize(width, height);
+ }
- @Override
- public void pause() {
- }
+ @Override
+ public void pause() {
+ }
- @Override
- public void resume() {
- }
+ @Override
+ public void resume() {
+ }
- @Override
- public void hide() {
- dispose();
- }
+ @Override
+ public void hide() {
+ dispose();
+ }
- @Override
- public void dispose() {
- FunctionUtils.wrapCheckedException(outerWorld::close);
- }
+ @Override
+ public void dispose() {
+ FunctionUtils.wrapCheckedException(outerWorld::close);
+ }
}
diff --git a/core/src/main/java/coffee/liz/abstractionengine/app/screen/MainMenu.java b/core/src/main/java/coffee/liz/abstractionengine/app/screen/MainMenu.java
index 30cc01f..46b5192 100644
--- a/core/src/main/java/coffee/liz/abstractionengine/app/screen/MainMenu.java
+++ b/core/src/main/java/coffee/liz/abstractionengine/app/screen/MainMenu.java
@@ -29,140 +29,140 @@ import java.util.Set;
@RequiredArgsConstructor
public class MainMenu implements Screen {
- public static final Vec2<Integer> GRID_DIMENSIONS = Vec2i.builder().x(50).y(50).build();
+ public static final Vec2<Integer> GRID_DIMENSIONS = Vec2i.builder().x(50).y(50).build();
- private static final Vec2<Float> BUTTON_SIZE = AbstractionEngineGame.WORLD_SIZE.scale(1 / 4f, 1 / 15f);
- private static final float PARALLAX_STRENGTH = 3f;
+ private static final Vec2<Float> BUTTON_SIZE = AbstractionEngineGame.WORLD_SIZE.scale(1 / 4f, 1 / 15f);
+ private static final float PARALLAX_STRENGTH = 3f;
- private final World<LifeInput> world = new DAGWorld<>(Map.of(LifeSystem.class, new LifeSystem(GRID_DIMENSIONS),
- EntropyAudioSystem.class, new EntropyAudioSystem()));
- private final AbstractionEngineGame game;
+ private final World<LifeInput> world = new DAGWorld<>(Map.of(LifeSystem.class, new LifeSystem(GRID_DIMENSIONS),
+ EntropyAudioSystem.class, new EntropyAudioSystem()));
+ private final AbstractionEngineGame game;
- private final Set<Vec2<Integer>> initialAlive = createGliderPattern();
+ private final Set<Vec2<Integer>> initialAlive = createGliderPattern();
- private Stage stage;
- private LifeGridActor lifeGridActor;
+ private Stage stage;
+ private LifeGridActor lifeGridActor;
- /**
- * Screen lifecycle hook.
- */
- @Override
- public void show() {
- Mat2.init(GRID_DIMENSIONS, pos -> world.createEntity().add(new GridPosition(pos))
- .add(initialAlive.contains(pos) ? CellState.LIVE : CellState.DEAD));
+ /**
+ * Screen lifecycle hook.
+ */
+ @Override
+ public void show() {
+ Mat2.init(GRID_DIMENSIONS, pos -> world.createEntity().add(new GridPosition(pos))
+ .add(initialAlive.contains(pos) ? CellState.LIVE : CellState.DEAD));
- stage = new Stage(game.viewport, game.batch);
- lifeGridActor = new LifeGridActor(game.shapeRenderer, world, GRID_DIMENSIONS, game.settings);
- lifeGridActor.setViewport(game.viewport);
- stage.addActor(lifeGridActor);
+ stage = new Stage(game.viewport, game.batch);
+ lifeGridActor = new LifeGridActor(game.shapeRenderer, world, GRID_DIMENSIONS, game.settings);
+ lifeGridActor.setViewport(game.viewport);
+ stage.addActor(lifeGridActor);
- final Button playButton = createButton("play", (game.viewport.getWorldWidth() - BUTTON_SIZE.getX()) / 2f,
- (game.viewport.getWorldHeight() - BUTTON_SIZE.getY()) / 2f);
- playButton.setOnClick(() -> game.setScreen(new GameScreen(game)));
- stage.addActor(playButton);
+ final Button playButton = createButton("play", (game.viewport.getWorldWidth() - BUTTON_SIZE.getX()) / 2f,
+ (game.viewport.getWorldHeight() - BUTTON_SIZE.getY()) / 2f);
+ playButton.setOnClick(() -> game.setScreen(new GameScreen(game)));
+ stage.addActor(playButton);
- Gdx.input.setInputProcessor(stage);
- }
+ Gdx.input.setInputProcessor(stage);
+ }
- private Button createButton(final String text, final float x, final float y) {
- final Button button = new Button(game.shapeRenderer, game.font, text);
- button.setPosition(x, y);
- button.setSize(BUTTON_SIZE.getX(), BUTTON_SIZE.getY());
- button.addButtonListener();
- return button;
- }
+ private Button createButton(final String text, final float x, final float y) {
+ final Button button = new Button(game.shapeRenderer, game.font, text);
+ button.setPosition(x, y);
+ button.setSize(BUTTON_SIZE.getX(), BUTTON_SIZE.getY());
+ button.addButtonListener();
+ return button;
+ }
- private static Set<Vec2<Integer>> createGliderPattern() {
- final int[][] downRight = {{0, 1, 0}, {0, 1, 1}, {1, 0, 1}};
- final int[][] downLeft = {{0, 1, 0}, {1, 1, 0}, {1, 0, 1}};
- final int[][] upRight = {{1, 0, 1}, {0, 1, 1}, {0, 1, 0}};
- final int[][] upLeft = {{1, 0, 1}, {1, 1, 0}, {0, 1, 0}};
+ private static Set<Vec2<Integer>> createGliderPattern() {
+ final int[][] downRight = {{0, 1, 0}, {0, 1, 1}, {1, 0, 1}};
+ final int[][] downLeft = {{0, 1, 0}, {1, 1, 0}, {1, 0, 1}};
+ final int[][] upRight = {{1, 0, 1}, {0, 1, 1}, {0, 1, 0}};
+ final int[][] upLeft = {{1, 0, 1}, {1, 1, 0}, {0, 1, 0}};
- final Set<Vec2<Integer>> pattern = new HashSet<>();
- stamp(pattern, upRight, 2, 2);
- stamp(pattern, upLeft, GRID_DIMENSIONS.getX() - 5, 2);
- stamp(pattern, downRight, 2, GRID_DIMENSIONS.getY() - 5);
- stamp(pattern, downLeft, GRID_DIMENSIONS.getX() - 5, GRID_DIMENSIONS.getY() - 5);
- return pattern;
- }
+ final Set<Vec2<Integer>> pattern = new HashSet<>();
+ stamp(pattern, upRight, 2, 2);
+ stamp(pattern, upLeft, GRID_DIMENSIONS.getX() - 5, 2);
+ stamp(pattern, downRight, 2, GRID_DIMENSIONS.getY() - 5);
+ stamp(pattern, downLeft, GRID_DIMENSIONS.getX() - 5, GRID_DIMENSIONS.getY() - 5);
+ return pattern;
+ }
- private static void stamp(final Set<Vec2<Integer>> cells, final int[][] pattern, final int offsetX,
- final int offsetY) {
- for (int y = 0; y < pattern.length; y++)
- for (int x = 0; x < pattern[y].length; x++)
- if (pattern[y][x] == 1)
- cells.add(Vec2i.builder().x(offsetX + x).y(offsetY + y).build());
- }
+ private static void stamp(final Set<Vec2<Integer>> cells, final int[][] pattern, final int offsetX,
+ final int offsetY) {
+ for (int y = 0; y < pattern.length; y++)
+ for (int x = 0; x < pattern[y].length; x++)
+ if (pattern[y][x] == 1)
+ cells.add(Vec2i.builder().x(offsetX + x).y(offsetY + y).build());
+ }
- /**
- * Screen render hook.
- *
- * @param delta
- * time since last frame
- */
- @Override
- public void render(final float delta) {
- game.viewport.apply();
+ /**
+ * Screen render hook.
+ *
+ * @param delta
+ * time since last frame
+ */
+ @Override
+ public void render(final float delta) {
+ game.viewport.apply();
- ScreenUtils.clear(Theme.BG);
+ ScreenUtils.clear(Theme.BG);
- updateParallax();
- stage.act(delta);
+ updateParallax();
+ stage.act(delta);
- stage.draw();
- }
+ stage.draw();
+ }
- private void updateParallax() {
- final Vector3 cursor = game.viewport.unproject(new Vector3(Gdx.input.getX(), Gdx.input.getY(), 0));
- final Vec2<Float> worldSize = Vec2f.builder().x(game.viewport.getWorldWidth()).y(game.viewport.getWorldHeight())
- .build();
- final Vec2<Float> normalized = Vec2f.builder().x(cursor.x).y(cursor.y).build()
- .scale(worldSize.transform(x -> 1f / x, y -> 1f / y)).transform(x -> x - 0.5f, y -> y - 0.5f);
- final Vec2<Float> parallax = normalized.scale(-PARALLAX_STRENGTH, -PARALLAX_STRENGTH);
- lifeGridActor.setParallaxOffset(parallax);
- }
+ private void updateParallax() {
+ final Vector3 cursor = game.viewport.unproject(new Vector3(Gdx.input.getX(), Gdx.input.getY(), 0));
+ final Vec2<Float> worldSize = Vec2f.builder().x(game.viewport.getWorldWidth()).y(game.viewport.getWorldHeight())
+ .build();
+ final Vec2<Float> normalized = Vec2f.builder().x(cursor.x).y(cursor.y).build()
+ .scale(worldSize.transform(x -> 1f / x, y -> 1f / y)).transform(x -> x - 0.5f, y -> y - 0.5f);
+ final Vec2<Float> parallax = normalized.scale(-PARALLAX_STRENGTH, -PARALLAX_STRENGTH);
+ lifeGridActor.setParallaxOffset(parallax);
+ }
- /**
- * Screen resize hook.
- *
- * @param width
- * new width in pixels
- * @param height
- * new height in pixels
- */
- @Override
- public void resize(final int width, final int height) {
- game.viewport.update(width, height, true);
- }
+ /**
+ * Screen resize hook.
+ *
+ * @param width
+ * new width in pixels
+ * @param height
+ * new height in pixels
+ */
+ @Override
+ public void resize(final int width, final int height) {
+ game.viewport.update(width, height, true);
+ }
- /**
- * Screen lifecycle hook.
- */
- @Override
- public void pause() {
- }
+ /**
+ * Screen lifecycle hook.
+ */
+ @Override
+ public void pause() {
+ }
- /**
- * Screen lifecycle hook.
- */
- @Override
- public void resume() {
- }
+ /**
+ * Screen lifecycle hook.
+ */
+ @Override
+ public void resume() {
+ }
- /**
- * Screen lifecycle hook.
- */
- @Override
- public void hide() {
- dispose();
- }
+ /**
+ * Screen lifecycle hook.
+ */
+ @Override
+ public void hide() {
+ dispose();
+ }
- /**
- * Screen cleanup hook.
- */
- @Override
- public void dispose() {
- FunctionUtils.wrapCheckedException(world::close);
- stage.dispose();
- }
+ /**
+ * Screen cleanup hook.
+ */
+ @Override
+ public void dispose() {
+ FunctionUtils.wrapCheckedException(world::close);
+ stage.dispose();
+ }
}
diff --git a/core/src/main/java/coffee/liz/abstractionengine/app/screen/ScrollLogo.java b/core/src/main/java/coffee/liz/abstractionengine/app/screen/ScrollLogo.java
index bb8aef2..c0183d3 100644
--- a/core/src/main/java/coffee/liz/abstractionengine/app/screen/ScrollLogo.java
+++ b/core/src/main/java/coffee/liz/abstractionengine/app/screen/ScrollLogo.java
@@ -15,138 +15,138 @@ import java.time.Duration;
@RequiredArgsConstructor
public class ScrollLogo implements Screen {
- private static final Duration SHOW_FOR = Duration.ofSeconds(7);
- private static final float LOGO_HEIGHT = 70f;
- private static final float PENGUIN_SIZE = 20f;
- private static final float SCROLL_PERCENT = 0.4f;
- private static final float EEPY_PERCENT = 0.3f;
- private static final float EEP_PERCENT = 0.15f;
- private static final float FADE_PERCENT = 0.15f;
+ private static final Duration SHOW_FOR = Duration.ofSeconds(7);
+ private static final float LOGO_HEIGHT = 70f;
+ private static final float PENGUIN_SIZE = 20f;
+ private static final float SCROLL_PERCENT = 0.4f;
+ private static final float EEPY_PERCENT = 0.3f;
+ private static final float EEP_PERCENT = 0.15f;
+ private static final float FADE_PERCENT = 0.15f;
- private final AbstractionEngineGame game;
+ private final AbstractionEngineGame game;
- private Stage stage;
- private Logo logo;
- private Penguin penguin;
- private Group animationGroup;
+ private Stage stage;
+ private Logo logo;
+ private Penguin penguin;
+ private Group animationGroup;
- /**
- * Screen lifecycle hook.
- */
- @Override
- public void show() {
- stage = new Stage(game.viewport, game.batch);
- logo = new Logo();
- penguin = new Penguin();
- animationGroup = new Group();
+ /**
+ * Screen lifecycle hook.
+ */
+ @Override
+ public void show() {
+ stage = new Stage(game.viewport, game.batch);
+ logo = new Logo();
+ penguin = new Penguin();
+ animationGroup = new Group();
- final float worldWidth = game.viewport.getWorldWidth();
- final float worldHeight = game.viewport.getWorldHeight();
- final float logoWidth = LOGO_HEIGHT * ((float) logo.getWidth() / logo.getHeight());
+ final float worldWidth = game.viewport.getWorldWidth();
+ final float worldHeight = game.viewport.getWorldHeight();
+ final float logoWidth = LOGO_HEIGHT * ((float) logo.getWidth() / logo.getHeight());
- logo.setSize(logoWidth, LOGO_HEIGHT);
- logo.setPosition(0, 0);
+ logo.setSize(logoWidth, LOGO_HEIGHT);
+ logo.setPosition(0, 0);
- penguin.setSize(PENGUIN_SIZE, PENGUIN_SIZE);
- penguin.setPosition((logoWidth - PENGUIN_SIZE) / 2f, -PENGUIN_SIZE - 6f);
- penguin.setState(Penguin.State.TOBAGGON);
+ penguin.setSize(PENGUIN_SIZE, PENGUIN_SIZE);
+ penguin.setPosition((logoWidth - PENGUIN_SIZE) / 2f, -PENGUIN_SIZE - 6f);
+ penguin.setState(Penguin.State.TOBAGGON);
- animationGroup.addActor(logo);
- animationGroup.addActor(penguin);
- animationGroup.setPosition((worldWidth - logoWidth) / 2f, worldHeight);
+ animationGroup.addActor(logo);
+ animationGroup.addActor(penguin);
+ animationGroup.setPosition((worldWidth - logoWidth) / 2f, worldHeight);
- stage.addActor(animationGroup);
+ stage.addActor(animationGroup);
- setupAnimations(worldWidth, worldHeight, logoWidth);
- }
+ setupAnimations(worldWidth, worldHeight, logoWidth);
+ }
- private void setupAnimations(final float worldWidth, final float worldHeight, final float logoWidth) {
- final float totalSeconds = SHOW_FOR.toMillis() / 1000f;
- final float scrollDuration = totalSeconds * SCROLL_PERCENT;
- final float eepyDuration = totalSeconds * EEPY_PERCENT;
- final float eepDuration = totalSeconds * EEP_PERCENT;
- final float fadeDuration = totalSeconds * FADE_PERCENT;
+ private void setupAnimations(final float worldWidth, final float worldHeight, final float logoWidth) {
+ final float totalSeconds = SHOW_FOR.toMillis() / 1000f;
+ final float scrollDuration = totalSeconds * SCROLL_PERCENT;
+ final float eepyDuration = totalSeconds * EEPY_PERCENT;
+ final float eepDuration = totalSeconds * EEP_PERCENT;
+ final float fadeDuration = totalSeconds * FADE_PERCENT;
- final float targetY = (worldHeight - LOGO_HEIGHT) / 2f;
+ final float targetY = (worldHeight - LOGO_HEIGHT) / 2f;
- animationGroup
- .addAction(Actions.sequence(Actions.moveTo((worldWidth - logoWidth) / 2f, targetY, scrollDuration),
- Actions.run(() -> penguin.setState(Penguin.State.EEPY)), Actions.delay(eepyDuration),
- Actions.run(() -> penguin.setState(Penguin.State.EEPING)), Actions.delay(eepDuration),
- Actions.fadeOut(fadeDuration), Actions.run(this::requestTransition)));
- }
+ animationGroup
+ .addAction(Actions.sequence(Actions.moveTo((worldWidth - logoWidth) / 2f, targetY, scrollDuration),
+ Actions.run(() -> penguin.setState(Penguin.State.EEPY)), Actions.delay(eepyDuration),
+ Actions.run(() -> penguin.setState(Penguin.State.EEPING)), Actions.delay(eepDuration),
+ Actions.fadeOut(fadeDuration), Actions.run(this::requestTransition)));
+ }
- /**
- * Screen render hook.
- *
- * @param delta
- * time since last frame
- */
- @Override
- public void render(final float delta) {
- game.viewport.apply();
- ScreenUtils.clear(Theme.BG);
- if (game.settings.isSkipIntro()) {
- requestTransition();
- return;
- }
+ /**
+ * Screen render hook.
+ *
+ * @param delta
+ * time since last frame
+ */
+ @Override
+ public void render(final float delta) {
+ game.viewport.apply();
+ ScreenUtils.clear(Theme.BG);
+ if (game.settings.isSkipIntro()) {
+ requestTransition();
+ return;
+ }
- stage.act(delta);
- stage.draw();
- }
+ stage.act(delta);
+ stage.draw();
+ }
- /**
- * Screen resize hook.
- *
- * @param width
- * new width in pixels
- * @param height
- * new height in pixels
- */
- @Override
- public void resize(final int width, final int height) {
- game.viewport.update(width, height, true);
- }
+ /**
+ * Screen resize hook.
+ *
+ * @param width
+ * new width in pixels
+ * @param height
+ * new height in pixels
+ */
+ @Override
+ public void resize(final int width, final int height) {
+ game.viewport.update(width, height, true);
+ }
- /**
- * Screen lifecycle hook.
- */
- @Override
- public void pause() {
- }
+ /**
+ * Screen lifecycle hook.
+ */
+ @Override
+ public void pause() {
+ }
- /**
- * Screen lifecycle hook.
- */
- @Override
- public void resume() {
- }
+ /**
+ * Screen lifecycle hook.
+ */
+ @Override
+ public void resume() {
+ }
- /**
- * Screen lifecycle hook.
- */
- @Override
- public void hide() {
- dispose();
- }
+ /**
+ * Screen lifecycle hook.
+ */
+ @Override
+ public void hide() {
+ dispose();
+ }
- /**
- * Screen cleanup hook.
- */
- @Override
- public void dispose() {
- if (logo != null) {
- logo.dispose();
- }
- if (penguin != null) {
- penguin.dispose();
- }
- if (stage != null) {
- stage.dispose();
- }
- }
+ /**
+ * Screen cleanup hook.
+ */
+ @Override
+ public void dispose() {
+ if (logo != null) {
+ logo.dispose();
+ }
+ if (penguin != null) {
+ penguin.dispose();
+ }
+ if (stage != null) {
+ stage.dispose();
+ }
+ }
- private void requestTransition() {
- game.setScreen(new MainMenu(game));
- }
+ private void requestTransition() {
+ game.setScreen(new MainMenu(game));
+ }
}
diff --git a/core/src/main/java/coffee/liz/abstractionengine/app/screen/game/FrameState.java b/core/src/main/java/coffee/liz/abstractionengine/app/screen/game/FrameState.java
index 3f31530..275771f 100644
--- a/core/src/main/java/coffee/liz/abstractionengine/app/screen/game/FrameState.java
+++ b/core/src/main/java/coffee/liz/abstractionengine/app/screen/game/FrameState.java
@@ -11,6 +11,6 @@ import java.util.function.Predicate;
@Getter
@RequiredArgsConstructor
public final class FrameState {
- private final Settings settings;
- private final Predicate<Integer> isKeyPressed;
+ private final Settings settings;
+ private final Predicate<Integer> isKeyPressed;
}
diff --git a/core/src/main/java/coffee/liz/abstractionengine/app/screen/game/GameScreenWorld.java b/core/src/main/java/coffee/liz/abstractionengine/app/screen/game/GameScreenWorld.java
index a0c0b5b..137a5b0 100644
--- a/core/src/main/java/coffee/liz/abstractionengine/app/screen/game/GameScreenWorld.java
+++ b/core/src/main/java/coffee/liz/abstractionengine/app/screen/game/GameScreenWorld.java
@@ -1,7 +1,7 @@
package coffee.liz.abstractionengine.app.screen.game;
import coffee.liz.abstractionengine.app.config.Settings;
-import coffee.liz.abstractionengine.app.screen.game.system.GameWorldManagementSystem;
+import coffee.liz.abstractionengine.app.screen.game.system.GridWorldBridgeSystem;
import coffee.liz.abstractionengine.app.screen.game.system.GridInterpolationSystem;
import coffee.liz.abstractionengine.app.screen.game.system.InputSystem;
import coffee.liz.abstractionengine.app.screen.game.system.RenderSystem;
@@ -12,9 +12,9 @@ import com.badlogic.gdx.utils.viewport.FitViewport;
import java.util.Map;
public class GameScreenWorld extends DAGWorld<FrameState> {
- public GameScreenWorld(final Vec2<Integer> gridSize, final FitViewport viewport, final Settings settings) {
- super(Map.of(InputSystem.class, new InputSystem(), GameWorldManagementSystem.class,
- new GameWorldManagementSystem(gridSize), GridInterpolationSystem.class, new GridInterpolationSystem(),
- RenderSystem.class, new RenderSystem(viewport, gridSize, settings)));
- }
+ public GameScreenWorld(final Vec2<Integer> gridSize, final FitViewport viewport, final Settings settings) {
+ super(Map.of(InputSystem.class, new InputSystem(), GridWorldBridgeSystem.class,
+ new GridWorldBridgeSystem(gridSize), GridInterpolationSystem.class, new GridInterpolationSystem(),
+ RenderSystem.class, new RenderSystem(viewport, gridSize, settings)));
+ }
}
diff --git a/core/src/main/java/coffee/liz/abstractionengine/app/screen/game/component/GridEntityRef.java b/core/src/main/java/coffee/liz/abstractionengine/app/screen/game/component/ActorHolder.java
index 788d530..ad9c432 100644
--- a/core/src/main/java/coffee/liz/abstractionengine/app/screen/game/component/GridEntityRef.java
+++ b/core/src/main/java/coffee/liz/abstractionengine/app/screen/game/component/ActorHolder.java
@@ -1,11 +1,12 @@
package coffee.liz.abstractionengine.app.screen.game.component;
import coffee.liz.ecs.model.Component;
+import com.badlogic.gdx.scenes.scene2d.Actor;
import lombok.Getter;
import lombok.RequiredArgsConstructor;
-@RequiredArgsConstructor
@Getter
-public final class GridEntityRef implements Component {
- private final int gridEntityId;
+@RequiredArgsConstructor
+public class ActorHolder implements Component {
+ private final Actor actor;
}
diff --git a/core/src/main/java/coffee/liz/abstractionengine/app/screen/game/component/ExternalWorldEntityRef.java b/core/src/main/java/coffee/liz/abstractionengine/app/screen/game/component/ExternalWorldEntityRef.java
new file mode 100644
index 0000000..a544a70
--- /dev/null
+++ b/core/src/main/java/coffee/liz/abstractionengine/app/screen/game/component/ExternalWorldEntityRef.java
@@ -0,0 +1,12 @@
+package coffee.liz.abstractionengine.app.screen.game.component;
+
+import coffee.liz.ecs.model.Component;
+import coffee.liz.ecs.model.Entity;
+import lombok.Getter;
+import lombok.RequiredArgsConstructor;
+
+@RequiredArgsConstructor
+@Getter
+public final class ExternalWorldEntityRef implements Component {
+ private final Entity entity;
+}
diff --git a/core/src/main/java/coffee/liz/abstractionengine/app/screen/game/component/InterpolatedPosition.java b/core/src/main/java/coffee/liz/abstractionengine/app/screen/game/component/InterpolatedPosition.java
deleted file mode 100644
index 6700575..0000000
--- a/core/src/main/java/coffee/liz/abstractionengine/app/screen/game/component/InterpolatedPosition.java
+++ /dev/null
@@ -1,18 +0,0 @@
-package coffee.liz.abstractionengine.app.screen.game.component;
-
-import coffee.liz.ecs.math.Vec2;
-import coffee.liz.ecs.model.Component;
-import lombok.Getter;
-import lombok.RequiredArgsConstructor;
-
-@RequiredArgsConstructor
-@Getter
-public final class InterpolatedPosition implements Component {
- private final Vec2<Float> from;
- private final Vec2<Float> to;
- private final Vec2<Float> current;
-
- public static InterpolatedPosition atRest(final Vec2<Float> position) {
- return new InterpolatedPosition(position, position, position);
- }
-}
diff --git a/core/src/main/java/coffee/liz/abstractionengine/app/screen/game/system/GameWorldManagementSystem.java b/core/src/main/java/coffee/liz/abstractionengine/app/screen/game/system/GameWorldManagementSystem.java
deleted file mode 100644
index 74355d1..0000000
--- a/core/src/main/java/coffee/liz/abstractionengine/app/screen/game/system/GameWorldManagementSystem.java
+++ /dev/null
@@ -1,100 +0,0 @@
-package coffee.liz.abstractionengine.app.screen.game.system;
-
-import coffee.liz.abstractionengine.AbstractionEngineGridWorld;
-import coffee.liz.abstractionengine.app.screen.game.FrameState;
-import coffee.liz.abstractionengine.app.screen.game.component.GridEntityRef;
-import coffee.liz.abstractionengine.app.screen.game.component.InterpolatedPosition;
-import coffee.liz.abstractionengine.app.utils.FunctionUtils;
-import coffee.liz.abstractionengine.entity.EntityFactory;
-import coffee.liz.abstractionengine.entity.EntityType;
-import coffee.liz.abstractionengine.grid.component.GridInputState;
-import coffee.liz.abstractionengine.grid.component.GridPosition;
-import coffee.liz.ecs.math.Vec2;
-import coffee.liz.ecs.math.Vec2i;
-import coffee.liz.ecs.model.Entity;
-import coffee.liz.ecs.model.System;
-import coffee.liz.ecs.model.World;
-import lombok.Getter;
-
-import java.time.Duration;
-import java.util.Collection;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.Map;
-import java.util.Set;
-
-public class GameWorldManagementSystem implements System<FrameState> {
- private final AbstractionEngineGridWorld gridWorld;
- private final Vec2<Integer> gridSize;
- private final Map<Integer, Entity> gridToOuterMap = new HashMap<>();
-
- @Getter
- private boolean stepped = false;
-
- public GameWorldManagementSystem(final Vec2<Integer> gridSize) {
- this.gridSize = gridSize;
- this.gridWorld = new AbstractionEngineGridWorld(gridSize);
- }
-
- public void populateLevel() {
- EntityFactory.populateRect(gridSize, gridWorld, EntityFactory.Wall::addToWorld);
- EntityFactory.Player.addToWorld(gridWorld, Vec2i.builder().y(10).x(10).build());
- EntityFactory.Abstraction.addToWorld(gridWorld, Vec2i.builder().y(10).x(12).build());
- EntityFactory.Abstraction.addToWorld(gridWorld, Vec2i.builder().y(10).x(13).build());
- gridWorld.update(GridInputState.builder().movement(Vec2i.ZERO).build());
- }
-
- @Override
- public Collection<Class<? extends System<FrameState>>> getDependencies() {
- return Set.of(InputSystem.class);
- }
-
- @Override
- public void update(final World<FrameState> world, final FrameState state, final Duration dt) {
- final InputSystem inputSystem = world.getSystem(InputSystem.class);
- final Vec2<Integer> movement = inputSystem.getStepMovement();
-
- stepped = !movement.equals(Vec2i.ZERO);
- if (stepped) {
- final GridInputState gridInput = GridInputState.builder().movement(movement).build();
- gridWorld.update(gridInput);
- }
-
- syncEntities(world);
- }
-
- private void syncEntities(final World<FrameState> outerWorld) {
- final Set<Entity> gridEntities = gridWorld.query(Set.of(GridPosition.class, EntityType.class));
- final Set<Integer> seenGridIds = new HashSet<>();
-
- for (final Entity gridEntity : gridEntities) {
- seenGridIds.add(gridEntity.getId());
-
- if (!gridToOuterMap.containsKey(gridEntity.getId())) {
- final Entity outer = outerWorld.createEntity();
- final Vec2<Float> pos = gridEntity.get(GridPosition.class).getPosition().floatValue();
- outer.add(new GridEntityRef(gridEntity.getId()));
- outer.add(gridEntity.get(EntityType.class));
- outer.add(InterpolatedPosition.atRest(pos));
- gridToOuterMap.put(gridEntity.getId(), outer);
- } else if (stepped) {
- final Entity outer = gridToOuterMap.get(gridEntity.getId());
- final InterpolatedPosition current = outer.get(InterpolatedPosition.class);
- final Vec2<Float> newTarget = gridEntity.get(GridPosition.class).getPosition().floatValue();
- outer.add(new InterpolatedPosition(current.getCurrent(), newTarget, current.getCurrent()));
- }
- }
-
- final Set<Integer> removedIds = new HashSet<>(gridToOuterMap.keySet());
- removedIds.removeAll(seenGridIds);
- for (final int removedId : removedIds) {
- final Entity outer = gridToOuterMap.remove(removedId);
- outerWorld.removeEntity(outer);
- }
- }
-
- @Override
- public void close() {
- FunctionUtils.wrapCheckedException(gridWorld::close);
- }
-}
diff --git a/core/src/main/java/coffee/liz/abstractionengine/app/screen/game/system/GridInterpolationSystem.java b/core/src/main/java/coffee/liz/abstractionengine/app/screen/game/system/GridInterpolationSystem.java
index 2e4826d..0d2d34b 100644
--- a/core/src/main/java/coffee/liz/abstractionengine/app/screen/game/system/GridInterpolationSystem.java
+++ b/core/src/main/java/coffee/liz/abstractionengine/app/screen/game/system/GridInterpolationSystem.java
@@ -1,9 +1,13 @@
package coffee.liz.abstractionengine.app.screen.game.system;
import coffee.liz.abstractionengine.app.screen.game.FrameState;
-import coffee.liz.abstractionengine.app.screen.game.component.InterpolatedPosition;
+import coffee.liz.abstractionengine.app.screen.game.component.ActorHolder;
+import coffee.liz.abstractionengine.app.screen.game.component.ExternalWorldEntityRef;
+import coffee.liz.abstractionengine.entity.EntityType;
+import coffee.liz.abstractionengine.grid.component.GridPosition;
import coffee.liz.ecs.math.Vec2;
import coffee.liz.ecs.math.Vec2f;
+import coffee.liz.ecs.model.Entity;
import coffee.liz.ecs.model.System;
import coffee.liz.ecs.model.World;
@@ -11,36 +15,56 @@ import java.time.Duration;
import java.util.Collection;
import java.util.Set;
+import com.badlogic.gdx.math.Interpolation;
+import com.badlogic.gdx.scenes.scene2d.Actor;
+import com.badlogic.gdx.scenes.scene2d.actions.MoveToAction;
+import lombok.extern.log4j.Log4j2;
+
+@Log4j2
public class GridInterpolationSystem implements System<FrameState> {
- private static final Duration INTERPOLATION_TIME = Duration.ofMillis(50);
+ private static final Duration INTERPOLATION_TIME = Duration.ofMillis(60);
- private Duration elapsed = Duration.ZERO;
+ @Override
+ public Collection<Class<? extends System<FrameState>>> getDependencies() {
+ return Set.of(GridWorldBridgeSystem.class);
+ }
- @Override
- public Collection<Class<? extends System<FrameState>>> getDependencies() {
- return Set.of(GameWorldManagementSystem.class);
- }
+ @Override
+ public void update(final World<FrameState> world, final FrameState state, final Duration dt) {
+ final GridWorldBridgeSystem bridgeSystem = world.getSystem(GridWorldBridgeSystem.class);
- @Override
- public void update(final World<FrameState> world, final FrameState state, final Duration dt) {
- final GameWorldManagementSystem gameWorldSystem = world.getSystem(GameWorldManagementSystem.class);
+ world.query(Set.of(ExternalWorldEntityRef.class, ActorHolder.class)).forEach(entity -> {
+ final Actor actor = entity.get(ActorHolder.class).getActor();
+ final boolean isAlreadyInterpolating = !actor.getActions().isEmpty();
+ if (isAlreadyInterpolating) {
+ return;
+ }
- if (gameWorldSystem.isStepped()) {
- elapsed = Duration.ZERO;
- }
+ final Entity ref = entity.get(ExternalWorldEntityRef.class).getEntity();
+ if (!ref.has(GridPosition.class)) {
+ return;
+ }
- elapsed = elapsed.plus(dt);
- final float t = Math.min(1.0f, (float) elapsed.toMillis() / INTERPOLATION_TIME.toMillis());
+ final Vec2<Float> position = Vec2f.builder().x(actor.getX()).y(actor.getY()).build();
+ final GridPosition gridPosition = ref.get(GridPosition.class);
+ final Vec2<Float> target = gridPosition.getPosition().floatValue().scale(bridgeSystem.getGridToWorld());
+ final boolean isAtTarget = target.minus(position).length() < 0.05;
+ if (isAtTarget) {
+ return;
+ }
- world.query(Set.of(InterpolatedPosition.class)).forEach(entity -> {
- final InterpolatedPosition pos = entity.get(InterpolatedPosition.class);
- final Vec2<Float> interpolated = lerp(pos.getFrom(), pos.getTo(), t);
- entity.add(new InterpolatedPosition(pos.getFrom(), pos.getTo(), interpolated));
- });
- }
+ final MoveToAction momentumAction = new MoveToAction();
+ momentumAction.setInterpolation(interpolationType(ref.get(EntityType.class)));
+ momentumAction.setPosition(target.getX(), target.getY());
+ momentumAction.setDuration(INTERPOLATION_TIME.toMillis() / 1000f);
+ actor.addAction(momentumAction);
+ });
+ }
- private static Vec2<Float> lerp(final Vec2<Float> from, final Vec2<Float> to, final float t) {
- return Vec2f.builder().x(from.getX() + (to.getX() - from.getX()) * t)
- .y(from.getY() + (to.getY() - from.getY()) * t).build();
- }
+ private Interpolation interpolationType(final EntityType type) {
+ return switch(type) {
+ case PLAYER -> Interpolation.pow3;
+ default -> new Interpolation.Swing(1.15f);
+ };
+ }
}
diff --git a/core/src/main/java/coffee/liz/abstractionengine/app/screen/game/system/GridWorldBridgeSystem.java b/core/src/main/java/coffee/liz/abstractionengine/app/screen/game/system/GridWorldBridgeSystem.java
new file mode 100644
index 0000000..52a21a6
--- /dev/null
+++ b/core/src/main/java/coffee/liz/abstractionengine/app/screen/game/system/GridWorldBridgeSystem.java
@@ -0,0 +1,119 @@
+package coffee.liz.abstractionengine.app.screen.game.system;
+
+import coffee.liz.abstractionengine.AbstractionEngineGridWorld;
+import coffee.liz.abstractionengine.app.AbstractionEngineGame;
+import coffee.liz.abstractionengine.app.actor.Abstraction;
+import coffee.liz.abstractionengine.app.actor.Penguin;
+import coffee.liz.abstractionengine.app.actor.Player;
+import coffee.liz.abstractionengine.app.actor.Wall;
+import coffee.liz.abstractionengine.app.screen.game.FrameState;
+import coffee.liz.abstractionengine.app.screen.game.component.ActorHolder;
+import coffee.liz.abstractionengine.app.screen.game.component.ExternalWorldEntityRef;
+import coffee.liz.abstractionengine.app.utils.FunctionUtils;
+import coffee.liz.abstractionengine.entity.EntityFactory;
+import coffee.liz.abstractionengine.entity.EntityType;
+import coffee.liz.abstractionengine.grid.component.GridInputState;
+import coffee.liz.abstractionengine.grid.component.GridPosition;
+import coffee.liz.ecs.math.Vec2;
+import coffee.liz.ecs.math.Vec2i;
+import coffee.liz.ecs.model.Entity;
+import coffee.liz.ecs.model.System;
+import coffee.liz.ecs.model.World;
+import lombok.Getter;
+
+import java.time.Duration;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+import java.util.stream.Collectors;
+
+import com.badlogic.gdx.scenes.scene2d.Actor;
+import com.badlogic.gdx.scenes.scene2d.Stage;
+
+public class GridWorldBridgeSystem implements System<FrameState> {
+ private final Map<Integer, Entity> outerIdToInnerEntity = new HashMap<>();
+ private final AbstractionEngineGridWorld outerWorld;
+ private final Vec2<Integer> gridSize;
+
+ @Getter
+ private final Vec2<Float> gridToWorld;
+ @Getter
+ private final Vec2<Float> worldToGrid;
+
+ public GridWorldBridgeSystem(final Vec2<Integer> gridSize) {
+ this.gridSize = gridSize;
+ this.outerWorld = new AbstractionEngineGridWorld(gridSize);
+
+ this.gridToWorld = AbstractionEngineGame.WORLD_SIZE.scale(gridSize.floatValue().transform(x -> 1f / x, y -> 1f / y));
+ this.worldToGrid = gridSize.floatValue().scale(AbstractionEngineGame.WORLD_SIZE.floatValue().transform(x -> 1f/x, y -> 1f/y));
+ }
+
+ public void initLevel() {
+ EntityFactory.populateRect(gridSize, outerWorld, EntityFactory.Wall::addToWorld);
+ EntityFactory.Player.addToWorld(outerWorld, Vec2i.builder().y(10).x(10).build());
+ EntityFactory.Abstraction.addToWorld(outerWorld, Vec2i.builder().y(10).x(12).build());
+ EntityFactory.Abstraction.addToWorld(outerWorld, Vec2i.builder().y(10).x(13).build());
+ outerWorld.update(GridInputState.builder().movement(Vec2i.ZERO).build());
+ }
+
+ @Override
+ public Collection<Class<? extends System<FrameState>>> getDependencies() {
+ return Set.of(InputSystem.class);
+ }
+
+ @Override
+ public void update(final World<FrameState> world, final FrameState state, final Duration dt) {
+ final InputSystem inputSystem = world.getSystem(InputSystem.class);
+ final GridInputState gridInputState = inputSystem.getGridInputState();
+ outerWorld.update(gridInputState);
+ syncEntities(world);
+ }
+
+ private void syncEntities(final World<FrameState> world) {
+ final Set<Entity> gridEntities = outerWorld.query(Set.of(GridPosition.class, EntityType.class));
+ final Set<Integer> seenGridIds = new HashSet<>();
+
+ for (final Entity gridEntity : gridEntities) {
+ seenGridIds.add(gridEntity.getId());
+
+ final boolean isNewEntity = !outerIdToInnerEntity.containsKey(gridEntity.getId());
+ if (!isNewEntity) {
+ continue;
+ }
+
+ final Entity outer = world.createEntity();
+ outer.add(new ActorHolder(
+ createActor(gridEntity.get(EntityType.class), world.getSystem(RenderSystem.class).getStage())));
+ outer.add(new ExternalWorldEntityRef(gridEntity));
+ outer.add(gridEntity.get(EntityType.class));
+ outerIdToInnerEntity.put(gridEntity.getId(), outer);
+ }
+
+ final Set<Integer> outerRemoved = gridEntities.stream().map(Entity::getId)
+ .filter(id -> !seenGridIds.contains(id)).collect(Collectors.toSet());
+
+ for (final int removedId : outerRemoved) {
+ world.removeEntity(outerIdToInnerEntity.get(removedId));
+ outerIdToInnerEntity.remove(removedId);
+ }
+ }
+
+ @Override
+ public void close() {
+ FunctionUtils.wrapCheckedException(outerWorld::close);
+ }
+
+ private Actor createActor(final EntityType type, final Stage stage) {
+ final Actor actor = switch (type) {
+ case PLAYER -> new Penguin();
+ case ABSTRACTION -> new Abstraction();
+ case WALL -> new Wall();
+ default -> throw new UnsupportedOperationException();
+ };
+ actor.setBounds(0, 0, getGridToWorld().getX(), getGridToWorld().getX());
+ stage.addActor(actor);
+ return actor;
+ }
+}
diff --git a/core/src/main/java/coffee/liz/abstractionengine/app/screen/game/system/InputSystem.java b/core/src/main/java/coffee/liz/abstractionengine/app/screen/game/system/InputSystem.java
index b311221..b8e3782 100644
--- a/core/src/main/java/coffee/liz/abstractionengine/app/screen/game/system/InputSystem.java
+++ b/core/src/main/java/coffee/liz/abstractionengine/app/screen/game/system/InputSystem.java
@@ -2,73 +2,75 @@ package coffee.liz.abstractionengine.app.screen.game.system;
import coffee.liz.abstractionengine.app.config.KeyBinds;
import coffee.liz.abstractionengine.app.screen.game.FrameState;
+import coffee.liz.abstractionengine.grid.component.GridInputState;
import coffee.liz.ecs.math.Vec2;
import coffee.liz.ecs.math.Vec2i;
import coffee.liz.ecs.model.System;
import coffee.liz.ecs.model.World;
-import lombok.Getter;
import java.time.Duration;
import java.util.Collection;
import java.util.Set;
public class InputSystem implements System<FrameState> {
- private static final Duration INITIAL_DELAY = Duration.ofMillis(200);
- private static final Duration REPEAT_INTERVAL = Duration.ofMillis(80);
+ private static final Duration INITIAL_DELAY = Duration.ofMillis(200);
+ private static final Duration REPEAT_INTERVAL = Duration.ofMillis(80);
- private KeyBinds.Action heldAction = null;
- private Duration heldTime = Duration.ZERO;
- private boolean pastInitialDelay = false;
+ private KeyBinds.Action heldAction = null;
+ private Duration heldTime = Duration.ZERO;
+ private boolean pastInitialDelay = false;
+ private Vec2<Integer> stepMovement = Vec2i.ZERO;
- @Getter
- private Vec2<Integer> stepMovement = Vec2i.ZERO;
+ public GridInputState getGridInputState() {
+ return GridInputState.builder().movement(stepMovement).build();
+ }
- @Override
- public Collection<Class<? extends System<FrameState>>> getDependencies() {
- return Set.of();
- }
+ @Override
+ public Collection<Class<? extends System<FrameState>>> getDependencies() {
+ return Set.of();
+ }
- @Override
- public void update(final World<FrameState> world, final FrameState state, final Duration dt) {
- final Set<KeyBinds.Action> currentlyActive = state.getSettings().getKeyBinds()
- .filterActiveActions(state.getIsKeyPressed());
+ @Override
+ public void update(final World<FrameState> world, final FrameState state, final Duration dt) {
+ final Set<KeyBinds.Action> currentlyActive = state.getSettings().getKeyBinds()
+ .filterActiveActions(state.getIsKeyPressed());
- if (currentlyActive.isEmpty()) {
- heldAction = null;
- stepMovement = Vec2i.ZERO;
- return;
- }
+ if (currentlyActive.isEmpty()) {
+ heldAction = null;
+ stepMovement = Vec2i.ZERO;
+ return;
+ }
- final KeyBinds.Action active = currentlyActive.contains(heldAction)
- ? heldAction
- : currentlyActive.iterator().next();
+ final KeyBinds.Action active = currentlyActive.contains(heldAction)
+ ? heldAction
+ : currentlyActive.iterator().next();
- if (!active.equals(heldAction)) {
- heldAction = active;
- heldTime = Duration.ZERO;
- pastInitialDelay = false;
- stepMovement = actionToMovement(active);
- } else {
- heldTime = heldTime.plus(dt);
- if (!pastInitialDelay && heldTime.compareTo(INITIAL_DELAY) >= 0) {
- pastInitialDelay = true;
- heldTime = heldTime.minus(INITIAL_DELAY);
- stepMovement = actionToMovement(active);
- } else if (pastInitialDelay && heldTime.compareTo(REPEAT_INTERVAL) >= 0) {
- heldTime = heldTime.minus(REPEAT_INTERVAL);
- stepMovement = actionToMovement(active);
- } else {
- stepMovement = Vec2i.ZERO;
- }
- }
- }
+ if (!active.equals(heldAction)) {
+ heldAction = active;
+ heldTime = Duration.ZERO;
+ pastInitialDelay = false;
+ stepMovement = actionToMovement(active);
+ } else {
+ heldTime = heldTime.plus(dt);
+ if (!pastInitialDelay && heldTime.compareTo(INITIAL_DELAY) >= 0) {
+ pastInitialDelay = true;
+ heldTime = heldTime.minus(INITIAL_DELAY);
+ stepMovement = actionToMovement(active);
+ } else if (pastInitialDelay && heldTime.compareTo(REPEAT_INTERVAL) >= 0) {
+ heldTime = heldTime.minus(REPEAT_INTERVAL);
+ stepMovement = actionToMovement(active);
+ } else {
+ stepMovement = Vec2i.ZERO;
+ }
+ }
+ }
- private static Vec2<Integer> actionToMovement(final KeyBinds.Action action) {
- return switch (action) {
- case MOVE_UP -> Vec2i.NORTH;
- case MOVE_DOWN -> Vec2i.SOUTH;
- case MOVE_LEFT -> Vec2i.WEST;
- case MOVE_RIGHT -> Vec2i.EAST;
- };
- }
+ private static Vec2<Integer> actionToMovement(final KeyBinds.Action action) {
+ return switch (action) {
+ case MOVE_UP -> Vec2i.NORTH;
+ case MOVE_DOWN -> Vec2i.SOUTH;
+ case MOVE_LEFT -> Vec2i.WEST;
+ case MOVE_RIGHT -> Vec2i.EAST;
+ };
+ }
}
diff --git a/core/src/main/java/coffee/liz/abstractionengine/app/screen/game/system/RenderSystem.java b/core/src/main/java/coffee/liz/abstractionengine/app/screen/game/system/RenderSystem.java
index 9a839d8..0bb4f54 100644
--- a/core/src/main/java/coffee/liz/abstractionengine/app/screen/game/system/RenderSystem.java
+++ b/core/src/main/java/coffee/liz/abstractionengine/app/screen/game/system/RenderSystem.java
@@ -1,16 +1,15 @@
package coffee.liz.abstractionengine.app.screen.game.system;
import coffee.liz.abstractionengine.app.Theme;
-import coffee.liz.abstractionengine.app.actor.GridBoardActor;
import coffee.liz.abstractionengine.app.config.Settings;
import coffee.liz.abstractionengine.app.screen.game.FrameState;
-import coffee.liz.abstractionengine.app.screen.game.component.InterpolatedPosition;
import coffee.liz.abstractionengine.app.ui.editor.LambdaEditor;
-import coffee.liz.abstractionengine.entity.EntityType;
import coffee.liz.ecs.math.Vec2;
import coffee.liz.ecs.math.Vec2f;
import coffee.liz.ecs.model.System;
import coffee.liz.ecs.model.World;
+import lombok.Getter;
+
import com.badlogic.gdx.InputMultiplexer;
import com.badlogic.gdx.InputProcessor;
import com.badlogic.gdx.graphics.glutils.ShapeRenderer;
@@ -22,83 +21,82 @@ import com.kotcrab.vis.ui.VisUI;
import java.time.Duration;
import java.util.Collection;
-import java.util.List;
import java.util.Set;
public class RenderSystem implements System<FrameState> {
- private final FitViewport viewport;
- private final Vec2<Integer> gridSize;
- private final ShapeRenderer shapeRenderer;
- private final Stage stage;
- private final Stage uiStage;
- private final GridBoardActor boardActor;
- private final InputMultiplexer inputMultiplexer;
+ private final FitViewport viewport;
+ private final Vec2<Integer> gridSize;
+ private final ShapeRenderer shapeRenderer;
+ @Getter
+ private final Stage stage;
+ private final Stage uiStage;
+ private final InputMultiplexer inputMultiplexer;
- public RenderSystem(final FitViewport viewport, final Vec2<Integer> gridSize, final Settings settings) {
- this.viewport = viewport;
- this.gridSize = gridSize;
- this.shapeRenderer = new ShapeRenderer();
- this.stage = new Stage(viewport);
- this.boardActor = new GridBoardActor(shapeRenderer, gridSize);
+ public RenderSystem(final FitViewport viewport, final Vec2<Integer> gridSize, final Settings settings) {
+ this.viewport = viewport;
+ this.gridSize = gridSize;
+ this.shapeRenderer = new ShapeRenderer();
+ this.stage = new Stage(viewport);
- stage.addActor(boardActor);
+ // stage.addActor(boardActor);
- VisUI.load();
- this.uiStage = new Stage(new ScreenViewport());
- uiStage.addActor(new LambdaEditor(settings.isVimMode()));
+ VisUI.load();
+ this.uiStage = new Stage(new ScreenViewport());
+ uiStage.addActor(new LambdaEditor(settings.isVimMode()));
- // TODO: Move this to an input system
- this.inputMultiplexer = new InputMultiplexer(uiStage, stage);
- }
+ // TODO: Move this to an input system
+ this.inputMultiplexer = new InputMultiplexer(uiStage, stage);
+ }
- public InputProcessor getInputProcessor() {
- return inputMultiplexer;
- }
+ public InputProcessor getInputProcessor() {
+ return inputMultiplexer;
+ }
- public void resize(final int width, final int height) {
- uiStage.getViewport().update(width, height, true);
- }
+ public void resize(final int width, final int height) {
+ uiStage.getViewport().update(width, height, true);
+ }
- @Override
- public Collection<Class<? extends System<FrameState>>> getDependencies() {
- return Set.of(GridInterpolationSystem.class);
- }
+ @Override
+ public Collection<Class<? extends System<FrameState>>> getDependencies() {
+ return Set.of(GridInterpolationSystem.class);
+ }
- @Override
- public void update(final World<FrameState> world, final FrameState state, final Duration dt) {
- ScreenUtils.clear(Theme.BG);
+ @Override
+ public void update(final World<FrameState> world, final FrameState state, final Duration dt) {
+ ScreenUtils.clear(Theme.BG);
- final Vec2<Float> cellSize = computeCellSize();
- final List<GridBoardActor.RenderableEntity> renderables = world
- .query(Set.of(InterpolatedPosition.class, EntityType.class)).stream().map(entity -> {
- final InterpolatedPosition pos = entity.get(InterpolatedPosition.class);
- final EntityType type = entity.get(EntityType.class);
- final Vec2<Float> drawPos = pos.getCurrent().scale(cellSize);
- return new GridBoardActor.RenderableEntity(type, drawPos, cellSize);
- }).toList();
+ final Vec2<Float> cellSize = computeCellSize();
+ // final List<GridBoardActor.RenderableEntity> renderables = world
+ // .query(Set.of(InterpolatedPosition.class,
+ // EntityType.class)).stream().map(entity -> {
+ // final InterpolatedPosition pos = entity.get(InterpolatedPosition.class);
+ // final EntityType type = entity.get(EntityType.class);
+ // final Vec2<Float> drawPos = pos.getCurrent().scale(cellSize);
+ // return new GridBoardActor.RenderableEntity(type, drawPos, cellSize);
+ // }).toList();
- boardActor.setCellSize(cellSize);
- boardActor.setEntities(renderables);
+ // boardActor.setCellSize(cellSize);
+ // boardActor.setEntities(renderables);
- final float deltaSeconds = dt.toMillis() / 1000f;
- stage.act(deltaSeconds);
- stage.draw();
+ final float deltaSeconds = dt.toMillis() / 1000f;
+ stage.act(deltaSeconds);
+ stage.draw();
- uiStage.getViewport().apply();
- uiStage.act(deltaSeconds);
- uiStage.draw();
- }
+ uiStage.getViewport().apply();
+ uiStage.act(deltaSeconds);
+ uiStage.draw();
+ }
- @Override
- public void close() {
- uiStage.dispose();
- stage.dispose();
- shapeRenderer.dispose();
- VisUI.dispose();
- }
+ @Override
+ public void close() {
+ uiStage.dispose();
+ stage.dispose();
+ shapeRenderer.dispose();
+ VisUI.dispose();
+ }
- private Vec2<Float> computeCellSize() {
- return Vec2f.builder().x(viewport.getWorldWidth() / gridSize.getX())
- .y(viewport.getWorldHeight() / gridSize.getY()).build();
- }
+ private Vec2<Float> computeCellSize() {
+ return Vec2f.builder().x(viewport.getWorldWidth() / gridSize.getX())
+ .y(viewport.getWorldHeight() / gridSize.getY()).build();
+ }
}
diff --git a/core/src/main/java/coffee/liz/abstractionengine/app/ui/editor/CursorStyle.java b/core/src/main/java/coffee/liz/abstractionengine/app/ui/editor/CursorStyle.java
index c8b82af..f4c75b3 100644
--- a/core/src/main/java/coffee/liz/abstractionengine/app/ui/editor/CursorStyle.java
+++ b/core/src/main/java/coffee/liz/abstractionengine/app/ui/editor/CursorStyle.java
@@ -1,5 +1,5 @@
package coffee.liz.abstractionengine.app.ui.editor;
public enum CursorStyle {
- CARET, BLOCK, CARET_AND_BLOCK, HIDDEN
+ CARET, BLOCK, CARET_AND_BLOCK, HIDDEN
}
diff --git a/core/src/main/java/coffee/liz/abstractionengine/app/ui/editor/EditorModifier.java b/core/src/main/java/coffee/liz/abstractionengine/app/ui/editor/EditorModifier.java
index fa9dd00..b8f6802 100644
--- a/core/src/main/java/coffee/liz/abstractionengine/app/ui/editor/EditorModifier.java
+++ b/core/src/main/java/coffee/liz/abstractionengine/app/ui/editor/EditorModifier.java
@@ -1,5 +1,5 @@
package coffee.liz.abstractionengine.app.ui.editor;
public enum EditorModifier {
- CTRL, ALT, SHIFT, META
+ CTRL, ALT, SHIFT, META
}
diff --git a/core/src/main/java/coffee/liz/abstractionengine/app/ui/editor/EditorTextArea.java b/core/src/main/java/coffee/liz/abstractionengine/app/ui/editor/EditorTextArea.java
index e2570b4..144141f 100644
--- a/core/src/main/java/coffee/liz/abstractionengine/app/ui/editor/EditorTextArea.java
+++ b/core/src/main/java/coffee/liz/abstractionengine/app/ui/editor/EditorTextArea.java
@@ -21,254 +21,254 @@ import java.util.EnumSet;
import java.util.Set;
public class EditorTextArea extends EditorHighlightTextAreaBridge {
- private static final Color CURRENT_LINE_COLOR = new Color(Theme.SURFACE_ALT.r, Theme.SURFACE_ALT.g,
- Theme.SURFACE_ALT.b, 0.5f);
- private static final Color BLOCK_CURSOR_COLOR = new Color(Theme.FG.r, Theme.FG.g, Theme.FG.b, 0.7f);
- private static final Set<EditorModifier> EMPTY_MODIFIERS = Set.of();
- private static final Drawable INVISIBLE_CURSOR = new BaseDrawable() {
- };
+ private static final Color CURRENT_LINE_COLOR = new Color(Theme.SURFACE_ALT.r, Theme.SURFACE_ALT.g,
+ Theme.SURFACE_ALT.b, 0.5f);
+ private static final Color BLOCK_CURSOR_COLOR = new Color(Theme.FG.r, Theme.FG.g, Theme.FG.b, 0.7f);
+ private static final Set<EditorModifier> EMPTY_MODIFIERS = Set.of();
+ private static final Drawable INVISIBLE_CURSOR = new BaseDrawable() {
+ };
- private final float gutterWidth;
- private final float charWidth;
- private final ShapeRenderer shapeRenderer;
- @Setter
- private InputStrategy inputStrategy;
+ private final float gutterWidth;
+ private final float charWidth;
+ private final ShapeRenderer shapeRenderer;
+ @Setter
+ private InputStrategy inputStrategy;
- public EditorTextArea(final String text, final VisTextFieldStyle style, final float gutterWidth) {
- super(text, padStyle(style, gutterWidth));
- this.gutterWidth = gutterWidth;
- this.charWidth = style.font.getData().spaceXadvance;
- this.shapeRenderer = new ShapeRenderer();
- }
+ public EditorTextArea(final String text, final VisTextFieldStyle style, final float gutterWidth) {
+ super(text, padStyle(style, gutterWidth));
+ this.gutterWidth = gutterWidth;
+ this.charWidth = style.font.getData().spaceXadvance;
+ this.shapeRenderer = new ShapeRenderer();
+ }
- public void syncCursorState() {
- editorSyncCursorState();
- scrollCursorIntoView();
- }
+ public void syncCursorState() {
+ editorSyncCursorState();
+ scrollCursorIntoView();
+ }
- public void setSelectionEndpoints(final int selectionStart, final int cursorPosition) {
- editorSetSelectionEndpoints(selectionStart, cursorPosition);
- scrollCursorIntoView();
- }
+ public void setSelectionEndpoints(final int selectionStart, final int cursorPosition) {
+ editorSetSelectionEndpoints(selectionStart, cursorPosition);
+ scrollCursorIntoView();
+ }
- public void setCursorKeepingSelection(final int cursorPosition) {
- editorSetCursorKeepingSelection(cursorPosition);
- scrollCursorIntoView();
- }
+ public void setCursorKeepingSelection(final int cursorPosition) {
+ editorSetCursorKeepingSelection(cursorPosition);
+ scrollCursorIntoView();
+ }
- @Override
- protected InputListener createInputListener() {
- return new TextAreaListener() {
- @Override
- public boolean keyDown(final InputEvent event, final int keycode) {
- if (inputStrategy != null) {
- final KeyEvent keyEvent = new KeyEvent(keycode, currentModifiers());
- if (inputStrategy.onKeyDown(keyEvent)) {
- return true;
- }
- }
- return super.keyDown(event, keycode);
- }
+ @Override
+ protected InputListener createInputListener() {
+ return new TextAreaListener() {
+ @Override
+ public boolean keyDown(final InputEvent event, final int keycode) {
+ if (inputStrategy != null) {
+ final KeyEvent keyEvent = new KeyEvent(keycode, currentModifiers());
+ if (inputStrategy.onKeyDown(keyEvent)) {
+ return true;
+ }
+ }
+ return super.keyDown(event, keycode);
+ }
- @Override
- public boolean keyTyped(final InputEvent event, final char character) {
- if (inputStrategy != null && inputStrategy.onKeyTyped(character)) {
- return true;
- }
- return super.keyTyped(event, character);
- }
+ @Override
+ public boolean keyTyped(final InputEvent event, final char character) {
+ if (inputStrategy != null && inputStrategy.onKeyTyped(character)) {
+ return true;
+ }
+ return super.keyTyped(event, character);
+ }
- @Override
- public void clicked(final InputEvent event, final float x, final float y) {
- final int count = getTapCount() % 4;
- if (count == 0) {
- clearSelection();
- }
- if (count == 2) {
- final Drawable bg = getStyle().background;
- final float adjustedX = bg != null ? Math.max(0, x - bg.getLeftWidth()) : x;
- final int[] word = wordUnderCursor(letterUnderCursor(adjustedX));
- setSelection(word[0], word[1]);
- }
- }
- };
- }
+ @Override
+ public void clicked(final InputEvent event, final float x, final float y) {
+ final int count = getTapCount() % 4;
+ if (count == 0) {
+ clearSelection();
+ }
+ if (count == 2) {
+ final Drawable bg = getStyle().background;
+ final float adjustedX = bg != null ? Math.max(0, x - bg.getLeftWidth()) : x;
+ final int[] word = wordUnderCursor(letterUnderCursor(adjustedX));
+ setSelection(word[0], word[1]);
+ }
+ }
+ };
+ }
- @Override
- protected void drawCursor(final Drawable cursorPatch, final Batch batch, final BitmapFont font, final float x,
- final float y) {
- if (shouldRenderBlockCursor()) {
- if (shouldRenderCaret()) {
- super.drawCursor(cursorPatch, batch, font, x, y);
- } else {
- super.drawCursor(INVISIBLE_CURSOR, batch, font, x, y);
- }
- return;
- }
+ @Override
+ protected void drawCursor(final Drawable cursorPatch, final Batch batch, final BitmapFont font, final float x,
+ final float y) {
+ if (shouldRenderBlockCursor()) {
+ if (shouldRenderCaret()) {
+ super.drawCursor(cursorPatch, batch, font, x, y);
+ } else {
+ super.drawCursor(INVISIBLE_CURSOR, batch, font, x, y);
+ }
+ return;
+ }
- if (shouldRenderCaret()) {
- super.drawCursor(cursorPatch, batch, font, x, y);
- }
- }
+ if (shouldRenderCaret()) {
+ super.drawCursor(cursorPatch, batch, font, x, y);
+ }
+ }
- @Override
- protected void drawText(final Batch batch, final BitmapFont font, final float x, final float y) {
- final float parentAlpha = font.getColor().a;
- final int first = getFirstLineShowing();
- final int count = getLinesShowing();
- final int total = getLineNumberCount();
- final int cursorLine = getCursorLine();
- final float lineHeight = font.getLineHeight();
+ @Override
+ protected void drawText(final Batch batch, final BitmapFont font, final float x, final float y) {
+ final float parentAlpha = font.getColor().a;
+ final int first = getFirstLineShowing();
+ final int count = getLinesShowing();
+ final int total = getLineNumberCount();
+ final int cursorLine = getCursorLine();
+ final float lineHeight = font.getLineHeight();
- batch.end();
- Gdx.gl.glEnable(GL20.GL_BLEND);
- shapeRenderer.setProjectionMatrix(batch.getProjectionMatrix());
- shapeRenderer.setTransformMatrix(batch.getTransformMatrix());
- shapeRenderer.begin(ShapeRenderer.ShapeType.Filled);
- if (cursorLine >= first && cursorLine < first + count) {
- final float highlightY = y - font.getCapHeight() + font.getDescent() - (cursorLine - first) * lineHeight;
- shapeRenderer.setColor(CURRENT_LINE_COLOR.r, CURRENT_LINE_COLOR.g, CURRENT_LINE_COLOR.b,
- CURRENT_LINE_COLOR.a * parentAlpha);
- shapeRenderer.rect(x - gutterWidth, highlightY, getWidth(), lineHeight);
- }
+ batch.end();
+ Gdx.gl.glEnable(GL20.GL_BLEND);
+ shapeRenderer.setProjectionMatrix(batch.getProjectionMatrix());
+ shapeRenderer.setTransformMatrix(batch.getTransformMatrix());
+ shapeRenderer.begin(ShapeRenderer.ShapeType.Filled);
+ if (cursorLine >= first && cursorLine < first + count) {
+ final float highlightY = y - font.getCapHeight() + font.getDescent() - (cursorLine - first) * lineHeight;
+ shapeRenderer.setColor(CURRENT_LINE_COLOR.r, CURRENT_LINE_COLOR.g, CURRENT_LINE_COLOR.b,
+ CURRENT_LINE_COLOR.a * parentAlpha);
+ shapeRenderer.rect(x - gutterWidth, highlightY, getWidth(), lineHeight);
+ }
- if (shouldRenderBlockCursor() && isFocused()) {
- // Keep VisTextArea cursor metrics current even when caret is hidden.
- super.drawCursor(INVISIBLE_CURSOR, batch, font, x, y);
- drawBlockCursor(font, x, y, first, cursorLine, lineHeight, parentAlpha);
- }
- shapeRenderer.end();
- Gdx.gl.glDisable(GL20.GL_BLEND);
- batch.begin();
+ if (shouldRenderBlockCursor() && isFocused()) {
+ // Keep VisTextArea cursor metrics current even when caret is hidden.
+ super.drawCursor(INVISIBLE_CURSOR, batch, font, x, y);
+ drawBlockCursor(font, x, y, first, cursorLine, lineHeight, parentAlpha);
+ }
+ shapeRenderer.end();
+ Gdx.gl.glDisable(GL20.GL_BLEND);
+ batch.begin();
- drawLineNumbers(batch, font, x, y, first, count, total, cursorLine, lineHeight, parentAlpha);
+ drawLineNumbers(batch, font, x, y, first, count, total, cursorLine, lineHeight, parentAlpha);
- font.setColor(1, 1, 1, parentAlpha);
- super.drawText(batch, font, x, y);
- }
+ font.setColor(1, 1, 1, parentAlpha);
+ super.drawText(batch, font, x, y);
+ }
- private static VisTextFieldStyle padStyle(final VisTextFieldStyle original, final float gutterWidth) {
- final VisTextFieldStyle style = new VisTextFieldStyle(original);
- style.background = wrapIfPresent(style.background, gutterWidth);
- style.backgroundOver = wrapIfPresent(style.backgroundOver, gutterWidth);
- style.focusedBackground = wrapIfPresent(style.focusedBackground, gutterWidth);
- style.disabledBackground = wrapIfPresent(style.disabledBackground, gutterWidth);
- return style;
- }
+ private static VisTextFieldStyle padStyle(final VisTextFieldStyle original, final float gutterWidth) {
+ final VisTextFieldStyle style = new VisTextFieldStyle(original);
+ style.background = wrapIfPresent(style.background, gutterWidth);
+ style.backgroundOver = wrapIfPresent(style.backgroundOver, gutterWidth);
+ style.focusedBackground = wrapIfPresent(style.focusedBackground, gutterWidth);
+ style.disabledBackground = wrapIfPresent(style.disabledBackground, gutterWidth);
+ return style;
+ }
- private static Drawable wrapIfPresent(final Drawable drawable, final float gutterWidth) {
- return drawable != null ? new GutterPaddedDrawable(drawable, gutterWidth) : null;
- }
+ private static Drawable wrapIfPresent(final Drawable drawable, final float gutterWidth) {
+ return drawable != null ? new GutterPaddedDrawable(drawable, gutterWidth) : null;
+ }
- private void drawLineNumbers(final Batch batch, final BitmapFont font, final float x, final float y,
- final int firstLine, final int visibleLineCount, final int totalLines, final int cursorLine,
- final float lineHeight, final float parentAlpha) {
- final LineNumberMode mode = resolveRenderState().lineNumberMode();
- if (mode == LineNumberMode.OFF) {
- return;
- }
+ private void drawLineNumbers(final Batch batch, final BitmapFont font, final float x, final float y,
+ final int firstLine, final int visibleLineCount, final int totalLines, final int cursorLine,
+ final float lineHeight, final float parentAlpha) {
+ final LineNumberMode mode = resolveRenderState().lineNumberMode();
+ if (mode == LineNumberMode.OFF) {
+ return;
+ }
- float offsetY = 0f;
- for (int line = firstLine; line < firstLine + visibleLineCount && line < totalLines; line++) {
- final Color color = line == cursorLine ? Theme.FG : Theme.BORDER_LIGHT;
- font.setColor(color.r, color.g, color.b, color.a * parentAlpha);
- final String lineNum = formatLineNumber(mode, line, cursorLine);
- font.draw(batch, lineNum, x - gutterWidth, y + offsetY);
- offsetY -= lineHeight;
- }
- }
+ float offsetY = 0f;
+ for (int line = firstLine; line < firstLine + visibleLineCount && line < totalLines; line++) {
+ final Color color = line == cursorLine ? Theme.FG : Theme.BORDER_LIGHT;
+ font.setColor(color.r, color.g, color.b, color.a * parentAlpha);
+ final String lineNum = formatLineNumber(mode, line, cursorLine);
+ font.draw(batch, lineNum, x - gutterWidth, y + offsetY);
+ offsetY -= lineHeight;
+ }
+ }
- private int getLineNumberCount() {
- final int totalLines = getLines();
- if (totalLines > 1 && getText().endsWith("\n")) {
- return totalLines - 1;
- }
- return totalLines;
- }
+ private int getLineNumberCount() {
+ final int totalLines = getLines();
+ if (totalLines > 1 && getText().endsWith("\n")) {
+ return totalLines - 1;
+ }
+ return totalLines;
+ }
- private String formatLineNumber(final LineNumberMode mode, final int line, final int cursorLine) {
- if (mode == LineNumberMode.RELATIVE && line != cursorLine) {
- return String.valueOf(Math.abs(line - cursorLine));
- }
- return String.valueOf(line + 1);
- }
+ private String formatLineNumber(final LineNumberMode mode, final int line, final int cursorLine) {
+ if (mode == LineNumberMode.RELATIVE && line != cursorLine) {
+ return String.valueOf(Math.abs(line - cursorLine));
+ }
+ return String.valueOf(line + 1);
+ }
- private void drawBlockCursor(final BitmapFont font, final float x, final float y, final int firstLine,
- final int cursorLine, final float lineHeight, final float parentAlpha) {
- final float cursorX = x + getCursorX();
- final float cursorY = y - font.getCapHeight() + font.getDescent() - (cursorLine - firstLine) * lineHeight;
- shapeRenderer.setColor(BLOCK_CURSOR_COLOR.r, BLOCK_CURSOR_COLOR.g, BLOCK_CURSOR_COLOR.b,
- BLOCK_CURSOR_COLOR.a * parentAlpha);
- shapeRenderer.rect(cursorX, cursorY, Math.max(1f, charWidth), lineHeight);
- }
+ private void drawBlockCursor(final BitmapFont font, final float x, final float y, final int firstLine,
+ final int cursorLine, final float lineHeight, final float parentAlpha) {
+ final float cursorX = x + getCursorX();
+ final float cursorY = y - font.getCapHeight() + font.getDescent() - (cursorLine - firstLine) * lineHeight;
+ shapeRenderer.setColor(BLOCK_CURSOR_COLOR.r, BLOCK_CURSOR_COLOR.g, BLOCK_CURSOR_COLOR.b,
+ BLOCK_CURSOR_COLOR.a * parentAlpha);
+ shapeRenderer.rect(cursorX, cursorY, Math.max(1f, charWidth), lineHeight);
+ }
- private boolean shouldRenderCaret() {
- final CursorStyle cursorStyle = resolveRenderState().cursorStyle();
- return cursorStyle == CursorStyle.CARET || cursorStyle == CursorStyle.CARET_AND_BLOCK;
- }
+ private boolean shouldRenderCaret() {
+ final CursorStyle cursorStyle = resolveRenderState().cursorStyle();
+ return cursorStyle == CursorStyle.CARET || cursorStyle == CursorStyle.CARET_AND_BLOCK;
+ }
- private boolean shouldRenderBlockCursor() {
- final CursorStyle cursorStyle = resolveRenderState().cursorStyle();
- return cursorStyle == CursorStyle.BLOCK || cursorStyle == CursorStyle.CARET_AND_BLOCK;
- }
+ private boolean shouldRenderBlockCursor() {
+ final CursorStyle cursorStyle = resolveRenderState().cursorStyle();
+ return cursorStyle == CursorStyle.BLOCK || cursorStyle == CursorStyle.CARET_AND_BLOCK;
+ }
- private RenderState resolveRenderState() {
- if (inputStrategy == null) {
- return RenderState.DEFAULT;
- }
- final RenderState renderState = inputStrategy.getRenderState();
- return renderState != null ? renderState : RenderState.DEFAULT;
- }
+ private RenderState resolveRenderState() {
+ if (inputStrategy == null) {
+ return RenderState.DEFAULT;
+ }
+ final RenderState renderState = inputStrategy.getRenderState();
+ return renderState != null ? renderState : RenderState.DEFAULT;
+ }
- private boolean isFocused() {
- final Stage stage = getStage();
- return stage != null && stage.getKeyboardFocus() == this && !isDisabled();
- }
+ private boolean isFocused() {
+ final Stage stage = getStage();
+ return stage != null && stage.getKeyboardFocus() == this && !isDisabled();
+ }
- private void scrollCursorIntoView() {
- if (!(getParent() instanceof ScrollPane scrollPane)) {
- return;
- }
+ private void scrollCursorIntoView() {
+ if (!(getParent() instanceof ScrollPane scrollPane)) {
+ return;
+ }
- final float lineHeight = getStyle().font.getLineHeight();
- final float cursorX = getCursorX();
- final float cursorY = getHeight() - getCursorY() + lineHeight;
- scrollPane.scrollTo(cursorX, cursorY, Math.max(1f, charWidth), lineHeight, false, false);
- }
+ final float lineHeight = getStyle().font.getLineHeight();
+ final float cursorX = getCursorX();
+ final float cursorY = getHeight() - getCursorY() + lineHeight;
+ scrollPane.scrollTo(cursorX, cursorY, Math.max(1f, charWidth), lineHeight, false, false);
+ }
- private Set<EditorModifier> currentModifiers() {
- if (Gdx.input == null) {
- return EMPTY_MODIFIERS;
- }
+ private Set<EditorModifier> currentModifiers() {
+ if (Gdx.input == null) {
+ return EMPTY_MODIFIERS;
+ }
- final EnumSet<EditorModifier> modifiers = EnumSet.noneOf(EditorModifier.class);
- if (Gdx.input.isKeyPressed(Input.Keys.CONTROL_LEFT) || Gdx.input.isKeyPressed(Input.Keys.CONTROL_RIGHT)) {
- modifiers.add(EditorModifier.CTRL);
- }
- if (Gdx.input.isKeyPressed(Input.Keys.ALT_LEFT) || Gdx.input.isKeyPressed(Input.Keys.ALT_RIGHT)) {
- modifiers.add(EditorModifier.ALT);
- }
- if (Gdx.input.isKeyPressed(Input.Keys.SHIFT_LEFT) || Gdx.input.isKeyPressed(Input.Keys.SHIFT_RIGHT)) {
- modifiers.add(EditorModifier.SHIFT);
- }
- if (Gdx.input.isKeyPressed(Input.Keys.SYM)) {
- modifiers.add(EditorModifier.META);
- }
- return modifiers.isEmpty() ? EMPTY_MODIFIERS : modifiers;
- }
+ final EnumSet<EditorModifier> modifiers = EnumSet.noneOf(EditorModifier.class);
+ if (Gdx.input.isKeyPressed(Input.Keys.CONTROL_LEFT) || Gdx.input.isKeyPressed(Input.Keys.CONTROL_RIGHT)) {
+ modifiers.add(EditorModifier.CTRL);
+ }
+ if (Gdx.input.isKeyPressed(Input.Keys.ALT_LEFT) || Gdx.input.isKeyPressed(Input.Keys.ALT_RIGHT)) {
+ modifiers.add(EditorModifier.ALT);
+ }
+ if (Gdx.input.isKeyPressed(Input.Keys.SHIFT_LEFT) || Gdx.input.isKeyPressed(Input.Keys.SHIFT_RIGHT)) {
+ modifiers.add(EditorModifier.SHIFT);
+ }
+ if (Gdx.input.isKeyPressed(Input.Keys.SYM)) {
+ modifiers.add(EditorModifier.META);
+ }
+ return modifiers.isEmpty() ? EMPTY_MODIFIERS : modifiers;
+ }
- private static final class GutterPaddedDrawable extends BaseDrawable {
- private final Drawable wrapped;
+ private static final class GutterPaddedDrawable extends BaseDrawable {
+ private final Drawable wrapped;
- GutterPaddedDrawable(final Drawable wrapped, final float gutterWidth) {
- super(wrapped);
- this.wrapped = wrapped;
- setLeftWidth(wrapped.getLeftWidth() + gutterWidth);
- }
+ GutterPaddedDrawable(final Drawable wrapped, final float gutterWidth) {
+ super(wrapped);
+ this.wrapped = wrapped;
+ setLeftWidth(wrapped.getLeftWidth() + gutterWidth);
+ }
- @Override
- public void draw(final Batch batch, final float x, final float y, final float width, final float height) {
- wrapped.draw(batch, x, y, width, height);
- }
- }
+ @Override
+ public void draw(final Batch batch, final float x, final float y, final float width, final float height) {
+ wrapped.draw(batch, x, y, width, height);
+ }
+ }
}
diff --git a/core/src/main/java/coffee/liz/abstractionengine/app/ui/editor/InputStrategy.java b/core/src/main/java/coffee/liz/abstractionengine/app/ui/editor/InputStrategy.java
index 49816d3..ba55466 100644
--- a/core/src/main/java/coffee/liz/abstractionengine/app/ui/editor/InputStrategy.java
+++ b/core/src/main/java/coffee/liz/abstractionengine/app/ui/editor/InputStrategy.java
@@ -1,11 +1,11 @@
package coffee.liz.abstractionengine.app.ui.editor;
public interface InputStrategy {
- boolean onKeyDown(KeyEvent event);
+ boolean onKeyDown(KeyEvent event);
- boolean onKeyTyped(char character);
+ boolean onKeyTyped(char character);
- default RenderState getRenderState() {
- return RenderState.DEFAULT;
- }
+ default RenderState getRenderState() {
+ return RenderState.DEFAULT;
+ }
}
diff --git a/core/src/main/java/coffee/liz/abstractionengine/app/ui/editor/KeyEvent.java b/core/src/main/java/coffee/liz/abstractionengine/app/ui/editor/KeyEvent.java
index 4da2f60..c4bade5 100644
--- a/core/src/main/java/coffee/liz/abstractionengine/app/ui/editor/KeyEvent.java
+++ b/core/src/main/java/coffee/liz/abstractionengine/app/ui/editor/KeyEvent.java
@@ -3,7 +3,7 @@ package coffee.liz.abstractionengine.app.ui.editor;
import java.util.Set;
public record KeyEvent(int keycode, Set<EditorModifier> modifiers) {
- public boolean hasModifier(final EditorModifier modifier) {
- return modifiers.contains(modifier);
- }
+ public boolean hasModifier(final EditorModifier modifier) {
+ return modifiers.contains(modifier);
+ }
}
diff --git a/core/src/main/java/coffee/liz/abstractionengine/app/ui/editor/LambdaEditor.java b/core/src/main/java/coffee/liz/abstractionengine/app/ui/editor/LambdaEditor.java
index 46fcb22..11a4b0e 100644
--- a/core/src/main/java/coffee/liz/abstractionengine/app/ui/editor/LambdaEditor.java
+++ b/core/src/main/java/coffee/liz/abstractionengine/app/ui/editor/LambdaEditor.java
@@ -15,66 +15,66 @@ import com.kotcrab.vis.ui.widget.VisTextField.VisTextFieldStyle;
import com.kotcrab.vis.ui.widget.VisWindow;
public class LambdaEditor extends VisWindow {
- private static final int FONT_SIZE = 15;
- private static final float WINDOW_ALPHA = 0.92f;
+ private static final int FONT_SIZE = 15;
+ private static final float WINDOW_ALPHA = 0.92f;
- private static final String DEFAULT_TEXT = "-- Church numerals\n" + "let zero = λf.λx.x;\n"
- + "let one = λf.λx.f x;\n" + "let succ = λn.λf.λx.f (n f x);\n" + "let add = λm.λn.λf.λx.m f (n f x);\n"
- + "\n" + "succ (add one zero)\n";
+ private static final String DEFAULT_TEXT = "-- Church numerals\n" + "let zero = λf.λx.x;\n"
+ + "let one = λf.λx.f x;\n" + "let succ = λn.λf.λx.f (n f x);\n" + "let add = λm.λn.λf.λx.m f (n f x);\n"
+ + "\n" + "succ (add one zero)\n";
- private final BitmapFont font;
+ private final BitmapFont font;
- public LambdaEditor(final boolean vimMode) {
- super("λ-editor");
+ public LambdaEditor(final boolean vimMode) {
+ super("λ-editor");
- TableUtils.setSpacingDefaults(this);
- columnDefaults(0).left();
+ TableUtils.setSpacingDefaults(this);
+ columnDefaults(0).left();
- this.font = FontHelper.initFont(FONT_SIZE, FontHelper.MONO, 1f);
+ this.font = FontHelper.initFont(FONT_SIZE, FontHelper.MONO, 1f);
- setResizable(true);
- addCloseButton();
- addEditor(vimMode);
+ setResizable(true);
+ addCloseButton();
+ addEditor(vimMode);
- setSize(400, 300);
- setColor(1, 1, 1, WINDOW_ALPHA);
- centerWindow();
- }
+ setSize(400, 300);
+ setColor(1, 1, 1, WINDOW_ALPHA);
+ centerWindow();
+ }
- private void addEditor(final boolean vimMode) {
- final VisTextFieldStyle style = new VisTextFieldStyle(VisUI.getSkin().get("textArea", VisTextFieldStyle.class));
- style.font = font;
+ private void addEditor(final boolean vimMode) {
+ final VisTextFieldStyle style = new VisTextFieldStyle(VisUI.getSkin().get("textArea", VisTextFieldStyle.class));
+ style.font = font;
- final GlyphLayout layout = new GlyphLayout(font, "000 ");
- final float gutterWidth = layout.width;
+ final GlyphLayout layout = new GlyphLayout(font, "000 ");
+ final float gutterWidth = layout.width;
- final EditorTextArea textArea = new EditorTextArea(DEFAULT_TEXT, style, gutterWidth);
- textArea.setHighlighter(createHighlighter());
+ final EditorTextArea textArea = new EditorTextArea(DEFAULT_TEXT, style, gutterWidth);
+ textArea.setHighlighter(createHighlighter());
- final ScrollPane scrollPane = textArea.createCompatibleScrollPane();
- scrollPane.setFadeScrollBars(false);
+ final ScrollPane scrollPane = textArea.createCompatibleScrollPane();
+ scrollPane.setFadeScrollBars(false);
- final VisLabel statusLabel = new VisLabel(vimMode ? "-- NORMAL --" : "-- INSERT --");
- statusLabel.setAlignment(Align.left);
+ final VisLabel statusLabel = new VisLabel(vimMode ? "-- NORMAL --" : "-- INSERT --");
+ statusLabel.setAlignment(Align.left);
- if (vimMode) {
- final VimEngine controller = new VimEngine(textArea, statusLabel::setText);
- textArea.setInputStrategy(controller);
- statusLabel.setText(controller.getStatusText());
- }
+ if (vimMode) {
+ final VimEngine controller = new VimEngine(textArea, statusLabel::setText);
+ textArea.setInputStrategy(controller);
+ statusLabel.setText(controller.getStatusText());
+ }
- add(scrollPane).grow().row();
- add(statusLabel).growX().padTop(6f);
- }
+ add(scrollPane).grow().row();
+ add(statusLabel).growX().padTop(6f);
+ }
- private static Highlighter createHighlighter() {
- final Highlighter highlighter = new Highlighter();
- highlighter.regex(Theme.MUTED, "--[^\\n]*");
- highlighter.regex(Theme.PRIMARY, "\\blet\\b");
- highlighter.regex(Theme.SECONDARY, "[λ\\\\]");
- highlighter.regex(Theme.SECONDARY, "\\.");
- highlighter.regex(Theme.BORDER_LIGHT, "[=;]");
- highlighter.regex(Theme.BORDER_LIGHT, "[()]");
- return highlighter;
- }
+ private static Highlighter createHighlighter() {
+ final Highlighter highlighter = new Highlighter();
+ highlighter.regex(Theme.MUTED, "--[^\\n]*");
+ highlighter.regex(Theme.PRIMARY, "\\blet\\b");
+ highlighter.regex(Theme.SECONDARY, "[λ\\\\]");
+ highlighter.regex(Theme.SECONDARY, "\\.");
+ highlighter.regex(Theme.BORDER_LIGHT, "[=;]");
+ highlighter.regex(Theme.BORDER_LIGHT, "[()]");
+ return highlighter;
+ }
}
diff --git a/core/src/main/java/coffee/liz/abstractionengine/app/ui/editor/LineNumberMode.java b/core/src/main/java/coffee/liz/abstractionengine/app/ui/editor/LineNumberMode.java
index 3ec768d..0ab0f20 100644
--- a/core/src/main/java/coffee/liz/abstractionengine/app/ui/editor/LineNumberMode.java
+++ b/core/src/main/java/coffee/liz/abstractionengine/app/ui/editor/LineNumberMode.java
@@ -1,5 +1,5 @@
package coffee.liz.abstractionengine.app.ui.editor;
public enum LineNumberMode {
- OFF, ABSOLUTE, RELATIVE
+ OFF, ABSOLUTE, RELATIVE
}
diff --git a/core/src/main/java/coffee/liz/abstractionengine/app/ui/editor/RenderState.java b/core/src/main/java/coffee/liz/abstractionengine/app/ui/editor/RenderState.java
index a04c988..8961cfa 100644
--- a/core/src/main/java/coffee/liz/abstractionengine/app/ui/editor/RenderState.java
+++ b/core/src/main/java/coffee/liz/abstractionengine/app/ui/editor/RenderState.java
@@ -1,5 +1,5 @@
package coffee.liz.abstractionengine.app.ui.editor;
public record RenderState(CursorStyle cursorStyle, LineNumberMode lineNumberMode) {
- public static final RenderState DEFAULT = new RenderState(CursorStyle.CARET, LineNumberMode.ABSOLUTE);
+ public static final RenderState DEFAULT = new RenderState(CursorStyle.CARET, LineNumberMode.ABSOLUTE);
}
diff --git a/core/src/main/java/coffee/liz/abstractionengine/app/ui/editor/vim/EditorBuffer.java b/core/src/main/java/coffee/liz/abstractionengine/app/ui/editor/vim/EditorBuffer.java
index eadc8e8..0ccde34 100644
--- a/core/src/main/java/coffee/liz/abstractionengine/app/ui/editor/vim/EditorBuffer.java
+++ b/core/src/main/java/coffee/liz/abstractionengine/app/ui/editor/vim/EditorBuffer.java
@@ -1,21 +1,21 @@
package coffee.liz.abstractionengine.app.ui.editor.vim;
public interface EditorBuffer {
- String getText();
+ String getText();
- void setText(String text);
+ void setText(String text);
- int getCursorPosition();
+ int getCursorPosition();
- void setCursorPosition(int cursorPosition);
+ void setCursorPosition(int cursorPosition);
- int getCursorLine();
+ int getCursorLine();
- int getLines();
+ int getLines();
- void moveCursorLine(int line);
+ void moveCursorLine(int line);
- void setSelectionEndpoints(int selectionStart, int cursorPosition);
+ void setSelectionEndpoints(int selectionStart, int cursorPosition);
- void clearSelection();
+ void clearSelection();
}
diff --git a/core/src/main/java/coffee/liz/abstractionengine/app/ui/editor/vim/Mode.java b/core/src/main/java/coffee/liz/abstractionengine/app/ui/editor/vim/Mode.java
index e470f91..97e1d62 100644
--- a/core/src/main/java/coffee/liz/abstractionengine/app/ui/editor/vim/Mode.java
+++ b/core/src/main/java/coffee/liz/abstractionengine/app/ui/editor/vim/Mode.java
@@ -1,5 +1,5 @@
package coffee.liz.abstractionengine.app.ui.editor.vim;
public enum Mode {
- NORMAL, INSERT, VISUAL, VISUAL_LINE, SEARCH
+ NORMAL, INSERT, VISUAL, VISUAL_LINE, SEARCH
}
diff --git a/core/src/main/java/coffee/liz/abstractionengine/app/ui/editor/vim/VimConfig.java b/core/src/main/java/coffee/liz/abstractionengine/app/ui/editor/vim/VimConfig.java
index 050790c..5b62f61 100644
--- a/core/src/main/java/coffee/liz/abstractionengine/app/ui/editor/vim/VimConfig.java
+++ b/core/src/main/java/coffee/liz/abstractionengine/app/ui/editor/vim/VimConfig.java
@@ -1,34 +1,34 @@
package coffee.liz.abstractionengine.app.ui.editor.vim;
public record VimConfig(int maxUndoStates, char ctrlRedoCharacter, String normalStatusLabel, String insertStatusLabel,
- String visualStatusLabel, String visualLineStatusLabel, boolean wrapSearch) {
- private static final int DEFAULT_MAX_UNDO_STATES = 200;
- private static final char DEFAULT_CTRL_REDO_CHARACTER = 18;
- private static final String DEFAULT_NORMAL_STATUS_LABEL = "-- NORMAL --";
- private static final String DEFAULT_INSERT_STATUS_LABEL = "-- INSERT --";
- private static final String DEFAULT_VISUAL_STATUS_LABEL = "-- VISUAL --";
- private static final String DEFAULT_VISUAL_LINE_STATUS_LABEL = "-- VISUAL LINE --";
+ String visualStatusLabel, String visualLineStatusLabel, boolean wrapSearch) {
+ private static final int DEFAULT_MAX_UNDO_STATES = 200;
+ private static final char DEFAULT_CTRL_REDO_CHARACTER = 18;
+ private static final String DEFAULT_NORMAL_STATUS_LABEL = "-- NORMAL --";
+ private static final String DEFAULT_INSERT_STATUS_LABEL = "-- INSERT --";
+ private static final String DEFAULT_VISUAL_STATUS_LABEL = "-- VISUAL --";
+ private static final String DEFAULT_VISUAL_LINE_STATUS_LABEL = "-- VISUAL LINE --";
- public VimConfig {
- if (maxUndoStates <= 0) {
- throw new IllegalArgumentException("maxUndoStates must be positive");
- }
- if (normalStatusLabel == null || normalStatusLabel.isEmpty()) {
- throw new IllegalArgumentException("normalStatusLabel must not be empty");
- }
- if (insertStatusLabel == null || insertStatusLabel.isEmpty()) {
- throw new IllegalArgumentException("insertStatusLabel must not be empty");
- }
- if (visualStatusLabel == null || visualStatusLabel.isEmpty()) {
- throw new IllegalArgumentException("visualStatusLabel must not be empty");
- }
- if (visualLineStatusLabel == null || visualLineStatusLabel.isEmpty()) {
- throw new IllegalArgumentException("visualLineStatusLabel must not be empty");
- }
- }
+ public VimConfig {
+ if (maxUndoStates <= 0) {
+ throw new IllegalArgumentException("maxUndoStates must be positive");
+ }
+ if (normalStatusLabel == null || normalStatusLabel.isEmpty()) {
+ throw new IllegalArgumentException("normalStatusLabel must not be empty");
+ }
+ if (insertStatusLabel == null || insertStatusLabel.isEmpty()) {
+ throw new IllegalArgumentException("insertStatusLabel must not be empty");
+ }
+ if (visualStatusLabel == null || visualStatusLabel.isEmpty()) {
+ throw new IllegalArgumentException("visualStatusLabel must not be empty");
+ }
+ if (visualLineStatusLabel == null || visualLineStatusLabel.isEmpty()) {
+ throw new IllegalArgumentException("visualLineStatusLabel must not be empty");
+ }
+ }
- public static VimConfig defaults() {
- return new VimConfig(DEFAULT_MAX_UNDO_STATES, DEFAULT_CTRL_REDO_CHARACTER, DEFAULT_NORMAL_STATUS_LABEL,
- DEFAULT_INSERT_STATUS_LABEL, DEFAULT_VISUAL_STATUS_LABEL, DEFAULT_VISUAL_LINE_STATUS_LABEL, true);
- }
+ public static VimConfig defaults() {
+ return new VimConfig(DEFAULT_MAX_UNDO_STATES, DEFAULT_CTRL_REDO_CHARACTER, DEFAULT_NORMAL_STATUS_LABEL,
+ DEFAULT_INSERT_STATUS_LABEL, DEFAULT_VISUAL_STATUS_LABEL, DEFAULT_VISUAL_LINE_STATUS_LABEL, true);
+ }
}
diff --git a/core/src/main/java/coffee/liz/abstractionengine/app/ui/editor/vim/VimEngine.java b/core/src/main/java/coffee/liz/abstractionengine/app/ui/editor/vim/VimEngine.java
index dd577fb..ab5f203 100644
--- a/core/src/main/java/coffee/liz/abstractionengine/app/ui/editor/vim/VimEngine.java
+++ b/core/src/main/java/coffee/liz/abstractionengine/app/ui/editor/vim/VimEngine.java
@@ -31,175 +31,175 @@ import java.util.Set;
import java.util.function.Consumer;
public class VimEngine implements InputStrategy {
- private final VimConfig config;
- private final KeyContext context;
- private final StatusFormatter statusFormatter;
- private final ModeHandler<NormalState> normalModeHandler;
- private final ModeHandler<InsertState> insertModeHandler;
- private final ModeHandler<VisualState> visualModeHandler;
- private final ModeHandler<VisualLineState> visualLineModeHandler;
- private final ModeHandler<SearchState> searchModeHandler;
+ private final VimConfig config;
+ private final KeyContext context;
+ private final StatusFormatter statusFormatter;
+ private final ModeHandler<NormalState> normalModeHandler;
+ private final ModeHandler<InsertState> insertModeHandler;
+ private final ModeHandler<VisualState> visualModeHandler;
+ private final ModeHandler<VisualLineState> visualLineModeHandler;
+ private final ModeHandler<SearchState> searchModeHandler;
- private ModeState state;
+ private ModeState state;
- public VimEngine(final EditorTextArea textArea, final Consumer<String> statusSink, final VimConfig config) {
- this(new TextAreaBuffer(textArea), statusSink, config);
- }
+ public VimEngine(final EditorTextArea textArea, final Consumer<String> statusSink, final VimConfig config) {
+ this(new TextAreaBuffer(textArea), statusSink, config);
+ }
- public VimEngine(final EditorTextArea textArea, final Consumer<String> statusSink) {
- this(textArea, statusSink, VimConfig.defaults());
- }
+ public VimEngine(final EditorTextArea textArea, final Consumer<String> statusSink) {
+ this(textArea, statusSink, VimConfig.defaults());
+ }
- public VimEngine(final EditorTextArea textArea) {
- this(textArea, null, VimConfig.defaults());
- }
+ public VimEngine(final EditorTextArea textArea) {
+ this(textArea, null, VimConfig.defaults());
+ }
- public VimEngine(final EditorBuffer buffer, final Consumer<String> statusSink, final VimConfig config) {
- this.config = config != null ? config : VimConfig.defaults();
- this.context = new KeyContext(buffer, statusSink, new TextNavigation(),
- new UndoManager(this.config.maxUndoStates()), new Register(), this.config);
- this.statusFormatter = new StatusFormatter();
- this.normalModeHandler = new NormalModeHandler();
- this.insertModeHandler = new InsertModeHandler();
- this.visualModeHandler = new VisualModeHandler();
- this.visualLineModeHandler = new VisualLineModeHandler();
- this.searchModeHandler = new SearchModeHandler();
- this.state = NormalState.DEFAULT;
- context.recordUndoState();
- publishStatus();
- }
+ public VimEngine(final EditorBuffer buffer, final Consumer<String> statusSink, final VimConfig config) {
+ this.config = config != null ? config : VimConfig.defaults();
+ this.context = new KeyContext(buffer, statusSink, new TextNavigation(),
+ new UndoManager(this.config.maxUndoStates()), new Register(), this.config);
+ this.statusFormatter = new StatusFormatter();
+ this.normalModeHandler = new NormalModeHandler();
+ this.insertModeHandler = new InsertModeHandler();
+ this.visualModeHandler = new VisualModeHandler();
+ this.visualLineModeHandler = new VisualLineModeHandler();
+ this.searchModeHandler = new SearchModeHandler();
+ this.state = NormalState.DEFAULT;
+ context.recordUndoState();
+ publishStatus();
+ }
- public VimEngine(final EditorBuffer buffer, final Consumer<String> statusSink) {
- this(buffer, statusSink, VimConfig.defaults());
- }
+ public VimEngine(final EditorBuffer buffer, final Consumer<String> statusSink) {
+ this(buffer, statusSink, VimConfig.defaults());
+ }
- @Override
- public boolean onKeyDown(final KeyEvent event) {
- return handleKeyDown(event);
- }
+ @Override
+ public boolean onKeyDown(final KeyEvent event) {
+ return handleKeyDown(event);
+ }
- @Override
- public boolean onKeyTyped(final char character) {
- return handleKeyTyped(character);
- }
+ @Override
+ public boolean onKeyTyped(final char character) {
+ return handleKeyTyped(character);
+ }
- @Override
- public RenderState getRenderState() {
- if (isBlockCursorMode(state)) {
- return new RenderState(CursorStyle.BLOCK, LineNumberMode.RELATIVE);
- }
- return new RenderState(CursorStyle.CARET, LineNumberMode.ABSOLUTE);
- }
+ @Override
+ public RenderState getRenderState() {
+ if (isBlockCursorMode(state)) {
+ return new RenderState(CursorStyle.BLOCK, LineNumberMode.RELATIVE);
+ }
+ return new RenderState(CursorStyle.CARET, LineNumberMode.ABSOLUTE);
+ }
- public String getStatusText() {
- return context.getStatusText();
- }
+ public String getStatusText() {
+ return context.getStatusText();
+ }
- public boolean handleKeyDown(final int keycode) {
- return handleKeyDown(new KeyEvent(keycode, Set.of()));
- }
+ public boolean handleKeyDown(final int keycode) {
+ return handleKeyDown(new KeyEvent(keycode, Set.of()));
+ }
- public boolean handleKeyDown(final int keycode, final boolean ctrlDown) {
- final Set<EditorModifier> modifiers = ctrlDown ? Set.of(EditorModifier.CTRL) : Set.of();
- return handleKeyDown(new KeyEvent(keycode, modifiers));
- }
+ public boolean handleKeyDown(final int keycode, final boolean ctrlDown) {
+ final Set<EditorModifier> modifiers = ctrlDown ? Set.of(EditorModifier.CTRL) : Set.of();
+ return handleKeyDown(new KeyEvent(keycode, modifiers));
+ }
- public boolean handleKeyDown(final KeyEvent event) {
- context.setCurrentKeyEvent(event);
- if (isInsertState(state)) {
- final boolean consumed = applyHandleResult(insertModeHandler.onKeyDown((InsertState) state, context));
- return consumed;
- }
+ public boolean handleKeyDown(final KeyEvent event) {
+ context.setCurrentKeyEvent(event);
+ if (isInsertState(state)) {
+ final boolean consumed = applyHandleResult(insertModeHandler.onKeyDown((InsertState) state, context));
+ return consumed;
+ }
- if (isRedoKeyDown(event)) {
- state = context.redoToNormalState();
- context.suppressNextRedoTyped();
- publishStatus();
- return true;
- }
+ if (isRedoKeyDown(event)) {
+ state = context.redoToNormalState();
+ context.suppressNextRedoTyped();
+ publishStatus();
+ return true;
+ }
- final HandleResult result = dispatchKeyDown(state);
- if (applyHandleResult(result)) {
- return true;
- }
+ final HandleResult result = dispatchKeyDown(state);
+ if (applyHandleResult(result)) {
+ return true;
+ }
- return !isInsertState(state);
- }
+ return !isInsertState(state);
+ }
- public boolean handleKeyTyped(final char character) {
- if (character == config.ctrlRedoCharacter()) {
- if (context.consumeRedoTypedSuppression()) {
- return true;
- }
- state = context.redoToNormalState();
- publishStatus();
- return true;
- }
+ public boolean handleKeyTyped(final char character) {
+ if (character == config.ctrlRedoCharacter()) {
+ if (context.consumeRedoTypedSuppression()) {
+ return true;
+ }
+ state = context.redoToNormalState();
+ publishStatus();
+ return true;
+ }
- if (context.consumeSuppressedTypedCommand()) {
- return true;
- }
- context.clearRedoTypedSuppression();
+ if (context.consumeSuppressedTypedCommand()) {
+ return true;
+ }
+ context.clearRedoTypedSuppression();
- if (isInsertState(state)) {
- return false;
- }
+ if (isInsertState(state)) {
+ return false;
+ }
- final HandleResult result = dispatchKeyTyped(state, character);
- if (applyHandleResult(result)) {
- return true;
- }
+ final HandleResult result = dispatchKeyTyped(state, character);
+ if (applyHandleResult(result)) {
+ return true;
+ }
- return !isInsertState(state);
- }
+ return !isInsertState(state);
+ }
- private HandleResult dispatchKeyDown(final ModeState modeState) {
- return switch (modeState) {
- case NormalState normalState -> normalModeHandler.onKeyDown(normalState, context);
- case InsertState insertState -> insertModeHandler.onKeyDown(insertState, context);
- case VisualState visualState -> visualModeHandler.onKeyDown(visualState, context);
- case VisualLineState visualLineState -> visualLineModeHandler.onKeyDown(visualLineState, context);
- case SearchState searchState -> searchModeHandler.onKeyDown(searchState, context);
- };
- }
+ private HandleResult dispatchKeyDown(final ModeState modeState) {
+ return switch (modeState) {
+ case NormalState normalState -> normalModeHandler.onKeyDown(normalState, context);
+ case InsertState insertState -> insertModeHandler.onKeyDown(insertState, context);
+ case VisualState visualState -> visualModeHandler.onKeyDown(visualState, context);
+ case VisualLineState visualLineState -> visualLineModeHandler.onKeyDown(visualLineState, context);
+ case SearchState searchState -> searchModeHandler.onKeyDown(searchState, context);
+ };
+ }
- private HandleResult dispatchKeyTyped(final ModeState modeState, final char character) {
- return switch (modeState) {
- case NormalState normalState -> normalModeHandler.onKeyTyped(normalState, character, context);
- case InsertState insertState -> insertModeHandler.onKeyTyped(insertState, character, context);
- case VisualState visualState -> visualModeHandler.onKeyTyped(visualState, character, context);
- case VisualLineState visualLineState ->
- visualLineModeHandler.onKeyTyped(visualLineState, character, context);
- case SearchState searchState -> searchModeHandler.onKeyTyped(searchState, character, context);
- };
- }
+ private HandleResult dispatchKeyTyped(final ModeState modeState, final char character) {
+ return switch (modeState) {
+ case NormalState normalState -> normalModeHandler.onKeyTyped(normalState, character, context);
+ case InsertState insertState -> insertModeHandler.onKeyTyped(insertState, character, context);
+ case VisualState visualState -> visualModeHandler.onKeyTyped(visualState, character, context);
+ case VisualLineState visualLineState ->
+ visualLineModeHandler.onKeyTyped(visualLineState, character, context);
+ case SearchState searchState -> searchModeHandler.onKeyTyped(searchState, character, context);
+ };
+ }
- private boolean applyHandleResult(final HandleResult result) {
- if (result.suppressTyped()) {
- context.incrementSuppressedTypedCommands();
- }
- if (result.nextState() != null) {
- state = result.nextState();
- }
- publishStatus();
- return result.consumed();
- }
+ private boolean applyHandleResult(final HandleResult result) {
+ if (result.suppressTyped()) {
+ context.incrementSuppressedTypedCommands();
+ }
+ if (result.nextState() != null) {
+ state = result.nextState();
+ }
+ publishStatus();
+ return result.consumed();
+ }
- private boolean isRedoKeyDown(final KeyEvent event) {
- final boolean ctrlDown = event.hasModifier(EditorModifier.CTRL) || event.hasModifier(EditorModifier.META);
- return ctrlDown && event.keycode() == Input.Keys.R;
- }
+ private boolean isRedoKeyDown(final KeyEvent event) {
+ final boolean ctrlDown = event.hasModifier(EditorModifier.CTRL) || event.hasModifier(EditorModifier.META);
+ return ctrlDown && event.keycode() == Input.Keys.R;
+ }
- private boolean isInsertState(final ModeState modeState) {
- return modeState instanceof InsertState;
- }
+ private boolean isInsertState(final ModeState modeState) {
+ return modeState instanceof InsertState;
+ }
- private boolean isBlockCursorMode(final ModeState modeState) {
- return modeState instanceof NormalState || modeState instanceof VisualState
- || modeState instanceof VisualLineState;
- }
+ private boolean isBlockCursorMode(final ModeState modeState) {
+ return modeState instanceof NormalState || modeState instanceof VisualState
+ || modeState instanceof VisualLineState;
+ }
- private void publishStatus() {
- context.publishStatus(statusFormatter.format(state, config));
- }
+ private void publishStatus() {
+ context.publishStatus(statusFormatter.format(state, config));
+ }
}
diff --git a/core/src/main/java/coffee/liz/abstractionengine/app/ui/editor/vim/buffer/TextAreaBuffer.java b/core/src/main/java/coffee/liz/abstractionengine/app/ui/editor/vim/buffer/TextAreaBuffer.java
index 36fe9d3..428976e 100644
--- a/core/src/main/java/coffee/liz/abstractionengine/app/ui/editor/vim/buffer/TextAreaBuffer.java
+++ b/core/src/main/java/coffee/liz/abstractionengine/app/ui/editor/vim/buffer/TextAreaBuffer.java
@@ -6,59 +6,59 @@ import lombok.RequiredArgsConstructor;
@RequiredArgsConstructor
public class TextAreaBuffer implements EditorBuffer {
- private final EditorTextArea textArea;
+ private final EditorTextArea textArea;
- @Override
- public String getText() {
- return textArea.getText();
- }
+ @Override
+ public String getText() {
+ return textArea.getText();
+ }
- @Override
- public void setText(final String text) {
- if (text.equals(textArea.getText())) {
- return;
- }
- textArea.setText(text);
- textArea.syncCursorState();
- }
+ @Override
+ public void setText(final String text) {
+ if (text.equals(textArea.getText())) {
+ return;
+ }
+ textArea.setText(text);
+ textArea.syncCursorState();
+ }
- @Override
- public int getCursorPosition() {
- return textArea.getCursorPosition();
- }
+ @Override
+ public int getCursorPosition() {
+ return textArea.getCursorPosition();
+ }
- @Override
- public void setCursorPosition(final int cursorPosition) {
- final int clampedCursor = Math.max(0, Math.min(cursorPosition, textArea.getText().length()));
- if (clampedCursor == textArea.getCursorPosition()) {
- return;
- }
- textArea.setCursorPosition(clampedCursor);
- textArea.syncCursorState();
- }
+ @Override
+ public void setCursorPosition(final int cursorPosition) {
+ final int clampedCursor = Math.max(0, Math.min(cursorPosition, textArea.getText().length()));
+ if (clampedCursor == textArea.getCursorPosition()) {
+ return;
+ }
+ textArea.setCursorPosition(clampedCursor);
+ textArea.syncCursorState();
+ }
- @Override
- public int getCursorLine() {
- return textArea.getCursorLine();
- }
+ @Override
+ public int getCursorLine() {
+ return textArea.getCursorLine();
+ }
- @Override
- public int getLines() {
- return textArea.getLines();
- }
+ @Override
+ public int getLines() {
+ return textArea.getLines();
+ }
- @Override
- public void moveCursorLine(final int line) {
- textArea.moveCursorLine(line);
- }
+ @Override
+ public void moveCursorLine(final int line) {
+ textArea.moveCursorLine(line);
+ }
- @Override
- public void setSelectionEndpoints(final int selectionStart, final int cursorPosition) {
- textArea.setSelectionEndpoints(selectionStart, cursorPosition);
- }
+ @Override
+ public void setSelectionEndpoints(final int selectionStart, final int cursorPosition) {
+ textArea.setSelectionEndpoints(selectionStart, cursorPosition);
+ }
- @Override
- public void clearSelection() {
- textArea.clearSelection();
- }
+ @Override
+ public void clearSelection() {
+ textArea.clearSelection();
+ }
}
diff --git a/core/src/main/java/coffee/liz/abstractionengine/app/ui/editor/vim/context/KeyContext.java b/core/src/main/java/coffee/liz/abstractionengine/app/ui/editor/vim/context/KeyContext.java
index a15232d..63ebff9 100644
--- a/core/src/main/java/coffee/liz/abstractionengine/app/ui/editor/vim/context/KeyContext.java
+++ b/core/src/main/java/coffee/liz/abstractionengine/app/ui/editor/vim/context/KeyContext.java
@@ -24,683 +24,683 @@ import java.util.Set;
import java.util.function.Consumer;
public class KeyContext {
- private final EditorBuffer editorBuffer;
- private final Consumer<String> statusUpdater;
- private final TextNavigation navigation;
- private final UndoManager undoManager;
- private final Register register;
- private final VimConfig config;
+ private final EditorBuffer editorBuffer;
+ private final Consumer<String> statusUpdater;
+ private final TextNavigation navigation;
+ private final UndoManager undoManager;
+ private final Register register;
+ private final VimConfig config;
- private String statusText;
- private String lastSearchQuery;
- private SearchDirection lastSearchDirection;
- private SearchIterator searchIterator;
- private String searchIteratorQuery;
- private String searchIteratorText;
- private int suppressedTypedCommands;
- private boolean suppressNextRedoTyped;
- private KeyEvent currentKeyEvent;
+ private String statusText;
+ private String lastSearchQuery;
+ private SearchDirection lastSearchDirection;
+ private SearchIterator searchIterator;
+ private String searchIteratorQuery;
+ private String searchIteratorText;
+ private int suppressedTypedCommands;
+ private boolean suppressNextRedoTyped;
+ private KeyEvent currentKeyEvent;
- public KeyContext(final EditorBuffer editorBuffer, final Consumer<String> statusUpdater,
- final TextNavigation navigation, final UndoManager undoManager, final Register register,
- final VimConfig config) {
- this.editorBuffer = editorBuffer;
- this.statusUpdater = statusUpdater;
- this.navigation = navigation;
- this.undoManager = undoManager;
- this.register = register;
- this.config = config;
- this.statusText = "";
- this.lastSearchQuery = "";
- this.lastSearchDirection = SearchDirection.FORWARD;
- this.searchIterator = null;
- this.searchIteratorQuery = "";
- this.searchIteratorText = "";
- this.suppressedTypedCommands = 0;
- this.suppressNextRedoTyped = false;
- this.currentKeyEvent = new KeyEvent(Input.Keys.UNKNOWN, Set.of());
- }
+ public KeyContext(final EditorBuffer editorBuffer, final Consumer<String> statusUpdater,
+ final TextNavigation navigation, final UndoManager undoManager, final Register register,
+ final VimConfig config) {
+ this.editorBuffer = editorBuffer;
+ this.statusUpdater = statusUpdater;
+ this.navigation = navigation;
+ this.undoManager = undoManager;
+ this.register = register;
+ this.config = config;
+ this.statusText = "";
+ this.lastSearchQuery = "";
+ this.lastSearchDirection = SearchDirection.FORWARD;
+ this.searchIterator = null;
+ this.searchIteratorQuery = "";
+ this.searchIteratorText = "";
+ this.suppressedTypedCommands = 0;
+ this.suppressNextRedoTyped = false;
+ this.currentKeyEvent = new KeyEvent(Input.Keys.UNKNOWN, Set.of());
+ }
- public EditorBuffer editorBuffer() {
- return editorBuffer;
- }
+ public EditorBuffer editorBuffer() {
+ return editorBuffer;
+ }
- public TextNavigation navigation() {
- return navigation;
- }
+ public TextNavigation navigation() {
+ return navigation;
+ }
- public VimConfig config() {
- return config;
- }
+ public VimConfig config() {
+ return config;
+ }
- public void setCurrentKeyEvent(final KeyEvent currentKeyEvent) {
- this.currentKeyEvent = currentKeyEvent;
- }
+ public void setCurrentKeyEvent(final KeyEvent currentKeyEvent) {
+ this.currentKeyEvent = currentKeyEvent;
+ }
- public KeyEvent currentKeyEvent() {
- return currentKeyEvent;
- }
+ public KeyEvent currentKeyEvent() {
+ return currentKeyEvent;
+ }
- public String getStatusText() {
- return statusText;
- }
+ public String getStatusText() {
+ return statusText;
+ }
- public void publishStatus(final String status) {
- if (!status.equals(statusText)) {
- statusText = status;
- if (statusUpdater != null) {
- statusUpdater.accept(statusText);
- }
- }
- }
+ public void publishStatus(final String status) {
+ if (!status.equals(statusText)) {
+ statusText = status;
+ if (statusUpdater != null) {
+ statusUpdater.accept(statusText);
+ }
+ }
+ }
- public String getLastSearchQuery() {
- return lastSearchQuery;
- }
+ public String getLastSearchQuery() {
+ return lastSearchQuery;
+ }
- public void setLastSearchQuery(final String lastSearchQuery) {
- this.lastSearchQuery = lastSearchQuery == null ? "" : lastSearchQuery;
- }
+ public void setLastSearchQuery(final String lastSearchQuery) {
+ this.lastSearchQuery = lastSearchQuery == null ? "" : lastSearchQuery;
+ }
- public void incrementSuppressedTypedCommands() {
- suppressedTypedCommands++;
- }
+ public void incrementSuppressedTypedCommands() {
+ suppressedTypedCommands++;
+ }
- public boolean consumeSuppressedTypedCommand() {
- if (suppressedTypedCommands <= 0) {
- return false;
- }
- suppressedTypedCommands--;
- return true;
- }
+ public boolean consumeSuppressedTypedCommand() {
+ if (suppressedTypedCommands <= 0) {
+ return false;
+ }
+ suppressedTypedCommands--;
+ return true;
+ }
- public void suppressNextRedoTyped() {
- suppressNextRedoTyped = true;
- }
+ public void suppressNextRedoTyped() {
+ suppressNextRedoTyped = true;
+ }
- public boolean consumeRedoTypedSuppression() {
- if (!suppressNextRedoTyped) {
- return false;
- }
- suppressNextRedoTyped = false;
- return true;
- }
+ public boolean consumeRedoTypedSuppression() {
+ if (!suppressNextRedoTyped) {
+ return false;
+ }
+ suppressNextRedoTyped = false;
+ return true;
+ }
- public void clearRedoTypedSuppression() {
- suppressNextRedoTyped = false;
- }
+ public void clearRedoTypedSuppression() {
+ suppressNextRedoTyped = false;
+ }
- public Character toCommandCharacter() {
- final int keycode = currentKeyEvent.keycode();
- final boolean shiftDown = currentKeyEvent.hasModifier(EditorModifier.SHIFT);
+ public Character toCommandCharacter() {
+ final int keycode = currentKeyEvent.keycode();
+ final boolean shiftDown = currentKeyEvent.hasModifier(EditorModifier.SHIFT);
- if (keycode == Input.Keys.SLASH) {
- return shiftDown ? '?' : '/';
- }
+ if (keycode == Input.Keys.SLASH) {
+ return shiftDown ? '?' : '/';
+ }
- if (keycode == Input.Keys.NUM_4 && shiftDown) {
- return '$';
- }
+ if (keycode == Input.Keys.NUM_4 && shiftDown) {
+ return '$';
+ }
- final String keyName = Input.Keys.toString(keycode);
- if (keyName == null || keyName.length() != 1) {
- return null;
- }
+ final String keyName = Input.Keys.toString(keycode);
+ if (keyName == null || keyName.length() != 1) {
+ return null;
+ }
- final char key = keyName.charAt(0);
- if (Character.isLetter(key)) {
- return shiftDown ? Character.toUpperCase(key) : Character.toLowerCase(key);
- }
+ final char key = keyName.charAt(0);
+ if (Character.isLetter(key)) {
+ return shiftDown ? Character.toUpperCase(key) : Character.toLowerCase(key);
+ }
- if (Character.isDigit(key) && !shiftDown) {
- return key;
- }
+ if (Character.isDigit(key) && !shiftDown) {
+ return key;
+ }
- return null;
- }
+ return null;
+ }
- public int readCount(final int count) {
- return count > 0 ? count : 1;
- }
+ public int readCount(final int count) {
+ return count > 0 ? count : 1;
+ }
- public int resetPreferredColumn(final char character, final int preferredColumn) {
- if (character == 'j' || character == 'k') {
- return preferredColumn;
- }
- return -1;
- }
+ public int resetPreferredColumn(final char character, final int preferredColumn) {
+ if (character == 'j' || character == 'k') {
+ return preferredColumn;
+ }
+ return -1;
+ }
- public void moveLeft() {
- final int cursor = editorBuffer.getCursorPosition();
- final int lineStart = navigation.findLineStart(editorBuffer.getText(), cursor);
- if (cursor > lineStart) {
- editorBuffer.setCursorPosition(cursor - 1);
- }
- }
+ public void moveLeft() {
+ final int cursor = editorBuffer.getCursorPosition();
+ final int lineStart = navigation.findLineStart(editorBuffer.getText(), cursor);
+ if (cursor > lineStart) {
+ editorBuffer.setCursorPosition(cursor - 1);
+ }
+ }
- public void moveRightNormal() {
- final String text = editorBuffer.getText();
- final int cursor = editorBuffer.getCursorPosition();
- final int lineEnd = navigation.findLineEnd(text, cursor);
- if (cursor < lineEnd) {
- editorBuffer.setCursorPosition(cursor + 1);
- }
- }
+ public void moveRightNormal() {
+ final String text = editorBuffer.getText();
+ final int cursor = editorBuffer.getCursorPosition();
+ final int lineEnd = navigation.findLineEnd(text, cursor);
+ if (cursor < lineEnd) {
+ editorBuffer.setCursorPosition(cursor + 1);
+ }
+ }
- public void moveRightForAppend() {
- final String text = editorBuffer.getText();
- final int cursor = editorBuffer.getCursorPosition();
- if (cursor < text.length() && text.charAt(cursor) != '\n') {
- editorBuffer.setCursorPosition(cursor + 1);
- }
- }
+ public void moveRightForAppend() {
+ final String text = editorBuffer.getText();
+ final int cursor = editorBuffer.getCursorPosition();
+ if (cursor < text.length() && text.charAt(cursor) != '\n') {
+ editorBuffer.setCursorPosition(cursor + 1);
+ }
+ }
- public int moveVertical(final int delta, final int repeats, final int preferredColumn,
- final boolean clampInNormalMode) {
- int preferred = preferredColumn;
- for (int i = 0; i < repeats; i++) {
- preferred = moveVerticalOnce(delta, preferred, clampInNormalMode);
- }
- return preferred;
- }
+ public int moveVertical(final int delta, final int repeats, final int preferredColumn,
+ final boolean clampInNormalMode) {
+ int preferred = preferredColumn;
+ for (int i = 0; i < repeats; i++) {
+ preferred = moveVerticalOnce(delta, preferred, clampInNormalMode);
+ }
+ return preferred;
+ }
- private int moveVerticalOnce(final int delta, final int preferredColumn, final boolean clampInNormalMode) {
- if (delta == 0) {
- return preferredColumn;
- }
+ private int moveVerticalOnce(final int delta, final int preferredColumn, final boolean clampInNormalMode) {
+ if (delta == 0) {
+ return preferredColumn;
+ }
- final String text = editorBuffer.getText();
- if (text.isEmpty()) {
- return preferredColumn;
- }
+ final String text = editorBuffer.getText();
+ if (text.isEmpty()) {
+ return preferredColumn;
+ }
- final int cursor = editorBuffer.getCursorPosition();
- final int currentLineStart = navigation.findLineStart(text, cursor);
- final int resolvedPreferred = preferredColumn < 0 ? Math.max(0, cursor - currentLineStart) : preferredColumn;
+ final int cursor = editorBuffer.getCursorPosition();
+ final int currentLineStart = navigation.findLineStart(text, cursor);
+ final int resolvedPreferred = preferredColumn < 0 ? Math.max(0, cursor - currentLineStart) : preferredColumn;
- int targetStart = currentLineStart;
- if (delta > 0) {
- targetStart = navigation.findNextLineStart(text, targetStart);
- if (targetStart < 0 || targetStart > text.length()) {
- return resolvedPreferred;
- }
- } else {
- targetStart = navigation.findPreviousLineStart(text, targetStart);
- if (targetStart < 0) {
- return resolvedPreferred;
- }
- }
+ int targetStart = currentLineStart;
+ if (delta > 0) {
+ targetStart = navigation.findNextLineStart(text, targetStart);
+ if (targetStart < 0 || targetStart > text.length()) {
+ return resolvedPreferred;
+ }
+ } else {
+ targetStart = navigation.findPreviousLineStart(text, targetStart);
+ if (targetStart < 0) {
+ return resolvedPreferred;
+ }
+ }
- final int targetEndExclusive = navigation.findLineEndExclusiveByStart(text, targetStart);
- final int targetLineLength = Math.max(0, targetEndExclusive - targetStart);
- final int maxColumn = targetLineLength > 0 ? targetLineLength - 1 : 0;
- final int targetColumn = Math.min(resolvedPreferred, maxColumn);
- editorBuffer.setCursorPosition(targetStart + targetColumn);
- if (clampInNormalMode) {
- clampCursorInNormalMode();
- }
- return resolvedPreferred;
- }
+ final int targetEndExclusive = navigation.findLineEndExclusiveByStart(text, targetStart);
+ final int targetLineLength = Math.max(0, targetEndExclusive - targetStart);
+ final int maxColumn = targetLineLength > 0 ? targetLineLength - 1 : 0;
+ final int targetColumn = Math.min(resolvedPreferred, maxColumn);
+ editorBuffer.setCursorPosition(targetStart + targetColumn);
+ if (clampInNormalMode) {
+ clampCursorInNormalMode();
+ }
+ return resolvedPreferred;
+ }
- public void moveWordForward() {
- final String text = editorBuffer.getText();
- int cursor = editorBuffer.getCursorPosition();
- final int length = text.length();
+ public void moveWordForward() {
+ final String text = editorBuffer.getText();
+ int cursor = editorBuffer.getCursorPosition();
+ final int length = text.length();
- if (cursor >= length) {
- return;
- }
+ if (cursor >= length) {
+ return;
+ }
- final int originalCursor = cursor;
- final char current = text.charAt(cursor);
+ final int originalCursor = cursor;
+ final char current = text.charAt(cursor);
- if (navigation.isWordCharacter(current)) {
- while (cursor < length && navigation.isWordCharacter(text.charAt(cursor))) {
- cursor++;
- }
- while (cursor < length && navigation.isInlineWhitespace(text.charAt(cursor))) {
- cursor++;
- }
- } else if (navigation.isPunctuationWord(current)) {
- while (cursor < length && navigation.isPunctuationWord(text.charAt(cursor))) {
- cursor++;
- }
- while (cursor < length && navigation.isInlineWhitespace(text.charAt(cursor))) {
- cursor++;
- }
- if (cursor >= length) {
- cursor = originalCursor;
- }
- } else if (navigation.isInlineWhitespace(current)) {
- while (cursor < length && navigation.isInlineWhitespace(text.charAt(cursor))) {
- cursor++;
- }
- } else if (current == '\n' || current == '\r') {
- if (cursor < length) {
- cursor++;
- }
- while (cursor < length && navigation.isInlineWhitespace(text.charAt(cursor))) {
- cursor++;
- }
- }
+ if (navigation.isWordCharacter(current)) {
+ while (cursor < length && navigation.isWordCharacter(text.charAt(cursor))) {
+ cursor++;
+ }
+ while (cursor < length && navigation.isInlineWhitespace(text.charAt(cursor))) {
+ cursor++;
+ }
+ } else if (navigation.isPunctuationWord(current)) {
+ while (cursor < length && navigation.isPunctuationWord(text.charAt(cursor))) {
+ cursor++;
+ }
+ while (cursor < length && navigation.isInlineWhitespace(text.charAt(cursor))) {
+ cursor++;
+ }
+ if (cursor >= length) {
+ cursor = originalCursor;
+ }
+ } else if (navigation.isInlineWhitespace(current)) {
+ while (cursor < length && navigation.isInlineWhitespace(text.charAt(cursor))) {
+ cursor++;
+ }
+ } else if (current == '\n' || current == '\r') {
+ if (cursor < length) {
+ cursor++;
+ }
+ while (cursor < length && navigation.isInlineWhitespace(text.charAt(cursor))) {
+ cursor++;
+ }
+ }
- editorBuffer.setCursorPosition(Math.min(cursor, length));
- }
+ editorBuffer.setCursorPosition(Math.min(cursor, length));
+ }
- public void moveWordBackward() {
- final String text = editorBuffer.getText();
- int cursor = editorBuffer.getCursorPosition();
+ public void moveWordBackward() {
+ final String text = editorBuffer.getText();
+ int cursor = editorBuffer.getCursorPosition();
- if (cursor <= 0) {
- return;
- }
+ if (cursor <= 0) {
+ return;
+ }
- cursor--;
- while (cursor > 0 && Character.isWhitespace(text.charAt(cursor))) {
- cursor--;
- }
+ cursor--;
+ while (cursor > 0 && Character.isWhitespace(text.charAt(cursor))) {
+ cursor--;
+ }
- final char current = text.charAt(cursor);
- if (navigation.isWordCharacter(current)) {
- while (cursor > 0 && navigation.isWordCharacter(text.charAt(cursor - 1))) {
- cursor--;
- }
- } else {
- while (cursor > 0) {
- final char previous = text.charAt(cursor - 1);
- if (Character.isWhitespace(previous) || navigation.isWordCharacter(previous)) {
- break;
- }
- cursor--;
- }
- }
+ final char current = text.charAt(cursor);
+ if (navigation.isWordCharacter(current)) {
+ while (cursor > 0 && navigation.isWordCharacter(text.charAt(cursor - 1))) {
+ cursor--;
+ }
+ } else {
+ while (cursor > 0) {
+ final char previous = text.charAt(cursor - 1);
+ if (Character.isWhitespace(previous) || navigation.isWordCharacter(previous)) {
+ break;
+ }
+ cursor--;
+ }
+ }
- editorBuffer.setCursorPosition(cursor);
- }
+ editorBuffer.setCursorPosition(cursor);
+ }
- public void moveLineStart() {
- final int cursor = editorBuffer.getCursorPosition();
- editorBuffer.setCursorPosition(navigation.findLineStart(editorBuffer.getText(), cursor));
- }
+ public void moveLineStart() {
+ final int cursor = editorBuffer.getCursorPosition();
+ editorBuffer.setCursorPosition(navigation.findLineStart(editorBuffer.getText(), cursor));
+ }
- public void moveLineEnd() {
- final int cursor = editorBuffer.getCursorPosition();
- editorBuffer.setCursorPosition(navigation.findLineEnd(editorBuffer.getText(), cursor));
- }
+ public void moveLineEnd() {
+ final int cursor = editorBuffer.getCursorPosition();
+ editorBuffer.setCursorPosition(navigation.findLineEnd(editorBuffer.getText(), cursor));
+ }
- public void moveDocumentEnd() {
- final String text = editorBuffer.getText();
- if (!text.isEmpty()) {
- editorBuffer.setCursorPosition(navigation.lastNavigablePosition(text));
- }
- }
+ public void moveDocumentEnd() {
+ final String text = editorBuffer.getText();
+ if (!text.isEmpty()) {
+ editorBuffer.setCursorPosition(navigation.lastNavigablePosition(text));
+ }
+ }
- public void moveDocumentStart() {
- editorBuffer.setCursorPosition(0);
- clampCursorInNormalMode();
- }
+ public void moveDocumentStart() {
+ editorBuffer.setCursorPosition(0);
+ clampCursorInNormalMode();
+ }
- public void openLineBelow() {
- final String text = editorBuffer.getText();
- final int insertAt = navigation.findBelowLineInsertionIndex(text, editorBuffer.getCursorPosition());
- editorBuffer.setText(text.substring(0, insertAt) + "\n" + text.substring(insertAt));
- editorBuffer.setCursorPosition(Math.min(insertAt, editorBuffer.getText().length()));
- invalidateSearchIterator();
- recordUndoState();
- }
+ public void openLineBelow() {
+ final String text = editorBuffer.getText();
+ final int insertAt = navigation.findBelowLineInsertionIndex(text, editorBuffer.getCursorPosition());
+ editorBuffer.setText(text.substring(0, insertAt) + "\n" + text.substring(insertAt));
+ editorBuffer.setCursorPosition(Math.min(insertAt, editorBuffer.getText().length()));
+ invalidateSearchIterator();
+ recordUndoState();
+ }
- public void openLineAbove() {
- final String text = editorBuffer.getText();
- final int lineStart = navigation.findLineStart(text, editorBuffer.getCursorPosition());
- editorBuffer.setText(text.substring(0, lineStart) + "\n" + text.substring(lineStart));
- editorBuffer.setCursorPosition(lineStart);
- invalidateSearchIterator();
- recordUndoState();
- }
+ public void openLineAbove() {
+ final String text = editorBuffer.getText();
+ final int lineStart = navigation.findLineStart(text, editorBuffer.getCursorPosition());
+ editorBuffer.setText(text.substring(0, lineStart) + "\n" + text.substring(lineStart));
+ editorBuffer.setCursorPosition(lineStart);
+ invalidateSearchIterator();
+ recordUndoState();
+ }
- public void deleteCharUnderCursor() {
- final String text = editorBuffer.getText();
- final int cursor = editorBuffer.getCursorPosition();
- if (cursor >= text.length() || text.charAt(cursor) == '\n') {
- return;
- }
- register.setText(String.valueOf(text.charAt(cursor)));
- register.setType(RegisterType.CHARACTER);
- editorBuffer.setText(text.substring(0, cursor) + text.substring(cursor + 1));
- editorBuffer.setCursorPosition(Math.min(cursor, editorBuffer.getText().length()));
- invalidateSearchIterator();
- }
+ public void deleteCharUnderCursor() {
+ final String text = editorBuffer.getText();
+ final int cursor = editorBuffer.getCursorPosition();
+ if (cursor >= text.length() || text.charAt(cursor) == '\n') {
+ return;
+ }
+ register.setText(String.valueOf(text.charAt(cursor)));
+ register.setType(RegisterType.CHARACTER);
+ editorBuffer.setText(text.substring(0, cursor) + text.substring(cursor + 1));
+ editorBuffer.setCursorPosition(Math.min(cursor, editorBuffer.getText().length()));
+ invalidateSearchIterator();
+ }
- public void deleteLines(final int repeats) {
- final String text = editorBuffer.getText();
- final int start = navigation.findLineStart(text, editorBuffer.getCursorPosition());
- int end = start;
- for (int i = 0; i < repeats; i++) {
- end = navigation.findNextLineStart(text, end);
- if (end == -1) {
- end = text.length();
- break;
- }
- }
- if (start >= end) {
- return;
- }
- register.setText(normalizeLineRegister(text.substring(start, end)));
- register.setType(RegisterType.LINE);
- editorBuffer.setText(text.substring(0, start) + text.substring(end));
- editorBuffer.setCursorPosition(Math.min(start, editorBuffer.getText().length()));
- clampCursorInNormalMode();
- invalidateSearchIterator();
- }
+ public void deleteLines(final int repeats) {
+ final String text = editorBuffer.getText();
+ final int start = navigation.findLineStart(text, editorBuffer.getCursorPosition());
+ int end = start;
+ for (int i = 0; i < repeats; i++) {
+ end = navigation.findNextLineStart(text, end);
+ if (end == -1) {
+ end = text.length();
+ break;
+ }
+ }
+ if (start >= end) {
+ return;
+ }
+ register.setText(normalizeLineRegister(text.substring(start, end)));
+ register.setType(RegisterType.LINE);
+ editorBuffer.setText(text.substring(0, start) + text.substring(end));
+ editorBuffer.setCursorPosition(Math.min(start, editorBuffer.getText().length()));
+ clampCursorInNormalMode();
+ invalidateSearchIterator();
+ }
- public void yankLines(final int repeats) {
- final String text = editorBuffer.getText();
- final int start = navigation.findLineStart(text, editorBuffer.getCursorPosition());
- int end = start;
- for (int i = 0; i < repeats; i++) {
- end = navigation.findNextLineStart(text, end);
- if (end == -1) {
- end = text.length();
- break;
- }
- }
- if (start < end) {
- register.setText(normalizeLineRegister(text.substring(start, end)));
- register.setType(RegisterType.LINE);
- }
- }
+ public void yankLines(final int repeats) {
+ final String text = editorBuffer.getText();
+ final int start = navigation.findLineStart(text, editorBuffer.getCursorPosition());
+ int end = start;
+ for (int i = 0; i < repeats; i++) {
+ end = navigation.findNextLineStart(text, end);
+ if (end == -1) {
+ end = text.length();
+ break;
+ }
+ }
+ if (start < end) {
+ register.setText(normalizeLineRegister(text.substring(start, end)));
+ register.setType(RegisterType.LINE);
+ }
+ }
- public void changeLines(final int repeats) {
- deleteLines(repeats);
- }
+ public void changeLines(final int repeats) {
+ deleteLines(repeats);
+ }
- public void pasteAfter() {
- if (register.getText().isEmpty()) {
- return;
- }
- final String text = editorBuffer.getText();
- final int cursor = editorBuffer.getCursorPosition();
- if (register.getType() == RegisterType.LINE) {
- final int insertAt = navigation.findBelowLineInsertionIndex(text, cursor);
- String inserted = register.getText();
- if (insertAt == text.length() && insertAt > 0 && text.charAt(insertAt - 1) != '\n') {
- inserted = "\n" + inserted;
- }
- editorBuffer.setText(text.substring(0, insertAt) + inserted + text.substring(insertAt));
- editorBuffer.setCursorPosition(Math.min(insertAt, editorBuffer.getText().length()));
- invalidateSearchIterator();
- return;
- }
+ public void pasteAfter() {
+ if (register.getText().isEmpty()) {
+ return;
+ }
+ final String text = editorBuffer.getText();
+ final int cursor = editorBuffer.getCursorPosition();
+ if (register.getType() == RegisterType.LINE) {
+ final int insertAt = navigation.findBelowLineInsertionIndex(text, cursor);
+ String inserted = register.getText();
+ if (insertAt == text.length() && insertAt > 0 && text.charAt(insertAt - 1) != '\n') {
+ inserted = "\n" + inserted;
+ }
+ editorBuffer.setText(text.substring(0, insertAt) + inserted + text.substring(insertAt));
+ editorBuffer.setCursorPosition(Math.min(insertAt, editorBuffer.getText().length()));
+ invalidateSearchIterator();
+ return;
+ }
- final int insertAt = Math.min(cursor + 1, text.length());
- editorBuffer.setText(text.substring(0, insertAt) + register.getText() + text.substring(insertAt));
- editorBuffer.setCursorPosition(insertAt + register.getText().length() - 1);
- invalidateSearchIterator();
- }
+ final int insertAt = Math.min(cursor + 1, text.length());
+ editorBuffer.setText(text.substring(0, insertAt) + register.getText() + text.substring(insertAt));
+ editorBuffer.setCursorPosition(insertAt + register.getText().length() - 1);
+ invalidateSearchIterator();
+ }
- public void pasteBefore() {
- if (register.getText().isEmpty()) {
- return;
- }
- final String text = editorBuffer.getText();
- final int cursor = editorBuffer.getCursorPosition();
- if (register.getType() == RegisterType.LINE) {
- final int insertAt = navigation.findLineStart(text, cursor);
- editorBuffer.setText(text.substring(0, insertAt) + register.getText() + text.substring(insertAt));
- editorBuffer.setCursorPosition(insertAt);
- invalidateSearchIterator();
- return;
- }
+ public void pasteBefore() {
+ if (register.getText().isEmpty()) {
+ return;
+ }
+ final String text = editorBuffer.getText();
+ final int cursor = editorBuffer.getCursorPosition();
+ if (register.getType() == RegisterType.LINE) {
+ final int insertAt = navigation.findLineStart(text, cursor);
+ editorBuffer.setText(text.substring(0, insertAt) + register.getText() + text.substring(insertAt));
+ editorBuffer.setCursorPosition(insertAt);
+ invalidateSearchIterator();
+ return;
+ }
- final int insertAt = cursor;
- editorBuffer.setText(text.substring(0, insertAt) + register.getText() + text.substring(insertAt));
- editorBuffer.setCursorPosition(insertAt + register.getText().length() - 1);
- invalidateSearchIterator();
- }
+ final int insertAt = cursor;
+ editorBuffer.setText(text.substring(0, insertAt) + register.getText() + text.substring(insertAt));
+ editorBuffer.setCursorPosition(insertAt + register.getText().length() - 1);
+ invalidateSearchIterator();
+ }
- public void updateVisualSelection(final int anchor) {
- final int cursor = editorBuffer.getCursorPosition();
- if (cursor != anchor) {
- int selectionStart = anchor;
- if (cursor < anchor && anchor < editorBuffer.getText().length()) {
- selectionStart = anchor + 1;
- }
- editorBuffer.setSelectionEndpoints(selectionStart, cursor);
- } else {
- editorBuffer.clearSelection();
- }
- }
+ public void updateVisualSelection(final int anchor) {
+ final int cursor = editorBuffer.getCursorPosition();
+ if (cursor != anchor) {
+ int selectionStart = anchor;
+ if (cursor < anchor && anchor < editorBuffer.getText().length()) {
+ selectionStart = anchor + 1;
+ }
+ editorBuffer.setSelectionEndpoints(selectionStart, cursor);
+ } else {
+ editorBuffer.clearSelection();
+ }
+ }
- public void updateVisualLineSelection(final int anchorLine, final int cursorLine) {
- final String text = editorBuffer.getText();
- final int startLine = Math.min(anchorLine, cursorLine);
- final int endLine = Math.max(anchorLine, cursorLine);
- final int start = navigation.findLineStartByLine(text, startLine);
- final int end = navigation.findLineSelectionEndByLine(text, endLine);
- if (start < end) {
- final int selectionStart = cursorLine > anchorLine ? start : end;
- final int cursorPosition = cursorLine > anchorLine
- ? resolveVisualLineCursorPosition(text, start, end)
- : start;
- editorBuffer.setSelectionEndpoints(selectionStart, cursorPosition);
- } else {
- editorBuffer.clearSelection();
- }
- }
+ public void updateVisualLineSelection(final int anchorLine, final int cursorLine) {
+ final String text = editorBuffer.getText();
+ final int startLine = Math.min(anchorLine, cursorLine);
+ final int endLine = Math.max(anchorLine, cursorLine);
+ final int start = navigation.findLineStartByLine(text, startLine);
+ final int end = navigation.findLineSelectionEndByLine(text, endLine);
+ if (start < end) {
+ final int selectionStart = cursorLine > anchorLine ? start : end;
+ final int cursorPosition = cursorLine > anchorLine
+ ? resolveVisualLineCursorPosition(text, start, end)
+ : start;
+ editorBuffer.setSelectionEndpoints(selectionStart, cursorPosition);
+ } else {
+ editorBuffer.clearSelection();
+ }
+ }
- public int adjustVisualLineCursor(final int cursorLine, final int delta) {
- final int maxLine = maxSelectableLineIndex();
- return Math.max(0, Math.min(maxLine, cursorLine + delta));
- }
+ public int adjustVisualLineCursor(final int cursorLine, final int delta) {
+ final int maxLine = maxSelectableLineIndex();
+ return Math.max(0, Math.min(maxLine, cursorLine + delta));
+ }
- public int maxSelectableLineIndex() {
- int totalLines = editorBuffer.getLines();
- final String text = editorBuffer.getText();
- if (totalLines > 1 && text.endsWith("\n")) {
- totalLines--;
- }
- return Math.max(0, totalLines - 1);
- }
+ public int maxSelectableLineIndex() {
+ int totalLines = editorBuffer.getLines();
+ final String text = editorBuffer.getText();
+ if (totalLines > 1 && text.endsWith("\n")) {
+ totalLines--;
+ }
+ return Math.max(0, totalLines - 1);
+ }
- private int resolveVisualLineCursorPosition(final String text, final int lineStart, final int selectionEnd) {
- if (!text.isEmpty() && selectionEnd == text.length() && text.charAt(text.length() - 1) == '\n') {
- return Math.max(lineStart, selectionEnd - 1);
- }
- return selectionEnd;
- }
+ private int resolveVisualLineCursorPosition(final String text, final int lineStart, final int selectionEnd) {
+ if (!text.isEmpty() && selectionEnd == text.length() && text.charAt(text.length() - 1) == '\n') {
+ return Math.max(lineStart, selectionEnd - 1);
+ }
+ return selectionEnd;
+ }
- public HandleResult applyVisualOperator(final VisualState state, final PendingOperator operator) {
- final int start = Math.min(state.anchor(), editorBuffer.getCursorPosition());
- final int max = Math.max(state.anchor(), editorBuffer.getCursorPosition());
- final int end = Math.min(editorBuffer.getText().length(), max + 1);
- if (start >= end) {
- editorBuffer.clearSelection();
- return HandleResult.handled(NormalState.DEFAULT);
- }
+ public HandleResult applyVisualOperator(final VisualState state, final PendingOperator operator) {
+ final int start = Math.min(state.anchor(), editorBuffer.getCursorPosition());
+ final int max = Math.max(state.anchor(), editorBuffer.getCursorPosition());
+ final int end = Math.min(editorBuffer.getText().length(), max + 1);
+ if (start >= end) {
+ editorBuffer.clearSelection();
+ return HandleResult.handled(NormalState.DEFAULT);
+ }
- final String text = editorBuffer.getText();
- register.setText(text.substring(start, end));
- register.setType(RegisterType.CHARACTER);
+ final String text = editorBuffer.getText();
+ register.setText(text.substring(start, end));
+ register.setType(RegisterType.CHARACTER);
- if (operator == PendingOperator.YANK) {
- editorBuffer.clearSelection();
- editorBuffer.setCursorPosition(start);
- clampCursorInNormalMode();
- return HandleResult.handled(NormalState.DEFAULT);
- }
+ if (operator == PendingOperator.YANK) {
+ editorBuffer.clearSelection();
+ editorBuffer.setCursorPosition(start);
+ clampCursorInNormalMode();
+ return HandleResult.handled(NormalState.DEFAULT);
+ }
- editorBuffer.setText(text.substring(0, start) + text.substring(end));
- editorBuffer.setCursorPosition(Math.min(start, editorBuffer.getText().length()));
- editorBuffer.clearSelection();
- recordUndoState();
- invalidateSearchIterator();
+ editorBuffer.setText(text.substring(0, start) + text.substring(end));
+ editorBuffer.setCursorPosition(Math.min(start, editorBuffer.getText().length()));
+ editorBuffer.clearSelection();
+ recordUndoState();
+ invalidateSearchIterator();
- if (operator == PendingOperator.CHANGE) {
- return HandleResult.handled(new InsertState(editorBuffer.getText(), editorBuffer.getCursorPosition()));
- }
- clampCursorInNormalMode();
- return HandleResult.handled(NormalState.DEFAULT);
- }
+ if (operator == PendingOperator.CHANGE) {
+ return HandleResult.handled(new InsertState(editorBuffer.getText(), editorBuffer.getCursorPosition()));
+ }
+ clampCursorInNormalMode();
+ return HandleResult.handled(NormalState.DEFAULT);
+ }
- public HandleResult applyVisualLineOperator(final VisualLineState state, final PendingOperator operator) {
- final String text = editorBuffer.getText();
- final int startLine = Math.min(state.anchorLine(), state.cursorLine());
- final int endLine = Math.max(state.anchorLine(), state.cursorLine());
- final int start = navigation.findLineStartByLine(text, startLine);
- final int end = navigation.findLineSelectionEndByLine(text, endLine);
- if (start >= end) {
- editorBuffer.clearSelection();
- return HandleResult.handled(NormalState.DEFAULT);
- }
+ public HandleResult applyVisualLineOperator(final VisualLineState state, final PendingOperator operator) {
+ final String text = editorBuffer.getText();
+ final int startLine = Math.min(state.anchorLine(), state.cursorLine());
+ final int endLine = Math.max(state.anchorLine(), state.cursorLine());
+ final int start = navigation.findLineStartByLine(text, startLine);
+ final int end = navigation.findLineSelectionEndByLine(text, endLine);
+ if (start >= end) {
+ editorBuffer.clearSelection();
+ return HandleResult.handled(NormalState.DEFAULT);
+ }
- register.setText(normalizeLineRegister(text.substring(start, end)));
- register.setType(RegisterType.LINE);
+ register.setText(normalizeLineRegister(text.substring(start, end)));
+ register.setType(RegisterType.LINE);
- if (operator == PendingOperator.YANK) {
- editorBuffer.clearSelection();
- editorBuffer.setCursorPosition(start);
- clampCursorInNormalMode();
- return HandleResult.handled(NormalState.DEFAULT);
- }
+ if (operator == PendingOperator.YANK) {
+ editorBuffer.clearSelection();
+ editorBuffer.setCursorPosition(start);
+ clampCursorInNormalMode();
+ return HandleResult.handled(NormalState.DEFAULT);
+ }
- editorBuffer.setText(text.substring(0, start) + text.substring(end));
- editorBuffer.setCursorPosition(Math.min(start, editorBuffer.getText().length()));
- editorBuffer.clearSelection();
- recordUndoState();
- invalidateSearchIterator();
+ editorBuffer.setText(text.substring(0, start) + text.substring(end));
+ editorBuffer.setCursorPosition(Math.min(start, editorBuffer.getText().length()));
+ editorBuffer.clearSelection();
+ recordUndoState();
+ invalidateSearchIterator();
- if (operator == PendingOperator.CHANGE) {
- return HandleResult.handled(new InsertState(editorBuffer.getText(), editorBuffer.getCursorPosition()));
- }
- clampCursorInNormalMode();
- return HandleResult.handled(NormalState.DEFAULT);
- }
+ if (operator == PendingOperator.CHANGE) {
+ return HandleResult.handled(new InsertState(editorBuffer.getText(), editorBuffer.getCursorPosition()));
+ }
+ clampCursorInNormalMode();
+ return HandleResult.handled(NormalState.DEFAULT);
+ }
- public boolean findNext(final String query, final SearchDirection direction) {
- if (query == null || query.isEmpty()) {
- return false;
- }
- final String text = editorBuffer.getText();
- if (text.isEmpty()) {
- return false;
- }
+ public boolean findNext(final String query, final SearchDirection direction) {
+ if (query == null || query.isEmpty()) {
+ return false;
+ }
+ final String text = editorBuffer.getText();
+ if (text.isEmpty()) {
+ return false;
+ }
- if (searchIterator == null || !query.equals(searchIteratorQuery) || direction != lastSearchDirection
- || !text.equals(searchIteratorText)) {
- searchIterator = new SearchIterator(text, query, editorBuffer.getCursorPosition(), direction,
- config.wrapSearch());
- searchIteratorQuery = query;
- searchIteratorText = text;
- lastSearchDirection = direction;
- }
+ if (searchIterator == null || !query.equals(searchIteratorQuery) || direction != lastSearchDirection
+ || !text.equals(searchIteratorText)) {
+ searchIterator = new SearchIterator(text, query, editorBuffer.getCursorPosition(), direction,
+ config.wrapSearch());
+ searchIteratorQuery = query;
+ searchIteratorText = text;
+ lastSearchDirection = direction;
+ }
- final OptionalInt found = searchIterator.nextMatch();
- if (found.isEmpty()) {
- return false;
- }
+ final OptionalInt found = searchIterator.nextMatch();
+ if (found.isEmpty()) {
+ return false;
+ }
- editorBuffer.setCursorPosition(found.getAsInt());
- clampCursorInNormalMode();
- return true;
- }
+ editorBuffer.setCursorPosition(found.getAsInt());
+ clampCursorInNormalMode();
+ return true;
+ }
- public void invalidateSearchIterator() {
- searchIterator = null;
- searchIteratorQuery = "";
- searchIteratorText = "";
- }
+ public void invalidateSearchIterator() {
+ searchIterator = null;
+ searchIteratorQuery = "";
+ searchIteratorText = "";
+ }
- public void recordUndoState() {
- undoManager.record(editorBuffer.getText(), editorBuffer.getCursorPosition());
- }
+ public void recordUndoState() {
+ undoManager.record(editorBuffer.getText(), editorBuffer.getCursorPosition());
+ }
- public ModeState undoToNormalState() {
- final UndoState previous = undoManager.undo();
- if (previous == null) {
- return NormalState.DEFAULT;
- }
- applyState(previous);
- return NormalState.DEFAULT;
- }
+ public ModeState undoToNormalState() {
+ final UndoState previous = undoManager.undo();
+ if (previous == null) {
+ return NormalState.DEFAULT;
+ }
+ applyState(previous);
+ return NormalState.DEFAULT;
+ }
- public ModeState redoToNormalState() {
- final UndoState target = undoManager.redo();
- if (target == null) {
- return NormalState.DEFAULT;
- }
- applyState(target);
- return NormalState.DEFAULT;
- }
+ public ModeState redoToNormalState() {
+ final UndoState target = undoManager.redo();
+ if (target == null) {
+ return NormalState.DEFAULT;
+ }
+ applyState(target);
+ return NormalState.DEFAULT;
+ }
- public void maybeRecordInsertEdit(final InsertState state) {
- final String currentText = editorBuffer.getText();
- final int currentCursor = editorBuffer.getCursorPosition();
- if (!currentText.equals(state.insertStartText()) || currentCursor != state.insertStartCursor()) {
- recordUndoState();
- }
- }
+ public void maybeRecordInsertEdit(final InsertState state) {
+ final String currentText = editorBuffer.getText();
+ final int currentCursor = editorBuffer.getCursorPosition();
+ if (!currentText.equals(state.insertStartText()) || currentCursor != state.insertStartCursor()) {
+ recordUndoState();
+ }
+ }
- private void applyState(final UndoState state) {
- editorBuffer.setText(state.getText());
- editorBuffer.setCursorPosition(Math.min(state.getCursor(), state.getText().length()));
- editorBuffer.clearSelection();
- clampCursorInNormalMode();
- invalidateSearchIterator();
- }
+ private void applyState(final UndoState state) {
+ editorBuffer.setText(state.getText());
+ editorBuffer.setCursorPosition(Math.min(state.getCursor(), state.getText().length()));
+ editorBuffer.clearSelection();
+ clampCursorInNormalMode();
+ invalidateSearchIterator();
+ }
- public void clampCursorInNormalMode() {
- final String text = editorBuffer.getText();
- if (text.isEmpty()) {
- editorBuffer.setCursorPosition(0);
- return;
- }
- final int maxCursor = navigation.maxCursorPositionInNormalMode(text);
- final int cursor = Math.min(editorBuffer.getCursorPosition(), maxCursor);
- final int lineStart = navigation.findLineStart(text, cursor);
- if (cursor < text.length() && text.charAt(cursor) == '\n' && cursor > lineStart) {
- editorBuffer.setCursorPosition(cursor - 1);
- } else {
- editorBuffer.setCursorPosition(cursor);
- }
- }
+ public void clampCursorInNormalMode() {
+ final String text = editorBuffer.getText();
+ if (text.isEmpty()) {
+ editorBuffer.setCursorPosition(0);
+ return;
+ }
+ final int maxCursor = navigation.maxCursorPositionInNormalMode(text);
+ final int cursor = Math.min(editorBuffer.getCursorPosition(), maxCursor);
+ final int lineStart = navigation.findLineStart(text, cursor);
+ if (cursor < text.length() && text.charAt(cursor) == '\n' && cursor > lineStart) {
+ editorBuffer.setCursorPosition(cursor - 1);
+ } else {
+ editorBuffer.setCursorPosition(cursor);
+ }
+ }
- public int getCursorPhysicalLine() {
- return editorBuffer.getCursorLine();
- }
+ public int getCursorPhysicalLine() {
+ return editorBuffer.getCursorLine();
+ }
- public String text() {
- return editorBuffer.getText();
- }
+ public String text() {
+ return editorBuffer.getText();
+ }
- public int cursor() {
- return editorBuffer.getCursorPosition();
- }
+ public int cursor() {
+ return editorBuffer.getCursorPosition();
+ }
- public void setCursor(final int position) {
- editorBuffer.setCursorPosition(position);
- }
+ public void setCursor(final int position) {
+ editorBuffer.setCursorPosition(position);
+ }
- public void setText(final String text) {
- editorBuffer.setText(text);
- invalidateSearchIterator();
- }
+ public void setText(final String text) {
+ editorBuffer.setText(text);
+ invalidateSearchIterator();
+ }
- public void clearSelection() {
- editorBuffer.clearSelection();
- }
+ public void clearSelection() {
+ editorBuffer.clearSelection();
+ }
- public void setSelectionEndpoints(final int selectionStart, final int cursorPosition) {
- editorBuffer.setSelectionEndpoints(selectionStart, cursorPosition);
- }
+ public void setSelectionEndpoints(final int selectionStart, final int cursorPosition) {
+ editorBuffer.setSelectionEndpoints(selectionStart, cursorPosition);
+ }
- public Register register() {
- return register;
- }
+ public Register register() {
+ return register;
+ }
- private String normalizeLineRegister(final String lineText) {
- if (lineText.isEmpty() || lineText.charAt(lineText.length() - 1) == '\n') {
- return lineText;
- }
- return lineText + "\n";
- }
+ private String normalizeLineRegister(final String lineText) {
+ if (lineText.isEmpty() || lineText.charAt(lineText.length() - 1) == '\n') {
+ return lineText;
+ }
+ return lineText + "\n";
+ }
}
diff --git a/core/src/main/java/coffee/liz/abstractionengine/app/ui/editor/vim/handler/CommandAction.java b/core/src/main/java/coffee/liz/abstractionengine/app/ui/editor/vim/handler/CommandAction.java
index 7a1b85c..9fcf694 100644
--- a/core/src/main/java/coffee/liz/abstractionengine/app/ui/editor/vim/handler/CommandAction.java
+++ b/core/src/main/java/coffee/liz/abstractionengine/app/ui/editor/vim/handler/CommandAction.java
@@ -4,5 +4,5 @@ import coffee.liz.abstractionengine.app.ui.editor.vim.context.KeyContext;
import coffee.liz.abstractionengine.app.ui.editor.vim.state.ModeState;
public interface CommandAction<S extends ModeState> {
- HandleResult execute(S state, KeyContext context);
+ HandleResult execute(S state, KeyContext context);
}
diff --git a/core/src/main/java/coffee/liz/abstractionengine/app/ui/editor/vim/handler/HandleResult.java b/core/src/main/java/coffee/liz/abstractionengine/app/ui/editor/vim/handler/HandleResult.java
index 9a4e2e4..b58fa77 100644
--- a/core/src/main/java/coffee/liz/abstractionengine/app/ui/editor/vim/handler/HandleResult.java
+++ b/core/src/main/java/coffee/liz/abstractionengine/app/ui/editor/vim/handler/HandleResult.java
@@ -3,30 +3,30 @@ package coffee.liz.abstractionengine.app.ui.editor.vim.handler;
import coffee.liz.abstractionengine.app.ui.editor.vim.state.ModeState;
public record HandleResult(boolean consumed, boolean suppressTyped, ModeState nextState) {
- public static HandleResult notHandled() {
- return new HandleResult(false, false, null);
- }
+ public static HandleResult notHandled() {
+ return new HandleResult(false, false, null);
+ }
- public static HandleResult handled() {
- return new HandleResult(true, false, null);
- }
+ public static HandleResult handled() {
+ return new HandleResult(true, false, null);
+ }
- public static HandleResult handled(final ModeState nextState) {
- return new HandleResult(true, false, nextState);
- }
+ public static HandleResult handled(final ModeState nextState) {
+ return new HandleResult(true, false, nextState);
+ }
- public static HandleResult handledAndSuppressTyped() {
- return new HandleResult(true, true, null);
- }
+ public static HandleResult handledAndSuppressTyped() {
+ return new HandleResult(true, true, null);
+ }
- public static HandleResult handledAndSuppressTyped(final ModeState nextState) {
- return new HandleResult(true, true, nextState);
- }
+ public static HandleResult handledAndSuppressTyped(final ModeState nextState) {
+ return new HandleResult(true, true, nextState);
+ }
- public HandleResult withSuppressTyped() {
- if (!consumed) {
- return this;
- }
- return new HandleResult(true, true, nextState);
- }
+ public HandleResult withSuppressTyped() {
+ if (!consumed) {
+ return this;
+ }
+ return new HandleResult(true, true, nextState);
+ }
}
diff --git a/core/src/main/java/coffee/liz/abstractionengine/app/ui/editor/vim/handler/InsertModeHandler.java b/core/src/main/java/coffee/liz/abstractionengine/app/ui/editor/vim/handler/InsertModeHandler.java
index 176664c..ff9c39f 100644
--- a/core/src/main/java/coffee/liz/abstractionengine/app/ui/editor/vim/handler/InsertModeHandler.java
+++ b/core/src/main/java/coffee/liz/abstractionengine/app/ui/editor/vim/handler/InsertModeHandler.java
@@ -6,19 +6,19 @@ import coffee.liz.abstractionengine.app.ui.editor.vim.context.KeyContext;
import com.badlogic.gdx.Input;
public class InsertModeHandler implements ModeHandler<InsertState> {
- @Override
- public HandleResult onKeyDown(final InsertState state, final KeyContext context) {
- if (context.currentKeyEvent().keycode() == Input.Keys.ESCAPE) {
- context.maybeRecordInsertEdit(state);
- context.clampCursorInNormalMode();
- context.clearSelection();
- return HandleResult.handled(NormalState.DEFAULT);
- }
- return HandleResult.notHandled();
- }
+ @Override
+ public HandleResult onKeyDown(final InsertState state, final KeyContext context) {
+ if (context.currentKeyEvent().keycode() == Input.Keys.ESCAPE) {
+ context.maybeRecordInsertEdit(state);
+ context.clampCursorInNormalMode();
+ context.clearSelection();
+ return HandleResult.handled(NormalState.DEFAULT);
+ }
+ return HandleResult.notHandled();
+ }
- @Override
- public HandleResult onKeyTyped(final InsertState state, final char character, final KeyContext context) {
- return HandleResult.notHandled();
- }
+ @Override
+ public HandleResult onKeyTyped(final InsertState state, final char character, final KeyContext context) {
+ return HandleResult.notHandled();
+ }
}
diff --git a/core/src/main/java/coffee/liz/abstractionengine/app/ui/editor/vim/handler/ModeHandler.java b/core/src/main/java/coffee/liz/abstractionengine/app/ui/editor/vim/handler/ModeHandler.java
index ed04ce2..430e9c4 100644
--- a/core/src/main/java/coffee/liz/abstractionengine/app/ui/editor/vim/handler/ModeHandler.java
+++ b/core/src/main/java/coffee/liz/abstractionengine/app/ui/editor/vim/handler/ModeHandler.java
@@ -4,7 +4,7 @@ import coffee.liz.abstractionengine.app.ui.editor.vim.context.KeyContext;
import coffee.liz.abstractionengine.app.ui.editor.vim.state.ModeState;
public interface ModeHandler<T extends ModeState> {
- HandleResult onKeyDown(T state, KeyContext context);
+ HandleResult onKeyDown(T state, KeyContext context);
- HandleResult onKeyTyped(T state, char character, KeyContext context);
+ HandleResult onKeyTyped(T state, char character, KeyContext context);
}
diff --git a/core/src/main/java/coffee/liz/abstractionengine/app/ui/editor/vim/handler/MotionAction.java b/core/src/main/java/coffee/liz/abstractionengine/app/ui/editor/vim/handler/MotionAction.java
index e6332dd..3e9a0bf 100644
--- a/core/src/main/java/coffee/liz/abstractionengine/app/ui/editor/vim/handler/MotionAction.java
+++ b/core/src/main/java/coffee/liz/abstractionengine/app/ui/editor/vim/handler/MotionAction.java
@@ -3,5 +3,5 @@ package coffee.liz.abstractionengine.app.ui.editor.vim.handler;
import coffee.liz.abstractionengine.app.ui.editor.vim.context.KeyContext;
public interface MotionAction {
- int execute(KeyContext context, int repeats, int preferredColumn, boolean clampInNormalMode);
+ int execute(KeyContext context, int repeats, int preferredColumn, boolean clampInNormalMode);
}
diff --git a/core/src/main/java/coffee/liz/abstractionengine/app/ui/editor/vim/handler/NormalModeHandler.java b/core/src/main/java/coffee/liz/abstractionengine/app/ui/editor/vim/handler/NormalModeHandler.java
index 65e6f71..e064b0e 100644
--- a/core/src/main/java/coffee/liz/abstractionengine/app/ui/editor/vim/handler/NormalModeHandler.java
+++ b/core/src/main/java/coffee/liz/abstractionengine/app/ui/editor/vim/handler/NormalModeHandler.java
@@ -14,313 +14,313 @@ import java.util.HashMap;
import java.util.Map;
public class NormalModeHandler implements ModeHandler<NormalState> {
- private final Map<Character, CommandAction<NormalState>> commandActions = createCommandActions();
- private final Map<Character, MotionAction> motionActions = createMotionActions();
+ private final Map<Character, CommandAction<NormalState>> commandActions = createCommandActions();
+ private final Map<Character, MotionAction> motionActions = createMotionActions();
- @Override
- public HandleResult onKeyDown(final NormalState state, final KeyContext context) {
- if (context.currentKeyEvent().keycode() == Input.Keys.ESCAPE) {
- return HandleResult.handled(NormalState.DEFAULT);
- }
+ @Override
+ public HandleResult onKeyDown(final NormalState state, final KeyContext context) {
+ if (context.currentKeyEvent().keycode() == Input.Keys.ESCAPE) {
+ return HandleResult.handled(NormalState.DEFAULT);
+ }
- final Character commandCharacter = context.toCommandCharacter();
- if (commandCharacter != null) {
- return onKeyTyped(state, commandCharacter.charValue(), context).withSuppressTyped();
- }
+ final Character commandCharacter = context.toCommandCharacter();
+ if (commandCharacter != null) {
+ return onKeyTyped(state, commandCharacter.charValue(), context).withSuppressTyped();
+ }
- return HandleResult.handled();
- }
+ return HandleResult.handled();
+ }
- @Override
- public HandleResult onKeyTyped(final NormalState state, final char character, final KeyContext context) {
- if (character >= '1' && character <= '9') {
- return HandleResult.handled(new NormalState(state.count() * 10 + (character - '0'), state.pendingOperator(),
- state.preferredColumn()));
- }
+ @Override
+ public HandleResult onKeyTyped(final NormalState state, final char character, final KeyContext context) {
+ if (character >= '1' && character <= '9') {
+ return HandleResult.handled(new NormalState(state.count() * 10 + (character - '0'), state.pendingOperator(),
+ state.preferredColumn()));
+ }
- if (character == '0' && state.count() > 0) {
- return HandleResult
- .handled(new NormalState(state.count() * 10, state.pendingOperator(), state.preferredColumn()));
- }
+ if (character == '0' && state.count() > 0) {
+ return HandleResult
+ .handled(new NormalState(state.count() * 10, state.pendingOperator(), state.preferredColumn()));
+ }
- if (state.pendingOperator() != PendingOperator.NONE) {
- return handlePendingOperator(state, character, context);
- }
+ if (state.pendingOperator() != PendingOperator.NONE) {
+ return handlePendingOperator(state, character, context);
+ }
- final NormalState normalizedState = new NormalState(state.count(), PendingOperator.NONE,
- context.resetPreferredColumn(character, state.preferredColumn()));
- final CommandAction<NormalState> action = commandActions.get(character);
- if (action == null) {
- return HandleResult.handled(new NormalState(0, PendingOperator.NONE, normalizedState.preferredColumn()));
- }
- return action.execute(normalizedState, context);
- }
+ final NormalState normalizedState = new NormalState(state.count(), PendingOperator.NONE,
+ context.resetPreferredColumn(character, state.preferredColumn()));
+ final CommandAction<NormalState> action = commandActions.get(character);
+ if (action == null) {
+ return HandleResult.handled(new NormalState(0, PendingOperator.NONE, normalizedState.preferredColumn()));
+ }
+ return action.execute(normalizedState, context);
+ }
- private HandleResult handlePendingOperator(final NormalState state, final char character,
- final KeyContext context) {
- if (state.pendingOperator() == PendingOperator.G_PREFIX) {
- if (character == 'g') {
- context.moveDocumentStart();
- }
- return HandleResult.handled(NormalState.DEFAULT);
- }
+ private HandleResult handlePendingOperator(final NormalState state, final char character,
+ final KeyContext context) {
+ if (state.pendingOperator() == PendingOperator.G_PREFIX) {
+ if (character == 'g') {
+ context.moveDocumentStart();
+ }
+ return HandleResult.handled(NormalState.DEFAULT);
+ }
- final PendingOperator operator = state.pendingOperator();
- final int repeats = context.readCount(state.count());
- if (character == 'd' && operator == PendingOperator.DELETE) {
- context.deleteLines(repeats);
- context.recordUndoState();
- return HandleResult.handled(NormalState.DEFAULT);
- }
- if (character == 'y' && operator == PendingOperator.YANK) {
- context.yankLines(repeats);
- return HandleResult.handled(NormalState.DEFAULT);
- }
- if (character == 'c' && operator == PendingOperator.CHANGE) {
- context.changeLines(repeats);
- context.recordUndoState();
- return HandleResult.handled(new InsertState(context.text(), context.cursor()));
- }
+ final PendingOperator operator = state.pendingOperator();
+ final int repeats = context.readCount(state.count());
+ if (character == 'd' && operator == PendingOperator.DELETE) {
+ context.deleteLines(repeats);
+ context.recordUndoState();
+ return HandleResult.handled(NormalState.DEFAULT);
+ }
+ if (character == 'y' && operator == PendingOperator.YANK) {
+ context.yankLines(repeats);
+ return HandleResult.handled(NormalState.DEFAULT);
+ }
+ if (character == 'c' && operator == PendingOperator.CHANGE) {
+ context.changeLines(repeats);
+ context.recordUndoState();
+ return HandleResult.handled(new InsertState(context.text(), context.cursor()));
+ }
- final int start = context.cursor();
- final int updatedPreferred = applyMotion(character, repeats, state.preferredColumn(), context, true);
- int end = context.cursor();
- if (character == '$') {
- end = Math.min(context.text().length(), end + 1);
- }
+ final int start = context.cursor();
+ final int updatedPreferred = applyMotion(character, repeats, state.preferredColumn(), context, true);
+ int end = context.cursor();
+ if (character == '$') {
+ end = Math.min(context.text().length(), end + 1);
+ }
- final int rangeStart = Math.min(start, end);
- final int rangeEnd = Math.max(start, end);
- if (rangeStart == rangeEnd) {
- if (character == 'l') {
- final String text = context.text();
- if (start < text.length() && text.charAt(start) != '\n') {
- context.register().setText(text.substring(start, start + 1));
- context.register().setType(RegisterType.CHARACTER);
- if (operator == PendingOperator.YANK) {
- return HandleResult.handled(new NormalState(0, PendingOperator.NONE, updatedPreferred));
- }
+ final int rangeStart = Math.min(start, end);
+ final int rangeEnd = Math.max(start, end);
+ if (rangeStart == rangeEnd) {
+ if (character == 'l') {
+ final String text = context.text();
+ if (start < text.length() && text.charAt(start) != '\n') {
+ context.register().setText(text.substring(start, start + 1));
+ context.register().setType(RegisterType.CHARACTER);
+ if (operator == PendingOperator.YANK) {
+ return HandleResult.handled(new NormalState(0, PendingOperator.NONE, updatedPreferred));
+ }
- context.setText(text.substring(0, start) + text.substring(start + 1));
- context.setCursor(Math.min(start, context.text().length()));
- context.clampCursorInNormalMode();
- context.recordUndoState();
- if (operator == PendingOperator.CHANGE) {
- return HandleResult.handled(new InsertState(context.text(), context.cursor()));
- }
- }
- }
- return HandleResult.handled(new NormalState(0, PendingOperator.NONE, updatedPreferred));
- }
+ context.setText(text.substring(0, start) + text.substring(start + 1));
+ context.setCursor(Math.min(start, context.text().length()));
+ context.clampCursorInNormalMode();
+ context.recordUndoState();
+ if (operator == PendingOperator.CHANGE) {
+ return HandleResult.handled(new InsertState(context.text(), context.cursor()));
+ }
+ }
+ }
+ return HandleResult.handled(new NormalState(0, PendingOperator.NONE, updatedPreferred));
+ }
- if (operator == PendingOperator.YANK) {
- context.register().setText(context.text().substring(rangeStart, rangeEnd));
- context.register().setType(RegisterType.CHARACTER);
- context.setCursor(start);
- context.clampCursorInNormalMode();
- return HandleResult.handled(new NormalState(0, PendingOperator.NONE, updatedPreferred));
- }
+ if (operator == PendingOperator.YANK) {
+ context.register().setText(context.text().substring(rangeStart, rangeEnd));
+ context.register().setType(RegisterType.CHARACTER);
+ context.setCursor(start);
+ context.clampCursorInNormalMode();
+ return HandleResult.handled(new NormalState(0, PendingOperator.NONE, updatedPreferred));
+ }
- final String text = context.text();
- context.register().setText(text.substring(rangeStart, rangeEnd));
- context.register().setType(RegisterType.CHARACTER);
- context.setText(text.substring(0, rangeStart) + text.substring(rangeEnd));
- context.setCursor(Math.min(rangeStart, context.text().length()));
- context.clampCursorInNormalMode();
- context.recordUndoState();
+ final String text = context.text();
+ context.register().setText(text.substring(rangeStart, rangeEnd));
+ context.register().setType(RegisterType.CHARACTER);
+ context.setText(text.substring(0, rangeStart) + text.substring(rangeEnd));
+ context.setCursor(Math.min(rangeStart, context.text().length()));
+ context.clampCursorInNormalMode();
+ context.recordUndoState();
- if (operator == PendingOperator.CHANGE) {
- return HandleResult.handled(new InsertState(context.text(), context.cursor()));
- }
- return HandleResult.handled(new NormalState(0, PendingOperator.NONE, updatedPreferred));
- }
+ if (operator == PendingOperator.CHANGE) {
+ return HandleResult.handled(new InsertState(context.text(), context.cursor()));
+ }
+ return HandleResult.handled(new NormalState(0, PendingOperator.NONE, updatedPreferred));
+ }
- private int applyMotion(final char motion, final int repeats, final int preferredColumn, final KeyContext context,
- final boolean clampInNormalMode) {
- final MotionAction action = motionActions.get(motion);
- if (action == null) {
- return preferredColumn;
- }
- return action.execute(context, repeats, preferredColumn, clampInNormalMode);
- }
+ private int applyMotion(final char motion, final int repeats, final int preferredColumn, final KeyContext context,
+ final boolean clampInNormalMode) {
+ final MotionAction action = motionActions.get(motion);
+ if (action == null) {
+ return preferredColumn;
+ }
+ return action.execute(context, repeats, preferredColumn, clampInNormalMode);
+ }
- private Map<Character, CommandAction<NormalState>> createCommandActions() {
- final Map<Character, CommandAction<NormalState>> map = new HashMap<>();
- map.put('h', (state, context) -> {
- final int repeats = context.readCount(state.count());
- for (int i = 0; i < repeats; i++) {
- context.moveLeft();
- }
- return HandleResult.handled(new NormalState(0, PendingOperator.NONE, state.preferredColumn()));
- });
- map.put('j', (state, context) -> {
- final int repeats = context.readCount(state.count());
- final int preferred = context.moveVertical(1, repeats, state.preferredColumn(), true);
- return HandleResult.handled(new NormalState(0, PendingOperator.NONE, preferred));
- });
- map.put('k', (state, context) -> {
- final int repeats = context.readCount(state.count());
- final int preferred = context.moveVertical(-1, repeats, state.preferredColumn(), true);
- return HandleResult.handled(new NormalState(0, PendingOperator.NONE, preferred));
- });
- map.put('l', (state, context) -> {
- final int repeats = context.readCount(state.count());
- for (int i = 0; i < repeats; i++) {
- context.moveRightNormal();
- }
- return HandleResult.handled(new NormalState(0, PendingOperator.NONE, state.preferredColumn()));
- });
- map.put('w', (state, context) -> {
- final int repeats = context.readCount(state.count());
- for (int i = 0; i < repeats; i++) {
- context.moveWordForward();
- }
- context.clampCursorInNormalMode();
- return HandleResult.handled(new NormalState(0, PendingOperator.NONE, state.preferredColumn()));
- });
- map.put('b', (state, context) -> {
- final int repeats = context.readCount(state.count());
- for (int i = 0; i < repeats; i++) {
- context.moveWordBackward();
- }
- return HandleResult.handled(new NormalState(0, PendingOperator.NONE, state.preferredColumn()));
- });
- map.put('0', (state, context) -> {
- context.moveLineStart();
- return HandleResult.handled(new NormalState(0, PendingOperator.NONE, state.preferredColumn()));
- });
- map.put('$', (state, context) -> {
- context.moveLineEnd();
- return HandleResult.handled(new NormalState(0, PendingOperator.NONE, state.preferredColumn()));
- });
- map.put('G', (state, context) -> {
- context.moveDocumentEnd();
- return HandleResult.handled(new NormalState(0, PendingOperator.NONE, state.preferredColumn()));
- });
- map.put('g', (state, context) -> HandleResult
- .handled(new NormalState(0, PendingOperator.G_PREFIX, state.preferredColumn())));
- map.put('i', (state, context) -> HandleResult.handled(new InsertState(context.text(), context.cursor())));
- map.put('a', (state, context) -> {
- context.moveRightForAppend();
- return HandleResult.handled(new InsertState(context.text(), context.cursor()));
- });
- map.put('o', (state, context) -> {
- context.openLineBelow();
- return HandleResult.handled(new InsertState(context.text(), context.cursor()));
- });
- map.put('O', (state, context) -> {
- context.openLineAbove();
- return HandleResult.handled(new InsertState(context.text(), context.cursor()));
- });
- map.put('x', (state, context) -> {
- final int repeats = context.readCount(state.count());
- for (int i = 0; i < repeats; i++) {
- context.deleteCharUnderCursor();
- }
- context.clampCursorInNormalMode();
- context.recordUndoState();
- return HandleResult.handled(new NormalState(0, PendingOperator.NONE, state.preferredColumn()));
- });
- map.put('d', (state, context) -> HandleResult
- .handled(new NormalState(0, PendingOperator.DELETE, state.preferredColumn())));
- map.put('y', (state, context) -> HandleResult
- .handled(new NormalState(0, PendingOperator.YANK, state.preferredColumn())));
- map.put('c', (state, context) -> HandleResult
- .handled(new NormalState(0, PendingOperator.CHANGE, state.preferredColumn())));
- map.put('p', (state, context) -> {
- final int repeats = context.readCount(state.count());
- for (int i = 0; i < repeats; i++) {
- context.pasteAfter();
- }
- context.clampCursorInNormalMode();
- context.recordUndoState();
- return HandleResult.handled(new NormalState(0, PendingOperator.NONE, state.preferredColumn()));
- });
- map.put('P', (state, context) -> {
- final int repeats = context.readCount(state.count());
- for (int i = 0; i < repeats; i++) {
- context.pasteBefore();
- }
- context.clampCursorInNormalMode();
- context.recordUndoState();
- return HandleResult.handled(new NormalState(0, PendingOperator.NONE, state.preferredColumn()));
- });
- map.put('v', (state, context) -> {
- final int anchor = context.cursor();
- context.updateVisualSelection(anchor);
- return HandleResult.handled(new VisualState(anchor, state.preferredColumn(), PendingOperator.NONE, 0));
- });
- map.put('V', (state, context) -> {
- final int anchorLine = context.getCursorPhysicalLine();
- context.updateVisualLineSelection(anchorLine, anchorLine);
- return HandleResult.handled(
- new VisualLineState(anchorLine, anchorLine, state.preferredColumn(), PendingOperator.NONE, 0));
- });
- map.put('/', (state, context) -> HandleResult
- .handled(new SearchState(new StringBuilder(), context.getLastSearchQuery(), SearchDirection.FORWARD)));
- map.put('?', (state, context) -> HandleResult
- .handled(new SearchState(new StringBuilder(), context.getLastSearchQuery(), SearchDirection.BACKWARD)));
- map.put('n', (state, context) -> {
- context.findNext(context.getLastSearchQuery(), SearchDirection.FORWARD);
- return HandleResult.handled(new NormalState(0, PendingOperator.NONE, state.preferredColumn()));
- });
- map.put('N', (state, context) -> {
- context.findNext(context.getLastSearchQuery(), SearchDirection.BACKWARD);
- return HandleResult.handled(new NormalState(0, PendingOperator.NONE, state.preferredColumn()));
- });
- map.put('u', (state, context) -> HandleResult.handled(context.undoToNormalState()));
- return map;
- }
+ private Map<Character, CommandAction<NormalState>> createCommandActions() {
+ final Map<Character, CommandAction<NormalState>> map = new HashMap<>();
+ map.put('h', (state, context) -> {
+ final int repeats = context.readCount(state.count());
+ for (int i = 0; i < repeats; i++) {
+ context.moveLeft();
+ }
+ return HandleResult.handled(new NormalState(0, PendingOperator.NONE, state.preferredColumn()));
+ });
+ map.put('j', (state, context) -> {
+ final int repeats = context.readCount(state.count());
+ final int preferred = context.moveVertical(1, repeats, state.preferredColumn(), true);
+ return HandleResult.handled(new NormalState(0, PendingOperator.NONE, preferred));
+ });
+ map.put('k', (state, context) -> {
+ final int repeats = context.readCount(state.count());
+ final int preferred = context.moveVertical(-1, repeats, state.preferredColumn(), true);
+ return HandleResult.handled(new NormalState(0, PendingOperator.NONE, preferred));
+ });
+ map.put('l', (state, context) -> {
+ final int repeats = context.readCount(state.count());
+ for (int i = 0; i < repeats; i++) {
+ context.moveRightNormal();
+ }
+ return HandleResult.handled(new NormalState(0, PendingOperator.NONE, state.preferredColumn()));
+ });
+ map.put('w', (state, context) -> {
+ final int repeats = context.readCount(state.count());
+ for (int i = 0; i < repeats; i++) {
+ context.moveWordForward();
+ }
+ context.clampCursorInNormalMode();
+ return HandleResult.handled(new NormalState(0, PendingOperator.NONE, state.preferredColumn()));
+ });
+ map.put('b', (state, context) -> {
+ final int repeats = context.readCount(state.count());
+ for (int i = 0; i < repeats; i++) {
+ context.moveWordBackward();
+ }
+ return HandleResult.handled(new NormalState(0, PendingOperator.NONE, state.preferredColumn()));
+ });
+ map.put('0', (state, context) -> {
+ context.moveLineStart();
+ return HandleResult.handled(new NormalState(0, PendingOperator.NONE, state.preferredColumn()));
+ });
+ map.put('$', (state, context) -> {
+ context.moveLineEnd();
+ return HandleResult.handled(new NormalState(0, PendingOperator.NONE, state.preferredColumn()));
+ });
+ map.put('G', (state, context) -> {
+ context.moveDocumentEnd();
+ return HandleResult.handled(new NormalState(0, PendingOperator.NONE, state.preferredColumn()));
+ });
+ map.put('g', (state, context) -> HandleResult
+ .handled(new NormalState(0, PendingOperator.G_PREFIX, state.preferredColumn())));
+ map.put('i', (state, context) -> HandleResult.handled(new InsertState(context.text(), context.cursor())));
+ map.put('a', (state, context) -> {
+ context.moveRightForAppend();
+ return HandleResult.handled(new InsertState(context.text(), context.cursor()));
+ });
+ map.put('o', (state, context) -> {
+ context.openLineBelow();
+ return HandleResult.handled(new InsertState(context.text(), context.cursor()));
+ });
+ map.put('O', (state, context) -> {
+ context.openLineAbove();
+ return HandleResult.handled(new InsertState(context.text(), context.cursor()));
+ });
+ map.put('x', (state, context) -> {
+ final int repeats = context.readCount(state.count());
+ for (int i = 0; i < repeats; i++) {
+ context.deleteCharUnderCursor();
+ }
+ context.clampCursorInNormalMode();
+ context.recordUndoState();
+ return HandleResult.handled(new NormalState(0, PendingOperator.NONE, state.preferredColumn()));
+ });
+ map.put('d', (state, context) -> HandleResult
+ .handled(new NormalState(0, PendingOperator.DELETE, state.preferredColumn())));
+ map.put('y', (state, context) -> HandleResult
+ .handled(new NormalState(0, PendingOperator.YANK, state.preferredColumn())));
+ map.put('c', (state, context) -> HandleResult
+ .handled(new NormalState(0, PendingOperator.CHANGE, state.preferredColumn())));
+ map.put('p', (state, context) -> {
+ final int repeats = context.readCount(state.count());
+ for (int i = 0; i < repeats; i++) {
+ context.pasteAfter();
+ }
+ context.clampCursorInNormalMode();
+ context.recordUndoState();
+ return HandleResult.handled(new NormalState(0, PendingOperator.NONE, state.preferredColumn()));
+ });
+ map.put('P', (state, context) -> {
+ final int repeats = context.readCount(state.count());
+ for (int i = 0; i < repeats; i++) {
+ context.pasteBefore();
+ }
+ context.clampCursorInNormalMode();
+ context.recordUndoState();
+ return HandleResult.handled(new NormalState(0, PendingOperator.NONE, state.preferredColumn()));
+ });
+ map.put('v', (state, context) -> {
+ final int anchor = context.cursor();
+ context.updateVisualSelection(anchor);
+ return HandleResult.handled(new VisualState(anchor, state.preferredColumn(), PendingOperator.NONE, 0));
+ });
+ map.put('V', (state, context) -> {
+ final int anchorLine = context.getCursorPhysicalLine();
+ context.updateVisualLineSelection(anchorLine, anchorLine);
+ return HandleResult.handled(
+ new VisualLineState(anchorLine, anchorLine, state.preferredColumn(), PendingOperator.NONE, 0));
+ });
+ map.put('/', (state, context) -> HandleResult
+ .handled(new SearchState(new StringBuilder(), context.getLastSearchQuery(), SearchDirection.FORWARD)));
+ map.put('?', (state, context) -> HandleResult
+ .handled(new SearchState(new StringBuilder(), context.getLastSearchQuery(), SearchDirection.BACKWARD)));
+ map.put('n', (state, context) -> {
+ context.findNext(context.getLastSearchQuery(), SearchDirection.FORWARD);
+ return HandleResult.handled(new NormalState(0, PendingOperator.NONE, state.preferredColumn()));
+ });
+ map.put('N', (state, context) -> {
+ context.findNext(context.getLastSearchQuery(), SearchDirection.BACKWARD);
+ return HandleResult.handled(new NormalState(0, PendingOperator.NONE, state.preferredColumn()));
+ });
+ map.put('u', (state, context) -> HandleResult.handled(context.undoToNormalState()));
+ return map;
+ }
- private Map<Character, MotionAction> createMotionActions() {
- final Map<Character, MotionAction> map = new HashMap<>();
- map.put('h', (context, repeats, preferredColumn, clampInNormalMode) -> {
- for (int i = 0; i < repeats; i++) {
- context.moveLeft();
- }
- return preferredColumn;
- });
- map.put('j', (context, repeats, preferredColumn, clampInNormalMode) -> context.moveVertical(1, repeats,
- preferredColumn, clampInNormalMode));
- map.put('k', (context, repeats, preferredColumn, clampInNormalMode) -> context.moveVertical(-1, repeats,
- preferredColumn, clampInNormalMode));
- map.put('l', (context, repeats, preferredColumn, clampInNormalMode) -> {
- for (int i = 0; i < repeats; i++) {
- context.moveRightNormal();
- }
- return preferredColumn;
- });
- map.put('w', (context, repeats, preferredColumn, clampInNormalMode) -> {
- for (int i = 0; i < repeats; i++) {
- context.moveWordForward();
- }
- if (clampInNormalMode) {
- context.clampCursorInNormalMode();
- }
- return preferredColumn;
- });
- map.put('b', (context, repeats, preferredColumn, clampInNormalMode) -> {
- for (int i = 0; i < repeats; i++) {
- context.moveWordBackward();
- }
- return preferredColumn;
- });
- map.put('0', (context, repeats, preferredColumn, clampInNormalMode) -> {
- context.moveLineStart();
- return preferredColumn;
- });
- map.put('$', (context, repeats, preferredColumn, clampInNormalMode) -> {
- context.moveLineEnd();
- return preferredColumn;
- });
- map.put('G', (context, repeats, preferredColumn, clampInNormalMode) -> {
- context.moveDocumentEnd();
- return preferredColumn;
- });
- map.put('g', (context, repeats, preferredColumn, clampInNormalMode) -> {
- context.moveDocumentStart();
- return preferredColumn;
- });
- return map;
- }
+ private Map<Character, MotionAction> createMotionActions() {
+ final Map<Character, MotionAction> map = new HashMap<>();
+ map.put('h', (context, repeats, preferredColumn, clampInNormalMode) -> {
+ for (int i = 0; i < repeats; i++) {
+ context.moveLeft();
+ }
+ return preferredColumn;
+ });
+ map.put('j', (context, repeats, preferredColumn, clampInNormalMode) -> context.moveVertical(1, repeats,
+ preferredColumn, clampInNormalMode));
+ map.put('k', (context, repeats, preferredColumn, clampInNormalMode) -> context.moveVertical(-1, repeats,
+ preferredColumn, clampInNormalMode));
+ map.put('l', (context, repeats, preferredColumn, clampInNormalMode) -> {
+ for (int i = 0; i < repeats; i++) {
+ context.moveRightNormal();
+ }
+ return preferredColumn;
+ });
+ map.put('w', (context, repeats, preferredColumn, clampInNormalMode) -> {
+ for (int i = 0; i < repeats; i++) {
+ context.moveWordForward();
+ }
+ if (clampInNormalMode) {
+ context.clampCursorInNormalMode();
+ }
+ return preferredColumn;
+ });
+ map.put('b', (context, repeats, preferredColumn, clampInNormalMode) -> {
+ for (int i = 0; i < repeats; i++) {
+ context.moveWordBackward();
+ }
+ return preferredColumn;
+ });
+ map.put('0', (context, repeats, preferredColumn, clampInNormalMode) -> {
+ context.moveLineStart();
+ return preferredColumn;
+ });
+ map.put('$', (context, repeats, preferredColumn, clampInNormalMode) -> {
+ context.moveLineEnd();
+ return preferredColumn;
+ });
+ map.put('G', (context, repeats, preferredColumn, clampInNormalMode) -> {
+ context.moveDocumentEnd();
+ return preferredColumn;
+ });
+ map.put('g', (context, repeats, preferredColumn, clampInNormalMode) -> {
+ context.moveDocumentStart();
+ return preferredColumn;
+ });
+ return map;
+ }
}
diff --git a/core/src/main/java/coffee/liz/abstractionengine/app/ui/editor/vim/handler/SearchModeHandler.java b/core/src/main/java/coffee/liz/abstractionengine/app/ui/editor/vim/handler/SearchModeHandler.java
index c3e20f2..1c0bdd5 100644
--- a/core/src/main/java/coffee/liz/abstractionengine/app/ui/editor/vim/handler/SearchModeHandler.java
+++ b/core/src/main/java/coffee/liz/abstractionengine/app/ui/editor/vim/handler/SearchModeHandler.java
@@ -7,36 +7,36 @@ import coffee.liz.abstractionengine.app.ui.editor.vim.state.SearchState;
import com.badlogic.gdx.Input;
public class SearchModeHandler implements ModeHandler<SearchState> {
- @Override
- public HandleResult onKeyDown(final SearchState state, final KeyContext context) {
- if (context.currentKeyEvent().keycode() == Input.Keys.ESCAPE) {
- return HandleResult.handled(NormalState.DEFAULT);
- }
- return HandleResult.handled();
- }
+ @Override
+ public HandleResult onKeyDown(final SearchState state, final KeyContext context) {
+ if (context.currentKeyEvent().keycode() == Input.Keys.ESCAPE) {
+ return HandleResult.handled(NormalState.DEFAULT);
+ }
+ return HandleResult.handled();
+ }
- @Override
- public HandleResult onKeyTyped(final SearchState state, final char character, final KeyContext context) {
- if (character == '\r' || character == '\n') {
- final String query = state.query().toString();
- context.setLastSearchQuery(query);
- context.invalidateSearchIterator();
- context.findNext(query, state.direction());
- return HandleResult.handled(NormalState.DEFAULT);
- }
+ @Override
+ public HandleResult onKeyTyped(final SearchState state, final char character, final KeyContext context) {
+ if (character == '\r' || character == '\n') {
+ final String query = state.query().toString();
+ context.setLastSearchQuery(query);
+ context.invalidateSearchIterator();
+ context.findNext(query, state.direction());
+ return HandleResult.handled(NormalState.DEFAULT);
+ }
- if (character == '\b') {
- if (state.query().length() > 0) {
- state.query().setLength(state.query().length() - 1);
- }
- return HandleResult.handled(state);
- }
+ if (character == '\b') {
+ if (state.query().length() > 0) {
+ state.query().setLength(state.query().length() - 1);
+ }
+ return HandleResult.handled(state);
+ }
- if (character < 32 || character == 127) {
- return HandleResult.handled(state);
- }
+ if (character < 32 || character == 127) {
+ return HandleResult.handled(state);
+ }
- state.query().append(character);
- return HandleResult.handled(new SearchState(state.query(), state.lastQuery(), state.direction()));
- }
+ state.query().append(character);
+ return HandleResult.handled(new SearchState(state.query(), state.lastQuery(), state.direction()));
+ }
}
diff --git a/core/src/main/java/coffee/liz/abstractionengine/app/ui/editor/vim/handler/VisualLineModeHandler.java b/core/src/main/java/coffee/liz/abstractionengine/app/ui/editor/vim/handler/VisualLineModeHandler.java
index 7056e54..58617bd 100644
--- a/core/src/main/java/coffee/liz/abstractionengine/app/ui/editor/vim/handler/VisualLineModeHandler.java
+++ b/core/src/main/java/coffee/liz/abstractionengine/app/ui/editor/vim/handler/VisualLineModeHandler.java
@@ -9,84 +9,84 @@ import java.util.HashMap;
import java.util.Map;
public class VisualLineModeHandler implements ModeHandler<VisualLineState> {
- private final Map<Character, CommandAction<VisualLineState>> commandActions = createCommandActions();
+ private final Map<Character, CommandAction<VisualLineState>> commandActions = createCommandActions();
- @Override
- public HandleResult onKeyDown(final VisualLineState state, final KeyContext context) {
- if (context.currentKeyEvent().keycode() == Input.Keys.ESCAPE) {
- final int startLine = Math.min(state.anchorLine(), state.cursorLine());
- context.setCursor(context.navigation().findLineStartByLine(context.text(), startLine));
- context.clampCursorInNormalMode();
- context.clearSelection();
- return HandleResult.handled(NormalState.DEFAULT);
- }
+ @Override
+ public HandleResult onKeyDown(final VisualLineState state, final KeyContext context) {
+ if (context.currentKeyEvent().keycode() == Input.Keys.ESCAPE) {
+ final int startLine = Math.min(state.anchorLine(), state.cursorLine());
+ context.setCursor(context.navigation().findLineStartByLine(context.text(), startLine));
+ context.clampCursorInNormalMode();
+ context.clearSelection();
+ return HandleResult.handled(NormalState.DEFAULT);
+ }
- final Character commandCharacter = context.toCommandCharacter();
- if (commandCharacter != null) {
- return onKeyTyped(state, commandCharacter.charValue(), context).withSuppressTyped();
- }
+ final Character commandCharacter = context.toCommandCharacter();
+ if (commandCharacter != null) {
+ return onKeyTyped(state, commandCharacter.charValue(), context).withSuppressTyped();
+ }
- return HandleResult.handled();
- }
+ return HandleResult.handled();
+ }
- @Override
- public HandleResult onKeyTyped(final VisualLineState state, final char character, final KeyContext context) {
- if (character >= '1' && character <= '9') {
- return HandleResult.handled(new VisualLineState(state.anchorLine(), state.cursorLine(),
- state.preferredColumn(), state.pendingOperator(), state.count() * 10 + (character - '0')));
- }
- if (character == '0' && state.count() > 0) {
- return HandleResult.handled(new VisualLineState(state.anchorLine(), state.cursorLine(),
- state.preferredColumn(), state.pendingOperator(), state.count() * 10));
- }
+ @Override
+ public HandleResult onKeyTyped(final VisualLineState state, final char character, final KeyContext context) {
+ if (character >= '1' && character <= '9') {
+ return HandleResult.handled(new VisualLineState(state.anchorLine(), state.cursorLine(),
+ state.preferredColumn(), state.pendingOperator(), state.count() * 10 + (character - '0')));
+ }
+ if (character == '0' && state.count() > 0) {
+ return HandleResult.handled(new VisualLineState(state.anchorLine(), state.cursorLine(),
+ state.preferredColumn(), state.pendingOperator(), state.count() * 10));
+ }
- if (state.pendingOperator() == PendingOperator.G_PREFIX) {
- if (character == 'g') {
- final int cursorLine = 0;
- context.updateVisualLineSelection(state.anchorLine(), cursorLine);
- return HandleResult.handled(new VisualLineState(state.anchorLine(), cursorLine, state.preferredColumn(),
- PendingOperator.NONE, 0));
- }
- return HandleResult.handled(new VisualLineState(state.anchorLine(), state.cursorLine(),
- state.preferredColumn(), PendingOperator.NONE, 0));
- }
+ if (state.pendingOperator() == PendingOperator.G_PREFIX) {
+ if (character == 'g') {
+ final int cursorLine = 0;
+ context.updateVisualLineSelection(state.anchorLine(), cursorLine);
+ return HandleResult.handled(new VisualLineState(state.anchorLine(), cursorLine, state.preferredColumn(),
+ PendingOperator.NONE, 0));
+ }
+ return HandleResult.handled(new VisualLineState(state.anchorLine(), state.cursorLine(),
+ state.preferredColumn(), PendingOperator.NONE, 0));
+ }
- final CommandAction<VisualLineState> action = commandActions.get(character);
- if (action == null) {
- return HandleResult.handled(new VisualLineState(state.anchorLine(), state.cursorLine(),
- state.preferredColumn(), PendingOperator.NONE, 0));
- }
- return action.execute(new VisualLineState(state.anchorLine(), state.cursorLine(),
- context.resetPreferredColumn(character, state.preferredColumn()), PendingOperator.NONE, state.count()),
- context);
- }
+ final CommandAction<VisualLineState> action = commandActions.get(character);
+ if (action == null) {
+ return HandleResult.handled(new VisualLineState(state.anchorLine(), state.cursorLine(),
+ state.preferredColumn(), PendingOperator.NONE, 0));
+ }
+ return action.execute(new VisualLineState(state.anchorLine(), state.cursorLine(),
+ context.resetPreferredColumn(character, state.preferredColumn()), PendingOperator.NONE, state.count()),
+ context);
+ }
- private Map<Character, CommandAction<VisualLineState>> createCommandActions() {
- final Map<Character, CommandAction<VisualLineState>> map = new HashMap<>();
- map.put('j', (state, context) -> {
- final int cursorLine = context.adjustVisualLineCursor(state.cursorLine(), context.readCount(state.count()));
- context.updateVisualLineSelection(state.anchorLine(), cursorLine);
- return HandleResult.handled(new VisualLineState(state.anchorLine(), cursorLine, state.preferredColumn(),
- PendingOperator.NONE, 0));
- });
- map.put('k', (state, context) -> {
- final int cursorLine = context.adjustVisualLineCursor(state.cursorLine(),
- -context.readCount(state.count()));
- context.updateVisualLineSelection(state.anchorLine(), cursorLine);
- return HandleResult.handled(new VisualLineState(state.anchorLine(), cursorLine, state.preferredColumn(),
- PendingOperator.NONE, 0));
- });
- map.put('G', (state, context) -> {
- final int cursorLine = context.maxSelectableLineIndex();
- context.updateVisualLineSelection(state.anchorLine(), cursorLine);
- return HandleResult.handled(new VisualLineState(state.anchorLine(), cursorLine, state.preferredColumn(),
- PendingOperator.NONE, 0));
- });
- map.put('g', (state, context) -> HandleResult.handled(new VisualLineState(state.anchorLine(),
- state.cursorLine(), state.preferredColumn(), PendingOperator.G_PREFIX, 0)));
- map.put('d', (state, context) -> context.applyVisualLineOperator(state, PendingOperator.DELETE));
- map.put('y', (state, context) -> context.applyVisualLineOperator(state, PendingOperator.YANK));
- map.put('c', (state, context) -> context.applyVisualLineOperator(state, PendingOperator.CHANGE));
- return map;
- }
+ private Map<Character, CommandAction<VisualLineState>> createCommandActions() {
+ final Map<Character, CommandAction<VisualLineState>> map = new HashMap<>();
+ map.put('j', (state, context) -> {
+ final int cursorLine = context.adjustVisualLineCursor(state.cursorLine(), context.readCount(state.count()));
+ context.updateVisualLineSelection(state.anchorLine(), cursorLine);
+ return HandleResult.handled(new VisualLineState(state.anchorLine(), cursorLine, state.preferredColumn(),
+ PendingOperator.NONE, 0));
+ });
+ map.put('k', (state, context) -> {
+ final int cursorLine = context.adjustVisualLineCursor(state.cursorLine(),
+ -context.readCount(state.count()));
+ context.updateVisualLineSelection(state.anchorLine(), cursorLine);
+ return HandleResult.handled(new VisualLineState(state.anchorLine(), cursorLine, state.preferredColumn(),
+ PendingOperator.NONE, 0));
+ });
+ map.put('G', (state, context) -> {
+ final int cursorLine = context.maxSelectableLineIndex();
+ context.updateVisualLineSelection(state.anchorLine(), cursorLine);
+ return HandleResult.handled(new VisualLineState(state.anchorLine(), cursorLine, state.preferredColumn(),
+ PendingOperator.NONE, 0));
+ });
+ map.put('g', (state, context) -> HandleResult.handled(new VisualLineState(state.anchorLine(),
+ state.cursorLine(), state.preferredColumn(), PendingOperator.G_PREFIX, 0)));
+ map.put('d', (state, context) -> context.applyVisualLineOperator(state, PendingOperator.DELETE));
+ map.put('y', (state, context) -> context.applyVisualLineOperator(state, PendingOperator.YANK));
+ map.put('c', (state, context) -> context.applyVisualLineOperator(state, PendingOperator.CHANGE));
+ return map;
+ }
}
diff --git a/core/src/main/java/coffee/liz/abstractionengine/app/ui/editor/vim/handler/VisualModeHandler.java b/core/src/main/java/coffee/liz/abstractionengine/app/ui/editor/vim/handler/VisualModeHandler.java
index db794d5..7fe7d6a 100644
--- a/core/src/main/java/coffee/liz/abstractionengine/app/ui/editor/vim/handler/VisualModeHandler.java
+++ b/core/src/main/java/coffee/liz/abstractionengine/app/ui/editor/vim/handler/VisualModeHandler.java
@@ -9,124 +9,124 @@ import java.util.HashMap;
import java.util.Map;
public class VisualModeHandler implements ModeHandler<VisualState> {
- private final Map<Character, CommandAction<VisualState>> commandActions = createCommandActions();
+ private final Map<Character, CommandAction<VisualState>> commandActions = createCommandActions();
- @Override
- public HandleResult onKeyDown(final VisualState state, final KeyContext context) {
- if (context.currentKeyEvent().keycode() == Input.Keys.ESCAPE) {
- context.setCursor(Math.min(state.anchor(), context.cursor()));
- context.clampCursorInNormalMode();
- context.clearSelection();
- return HandleResult.handled(NormalState.DEFAULT);
- }
+ @Override
+ public HandleResult onKeyDown(final VisualState state, final KeyContext context) {
+ if (context.currentKeyEvent().keycode() == Input.Keys.ESCAPE) {
+ context.setCursor(Math.min(state.anchor(), context.cursor()));
+ context.clampCursorInNormalMode();
+ context.clearSelection();
+ return HandleResult.handled(NormalState.DEFAULT);
+ }
- final Character commandCharacter = context.toCommandCharacter();
- if (commandCharacter != null) {
- return onKeyTyped(state, commandCharacter.charValue(), context).withSuppressTyped();
- }
+ final Character commandCharacter = context.toCommandCharacter();
+ if (commandCharacter != null) {
+ return onKeyTyped(state, commandCharacter.charValue(), context).withSuppressTyped();
+ }
- return HandleResult.handled();
- }
+ return HandleResult.handled();
+ }
- @Override
- public HandleResult onKeyTyped(final VisualState state, final char character, final KeyContext context) {
- if (character >= '1' && character <= '9') {
- return HandleResult.handled(new VisualState(state.anchor(), state.preferredColumn(),
- state.pendingOperator(), state.count() * 10 + (character - '0')));
- }
- if (character == '0' && state.count() > 0) {
- return HandleResult.handled(new VisualState(state.anchor(), state.preferredColumn(),
- state.pendingOperator(), state.count() * 10));
- }
+ @Override
+ public HandleResult onKeyTyped(final VisualState state, final char character, final KeyContext context) {
+ if (character >= '1' && character <= '9') {
+ return HandleResult.handled(new VisualState(state.anchor(), state.preferredColumn(),
+ state.pendingOperator(), state.count() * 10 + (character - '0')));
+ }
+ if (character == '0' && state.count() > 0) {
+ return HandleResult.handled(new VisualState(state.anchor(), state.preferredColumn(),
+ state.pendingOperator(), state.count() * 10));
+ }
- if (state.pendingOperator() == PendingOperator.G_PREFIX) {
- if (character == 'g') {
- context.moveDocumentStart();
- context.updateVisualSelection(state.anchor());
- }
- return HandleResult
- .handled(new VisualState(state.anchor(), state.preferredColumn(), PendingOperator.NONE, 0));
- }
+ if (state.pendingOperator() == PendingOperator.G_PREFIX) {
+ if (character == 'g') {
+ context.moveDocumentStart();
+ context.updateVisualSelection(state.anchor());
+ }
+ return HandleResult
+ .handled(new VisualState(state.anchor(), state.preferredColumn(), PendingOperator.NONE, 0));
+ }
- final VisualState normalizedState = new VisualState(state.anchor(),
- context.resetPreferredColumn(character, state.preferredColumn()), PendingOperator.NONE, state.count());
- final CommandAction<VisualState> action = commandActions.get(character);
- if (action == null) {
- return HandleResult.handled(
- new VisualState(state.anchor(), normalizedState.preferredColumn(), PendingOperator.NONE, 0));
- }
- return action.execute(normalizedState, context);
- }
+ final VisualState normalizedState = new VisualState(state.anchor(),
+ context.resetPreferredColumn(character, state.preferredColumn()), PendingOperator.NONE, state.count());
+ final CommandAction<VisualState> action = commandActions.get(character);
+ if (action == null) {
+ return HandleResult.handled(
+ new VisualState(state.anchor(), normalizedState.preferredColumn(), PendingOperator.NONE, 0));
+ }
+ return action.execute(normalizedState, context);
+ }
- private Map<Character, CommandAction<VisualState>> createCommandActions() {
- final Map<Character, CommandAction<VisualState>> map = new HashMap<>();
- map.put('h', (state, context) -> {
- for (int i = 0; i < context.readCount(state.count()); i++) {
- context.moveLeft();
- }
- context.updateVisualSelection(state.anchor());
- return HandleResult
- .handled(new VisualState(state.anchor(), state.preferredColumn(), PendingOperator.NONE, 0));
- });
- map.put('j', (state, context) -> {
- final int preferred = context.moveVertical(1, context.readCount(state.count()), state.preferredColumn(),
- false);
- context.updateVisualSelection(state.anchor());
- return HandleResult.handled(new VisualState(state.anchor(), preferred, PendingOperator.NONE, 0));
- });
- map.put('k', (state, context) -> {
- final int preferred = context.moveVertical(-1, context.readCount(state.count()), state.preferredColumn(),
- false);
- context.updateVisualSelection(state.anchor());
- return HandleResult.handled(new VisualState(state.anchor(), preferred, PendingOperator.NONE, 0));
- });
- map.put('l', (state, context) -> {
- for (int i = 0; i < context.readCount(state.count()); i++) {
- context.moveRightNormal();
- }
- context.updateVisualSelection(state.anchor());
- return HandleResult
- .handled(new VisualState(state.anchor(), state.preferredColumn(), PendingOperator.NONE, 0));
- });
- map.put('w', (state, context) -> {
- for (int i = 0; i < context.readCount(state.count()); i++) {
- context.moveWordForward();
- }
- context.updateVisualSelection(state.anchor());
- return HandleResult
- .handled(new VisualState(state.anchor(), state.preferredColumn(), PendingOperator.NONE, 0));
- });
- map.put('b', (state, context) -> {
- for (int i = 0; i < context.readCount(state.count()); i++) {
- context.moveWordBackward();
- }
- context.updateVisualSelection(state.anchor());
- return HandleResult
- .handled(new VisualState(state.anchor(), state.preferredColumn(), PendingOperator.NONE, 0));
- });
- map.put('0', (state, context) -> {
- context.moveLineStart();
- context.updateVisualSelection(state.anchor());
- return HandleResult
- .handled(new VisualState(state.anchor(), state.preferredColumn(), PendingOperator.NONE, 0));
- });
- map.put('$', (state, context) -> {
- context.moveLineEnd();
- context.updateVisualSelection(state.anchor());
- return HandleResult
- .handled(new VisualState(state.anchor(), state.preferredColumn(), PendingOperator.NONE, 0));
- });
- map.put('G', (state, context) -> {
- context.moveDocumentEnd();
- context.updateVisualSelection(state.anchor());
- return HandleResult
- .handled(new VisualState(state.anchor(), state.preferredColumn(), PendingOperator.NONE, 0));
- });
- map.put('g', (state, context) -> HandleResult
- .handled(new VisualState(state.anchor(), state.preferredColumn(), PendingOperator.G_PREFIX, 0)));
- map.put('d', (state, context) -> context.applyVisualOperator(state, PendingOperator.DELETE));
- map.put('y', (state, context) -> context.applyVisualOperator(state, PendingOperator.YANK));
- map.put('c', (state, context) -> context.applyVisualOperator(state, PendingOperator.CHANGE));
- return map;
- }
+ private Map<Character, CommandAction<VisualState>> createCommandActions() {
+ final Map<Character, CommandAction<VisualState>> map = new HashMap<>();
+ map.put('h', (state, context) -> {
+ for (int i = 0; i < context.readCount(state.count()); i++) {
+ context.moveLeft();
+ }
+ context.updateVisualSelection(state.anchor());
+ return HandleResult
+ .handled(new VisualState(state.anchor(), state.preferredColumn(), PendingOperator.NONE, 0));
+ });
+ map.put('j', (state, context) -> {
+ final int preferred = context.moveVertical(1, context.readCount(state.count()), state.preferredColumn(),
+ false);
+ context.updateVisualSelection(state.anchor());
+ return HandleResult.handled(new VisualState(state.anchor(), preferred, PendingOperator.NONE, 0));
+ });
+ map.put('k', (state, context) -> {
+ final int preferred = context.moveVertical(-1, context.readCount(state.count()), state.preferredColumn(),
+ false);
+ context.updateVisualSelection(state.anchor());
+ return HandleResult.handled(new VisualState(state.anchor(), preferred, PendingOperator.NONE, 0));
+ });
+ map.put('l', (state, context) -> {
+ for (int i = 0; i < context.readCount(state.count()); i++) {
+ context.moveRightNormal();
+ }
+ context.updateVisualSelection(state.anchor());
+ return HandleResult
+ .handled(new VisualState(state.anchor(), state.preferredColumn(), PendingOperator.NONE, 0));
+ });
+ map.put('w', (state, context) -> {
+ for (int i = 0; i < context.readCount(state.count()); i++) {
+ context.moveWordForward();
+ }
+ context.updateVisualSelection(state.anchor());
+ return HandleResult
+ .handled(new VisualState(state.anchor(), state.preferredColumn(), PendingOperator.NONE, 0));
+ });
+ map.put('b', (state, context) -> {
+ for (int i = 0; i < context.readCount(state.count()); i++) {
+ context.moveWordBackward();
+ }
+ context.updateVisualSelection(state.anchor());
+ return HandleResult
+ .handled(new VisualState(state.anchor(), state.preferredColumn(), PendingOperator.NONE, 0));
+ });
+ map.put('0', (state, context) -> {
+ context.moveLineStart();
+ context.updateVisualSelection(state.anchor());
+ return HandleResult
+ .handled(new VisualState(state.anchor(), state.preferredColumn(), PendingOperator.NONE, 0));
+ });
+ map.put('$', (state, context) -> {
+ context.moveLineEnd();
+ context.updateVisualSelection(state.anchor());
+ return HandleResult
+ .handled(new VisualState(state.anchor(), state.preferredColumn(), PendingOperator.NONE, 0));
+ });
+ map.put('G', (state, context) -> {
+ context.moveDocumentEnd();
+ context.updateVisualSelection(state.anchor());
+ return HandleResult
+ .handled(new VisualState(state.anchor(), state.preferredColumn(), PendingOperator.NONE, 0));
+ });
+ map.put('g', (state, context) -> HandleResult
+ .handled(new VisualState(state.anchor(), state.preferredColumn(), PendingOperator.G_PREFIX, 0)));
+ map.put('d', (state, context) -> context.applyVisualOperator(state, PendingOperator.DELETE));
+ map.put('y', (state, context) -> context.applyVisualOperator(state, PendingOperator.YANK));
+ map.put('c', (state, context) -> context.applyVisualOperator(state, PendingOperator.CHANGE));
+ return map;
+ }
}
diff --git a/core/src/main/java/coffee/liz/abstractionengine/app/ui/editor/vim/model/Register.java b/core/src/main/java/coffee/liz/abstractionengine/app/ui/editor/vim/model/Register.java
index 9bacd59..44a3c4c 100644
--- a/core/src/main/java/coffee/liz/abstractionengine/app/ui/editor/vim/model/Register.java
+++ b/core/src/main/java/coffee/liz/abstractionengine/app/ui/editor/vim/model/Register.java
@@ -6,6 +6,6 @@ import lombok.Setter;
@Getter
@Setter
public class Register {
- private String text = "";
- private RegisterType type = RegisterType.CHARACTER;
+ private String text = "";
+ private RegisterType type = RegisterType.CHARACTER;
}
diff --git a/core/src/main/java/coffee/liz/abstractionengine/app/ui/editor/vim/model/RegisterType.java b/core/src/main/java/coffee/liz/abstractionengine/app/ui/editor/vim/model/RegisterType.java
index 9ecb900..71df9eb 100644
--- a/core/src/main/java/coffee/liz/abstractionengine/app/ui/editor/vim/model/RegisterType.java
+++ b/core/src/main/java/coffee/liz/abstractionengine/app/ui/editor/vim/model/RegisterType.java
@@ -1,5 +1,5 @@
package coffee.liz.abstractionengine.app.ui.editor.vim.model;
public enum RegisterType {
- CHARACTER, LINE
+ CHARACTER, LINE
}
diff --git a/core/src/main/java/coffee/liz/abstractionengine/app/ui/editor/vim/model/UndoManager.java b/core/src/main/java/coffee/liz/abstractionengine/app/ui/editor/vim/model/UndoManager.java
index 34b2122..affb1a8 100644
--- a/core/src/main/java/coffee/liz/abstractionengine/app/ui/editor/vim/model/UndoManager.java
+++ b/core/src/main/java/coffee/liz/abstractionengine/app/ui/editor/vim/model/UndoManager.java
@@ -6,47 +6,47 @@ import lombok.RequiredArgsConstructor;
@RequiredArgsConstructor
public class UndoManager {
- private final int maxUndo;
- private final Deque<UndoState> undoStack = new ArrayDeque<>();
- private final Deque<UndoState> redoStack = new ArrayDeque<>();
+ private final int maxUndo;
+ private final Deque<UndoState> undoStack = new ArrayDeque<>();
+ private final Deque<UndoState> redoStack = new ArrayDeque<>();
- public void record(final String text, final int cursor) {
- final UndoState candidate = new UndoState(text, cursor);
- final UndoState top = undoStack.peekLast();
- if (top != null && top.getCursor() == candidate.getCursor() && top.getText().equals(candidate.getText())) {
- return;
- }
+ public void record(final String text, final int cursor) {
+ final UndoState candidate = new UndoState(text, cursor);
+ final UndoState top = undoStack.peekLast();
+ if (top != null && top.getCursor() == candidate.getCursor() && top.getText().equals(candidate.getText())) {
+ return;
+ }
- undoStack.addLast(candidate);
- while (undoStack.size() > maxUndo) {
- undoStack.removeFirst();
- }
- redoStack.clear();
- }
+ undoStack.addLast(candidate);
+ while (undoStack.size() > maxUndo) {
+ undoStack.removeFirst();
+ }
+ redoStack.clear();
+ }
- public UndoState undo() {
- if (undoStack.size() <= 1) {
- return null;
- }
+ public UndoState undo() {
+ if (undoStack.size() <= 1) {
+ return null;
+ }
- final UndoState current = undoStack.removeLast();
- redoStack.addLast(current);
- return undoStack.peekLast();
- }
+ final UndoState current = undoStack.removeLast();
+ redoStack.addLast(current);
+ return undoStack.peekLast();
+ }
- public UndoState redo() {
- if (redoStack.isEmpty()) {
- return null;
- }
+ public UndoState redo() {
+ if (redoStack.isEmpty()) {
+ return null;
+ }
- final UndoState target = redoStack.removeLast();
- final UndoState top = undoStack.peekLast();
- if (top == null || !top.getText().equals(target.getText()) || top.getCursor() != target.getCursor()) {
- undoStack.addLast(target);
- while (undoStack.size() > maxUndo) {
- undoStack.removeFirst();
- }
- }
- return target;
- }
+ final UndoState target = redoStack.removeLast();
+ final UndoState top = undoStack.peekLast();
+ if (top == null || !top.getText().equals(target.getText()) || top.getCursor() != target.getCursor()) {
+ undoStack.addLast(target);
+ while (undoStack.size() > maxUndo) {
+ undoStack.removeFirst();
+ }
+ }
+ return target;
+ }
}
diff --git a/core/src/main/java/coffee/liz/abstractionengine/app/ui/editor/vim/model/UndoState.java b/core/src/main/java/coffee/liz/abstractionengine/app/ui/editor/vim/model/UndoState.java
index c91ebcd..04375aa 100644
--- a/core/src/main/java/coffee/liz/abstractionengine/app/ui/editor/vim/model/UndoState.java
+++ b/core/src/main/java/coffee/liz/abstractionengine/app/ui/editor/vim/model/UndoState.java
@@ -6,6 +6,6 @@ import lombok.RequiredArgsConstructor;
@Getter
@RequiredArgsConstructor
public class UndoState {
- private final String text;
- private final int cursor;
+ private final String text;
+ private final int cursor;
}
diff --git a/core/src/main/java/coffee/liz/abstractionengine/app/ui/editor/vim/navigation/TextNavigation.java b/core/src/main/java/coffee/liz/abstractionengine/app/ui/editor/vim/navigation/TextNavigation.java
index c9ef857..b74c1df 100644
--- a/core/src/main/java/coffee/liz/abstractionengine/app/ui/editor/vim/navigation/TextNavigation.java
+++ b/core/src/main/java/coffee/liz/abstractionengine/app/ui/editor/vim/navigation/TextNavigation.java
@@ -1,110 +1,110 @@
package coffee.liz.abstractionengine.app.ui.editor.vim.navigation;
public class TextNavigation {
- public int findLineStart(final String text, final int cursor) {
- int index = Math.max(0, Math.min(cursor, text.length()));
- while (index > 0 && text.charAt(index - 1) != '\n') {
- index--;
- }
- return index;
- }
+ public int findLineStart(final String text, final int cursor) {
+ int index = Math.max(0, Math.min(cursor, text.length()));
+ while (index > 0 && text.charAt(index - 1) != '\n') {
+ index--;
+ }
+ return index;
+ }
- public int findLineEnd(final String text, final int cursor) {
- final int lineStart = findLineStart(text, cursor);
- int index = lineStart;
- while (index < text.length() && text.charAt(index) != '\n') {
- index++;
- }
- if (index == lineStart) {
- return lineStart;
- }
- return index - 1;
- }
+ public int findLineEnd(final String text, final int cursor) {
+ final int lineStart = findLineStart(text, cursor);
+ int index = lineStart;
+ while (index < text.length() && text.charAt(index) != '\n') {
+ index++;
+ }
+ if (index == lineStart) {
+ return lineStart;
+ }
+ return index - 1;
+ }
- public int findLineEndExclusiveByStart(final String text, final int lineStart) {
- int index = lineStart;
- while (index < text.length() && text.charAt(index) != '\n') {
- index++;
- }
- return index;
- }
+ public int findLineEndExclusiveByStart(final String text, final int lineStart) {
+ int index = lineStart;
+ while (index < text.length() && text.charAt(index) != '\n') {
+ index++;
+ }
+ return index;
+ }
- public int findNextLineStart(final String text, final int start) {
- final int newline = text.indexOf('\n', Math.max(0, start));
- if (newline < 0) {
- return -1;
- }
- return newline + 1;
- }
+ public int findNextLineStart(final String text, final int start) {
+ final int newline = text.indexOf('\n', Math.max(0, start));
+ if (newline < 0) {
+ return -1;
+ }
+ return newline + 1;
+ }
- public int findPreviousLineStart(final String text, final int lineStart) {
- final int clampedLineStart = Math.max(0, Math.min(lineStart, text.length()));
- if (clampedLineStart <= 0) {
- return -1;
- }
- final int previousNewline = text.lastIndexOf('\n', clampedLineStart - 2);
- return previousNewline + 1;
- }
+ public int findPreviousLineStart(final String text, final int lineStart) {
+ final int clampedLineStart = Math.max(0, Math.min(lineStart, text.length()));
+ if (clampedLineStart <= 0) {
+ return -1;
+ }
+ final int previousNewline = text.lastIndexOf('\n', clampedLineStart - 2);
+ return previousNewline + 1;
+ }
- public int findBelowLineInsertionIndex(final String text, final int cursor) {
- final int lineStart = findLineStart(text, cursor);
- final int lineEnd = findLineEnd(text, cursor);
- final boolean currentLineIsEmpty = findLineEndExclusiveByStart(text, lineStart) == lineStart;
- int insertAt = Math.min(lineEnd + 1, text.length());
- if (!currentLineIsEmpty && insertAt < text.length() && text.charAt(insertAt) == '\n') {
- insertAt++;
- }
- return insertAt;
- }
+ public int findBelowLineInsertionIndex(final String text, final int cursor) {
+ final int lineStart = findLineStart(text, cursor);
+ final int lineEnd = findLineEnd(text, cursor);
+ final boolean currentLineIsEmpty = findLineEndExclusiveByStart(text, lineStart) == lineStart;
+ int insertAt = Math.min(lineEnd + 1, text.length());
+ if (!currentLineIsEmpty && insertAt < text.length() && text.charAt(insertAt) == '\n') {
+ insertAt++;
+ }
+ return insertAt;
+ }
- public int findLineStartByLine(final String text, final int lineNumber) {
- int line = 0;
- int index = 0;
- while (line < lineNumber && index < text.length()) {
- if (text.charAt(index) == '\n') {
- line++;
- }
- index++;
- }
- return index;
- }
+ public int findLineStartByLine(final String text, final int lineNumber) {
+ int line = 0;
+ int index = 0;
+ while (line < lineNumber && index < text.length()) {
+ if (text.charAt(index) == '\n') {
+ line++;
+ }
+ index++;
+ }
+ return index;
+ }
- public int findLineSelectionEndByLine(final String text, final int lineNumber) {
- int index = findLineStartByLine(text, lineNumber);
- while (index < text.length() && text.charAt(index) != '\n') {
- index++;
- }
- if (index < text.length() && text.charAt(index) == '\n') {
- return index + 1;
- }
- return text.length();
- }
+ public int findLineSelectionEndByLine(final String text, final int lineNumber) {
+ int index = findLineStartByLine(text, lineNumber);
+ while (index < text.length() && text.charAt(index) != '\n') {
+ index++;
+ }
+ if (index < text.length() && text.charAt(index) == '\n') {
+ return index + 1;
+ }
+ return text.length();
+ }
- public int lastNavigablePosition(final String text) {
- if (text.isEmpty()) {
- return 0;
- }
+ public int lastNavigablePosition(final String text) {
+ if (text.isEmpty()) {
+ return 0;
+ }
- return text.length() - 1;
- }
+ return text.length() - 1;
+ }
- public int maxCursorPositionInNormalMode(final String text) {
- if (text.isEmpty()) {
- return 0;
- }
- return text.length() - 1;
- }
+ public int maxCursorPositionInNormalMode(final String text) {
+ if (text.isEmpty()) {
+ return 0;
+ }
+ return text.length() - 1;
+ }
- public boolean isWordCharacter(final char character) {
- return Character.isLetterOrDigit(character) || character == '_';
- }
+ public boolean isWordCharacter(final char character) {
+ return Character.isLetterOrDigit(character) || character == '_';
+ }
- public boolean isInlineWhitespace(final char character) {
- return Character.isWhitespace(character) && character != '\n' && character != '\r';
- }
+ public boolean isInlineWhitespace(final char character) {
+ return Character.isWhitespace(character) && character != '\n' && character != '\r';
+ }
- public boolean isPunctuationWord(final char character) {
- return !isWordCharacter(character) && !Character.isWhitespace(character) && character != '\n'
- && character != '\r';
- }
+ public boolean isPunctuationWord(final char character) {
+ return !isWordCharacter(character) && !Character.isWhitespace(character) && character != '\n'
+ && character != '\r';
+ }
}
diff --git a/core/src/main/java/coffee/liz/abstractionengine/app/ui/editor/vim/search/SearchDirection.java b/core/src/main/java/coffee/liz/abstractionengine/app/ui/editor/vim/search/SearchDirection.java
index ca3d63e..b157d16 100644
--- a/core/src/main/java/coffee/liz/abstractionengine/app/ui/editor/vim/search/SearchDirection.java
+++ b/core/src/main/java/coffee/liz/abstractionengine/app/ui/editor/vim/search/SearchDirection.java
@@ -1,5 +1,5 @@
package coffee.liz.abstractionengine.app.ui.editor.vim.search;
public enum SearchDirection {
- FORWARD, BACKWARD
+ FORWARD, BACKWARD
}
diff --git a/core/src/main/java/coffee/liz/abstractionengine/app/ui/editor/vim/search/SearchIterator.java b/core/src/main/java/coffee/liz/abstractionengine/app/ui/editor/vim/search/SearchIterator.java
index 50f0e1c..a5e078b 100644
--- a/core/src/main/java/coffee/liz/abstractionengine/app/ui/editor/vim/search/SearchIterator.java
+++ b/core/src/main/java/coffee/liz/abstractionengine/app/ui/editor/vim/search/SearchIterator.java
@@ -3,56 +3,56 @@ package coffee.liz.abstractionengine.app.ui.editor.vim.search;
import java.util.OptionalInt;
public class SearchIterator {
- private final String text;
- private final String query;
- private final SearchDirection direction;
- private final boolean wrap;
- private int nextStart;
- private boolean wrapped;
+ private final String text;
+ private final String query;
+ private final SearchDirection direction;
+ private final boolean wrap;
+ private int nextStart;
+ private boolean wrapped;
- public SearchIterator(final String text, final String query, final int startIndex, final SearchDirection direction,
- final boolean wrap) {
- this.text = text == null ? "" : text;
- this.query = query == null ? "" : query;
- this.direction = direction;
- this.wrap = wrap;
- if (direction == SearchDirection.FORWARD) {
- this.nextStart = Math.min(this.text.length(), Math.max(0, startIndex + 1));
- } else {
- this.nextStart = Math.max(0, startIndex - 1);
- }
- this.wrapped = false;
- }
+ public SearchIterator(final String text, final String query, final int startIndex, final SearchDirection direction,
+ final boolean wrap) {
+ this.text = text == null ? "" : text;
+ this.query = query == null ? "" : query;
+ this.direction = direction;
+ this.wrap = wrap;
+ if (direction == SearchDirection.FORWARD) {
+ this.nextStart = Math.min(this.text.length(), Math.max(0, startIndex + 1));
+ } else {
+ this.nextStart = Math.max(0, startIndex - 1);
+ }
+ this.wrapped = false;
+ }
- public OptionalInt nextMatch() {
- if (query.isEmpty() || text.isEmpty()) {
- return OptionalInt.empty();
- }
+ public OptionalInt nextMatch() {
+ if (query.isEmpty() || text.isEmpty()) {
+ return OptionalInt.empty();
+ }
- if (direction == SearchDirection.FORWARD) {
- final int found = text.indexOf(query, nextStart);
- if (found >= 0) {
- nextStart = Math.min(text.length(), found + 1);
- return OptionalInt.of(found);
- }
- if (wrap && !wrapped) {
- wrapped = true;
- nextStart = 0;
- return nextMatch();
- }
- return OptionalInt.empty();
- }
+ if (direction == SearchDirection.FORWARD) {
+ final int found = text.indexOf(query, nextStart);
+ if (found >= 0) {
+ nextStart = Math.min(text.length(), found + 1);
+ return OptionalInt.of(found);
+ }
+ if (wrap && !wrapped) {
+ wrapped = true;
+ nextStart = 0;
+ return nextMatch();
+ }
+ return OptionalInt.empty();
+ }
- final int found = text.lastIndexOf(query, nextStart);
- if (found >= 0) {
- nextStart = Math.max(0, found - 1);
- return OptionalInt.of(found);
- }
- if (wrap && !wrapped) {
- wrapped = true;
- nextStart = Math.max(0, text.length() - 1);
- return nextMatch();
- }
- return OptionalInt.empty();
- }
+ final int found = text.lastIndexOf(query, nextStart);
+ if (found >= 0) {
+ nextStart = Math.max(0, found - 1);
+ return OptionalInt.of(found);
+ }
+ if (wrap && !wrapped) {
+ wrapped = true;
+ nextStart = Math.max(0, text.length() - 1);
+ return nextMatch();
+ }
+ return OptionalInt.empty();
+ }
}
diff --git a/core/src/main/java/coffee/liz/abstractionengine/app/ui/editor/vim/state/ModeState.java b/core/src/main/java/coffee/liz/abstractionengine/app/ui/editor/vim/state/ModeState.java
index 78d2fb8..e878dd7 100644
--- a/core/src/main/java/coffee/liz/abstractionengine/app/ui/editor/vim/state/ModeState.java
+++ b/core/src/main/java/coffee/liz/abstractionengine/app/ui/editor/vim/state/ModeState.java
@@ -1,15 +1,15 @@
package coffee.liz.abstractionengine.app.ui.editor.vim.state;
public sealed interface ModeState permits InsertState, NormalState, SearchState, VisualLineState, VisualState {
- default PendingOperator pendingOperator() {
- return PendingOperator.NONE;
- }
+ default PendingOperator pendingOperator() {
+ return PendingOperator.NONE;
+ }
- default int count() {
- return 0;
- }
+ default int count() {
+ return 0;
+ }
- default int preferredColumn() {
- return -1;
- }
+ default int preferredColumn() {
+ return -1;
+ }
}
diff --git a/core/src/main/java/coffee/liz/abstractionengine/app/ui/editor/vim/state/NormalState.java b/core/src/main/java/coffee/liz/abstractionengine/app/ui/editor/vim/state/NormalState.java
index 42b1d99..d86e842 100644
--- a/core/src/main/java/coffee/liz/abstractionengine/app/ui/editor/vim/state/NormalState.java
+++ b/core/src/main/java/coffee/liz/abstractionengine/app/ui/editor/vim/state/NormalState.java
@@ -1,5 +1,5 @@
package coffee.liz.abstractionengine.app.ui.editor.vim.state;
public record NormalState(int count, PendingOperator pendingOperator, int preferredColumn) implements ModeState {
- public static final NormalState DEFAULT = new NormalState(0, PendingOperator.NONE, -1);
+ public static final NormalState DEFAULT = new NormalState(0, PendingOperator.NONE, -1);
}
diff --git a/core/src/main/java/coffee/liz/abstractionengine/app/ui/editor/vim/state/PendingOperator.java b/core/src/main/java/coffee/liz/abstractionengine/app/ui/editor/vim/state/PendingOperator.java
index 1fc4425..60f22f0 100644
--- a/core/src/main/java/coffee/liz/abstractionengine/app/ui/editor/vim/state/PendingOperator.java
+++ b/core/src/main/java/coffee/liz/abstractionengine/app/ui/editor/vim/state/PendingOperator.java
@@ -1,5 +1,5 @@
package coffee.liz.abstractionengine.app.ui.editor.vim.state;
public enum PendingOperator {
- NONE, DELETE, YANK, CHANGE, G_PREFIX
+ NONE, DELETE, YANK, CHANGE, G_PREFIX
}
diff --git a/core/src/main/java/coffee/liz/abstractionengine/app/ui/editor/vim/state/SearchState.java b/core/src/main/java/coffee/liz/abstractionengine/app/ui/editor/vim/state/SearchState.java
index 7de6811..fb2ba40 100644
--- a/core/src/main/java/coffee/liz/abstractionengine/app/ui/editor/vim/state/SearchState.java
+++ b/core/src/main/java/coffee/liz/abstractionengine/app/ui/editor/vim/state/SearchState.java
@@ -3,9 +3,9 @@ package coffee.liz.abstractionengine.app.ui.editor.vim.state;
import coffee.liz.abstractionengine.app.ui.editor.vim.search.SearchDirection;
public record SearchState(StringBuilder query, String lastQuery, SearchDirection direction) implements ModeState {
- public SearchState {
- query = query == null ? new StringBuilder() : query;
- lastQuery = lastQuery == null ? "" : lastQuery;
- direction = direction == null ? SearchDirection.FORWARD : direction;
- }
+ public SearchState {
+ query = query == null ? new StringBuilder() : query;
+ lastQuery = lastQuery == null ? "" : lastQuery;
+ direction = direction == null ? SearchDirection.FORWARD : direction;
+ }
}
diff --git a/core/src/main/java/coffee/liz/abstractionengine/app/ui/editor/vim/state/VisualLineState.java b/core/src/main/java/coffee/liz/abstractionengine/app/ui/editor/vim/state/VisualLineState.java
index b486223..19c74b7 100644
--- a/core/src/main/java/coffee/liz/abstractionengine/app/ui/editor/vim/state/VisualLineState.java
+++ b/core/src/main/java/coffee/liz/abstractionengine/app/ui/editor/vim/state/VisualLineState.java
@@ -1,5 +1,5 @@
package coffee.liz.abstractionengine.app.ui.editor.vim.state;
public record VisualLineState(int anchorLine, int cursorLine, int preferredColumn, PendingOperator pendingOperator,
- int count) implements ModeState {
+ int count) implements ModeState {
}
diff --git a/core/src/main/java/coffee/liz/abstractionengine/app/ui/editor/vim/state/VisualState.java b/core/src/main/java/coffee/liz/abstractionengine/app/ui/editor/vim/state/VisualState.java
index 97604c8..373028c 100644
--- a/core/src/main/java/coffee/liz/abstractionengine/app/ui/editor/vim/state/VisualState.java
+++ b/core/src/main/java/coffee/liz/abstractionengine/app/ui/editor/vim/state/VisualState.java
@@ -1,5 +1,5 @@
package coffee.liz.abstractionengine.app.ui.editor.vim.state;
public record VisualState(int anchor, int preferredColumn, PendingOperator pendingOperator,
- int count) implements ModeState {
+ int count) implements ModeState {
}
diff --git a/core/src/main/java/coffee/liz/abstractionengine/app/ui/editor/vim/status/StatusFormatter.java b/core/src/main/java/coffee/liz/abstractionengine/app/ui/editor/vim/status/StatusFormatter.java
index 4ef8c17..ab5321f 100644
--- a/core/src/main/java/coffee/liz/abstractionengine/app/ui/editor/vim/status/StatusFormatter.java
+++ b/core/src/main/java/coffee/liz/abstractionengine/app/ui/editor/vim/status/StatusFormatter.java
@@ -10,47 +10,47 @@ import coffee.liz.abstractionengine.app.ui.editor.vim.state.VisualLineState;
import coffee.liz.abstractionengine.app.ui.editor.vim.state.VisualState;
public class StatusFormatter {
- public String format(final ModeState state, final VimConfig config) {
- return switch (state) {
- case NormalState normalState -> formatNormal(normalState, config);
- case InsertState ignored -> config.insertStatusLabel();
- case VisualState ignored -> config.visualStatusLabel();
- case VisualLineState ignored -> config.visualLineStatusLabel();
- case SearchState searchState -> '/' + searchState.query().toString();
- };
- }
+ public String format(final ModeState state, final VimConfig config) {
+ return switch (state) {
+ case NormalState normalState -> formatNormal(normalState, config);
+ case InsertState ignored -> config.insertStatusLabel();
+ case VisualState ignored -> config.visualStatusLabel();
+ case VisualLineState ignored -> config.visualLineStatusLabel();
+ case SearchState searchState -> '/' + searchState.query().toString();
+ };
+ }
- private String formatNormal(final NormalState state, final VimConfig config) {
- final StringBuilder builder = new StringBuilder(config.normalStatusLabel());
- appendOperator(builder, state.pendingOperator());
- if (state.count() > 0) {
- builder.append(" count=").append(state.count());
- }
- return builder.toString();
- }
+ private String formatNormal(final NormalState state, final VimConfig config) {
+ final StringBuilder builder = new StringBuilder(config.normalStatusLabel());
+ appendOperator(builder, state.pendingOperator());
+ if (state.count() > 0) {
+ builder.append(" count=").append(state.count());
+ }
+ return builder.toString();
+ }
- private void appendOperator(final StringBuilder builder, final PendingOperator pendingOperator) {
- if (pendingOperator == PendingOperator.NONE) {
- return;
- }
+ private void appendOperator(final StringBuilder builder, final PendingOperator pendingOperator) {
+ if (pendingOperator == PendingOperator.NONE) {
+ return;
+ }
- builder.append(" [");
- switch (pendingOperator) {
- case DELETE :
- builder.append('d');
- break;
- case YANK :
- builder.append('y');
- break;
- case CHANGE :
- builder.append('c');
- break;
- case G_PREFIX :
- builder.append('g');
- break;
- default :
- break;
- }
- builder.append(']');
- }
+ builder.append(" [");
+ switch (pendingOperator) {
+ case DELETE :
+ builder.append('d');
+ break;
+ case YANK :
+ builder.append('y');
+ break;
+ case CHANGE :
+ builder.append('c');
+ break;
+ case G_PREFIX :
+ builder.append('g');
+ break;
+ default :
+ break;
+ }
+ builder.append(']');
+ }
}
diff --git a/core/src/main/java/coffee/liz/abstractionengine/app/utils/FontHelper.java b/core/src/main/java/coffee/liz/abstractionengine/app/utils/FontHelper.java
index b38f25c..8db56a7 100644
--- a/core/src/main/java/coffee/liz/abstractionengine/app/utils/FontHelper.java
+++ b/core/src/main/java/coffee/liz/abstractionengine/app/utils/FontHelper.java
@@ -7,26 +7,26 @@ import com.badlogic.gdx.graphics.g2d.BitmapFont;
import com.badlogic.gdx.graphics.g2d.freetype.FreeTypeFontGenerator;
public final class FontHelper {
- private FontHelper() {
- }
+ private FontHelper() {
+ }
- public static final String RENDERABLE_CHARS = "λ" + FreeTypeFontGenerator.DEFAULT_CHARS;
- public static final String MONO = "fonts/JetBrainsMonoNerdFont-Regular.ttf";
+ public static final String RENDERABLE_CHARS = "λ" + FreeTypeFontGenerator.DEFAULT_CHARS;
+ public static final String MONO = "fonts/JetBrainsMonoNerdFont-Regular.ttf";
- public static BitmapFont initFont(final int size, final String path, final float scale) {
- final int scaleForHidpi = 4;
- final FreeTypeFontGenerator gen = new FreeTypeFontGenerator(Gdx.files.internal(path));
- final FreeTypeFontGenerator.FreeTypeFontParameter params = new FreeTypeFontGenerator.FreeTypeFontParameter();
- params.characters = RENDERABLE_CHARS;
- params.size = scaleForHidpi * size;
+ public static BitmapFont initFont(final int size, final String path, final float scale) {
+ final int scaleForHidpi = 4;
+ final FreeTypeFontGenerator gen = new FreeTypeFontGenerator(Gdx.files.internal(path));
+ final FreeTypeFontGenerator.FreeTypeFontParameter params = new FreeTypeFontGenerator.FreeTypeFontParameter();
+ params.characters = RENDERABLE_CHARS;
+ params.size = scaleForHidpi * size;
- final BitmapFont font = gen.generateFont(params);
- font.setFixedWidthGlyphs(RENDERABLE_CHARS);
- font.setUseIntegerPositions(false);
- font.getRegion().getTexture().setFilter(Texture.TextureFilter.Linear, Texture.TextureFilter.Linear);
- font.getData().setScale((1f / scaleForHidpi) * scale);
+ final BitmapFont font = gen.generateFont(params);
+ font.setFixedWidthGlyphs(RENDERABLE_CHARS);
+ font.setUseIntegerPositions(false);
+ font.getRegion().getTexture().setFilter(Texture.TextureFilter.Linear, Texture.TextureFilter.Linear);
+ font.getData().setScale((1f / scaleForHidpi) * scale);
- gen.dispose();
- return font;
- }
+ gen.dispose();
+ return font;
+ }
}
diff --git a/core/src/main/java/coffee/liz/abstractionengine/app/utils/FunctionUtils.java b/core/src/main/java/coffee/liz/abstractionengine/app/utils/FunctionUtils.java
index c219df0..c985e48 100644
--- a/core/src/main/java/coffee/liz/abstractionengine/app/utils/FunctionUtils.java
+++ b/core/src/main/java/coffee/liz/abstractionengine/app/utils/FunctionUtils.java
@@ -1,28 +1,28 @@
package coffee.liz.abstractionengine.app.utils;
public final class FunctionUtils {
- private FunctionUtils() {
- }
+ private FunctionUtils() {
+ }
- /**
- * Runs the provided action and wraps failures into a {@link RuntimeException}.
- *
- * @param run
- * action to execute
- */
- public static <E extends Throwable> void wrapCheckedException(final ThrowableRunnable<E> run) {
- try {
- run.run();
- } catch (final Throwable e) {
- throw new RuntimeException(e);
- }
- }
+ /**
+ * Runs the provided action and wraps failures into a {@link RuntimeException}.
+ *
+ * @param run
+ * action to execute
+ */
+ public static <E extends Throwable> void wrapCheckedException(final ThrowableRunnable<E> run) {
+ try {
+ run.run();
+ } catch (final Throwable e) {
+ throw new RuntimeException(e);
+ }
+ }
- @FunctionalInterface
- public interface ThrowableRunnable<E extends Throwable> {
- /**
- * Run.
- */
- void run() throws E;
- }
+ @FunctionalInterface
+ public interface ThrowableRunnable<E extends Throwable> {
+ /**
+ * Run.
+ */
+ void run() throws E;
+ }
}
diff --git a/core/src/main/java/coffee/liz/abstractionengine/app/utils/TimerUtils.java b/core/src/main/java/coffee/liz/abstractionengine/app/utils/TimerUtils.java
index dea7bd2..77f074b 100644
--- a/core/src/main/java/coffee/liz/abstractionengine/app/utils/TimerUtils.java
+++ b/core/src/main/java/coffee/liz/abstractionengine/app/utils/TimerUtils.java
@@ -3,22 +3,22 @@ package coffee.liz.abstractionengine.app.utils;
import com.badlogic.gdx.utils.Timer;
public final class TimerUtils {
- private TimerUtils() {
- }
+ private TimerUtils() {
+ }
- /**
- * Creates a {@link Timer.Task} from a runnable.
- *
- * @param r
- * action to run
- * @return timer task that runs the action
- */
- public static Timer.Task sideEffectTask(final Runnable r) {
- return new Timer.Task() {
- @Override
- public void run() {
- r.run();
- }
- };
- }
+ /**
+ * Creates a {@link Timer.Task} from a runnable.
+ *
+ * @param r
+ * action to run
+ * @return timer task that runs the action
+ */
+ public static Timer.Task sideEffectTask(final Runnable r) {
+ return new Timer.Task() {
+ @Override
+ public void run() {
+ r.run();
+ }
+ };
+ }
}
diff --git a/core/src/main/java/coffee/liz/abstractionengine/entity/EntityFactory.java b/core/src/main/java/coffee/liz/abstractionengine/entity/EntityFactory.java
index 99a6eb7..d8299aa 100644
--- a/core/src/main/java/coffee/liz/abstractionengine/entity/EntityFactory.java
+++ b/core/src/main/java/coffee/liz/abstractionengine/entity/EntityFactory.java
@@ -11,70 +11,70 @@ import java.util.List;
import java.util.function.BiFunction;
public final class EntityFactory {
- private EntityFactory() {
- }
+ private EntityFactory() {
+ }
- /**
- * {@link EntityType#PLAYER} factory.
- */
- public final class Player {
- private Player() {
- }
+ /**
+ * {@link EntityType#PLAYER} factory.
+ */
+ public final class Player {
+ private Player() {
+ }
- public static Entity addToWorld(final World<?> world, final Vec2<Integer> position) {
- return world.createEntity().add(new GridPosition(position)).add(new GridControllable())
- .add(EntityType.PLAYER).add(new EntityTypeGridCollidable());
- }
- }
+ public static Entity addToWorld(final World<?> world, final Vec2<Integer> position) {
+ return world.createEntity().add(new GridPosition(position)).add(new GridControllable())
+ .add(EntityType.PLAYER).add(new EntityTypeGridCollidable());
+ }
+ }
- /**
- * {@link EntityType#WALL} factory.
- */
- public final class Wall {
- private Wall() {
- }
+ /**
+ * {@link EntityType#WALL} factory.
+ */
+ public final class Wall {
+ private Wall() {
+ }
- public static Entity addToWorld(final World<?> world, final Vec2<Integer> position) {
- return world.createEntity().add(new GridPosition(position)).add(EntityType.WALL)
- .add(new EntityTypeGridCollidable());
- }
- }
+ public static Entity addToWorld(final World<?> world, final Vec2<Integer> position) {
+ return world.createEntity().add(new GridPosition(position)).add(EntityType.WALL)
+ .add(new EntityTypeGridCollidable());
+ }
+ }
- /**
- * {@link EntityType#ABSTRACTION} factory.
- */
- public final class Abstraction {
- private Abstraction() {
- }
+ /**
+ * {@link EntityType#ABSTRACTION} factory.
+ */
+ public final class Abstraction {
+ private Abstraction() {
+ }
- public static Entity addToWorld(final World<?> world, final Vec2<Integer> position) {
- return world.createEntity().add(new GridPosition(position)).add(EntityType.ABSTRACTION)
- .add(new EntityTypeGridCollidable());
- }
- }
+ public static Entity addToWorld(final World<?> world, final Vec2<Integer> position) {
+ return world.createEntity().add(new GridPosition(position)).add(EntityType.ABSTRACTION)
+ .add(new EntityTypeGridCollidable());
+ }
+ }
- /**
- * Populates entities on the border of a rectangle of defined dimensions.
- *
- * @param dimensions
- * are the world dimensions.
- * @param world
- * is the world to populate
- * @param factory
- * accepts the world and position in the world and creates the
- * entity.
- * @return 2d matrix of entities at each position in the world of populated
- * entities.
- */
- public static List<List<Entity>> populateRect(final Vec2<Integer> dimensions, final World<?> world,
- final BiFunction<World<?>, Vec2<Integer>, Entity> factory) {
- return Mat2.init(dimensions, pos -> {
- final boolean isXBorder = pos.getX() == 0 || pos.getX() == dimensions.getX() - 1;
- final boolean isYBorder = pos.getY() == 0 || pos.getY() == dimensions.getY() - 1;
- if (isXBorder || isYBorder) {
- return factory.apply(world, pos);
- }
- return null;
- });
- }
+ /**
+ * Populates entities on the border of a rectangle of defined dimensions.
+ *
+ * @param dimensions
+ * are the world dimensions.
+ * @param world
+ * is the world to populate
+ * @param factory
+ * accepts the world and position in the world and creates the
+ * entity.
+ * @return 2d matrix of entities at each position in the world of populated
+ * entities.
+ */
+ public static List<List<Entity>> populateRect(final Vec2<Integer> dimensions, final World<?> world,
+ final BiFunction<World<?>, Vec2<Integer>, Entity> factory) {
+ return Mat2.init(dimensions, pos -> {
+ final boolean isXBorder = pos.getX() == 0 || pos.getX() == dimensions.getX() - 1;
+ final boolean isYBorder = pos.getY() == 0 || pos.getY() == dimensions.getY() - 1;
+ if (isXBorder || isYBorder) {
+ return factory.apply(world, pos);
+ }
+ return null;
+ });
+ }
}
diff --git a/core/src/main/java/coffee/liz/abstractionengine/entity/EntityType.java b/core/src/main/java/coffee/liz/abstractionengine/entity/EntityType.java
index e0bf243..93fa160 100644
--- a/core/src/main/java/coffee/liz/abstractionengine/entity/EntityType.java
+++ b/core/src/main/java/coffee/liz/abstractionengine/entity/EntityType.java
@@ -9,44 +9,44 @@ import coffee.liz.ecs.model.Component;
* {@link coffee.liz.abstractionengine.AbstractionEngineGridWorld}
*/
public enum EntityType implements Component {
- /** Player entity */
- PLAYER,
- /** Wall entity. Nothing goes through this */
- WALL,
- /** Lambda term producer */
- PRODUCER,
- /** Lambda abstraction */
- ABSTRACTION,
- /** Lambda application */
- APPLICATION,
- /** Lava */
- LAVA,
- /** Bridge */
- BRIDGE;
+ /** Player entity */
+ PLAYER,
+ /** Wall entity. Nothing goes through this */
+ WALL,
+ /** Lambda term producer */
+ PRODUCER,
+ /** Lambda abstraction */
+ ABSTRACTION,
+ /** Lambda application */
+ APPLICATION,
+ /** Lava */
+ LAVA,
+ /** Bridge */
+ BRIDGE;
- /**
- * Gets the collision behavior to apply based on the colliding types.
- *
- * @param that
- * is the {@link EntityType} colliding.
- * @return collision behavior to resolve.
- */
- public CollisionBehavior collideWith(final EntityType that) {
- if (that.equals(WALL)) {
- return CollisionBehavior.builder().collisionBehaviorType(CollisionBehaviorType.WALL).priority(0).build();
- }
- if (this.equals(ABSTRACTION) && that.equals(APPLICATION)) {
- return CollisionBehavior.builder().collisionBehaviorType(CollisionBehaviorType.SWALLOW).priority(0).build();
- }
+ /**
+ * Gets the collision behavior to apply based on the colliding types.
+ *
+ * @param that
+ * is the {@link EntityType} colliding.
+ * @return collision behavior to resolve.
+ */
+ public CollisionBehavior collideWith(final EntityType that) {
+ if (that.equals(WALL)) {
+ return CollisionBehavior.builder().collisionBehaviorType(CollisionBehaviorType.WALL).priority(0).build();
+ }
+ if (this.equals(ABSTRACTION) && that.equals(APPLICATION)) {
+ return CollisionBehavior.builder().collisionBehaviorType(CollisionBehaviorType.SWALLOW).priority(0).build();
+ }
- if (that.equals(LAVA)) {
- return CollisionBehavior.builder().collisionBehaviorType(CollisionBehaviorType.SWALLOW).priority(1).build();
- }
- if (that.equals(BRIDGE)) { // BRIDGE takes precedence over LAVA, so stuff can walk on a bridge over
- // LAVA
- return CollisionBehavior.builder().collisionBehaviorType(CollisionBehaviorType.SWALLOW).priority(0).build();
- }
+ if (that.equals(LAVA)) {
+ return CollisionBehavior.builder().collisionBehaviorType(CollisionBehaviorType.SWALLOW).priority(1).build();
+ }
+ if (that.equals(BRIDGE)) { // BRIDGE takes precedence over LAVA, so stuff can walk on a bridge over
+ // LAVA
+ return CollisionBehavior.builder().collisionBehaviorType(CollisionBehaviorType.SWALLOW).priority(0).build();
+ }
- return CollisionBehavior.builder().collisionBehaviorType(CollisionBehaviorType.PROPAGATE).priority(0).build();
- }
+ return CollisionBehavior.builder().collisionBehaviorType(CollisionBehaviorType.PROPAGATE).priority(0).build();
+ }
}
diff --git a/core/src/main/java/coffee/liz/abstractionengine/entity/EntityTypeGridCollidable.java b/core/src/main/java/coffee/liz/abstractionengine/entity/EntityTypeGridCollidable.java
index c75b717..e7def51 100644
--- a/core/src/main/java/coffee/liz/abstractionengine/entity/EntityTypeGridCollidable.java
+++ b/core/src/main/java/coffee/liz/abstractionengine/entity/EntityTypeGridCollidable.java
@@ -7,8 +7,8 @@ import lombok.Data;
@Data
public class EntityTypeGridCollidable implements GridCollidable {
- @Override
- public CollisionBehavior getCollisionBehaviorBetween(final Entity me, final Entity them) {
- return me.get(EntityType.class).collideWith(them.get(EntityType.class));
- }
+ @Override
+ public CollisionBehavior getCollisionBehaviorBetween(final Entity me, final Entity them) {
+ return me.get(EntityType.class).collideWith(them.get(EntityType.class));
+ }
}
diff --git a/core/src/main/java/coffee/liz/abstractionengine/grid/component/GridCollidable.java b/core/src/main/java/coffee/liz/abstractionengine/grid/component/GridCollidable.java
index e72d4e8..44b36f2 100644
--- a/core/src/main/java/coffee/liz/abstractionengine/grid/component/GridCollidable.java
+++ b/core/src/main/java/coffee/liz/abstractionengine/grid/component/GridCollidable.java
@@ -10,56 +10,56 @@ import lombok.RequiredArgsConstructor;
/** {@link Component} for grid collision handling. */
public interface GridCollidable extends Component {
- @RequiredArgsConstructor
- @Data
- @Builder
- class CollisionBehavior implements Comparable<CollisionBehavior> {
- private final CollisionBehaviorType collisionBehaviorType;
- private final int priority;
+ @RequiredArgsConstructor
+ @Data
+ @Builder
+ class CollisionBehavior implements Comparable<CollisionBehavior> {
+ private final CollisionBehaviorType collisionBehaviorType;
+ private final int priority;
- public int compareTo(final CollisionBehavior other) {
- return Integer.compare(getPriority(), other.getPriority());
- }
+ public int compareTo(final CollisionBehavior other) {
+ return Integer.compare(getPriority(), other.getPriority());
+ }
- public enum CollisionBehaviorType {
- /** Propagate collision to next entity. */
- PROPAGATE,
- /** Block collision like a wall. */
- WALL,
- /** Swallow the colliding entity. */
- SWALLOW;
- }
- }
+ public enum CollisionBehaviorType {
+ /** Propagate collision to next entity. */
+ PROPAGATE,
+ /** Block collision like a wall. */
+ WALL,
+ /** Swallow the colliding entity. */
+ SWALLOW;
+ }
+ }
- /**
- * Get collision behavior for colliding entity.
- *
- * @param me
- * the staring colliding {@link Entity}
- * @param them
- * the colliding {@link Entity}
- * @return the {@link CollisionBehavior}
- */
- CollisionBehavior getCollisionBehaviorBetween(final Entity me, final Entity them);
+ /**
+ * Get collision behavior for colliding entity.
+ *
+ * @param me
+ * the staring colliding {@link Entity}
+ * @param them
+ * the colliding {@link Entity}
+ * @return the {@link CollisionBehavior}
+ */
+ CollisionBehavior getCollisionBehaviorBetween(final Entity me, final Entity them);
- /**
- * Handle swallowing an entity.
- *
- * @param them
- * the {@link Entity} being swallowed
- * @param world
- * the {@link World} to modify
- */
- default <T> void onSwallow(final Entity them, final World<T> world) {
- throw new UnsupportedOperationException("Does not swallow"); // ...could not be me~ (つ﹏⊂)
- }
+ /**
+ * Handle swallowing an entity.
+ *
+ * @param them
+ * the {@link Entity} being swallowed
+ * @param world
+ * the {@link World} to modify
+ */
+ default <T> void onSwallow(final Entity them, final World<T> world) {
+ throw new UnsupportedOperationException("Does not swallow"); // ...could not be me~ (つ﹏⊂)
+ }
- /**
- * Anything that implements GridCollidable should be keyed by GridCollidable.
- *
- * @return Key type
- */
- default Class<? extends Component> getKey() {
- return GridCollidable.class;
- }
+ /**
+ * Anything that implements GridCollidable should be keyed by GridCollidable.
+ *
+ * @return Key type
+ */
+ default Class<? extends Component> getKey() {
+ return GridCollidable.class;
+ }
}
diff --git a/core/src/main/java/coffee/liz/abstractionengine/grid/component/GridInputState.java b/core/src/main/java/coffee/liz/abstractionengine/grid/component/GridInputState.java
index 8fadb09..6ab0d2b 100644
--- a/core/src/main/java/coffee/liz/abstractionengine/grid/component/GridInputState.java
+++ b/core/src/main/java/coffee/liz/abstractionengine/grid/component/GridInputState.java
@@ -16,22 +16,22 @@ import jakarta.annotation.Nullable;
@AllArgsConstructor
@Builder
public class GridInputState {
- /** Movement {@link Vec2} direction. */
- @Nullable
- private final Vec2<Integer> movement;
+ /** Movement {@link Vec2} direction. */
+ @Nullable
+ private final Vec2<Integer> movement;
- /** Lambda term update to apply. */
- @Nullable
- private final UpdateLambdaTerm updateLambdaTerm;
+ /** Lambda term update to apply. */
+ @Nullable
+ private final UpdateLambdaTerm updateLambdaTerm;
- /** Update lambda term with target entity. */
- @Getter
- @RequiredArgsConstructor
- public static class UpdateLambdaTerm {
- /** {@link Entity} to update. */
- private final Entity toUpdate;
+ /** Update lambda term with target entity. */
+ @Getter
+ @RequiredArgsConstructor
+ public static class UpdateLambdaTerm {
+ /** {@link Entity} to update. */
+ private final Entity toUpdate;
- /** {@link LambdaProgram} to apply. */
- private final LambdaProgram lambdaProgram;
- }
+ /** {@link LambdaProgram} to apply. */
+ private final LambdaProgram lambdaProgram;
+ }
}
diff --git a/core/src/main/java/coffee/liz/abstractionengine/grid/component/GridMomentum.java b/core/src/main/java/coffee/liz/abstractionengine/grid/component/GridMomentum.java
index aec26b1..0281924 100644
--- a/core/src/main/java/coffee/liz/abstractionengine/grid/component/GridMomentum.java
+++ b/core/src/main/java/coffee/liz/abstractionengine/grid/component/GridMomentum.java
@@ -1,8 +1,10 @@
package coffee.liz.abstractionengine.grid.component;
import coffee.liz.ecs.math.Vec2;
+import coffee.liz.ecs.math.Vec2i;
import coffee.liz.ecs.model.Component;
+import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.Getter;
import lombok.RequiredArgsConstructor;
@@ -12,6 +14,6 @@ import lombok.RequiredArgsConstructor;
@Data
@Getter
public class GridMomentum implements Component {
- /** Velocity {@link Vec2}. */
- private final Vec2<Integer> velocity;
+ /** Current velocity {@link Vec2}. */
+ private final Vec2<Integer> velocity;
}
diff --git a/core/src/main/java/coffee/liz/abstractionengine/grid/component/GridPosition.java b/core/src/main/java/coffee/liz/abstractionengine/grid/component/GridPosition.java
index 4ec0557..7b1769e 100644
--- a/core/src/main/java/coffee/liz/abstractionengine/grid/component/GridPosition.java
+++ b/core/src/main/java/coffee/liz/abstractionengine/grid/component/GridPosition.java
@@ -12,5 +12,5 @@ import lombok.RequiredArgsConstructor;
@Data
@Getter
public class GridPosition implements Component {
- private final Vec2<Integer> position;
+ private final Vec2<Integer> position;
}
diff --git a/core/src/main/java/coffee/liz/abstractionengine/grid/system/BaseGridIndexSystem.java b/core/src/main/java/coffee/liz/abstractionengine/grid/system/BaseGridIndexSystem.java
index 4af8be0..ee77256 100644
--- a/core/src/main/java/coffee/liz/abstractionengine/grid/system/BaseGridIndexSystem.java
+++ b/core/src/main/java/coffee/liz/abstractionengine/grid/system/BaseGridIndexSystem.java
@@ -20,36 +20,36 @@ import java.util.Set;
@RequiredArgsConstructor
@Getter
public abstract class BaseGridIndexSystem<T> implements System<T> {
- protected final Vec2<Integer> dimensions;
- protected final List<List<Set<Entity>>> rows;
+ protected final Vec2<Integer> dimensions;
+ protected final List<List<Set<Entity>>> rows;
- public BaseGridIndexSystem(final Vec2<Integer> dimensions) {
- this.dimensions = dimensions;
- this.rows = Mat2.init(dimensions, _ -> new HashSet<>());
- }
+ public BaseGridIndexSystem(final Vec2<Integer> dimensions) {
+ this.dimensions = dimensions;
+ this.rows = Mat2.init(dimensions, _ -> new HashSet<>());
+ }
- @Override
- public Collection<Class<? extends System<T>>> getDependencies() {
- return Set.of();
- }
+ @Override
+ public Collection<Class<? extends System<T>>> getDependencies() {
+ return Set.of();
+ }
- @Override
- public void update(final World<T> world, final T state, final Duration dt) {
- rows.forEach(row -> row.forEach(Set::clear));
- world.query(Set.of(GridPosition.class)).forEach(entity -> {
- final GridPosition position = entity.get(GridPosition.class);
- rows.get(position.getPosition().getY()).get(position.getPosition().getX()).add(entity);
- });
- }
+ @Override
+ public void update(final World<T> world, final T state, final Duration dt) {
+ rows.forEach(row -> row.forEach(Set::clear));
+ world.query(Set.of(GridPosition.class)).forEach(entity -> {
+ final GridPosition position = entity.get(GridPosition.class);
+ rows.get(position.getPosition().getY()).get(position.getPosition().getX()).add(entity);
+ });
+ }
- public Collection<Entity> entitiesAt(final Vec2<Integer> pos) {
- if (!inBounds(pos)) {
- return Collections.emptySet();
- }
- return Set.copyOf(rows.get(pos.getY()).get(pos.getX()));
- }
+ public Collection<Entity> entitiesAt(final Vec2<Integer> pos) {
+ if (!inBounds(pos)) {
+ return Collections.emptySet();
+ }
+ return Set.copyOf(rows.get(pos.getY()).get(pos.getX()));
+ }
- public boolean inBounds(final Vec2<Integer> pos) {
- return pos.getX() >= 0 && pos.getX() < dimensions.getX() && pos.getY() >= 0 && pos.getY() < dimensions.getY();
- }
+ public boolean inBounds(final Vec2<Integer> pos) {
+ return pos.getX() >= 0 && pos.getX() < dimensions.getX() && pos.getY() >= 0 && pos.getY() < dimensions.getY();
+ }
}
diff --git a/core/src/main/java/coffee/liz/abstractionengine/grid/system/GridCollisionPropagatationSystem.java b/core/src/main/java/coffee/liz/abstractionengine/grid/system/GridCollisionPropagatationSystem.java
index 33c86c8..23a821d 100644
--- a/core/src/main/java/coffee/liz/abstractionengine/grid/system/GridCollisionPropagatationSystem.java
+++ b/core/src/main/java/coffee/liz/abstractionengine/grid/system/GridCollisionPropagatationSystem.java
@@ -24,85 +24,85 @@ import java.util.Set;
* System which resolves collisions between cells in the Grid.
*/
public class GridCollisionPropagatationSystem implements System<GridInputState> {
- @Override
- public Collection<Class<? extends System<GridInputState>>> getDependencies() {
- return Set.of(GridMovementSystem.class, GridIndexSystem.class);
- }
+ @Override
+ public Collection<Class<? extends System<GridInputState>>> getDependencies() {
+ return Set.of(GridMovementSystem.class, GridIndexSystem.class);
+ }
- @Override
- public void update(final World<GridInputState> world, final GridInputState state, final Duration dt) {
- world.query(Set.of(GridMomentum.class, GridPosition.class, GridCollidable.class)).forEach(pusher -> {
- final Vec2<Integer> velocity = pusher.get(GridMomentum.class).getVelocity();
- if (velocity.equals(Vec2i.ZERO)) {
- return;
- }
+ @Override
+ public void update(final World<GridInputState> world, final GridInputState state, final Duration dt) {
+ world.query(Set.of(GridMomentum.class, GridPosition.class, GridCollidable.class)).forEach(pusher -> {
+ final Vec2<Integer> velocity = pusher.get(GridMomentum.class).getVelocity();
+ if (velocity.equals(Vec2i.ZERO)) {
+ return;
+ }
- final Vec2<Integer> position = pusher.get(GridPosition.class).getPosition();
- final CollisionRayResult result = resolveCollisionRay(world, pusher, position, velocity);
+ final Vec2<Integer> position = pusher.get(GridPosition.class).getPosition();
+ final CollisionRayResult result = resolveCollisionRay(world, pusher, position, velocity);
- pusher.add(new GridMomentum(Vec2i.ZERO));
- if (result instanceof CollisionRayResult.Blocked) {
- return;
- }
+ pusher.add(new GridMomentum(Vec2i.ZERO));
+ if (result instanceof CollisionRayResult.Blocked) {
+ return;
+ }
- final CollisionRayResult.Propagated propagated = (CollisionRayResult.Propagated) result;
- propagated.ray().forEach(e -> e.add(new GridMomentum(propagated.direction())));
- propagated.swallows()
- .forEach(entry -> entry.getKey().get(GridCollidable.class).onSwallow(entry.getValue(), world));
- });
- }
+ final CollisionRayResult.Propagated propagated = (CollisionRayResult.Propagated) result;
+ propagated.ray().forEach(e -> e.add(new GridMomentum(propagated.direction())));
+ propagated.swallows()
+ .forEach(entry -> entry.getKey().get(GridCollidable.class).onSwallow(entry.getValue(), world));
+ });
+ }
- private CollisionRayResult resolveCollisionRay(World<GridInputState> world, Entity pusher, Vec2<Integer> start,
- Vec2<Integer> direction) {
- final GridIndexSystem gridIndex = world.getSystem(GridIndexSystem.class);
+ private CollisionRayResult resolveCollisionRay(World<GridInputState> world, Entity pusher, Vec2<Integer> start,
+ Vec2<Integer> direction) {
+ final GridIndexSystem gridIndex = world.getSystem(GridIndexSystem.class);
- final List<List<Entity>> ray = new ArrayList<>();
- ray.add(List.of(pusher));
- final Set<Map.Entry<Entity, Entity>> swallows = new HashSet<>();
+ final List<List<Entity>> ray = new ArrayList<>();
+ ray.add(List.of(pusher));
+ final Set<Map.Entry<Entity, Entity>> swallows = new HashSet<>();
- Vec2<Integer> gridPosition = start.plus(direction);
- while (!ray.getLast().isEmpty()) {
- if (!gridIndex.inBounds(gridPosition)) {
- return new CollisionRayResult.Blocked();
- }
+ Vec2<Integer> gridPosition = start.plus(direction);
+ while (!ray.getLast().isEmpty()) {
+ if (!gridIndex.inBounds(gridPosition)) {
+ return new CollisionRayResult.Blocked();
+ }
- final List<Entity> collidables = gridIndex.entitiesAt(gridPosition).stream()
- .filter(e -> e.has(GridCollidable.class)).toList();
- if (collidables.isEmpty()) {
- break;
- }
+ final List<Entity> collidables = gridIndex.entitiesAt(gridPosition).stream()
+ .filter(e -> e.has(GridCollidable.class)).toList();
+ if (collidables.isEmpty()) {
+ break;
+ }
- final List<Entity> nextRay = new ArrayList<>();
+ final List<Entity> nextRay = new ArrayList<>();
- for (final Entity push : ray.getLast()) {
- final Map.Entry<Entity, CollisionBehavior> behavior = collidables.stream()
- .map(c -> Map.entry(c, c.get(GridCollidable.class).getCollisionBehaviorBetween(push, c)))
- .min(Comparator.comparing(e -> e.getValue().getPriority())).orElseThrow();
+ for (final Entity push : ray.getLast()) {
+ final Map.Entry<Entity, CollisionBehavior> behavior = collidables.stream()
+ .map(c -> Map.entry(c, c.get(GridCollidable.class).getCollisionBehaviorBetween(push, c)))
+ .min(Comparator.comparing(e -> e.getValue().getPriority())).orElseThrow();
- switch (behavior.getValue().getCollisionBehaviorType()) {
- case PROPAGATE -> nextRay.add(behavior.getKey());
- case SWALLOW -> swallows.add(Map.entry(behavior.getKey(), push));
- case WALL -> {
- return new CollisionRayResult.Blocked();
- }
- }
- }
+ switch (behavior.getValue().getCollisionBehaviorType()) {
+ case PROPAGATE -> nextRay.add(behavior.getKey());
+ case SWALLOW -> swallows.add(Map.entry(behavior.getKey(), push));
+ case WALL -> {
+ return new CollisionRayResult.Blocked();
+ }
+ }
+ }
- ray.add(nextRay);
- gridPosition = gridPosition.plus(direction);
- }
+ ray.add(nextRay);
+ gridPosition = gridPosition.plus(direction);
+ }
- final Collection<Entity> rayEntities = ray.stream().flatMap(Collection::stream).toList();
- return new CollisionRayResult.Propagated(rayEntities, swallows, direction);
- }
+ final Collection<Entity> rayEntities = ray.stream().flatMap(Collection::stream).toList();
+ return new CollisionRayResult.Propagated(rayEntities, swallows, direction);
+ }
- private sealed interface CollisionRayResult permits CollisionRayResult.Propagated, CollisionRayResult.Blocked {
+ private sealed interface CollisionRayResult permits CollisionRayResult.Propagated, CollisionRayResult.Blocked {
- record Propagated(Collection<Entity> ray, Set<Map.Entry<Entity, Entity>> swallows,
- Vec2<Integer> direction) implements CollisionRayResult {
- }
+ record Propagated(Collection<Entity> ray, Set<Map.Entry<Entity, Entity>> swallows,
+ Vec2<Integer> direction) implements CollisionRayResult {
+ }
- record Blocked() implements CollisionRayResult {
- }
- }
+ record Blocked() implements CollisionRayResult {
+ }
+ }
}
diff --git a/core/src/main/java/coffee/liz/abstractionengine/grid/system/GridIndexSystem.java b/core/src/main/java/coffee/liz/abstractionengine/grid/system/GridIndexSystem.java
index ca2279f..aea669b 100644
--- a/core/src/main/java/coffee/liz/abstractionengine/grid/system/GridIndexSystem.java
+++ b/core/src/main/java/coffee/liz/abstractionengine/grid/system/GridIndexSystem.java
@@ -4,7 +4,7 @@ import coffee.liz.abstractionengine.grid.component.GridInputState;
import coffee.liz.ecs.math.Vec2;
public class GridIndexSystem extends BaseGridIndexSystem<GridInputState> {
- public GridIndexSystem(final Vec2<Integer> dimensions) {
- super(dimensions);
- }
+ public GridIndexSystem(final Vec2<Integer> dimensions) {
+ super(dimensions);
+ }
}
diff --git a/core/src/main/java/coffee/liz/abstractionengine/grid/system/GridMovementSystem.java b/core/src/main/java/coffee/liz/abstractionengine/grid/system/GridMovementSystem.java
index f5f1089..02f012b 100644
--- a/core/src/main/java/coffee/liz/abstractionengine/grid/system/GridMovementSystem.java
+++ b/core/src/main/java/coffee/liz/abstractionengine/grid/system/GridMovementSystem.java
@@ -18,14 +18,14 @@ import java.util.Set;
@RequiredArgsConstructor
@Getter
public class GridMovementSystem implements System<GridInputState> {
- @Override
- public Collection<Class<? extends System<GridInputState>>> getDependencies() {
- return Set.of();
- }
+ @Override
+ public Collection<Class<? extends System<GridInputState>>> getDependencies() {
+ return Set.of();
+ }
- @Override
- public void update(final World<GridInputState> world, final GridInputState state, final Duration dt) {
- world.query(Set.of(GridControllable.class, GridPosition.class))
- .forEach(entity -> entity.add(new GridMomentum(state.getMovement())));
- }
+ @Override
+ public void update(final World<GridInputState> world, final GridInputState state, final Duration dt) {
+ world.query(Set.of(GridControllable.class, GridPosition.class))
+ .forEach(entity -> entity.add(new GridMomentum(state.getMovement())));
+ }
}
diff --git a/core/src/main/java/coffee/liz/abstractionengine/grid/system/GridPhysicsSystem.java b/core/src/main/java/coffee/liz/abstractionengine/grid/system/GridPhysicsSystem.java
index 88f8d57..5e0e632 100644
--- a/core/src/main/java/coffee/liz/abstractionengine/grid/system/GridPhysicsSystem.java
+++ b/core/src/main/java/coffee/liz/abstractionengine/grid/system/GridPhysicsSystem.java
@@ -13,19 +13,19 @@ import java.util.Set;
/** System applying physics/position updates from momentum. */
public class GridPhysicsSystem implements System<GridInputState> {
- @Override
- public Collection<Class<? extends System<GridInputState>>> getDependencies() {
- return Set.of(GridCollisionPropagatationSystem.class);
- }
+ @Override
+ public Collection<Class<? extends System<GridInputState>>> getDependencies() {
+ return Set.of(GridCollisionPropagatationSystem.class);
+ }
- @Override
- public void update(final World<GridInputState> world, final GridInputState state, final Duration dt) {
- world.query(Set.of(GridMomentum.class, GridPosition.class)).forEach(entity -> {
- final GridMomentum momentum = entity.get(GridMomentum.class);
- final GridPosition position = entity.get(GridPosition.class);
+ @Override
+ public void update(final World<GridInputState> world, final GridInputState state, final Duration dt) {
+ world.query(Set.of(GridMomentum.class, GridPosition.class)).forEach(entity -> {
+ final GridMomentum momentum = entity.get(GridMomentum.class);
+ final GridPosition position = entity.get(GridPosition.class);
- entity.add(new GridPosition(position.getPosition().plus(momentum.getVelocity())));
- entity.add(new GridMomentum(Vec2i.ZERO));
- });
- }
+ entity.add(new GridPosition(position.getPosition().plus(momentum.getVelocity())));
+ entity.add(new GridMomentum(Vec2i.ZERO));
+ });
+ }
}