mirror of https://git.sr.ht/~kikoodx/kble
Unselection modes for mouse and keyboard (#2)
This commit is contained in:
parent
4fb7d33645
commit
a3a4483a44
18
README.md
18
README.md
|
@ -20,8 +20,8 @@ https://builds.sr.ht/~kikoodx/kble
|
|||
|
||||
## Manual compilation
|
||||
Build requirements: [Zig](https://ziglang.org/download/) master branch,
|
||||
[raylib](https://www.raylib.com).
|
||||
For Arch users, `zig-dev-bin` and `zig-git` are available in the AUR.
|
||||
[raylib](https://www.raylib.com). For Arch users, I made
|
||||
[`kble-git`](https://aur.archlinux.org/packages/kble-git/) available in the AUR.
|
||||
```sh
|
||||
$ # Clone this repository
|
||||
$ git clone https://git.sr.ht/~kikoodx/kble && cd kble
|
||||
|
@ -79,14 +79,16 @@ Modes:
|
|||
* `<return>`: normal mode, default
|
||||
* `i`: free selection mode
|
||||
* `v`: rectangle selection mode
|
||||
* `I`: free unselection mode
|
||||
* `V`: rectangle unselection mode
|
||||
* `c`: camera mode [not implemented]
|
||||
|
||||
# Mouse control
|
||||
Right click and left click are the same, except right click reset
|
||||
selection before taking effect.
|
||||
* Click: free selection.
|
||||
* Shift + Click: rectangle selection.
|
||||
* Click while selecting: end selection.
|
||||
# Default mouse control
|
||||
* Right click: free selection.
|
||||
* Shift + left click: rectangle selection.
|
||||
* Right click: libre unselection.
|
||||
* Shift + right click: rectangle unselection.
|
||||
* Left or right click while un·selecting: end selection.
|
||||
|
||||
# License
|
||||
Copyright (c) 2021 KikooDX
|
||||
|
|
|
@ -143,6 +143,14 @@ pub const ActionsDef = .{
|
|||
.category = ActionCat.mode,
|
||||
.next_mode = Mode.rectangle,
|
||||
},
|
||||
.mode_unselect = Action{
|
||||
.category = ActionCat.mode,
|
||||
.next_mode = Mode.unselect,
|
||||
},
|
||||
.mode_unrectangle = Action{
|
||||
.category = ActionCat.mode,
|
||||
.next_mode = Mode.unrectangle,
|
||||
},
|
||||
.mode_camera = Action{
|
||||
.category = ActionCat.mode,
|
||||
.next_mode = Mode.camera,
|
||||
|
|
|
@ -37,6 +37,8 @@ pub const theme = .{
|
|||
.normal = ray.GRAY,
|
||||
.select = ray.BLUE,
|
||||
.select_rect = ray.SKYBLUE,
|
||||
.unselect = ray.RED,
|
||||
.unrectangle = ray.PINK,
|
||||
.camera = ray.PURPLE,
|
||||
},
|
||||
};
|
||||
|
|
|
@ -19,16 +19,21 @@ pub fn cursor(scale: scaling.scale_type, offset: Vec2, pos: Vec2, mode: Mode) vo
|
|||
.normal => conf.theme.mode.normal,
|
||||
.select => conf.theme.mode.select,
|
||||
.rectangle => conf.theme.mode.select_rect,
|
||||
.unselect => conf.theme.mode.unselect,
|
||||
.unrectangle => conf.theme.mode.unrectangle,
|
||||
.camera => conf.theme.mode.camera,
|
||||
};
|
||||
ray.DrawRectangleLines(x, y, scale, scale, color);
|
||||
}
|
||||
|
||||
/// Draw rectangle selection preview.
|
||||
pub fn rectangle_selection(scale: scaling.scale_type, offset: Vec2, rect: Rect) void {
|
||||
pub fn rectangle_selection(scale: scaling.scale_type, offset: Vec2, rect: Rect, sel: bool) 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, conf.theme.mode.select_rect);
|
||||
ray.DrawRectangleLines(x, y, w, h, if (sel)
|
||||
conf.theme.mode.select_rect
|
||||
else
|
||||
conf.theme.mode.unrectangle);
|
||||
}
|
||||
|
|
35
src/main.zig
35
src/main.zig
|
@ -111,6 +111,8 @@ pub fn main() void {
|
|||
default_bindings['\n'] = &ActionsDef.mode_normal;
|
||||
default_bindings['i'] = &ActionsDef.mode_select;
|
||||
default_bindings['v'] = &ActionsDef.mode_rectangle;
|
||||
default_bindings['I'] = &ActionsDef.mode_unselect;
|
||||
default_bindings['V'] = &ActionsDef.mode_unrectangle;
|
||||
default_bindings['c'] = &ActionsDef.mode_camera;
|
||||
// Map user bindings.
|
||||
comptime {
|
||||
|
@ -158,7 +160,7 @@ pub fn main() void {
|
|||
|
||||
// TODO: move everything from this to a function (for config and macros support).
|
||||
const action: actions.Action = bindings[key].*;
|
||||
const apply_selection: bool = (mode == Mode.select);
|
||||
const apply_selection: bool = (mode == .select);
|
||||
|
||||
switch (action.category) {
|
||||
.none => std.log.info("No action bound to {}.", .{key}),
|
||||
|
@ -183,13 +185,13 @@ pub fn main() void {
|
|||
},
|
||||
.mode => {
|
||||
// Rectangle selection!
|
||||
if (mode == Mode.rectangle) {
|
||||
if (mode == .rectangle or mode == .unrectangle) {
|
||||
const selection = Rect.init_from_vec2(cursor, cursor_before);
|
||||
level.select_rect(selection, true);
|
||||
level.select_rect(selection, mode == .rectangle);
|
||||
}
|
||||
cursor_before = cursor; // Save position before selection.
|
||||
mode = action.next_mode;
|
||||
if (mode == Mode.select) // Select first tile.
|
||||
if (mode == .select) // Select first tile.
|
||||
level.select_cell(cursor, true);
|
||||
},
|
||||
}
|
||||
|
@ -217,12 +219,12 @@ pub fn main() void {
|
|||
|
||||
// When end selection event, get out of current mode and apply changes if necessary.
|
||||
if (end_sel_event and mouse.mode != Mouse.MouseMode.idle) {
|
||||
defer mouse.mode = Mouse.MouseMode.wait;
|
||||
defer mouse.mode = .wait;
|
||||
|
||||
// Select area.
|
||||
if (mouse.mode == Mouse.MouseMode.rect_sel) {
|
||||
if (mouse.mode == .rect_sel or mouse.mode == .unrect_sel) {
|
||||
const selection = Rect.init_from_vec2(mouse.start_pos, mouse.pos);
|
||||
level.select_rect(selection, true);
|
||||
level.select_rect(selection, mouse.mode == .rect_sel);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -235,22 +237,23 @@ pub fn main() void {
|
|||
ray.IsKeyDown(ray.KEY_RIGHT_SHIFT);
|
||||
if (click) { // Switch mode.
|
||||
cursor = mouse.pos;
|
||||
// Reset selection on right click.
|
||||
if (right_click) {
|
||||
verbs.clear_selection(&level, 1);
|
||||
}
|
||||
// Set position.
|
||||
mouse.start_pos = mouse.pos;
|
||||
mouse.mode = if (mod_rect_sel)
|
||||
// If right click then un<mode>
|
||||
mouse.mode = if (right_click and mod_rect_sel)
|
||||
Mouse.MouseMode.unrect_sel
|
||||
else if (right_click and !mod_rect_sel)
|
||||
Mouse.MouseMode.unsel
|
||||
else if (mod_rect_sel)
|
||||
Mouse.MouseMode.rect_sel
|
||||
else
|
||||
Mouse.MouseMode.sel;
|
||||
}
|
||||
},
|
||||
// Select stuff under the cursor.
|
||||
.sel => {
|
||||
.sel, .unsel => {
|
||||
cursor = mouse.pos;
|
||||
level.select_cell(mouse.pos, true);
|
||||
level.select_cell(mouse.pos, mouse.mode == .sel);
|
||||
},
|
||||
else => {},
|
||||
}
|
||||
|
@ -263,8 +266,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));
|
||||
if (mode == Mode.rectangle or mode == Mode.unrectangle)
|
||||
draw.rectangle_selection(scale, camera, Rect.init_from_vec2(cursor, cursor_before), mode == .rectangle);
|
||||
if (conf.mouse_enabled)
|
||||
mouse.draw(scale, camera);
|
||||
}
|
||||
|
|
|
@ -8,5 +8,7 @@ pub const Mode = enum {
|
|||
normal, // move cursor and do stuff
|
||||
select, // same, but select while doing so
|
||||
rectangle, // same, but select as a rectangle
|
||||
unselect, // remove from selection instead of adding to it
|
||||
unrectangle, // same as above for rectangle
|
||||
camera, // move camera instead
|
||||
};
|
||||
|
|
|
@ -20,6 +20,8 @@ pub const MouseMode = enum {
|
|||
idle,
|
||||
sel,
|
||||
rect_sel,
|
||||
unsel,
|
||||
unrect_sel,
|
||||
};
|
||||
|
||||
mode: MouseMode, // State.
|
||||
|
@ -38,16 +40,19 @@ pub fn init() Self {
|
|||
/// Draw cursor or preview rectangle selection depending on mode.
|
||||
pub fn draw(self: *Self, scale: scaling.scale_type, offset: Vec2) void {
|
||||
switch (self.mode) {
|
||||
MouseMode.sel => {
|
||||
// Cell size cursor.
|
||||
.idle, .wait, .sel, .unsel => {
|
||||
const x = (self.pos.x - offset.y) * scale;
|
||||
const y = (self.pos.y - offset.y) * scale;
|
||||
ray.DrawRectangleLines(x, y, scale, scale, conf.theme.mode.select);
|
||||
ray.DrawRectangleLines(x, y, scale, scale, switch (self.mode) {
|
||||
.sel => conf.theme.mode.select,
|
||||
.unsel => conf.theme.mode.unselect,
|
||||
else => conf.theme.mode.normal,
|
||||
});
|
||||
},
|
||||
MouseMode.rect_sel => {
|
||||
.rect_sel, .unrect_sel => {
|
||||
const rect = Rect.init_from_vec2(self.pos, self.start_pos);
|
||||
draw_fn.rectangle_selection(scale, offset, rect);
|
||||
draw_fn.rectangle_selection(scale, offset, rect, self.mode == .rect_sel);
|
||||
},
|
||||
else => {},
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue