mirror of https://git.sr.ht/~kikoodx/kble
Cleaned up code, implemented rectangle selection.
This commit is contained in:
parent
20c4d8ca1a
commit
989502edf9
|
@ -5,6 +5,7 @@ This is a work in progress program in unusable state.
|
|||
|
||||
# Short term design decisions
|
||||
Subject to change.
|
||||
* Efficiency, simplicity and clarity are key goals.
|
||||
* Fully keyboard driven modal editing. Mouse support is secondary.
|
||||
* GUI application made in [Zig](https://ziglang.org/) with
|
||||
[raylib](https://www.raylib.com/).
|
||||
|
@ -44,7 +45,7 @@ Verbs:
|
|||
Modes:
|
||||
* `<return>`: normal mode, default
|
||||
* `i`: free selection mode
|
||||
* `v`: rectangle selection mode [not implemented]
|
||||
* `v`: rectangle selection mode
|
||||
* `c`: camera mode [not implemented]
|
||||
|
||||
# Mouse control
|
||||
|
|
|
@ -25,7 +25,7 @@ pub const ActionCat = enum {
|
|||
pub const Action = struct {
|
||||
category: ActionCat,
|
||||
// Only one of these should be set, and only one should be used.
|
||||
function_move: fn (*Vec2, conf.arg_type, bool) movement.SelectionUpdate = movement.move_left,
|
||||
function_move: fn (*Vec2, conf.arg_type) movement.SelectionUpdate = movement.move_left,
|
||||
function_verb: fn (*Level, conf.arg_type) void = verbs.delete,
|
||||
function_scale: fn (scaling.scale_type) scaling.scale_type = scaling.scale_reset,
|
||||
next_mode: Mode = Mode.normal,
|
||||
|
|
10
src/draw.zig
10
src/draw.zig
|
@ -8,6 +8,7 @@ const ray = @cImport({
|
|||
});
|
||||
|
||||
const Vec2 = @import("vec2.zig");
|
||||
const Rect = @import("rect.zig");
|
||||
const scaling = @import("scaling.zig");
|
||||
const Mode = @import("modes.zig").Mode;
|
||||
|
||||
|
@ -23,3 +24,12 @@ pub fn cursor(scale: scaling.scale_type, offset: Vec2, pos: Vec2, mode: Mode) vo
|
|||
};
|
||||
ray.DrawRectangleLines(x, y, scale, scale, color);
|
||||
}
|
||||
|
||||
/// Draw rectangle selection preview.
|
||||
pub fn rectangle_selection(scale: scaling.scale_type, offset: Vec2, rect: Rect) void {
|
||||
const x = (rect.left_x - offset.x) * scale;
|
||||
const w = (rect.right_x - rect.left_x + 1) * scale;
|
||||
const y = (rect.top_y - offset.y) * scale;
|
||||
const h = (rect.bottom_y - rect.top_y + 1) * scale;
|
||||
ray.DrawRectangleLines(x, y, w, h, ray.SKYBLUE);
|
||||
}
|
||||
|
|
|
@ -135,12 +135,6 @@ pub fn select_rect(self: *Self, rect: Rect, state: bool) void {
|
|||
|
||||
/// Apply selection update to selection *kof*.
|
||||
pub fn apply_selection_update(self: *Self, selection_update: SelectionUpdate) void {
|
||||
// The update is exclusive, forget everything before it.
|
||||
if (selection_update.exclusive) {
|
||||
// Clear selection.
|
||||
self.select_clear(false);
|
||||
}
|
||||
|
||||
// Apply changes.
|
||||
self.select_rect(selection_update.area, selection_update.state);
|
||||
}
|
||||
|
|
23
src/main.zig
23
src/main.zig
|
@ -17,6 +17,7 @@ const Rect = @import("rect.zig");
|
|||
const Mouse = @import("mouse.zig");
|
||||
const draw = @import("draw.zig");
|
||||
const movement = @import("movement.zig");
|
||||
const verbs = @import("verbs.zig");
|
||||
const scaling = @import("scaling.zig");
|
||||
const actions = @import("actions.zig");
|
||||
const ActionsDef = actions.ActionsDef;
|
||||
|
@ -45,16 +46,19 @@ pub fn main() void {
|
|||
|
||||
// Create camera.
|
||||
// TODO: Can't move camera, implement camera mode.
|
||||
var camera: Vec2 = Vec2.init(0, 0);
|
||||
var camera: Vec2 = comptime Vec2.init(0, 0);
|
||||
|
||||
// Init scale, used by drawing code.
|
||||
var scale: scaling.scale_type = scaling.scale_default;
|
||||
|
||||
// Create mouse.
|
||||
var mouse: Mouse = Mouse.init();
|
||||
var mouse: Mouse = comptime Mouse.init();
|
||||
|
||||
// Create cursor.
|
||||
var cursor: Vec2 = Vec2.init(0, 0);
|
||||
var cursor: Vec2 = comptime Vec2.init(0, 0);
|
||||
|
||||
// Used by rectangle selection mode.
|
||||
var cursor_before: Vec2 = comptime Vec2.init(0, 0);
|
||||
|
||||
// Set default mode.
|
||||
var mode: Mode = Mode.normal;
|
||||
|
@ -132,14 +136,13 @@ pub fn main() void {
|
|||
0;
|
||||
|
||||
const action: actions.Action = bindings[key].*;
|
||||
const exclusive_movement: bool = false;
|
||||
const apply_selection: bool = (mode == Mode.select);
|
||||
|
||||
switch (action.category) {
|
||||
.none => std.log.info("No action bound to {}.", .{key}),
|
||||
.movement => {
|
||||
const selection_update: movement.SelectionUpdate =
|
||||
action.function_move(&cursor, 1, exclusive_movement);
|
||||
action.function_move(&cursor, 1);
|
||||
if (apply_selection and selection_update.active) {
|
||||
level.apply_selection_update(selection_update);
|
||||
}
|
||||
|
@ -151,6 +154,12 @@ pub fn main() void {
|
|||
scale = action.function_scale(scale);
|
||||
},
|
||||
.mode => {
|
||||
// Rectangle selection!
|
||||
if (mode == Mode.rectangle) {
|
||||
const selection = Rect.init_from_vec2(cursor, cursor_before);
|
||||
level.select_rect(selection, true);
|
||||
}
|
||||
cursor_before = cursor; // Save position before selection.
|
||||
mode = action.next_mode;
|
||||
},
|
||||
}
|
||||
|
@ -193,7 +202,7 @@ pub fn main() void {
|
|||
cursor = mouse.pos;
|
||||
// Reset selection on right click.
|
||||
if (right_click) {
|
||||
level.apply_selection_update(movement.move_but_dont(&cursor, 1, true));
|
||||
verbs.clear_selection(&level, 1);
|
||||
}
|
||||
// Set position.
|
||||
mouse.start_pos = mouse.pos;
|
||||
|
@ -219,6 +228,8 @@ pub fn main() void {
|
|||
level.draw(scale, camera);
|
||||
level.draw_selection(scale, camera);
|
||||
draw.cursor(scale, camera, cursor, mode);
|
||||
if (mode == Mode.rectangle)
|
||||
draw.rectangle_selection(scale, camera, Rect.init_from_vec2(cursor, cursor_before));
|
||||
mouse.draw(scale, camera);
|
||||
//ray.DrawFPS(0, 0);
|
||||
}
|
||||
|
|
|
@ -12,11 +12,10 @@ const std = @import("std");
|
|||
const Vec2 = @import("vec2.zig");
|
||||
const Rect = @import("rect.zig");
|
||||
const scaling = @import("scaling.zig");
|
||||
const draw_fn = @import("draw.zig");
|
||||
|
||||
const Self = @This();
|
||||
|
||||
const preview_color = ray.SKYBLUE;
|
||||
|
||||
pub const MouseMode = enum {
|
||||
wait, // Skip one turn.
|
||||
idle,
|
||||
|
@ -43,15 +42,11 @@ pub fn draw(self: *Self, scale: scaling.scale_type, offset: Vec2) void {
|
|||
MouseMode.sel => {
|
||||
const x = (self.pos.x - offset.y) * scale;
|
||||
const y = (self.pos.y - offset.y) * scale;
|
||||
ray.DrawRectangleLines(x, y, scale, scale, preview_color);
|
||||
ray.DrawRectangleLines(x, y, scale, scale, ray.SKYBLUE);
|
||||
},
|
||||
MouseMode.rect_sel => {
|
||||
const rect = Rect.init_from_vec2(self.pos, self.start_pos);
|
||||
const x = (rect.left_x - offset.x) * scale;
|
||||
const w = (rect.right_x - rect.left_x + 1) * scale;
|
||||
const y = (rect.top_y - offset.y) * scale;
|
||||
const h = (rect.bottom_y - rect.top_y + 1) * scale;
|
||||
ray.DrawRectangleLines(x, y, w, h, preview_color);
|
||||
draw_fn.rectangle_selection(scale, offset, rect);
|
||||
},
|
||||
else => {},
|
||||
}
|
||||
|
|
|
@ -17,13 +17,12 @@ const maxIntVec2 = comptime maxInt(Vec2.int_type);
|
|||
/// Describe changes to make on selection.
|
||||
pub const SelectionUpdate = struct {
|
||||
active: bool,
|
||||
exclusive: bool,
|
||||
area: Rect,
|
||||
state: bool,
|
||||
};
|
||||
|
||||
/// Universal move system, prefer direction wrappers.
|
||||
fn move(cursor: *Vec2, arg: conf.arg_type, exclusive_selection: bool, dx: i2, dy: i2) SelectionUpdate {
|
||||
fn move(cursor: *Vec2, arg: conf.arg_type, dx: i2, dy: i2) SelectionUpdate {
|
||||
const before: Vec2 = cursor.*;
|
||||
|
||||
if (dx > 0) {
|
||||
|
@ -51,58 +50,54 @@ fn move(cursor: *Vec2, arg: conf.arg_type, exclusive_selection: bool, dx: i2, dy
|
|||
|
||||
return SelectionUpdate{
|
||||
.active = true,
|
||||
.exclusive = exclusive_selection,
|
||||
.area = if (exclusive_selection)
|
||||
Rect.init_from_vec2(cursor.*, cursor.*)
|
||||
else
|
||||
Rect.init_from_vec2(before, cursor.*),
|
||||
.area = Rect.init_from_vec2(before, cursor.*),
|
||||
.state = true,
|
||||
};
|
||||
}
|
||||
|
||||
/// Just don't move.
|
||||
pub fn move_but_dont(cursor: *Vec2, arg: conf.arg_type, exclusive_selection: bool) SelectionUpdate {
|
||||
return move(cursor, arg, exclusive_selection, 0, 0);
|
||||
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, exclusive_selection: bool) SelectionUpdate {
|
||||
return move(cursor, arg, exclusive_selection, -1, 0);
|
||||
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, exclusive_selection: bool) SelectionUpdate {
|
||||
return move(cursor, arg, exclusive_selection, 1, 0);
|
||||
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, exclusive_selection: bool) SelectionUpdate {
|
||||
return move(cursor, arg, exclusive_selection, 0, -1);
|
||||
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, exclusive_selection: bool) SelectionUpdate {
|
||||
return move(cursor, arg, exclusive_selection, 0, 1);
|
||||
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, exclusive_selection: bool) SelectionUpdate {
|
||||
return move(cursor, arg, exclusive_selection, -1, -1);
|
||||
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, exclusive_selection: bool) SelectionUpdate {
|
||||
return move(cursor, arg, exclusive_selection, 1, -1);
|
||||
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, exclusive_selection: bool) SelectionUpdate {
|
||||
return move(cursor, arg, exclusive_selection, -1, 1);
|
||||
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, exclusive_selection: bool) SelectionUpdate {
|
||||
return move(cursor, arg, exclusive_selection, 1, 1);
|
||||
pub fn move_down_right(cursor: *Vec2, arg: conf.arg_type) SelectionUpdate {
|
||||
return move(cursor, arg, 1, 1);
|
||||
}
|
||||
|
||||
test "move left" {
|
||||
|
|
Loading…
Reference in New Issue