kble/src/movement.zig

123 lines
3.4 KiB
Zig

// SPDX-License-Identifier: MIT
// Copyright (c) 2021 KikooDX
// This file is part of [KBLE](https://sr.ht/~kikoodx/kble), which is
// MIT licensed. The MIT license requires this copyright notice to be
// included in all copies and substantial portions of the software.
//! Movement functions.
const std = @import("std");
const expect = std.testing.expect;
const maxInt = std.math.maxInt;
const conf = @import("conf.zig");
const Vec2 = @import("vec2.zig");
const Rect = @import("rect.zig");
const maxIntVec2 = comptime maxInt(Vec2.int_type);
/// Describe changes to make on selection.
pub const SelectionUpdate = struct {
active: bool,
area: Rect,
state: bool,
};
/// Universal move system, prefer direction wrappers.
fn move(cursor: *Vec2, arg: conf.arg_type, dx: i2, dy: i2) SelectionUpdate {
const before: Vec2 = cursor.*;
if (dx > 0) {
var i: conf.arg_type = 0;
while (i != arg and cursor.x < maxIntVec2) : (i += 1) {
cursor.x += 1;
}
} else if (dx < 0) {
var i: conf.arg_type = 0;
while (i != arg and cursor.x > 0) : (i += 1) {
cursor.x -= 1;
}
}
if (dy > 0) {
var i: conf.arg_type = 0;
while (i != arg and cursor.y < maxIntVec2) : (i += 1) {
cursor.y += 1;
}
} else if (dy < 0) {
var i: conf.arg_type = 0;
while (i != arg and cursor.y > 0) : (i += 1) {
cursor.y -= 1;
}
}
return SelectionUpdate{
.active = true,
.area = Rect.init_from_vec2(before, cursor.*),
.state = true,
};
}
/// Just don't move.
pub fn move_but_dont(cursor: *Vec2, arg: conf.arg_type) SelectionUpdate {
return move(cursor, arg, 0, 0);
}
/// Try to move the cursor `n` times left.
pub fn move_left(cursor: *Vec2, arg: conf.arg_type) SelectionUpdate {
return move(cursor, arg, -1, 0);
}
/// Try to move the cursor `n` times right.
pub fn move_right(cursor: *Vec2, arg: conf.arg_type) SelectionUpdate {
return move(cursor, arg, 1, 0);
}
/// Try to move the cursor `n` times up.
pub fn move_up(cursor: *Vec2, arg: conf.arg_type) SelectionUpdate {
return move(cursor, arg, 0, -1);
}
/// Try to move the cursor `n` times down.
pub fn move_down(cursor: *Vec2, arg: conf.arg_type) SelectionUpdate {
return move(cursor, arg, 0, 1);
}
/// Try to move the cursor `n` times up and left.
pub fn move_up_left(cursor: *Vec2, arg: conf.arg_type) SelectionUpdate {
return move(cursor, arg, -1, -1);
}
/// Try to move the cursor `n` times up and right.
pub fn move_up_right(cursor: *Vec2, arg: conf.arg_type) SelectionUpdate {
return move(cursor, arg, 1, -1);
}
/// Try to move the cursor `n` times down and left.
pub fn move_down_left(cursor: *Vec2, arg: conf.arg_type) SelectionUpdate {
return move(cursor, arg, -1, 1);
}
/// Try to move the cursor `n` times down and right.
pub fn move_down_right(cursor: *Vec2, arg: conf.arg_type) SelectionUpdate {
return move(cursor, arg, 1, 1);
}
test "move left" {
var cursor = Vec2.init(42, 51);
_ = move_left(&cursor, 2, false);
expect(cursor.x == 40);
_ = move_left(&cursor, 38, false);
expect(cursor.x == 2);
_ = move_left(&cursor, maxIntVec2, false);
expect(cursor.x == 0);
}
test "move right" {
var cursor = Vec2.init(564, 42);
_ = move_right(&cursor, 51, false);
expect(cursor.x == 615);
_ = move_right(&cursor, maxIntVec2, false);
expect(cursor.x == maxIntVec2);
}