add basic markers to the sides of a channel view
This commit is contained in:
parent
e33ab321d0
commit
a6a66d99fd
330
src/app.zig
330
src/app.zig
@ -8,9 +8,10 @@ const Graph = @import("./graph.zig");
|
|||||||
const NIDaq = @import("ni-daq/root.zig");
|
const NIDaq = @import("ni-daq/root.zig");
|
||||||
const rect_utils = @import("./rect-utils.zig");
|
const rect_utils = @import("./rect-utils.zig");
|
||||||
const TaskPool = @import("ni-daq/task-pool.zig");
|
const TaskPool = @import("ni-daq/task-pool.zig");
|
||||||
|
const utils = @import("./utils.zig");
|
||||||
|
|
||||||
const remap = @import("./utils.zig").remap;
|
const remap = utils.remap;
|
||||||
const lerpColor = @import("./utils.zig").lerpColor;
|
const lerpColor = utils.lerpColor;
|
||||||
const log = std.log.scoped(.app);
|
const log = std.log.scoped(.app);
|
||||||
const assert = std.debug.assert;
|
const assert = std.debug.assert;
|
||||||
const clamp = std.math.clamp;
|
const clamp = std.math.clamp;
|
||||||
@ -53,7 +54,7 @@ const ChannelView = struct {
|
|||||||
view_rect: Graph.ViewOptions,
|
view_rect: Graph.ViewOptions,
|
||||||
follow: bool = false,
|
follow: bool = false,
|
||||||
|
|
||||||
height: f32 = 200,
|
height: f32 = 300,
|
||||||
|
|
||||||
default_from: f32,
|
default_from: f32,
|
||||||
default_to: f32,
|
default_to: f32,
|
||||||
@ -498,7 +499,7 @@ fn showChannelViewSlider(self: *App, view_rect: *Graph.ViewOptions, sample_count
|
|||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
fn showChannelView(self: *App, channel_view: *ChannelView) !void {
|
fn showChannelViewGraph(self: *App, channel_view: *ChannelView) !void {
|
||||||
const source = self.getChannelSource(channel_view) orelse return;
|
const source = self.getChannelSource(channel_view) orelse return;
|
||||||
const samples = source.samples();
|
const samples = source.samples();
|
||||||
source.lockSamples();
|
source.lockSamples();
|
||||||
@ -506,90 +507,6 @@ fn showChannelView(self: *App, channel_view: *ChannelView) !void {
|
|||||||
|
|
||||||
var channel_rect_opts: *Graph.ViewOptions = &channel_view.view_rect;
|
var channel_rect_opts: *Graph.ViewOptions = &channel_view.view_rect;
|
||||||
|
|
||||||
const channel_box = self.ui.newBoxFromPtr(channel_view);
|
|
||||||
channel_box.background = rl.Color.blue;
|
|
||||||
channel_box.layout_axis = .Y;
|
|
||||||
channel_box.size.x = UI.Size.percent(1, 0);
|
|
||||||
channel_box.size.y = UI.Size.childrenSum(1);
|
|
||||||
self.ui.pushParent(channel_box);
|
|
||||||
defer self.ui.popParent();
|
|
||||||
|
|
||||||
{
|
|
||||||
const tools_box = self.ui.newBoxFromString("Graph tools");
|
|
||||||
tools_box.background = rl.Color.gray;
|
|
||||||
tools_box.layout_axis = .X;
|
|
||||||
tools_box.size.x = UI.Size.percent(1, 0);
|
|
||||||
tools_box.size.y = UI.Size.pixels(32, 1);
|
|
||||||
self.ui.pushParent(tools_box);
|
|
||||||
defer self.ui.popParent();
|
|
||||||
|
|
||||||
{
|
|
||||||
const reset_view_button = self.ui.button(.text, "Reset view");
|
|
||||||
reset_view_button.size.y = UI.Size.percent(1, 0);
|
|
||||||
|
|
||||||
if (self.ui.signalFromBox(reset_view_button).clicked()) {
|
|
||||||
channel_rect_opts.from = channel_view.default_from;
|
|
||||||
channel_rect_opts.to = channel_view.default_to;
|
|
||||||
channel_rect_opts.min_value = channel_view.default_min_value;
|
|
||||||
channel_rect_opts.max_value = channel_view.default_max_value;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (source == .device) {
|
|
||||||
const device_channel = source.device;
|
|
||||||
|
|
||||||
if (self.ni_daq) |*ni_daq| {
|
|
||||||
const record_button = self.ui.button(.text, "Record");
|
|
||||||
record_button.size.y = UI.Size.percent(1, 0);
|
|
||||||
|
|
||||||
if (device_channel.active_task != null) {
|
|
||||||
record_button.setText(.text, "Stop");
|
|
||||||
}
|
|
||||||
|
|
||||||
const signal = self.ui.signalFromBox(record_button);
|
|
||||||
if (signal.clicked()) {
|
|
||||||
if (device_channel.active_task) |task| {
|
|
||||||
try task.stop();
|
|
||||||
device_channel.active_task = null;
|
|
||||||
} else {
|
|
||||||
const channel_name = device_channel.name.buffer[0..device_channel.name.len :0];
|
|
||||||
device_channel.active_task = try self.task_pool.launchAIVoltageChannel(
|
|
||||||
ni_daq,
|
|
||||||
&device_channel.mutex,
|
|
||||||
&device_channel.samples,
|
|
||||||
.{
|
|
||||||
.continous = .{ .sample_rate = device_channel.max_sample_rate }
|
|
||||||
},
|
|
||||||
.{
|
|
||||||
.min_value = channel_view.default_min_value,
|
|
||||||
.max_value = channel_view.default_max_value,
|
|
||||||
.units = device_channel.units,
|
|
||||||
.channel = channel_name
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
channel_view.follow = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
{
|
|
||||||
const follow_button = self.ui.button(.text, "Follow");
|
|
||||||
follow_button.size.y = UI.Size.percent(1, 0);
|
|
||||||
if (channel_view.follow) {
|
|
||||||
follow_button.setText(.text, "Unfollow");
|
|
||||||
}
|
|
||||||
|
|
||||||
const signal = self.ui.signalFromBox(follow_button);
|
|
||||||
if (signal.clicked()) {
|
|
||||||
channel_view.follow = !channel_view.follow;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
{
|
|
||||||
const graph_box = self.ui.newBoxFromString("Graph");
|
const graph_box = self.ui.newBoxFromString("Graph");
|
||||||
graph_box.flags.insert(.clickable);
|
graph_box.flags.insert(.clickable);
|
||||||
graph_box.flags.insert(.draggable);
|
graph_box.flags.insert(.draggable);
|
||||||
@ -667,7 +584,7 @@ fn showChannelView(self: *App, channel_view: *ChannelView) !void {
|
|||||||
// TODO: Show error message that selected range is too small
|
// TODO: Show error message that selected range is too small
|
||||||
}
|
}
|
||||||
} else if (axis == .Y) {
|
} else if (axis == .Y) {
|
||||||
if (higher_sample - lower_sample > 0.01) {
|
if (higher_sample - lower_sample > 0.001) {
|
||||||
channel_rect_opts.min_value = lower_sample;
|
channel_rect_opts.min_value = lower_sample;
|
||||||
channel_rect_opts.max_value = higher_sample;
|
channel_rect_opts.max_value = higher_sample;
|
||||||
} else {
|
} else {
|
||||||
@ -756,27 +673,32 @@ fn showChannelView(self: *App, channel_view: *ChannelView) !void {
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (signal.dragged()) {
|
if (signal.dragged()) {
|
||||||
if (signal.shift_modifier) {
|
const middle_mouse_drag = signal.flags.contains(.middle_dragging);
|
||||||
const drag_offset = remap(
|
var x_offset: f64 = 0;
|
||||||
|
var y_offset: f64 = 0;
|
||||||
|
|
||||||
|
if (signal.shift_modifier or middle_mouse_drag) {
|
||||||
|
y_offset = remap(
|
||||||
f64,
|
f64,
|
||||||
0, graph_rect.height,
|
0, graph_rect.height,
|
||||||
0, channel_rect_opts.max_value - channel_rect_opts.min_value,
|
0, channel_rect_opts.max_value - channel_rect_opts.min_value,
|
||||||
signal.drag.y
|
signal.drag.y
|
||||||
);
|
);
|
||||||
|
}
|
||||||
|
|
||||||
channel_rect_opts.max_value += @floatCast(drag_offset);
|
if (!signal.shift_modifier or middle_mouse_drag) {
|
||||||
channel_rect_opts.min_value += @floatCast(drag_offset);
|
x_offset = remap(
|
||||||
} else {
|
|
||||||
const drag_offset = remap(
|
|
||||||
f64,
|
f64,
|
||||||
0, graph_rect.width,
|
0, graph_rect.width,
|
||||||
0, channel_rect_opts.to - channel_rect_opts.from,
|
0, channel_rect_opts.to - channel_rect_opts.from,
|
||||||
signal.drag.x
|
signal.drag.x
|
||||||
);
|
);
|
||||||
|
|
||||||
channel_rect_opts.from -= @floatCast(drag_offset);
|
|
||||||
channel_rect_opts.to -= @floatCast(drag_offset);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
channel_rect_opts.from -= @floatCast(x_offset);
|
||||||
|
channel_rect_opts.to -= @floatCast(x_offset);
|
||||||
|
channel_rect_opts.max_value += @floatCast(y_offset);
|
||||||
|
channel_rect_opts.min_value += @floatCast(y_offset);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -784,12 +706,218 @@ fn showChannelView(self: *App, channel_view: *ChannelView) !void {
|
|||||||
if (channel_view.view_cache.texture) |texture| {
|
if (channel_view.view_cache.texture) |texture| {
|
||||||
graph_box.texture = texture.texture;
|
graph_box.texture = texture.texture;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
fn showChannelView(self: *App, channel_view: *ChannelView) !void {
|
||||||
|
const source = self.getChannelSource(channel_view) orelse return;
|
||||||
|
|
||||||
|
var channel_rect_opts: *Graph.ViewOptions = &channel_view.view_rect;
|
||||||
|
|
||||||
|
const channel_box = self.ui.newBoxFromPtr(channel_view);
|
||||||
|
channel_box.background = rl.Color.blue;
|
||||||
|
channel_box.layout_axis = .Y;
|
||||||
|
channel_box.size.x = UI.Size.percent(1, 0);
|
||||||
|
channel_box.size.y = UI.Size.pixels(channel_view.height, 1);
|
||||||
|
self.ui.pushParent(channel_box);
|
||||||
|
defer self.ui.popParent();
|
||||||
|
|
||||||
|
{
|
||||||
|
const tools_box = self.ui.newBoxFromString("Graph tools");
|
||||||
|
tools_box.background = rl.Color.gray;
|
||||||
|
tools_box.layout_axis = .X;
|
||||||
|
tools_box.size.x = UI.Size.percent(1, 0);
|
||||||
|
tools_box.size.y = UI.Size.pixels(32, 1);
|
||||||
|
self.ui.pushParent(tools_box);
|
||||||
|
defer self.ui.popParent();
|
||||||
|
|
||||||
|
{
|
||||||
|
const reset_view_button = self.ui.button(.text, "Reset view");
|
||||||
|
reset_view_button.size.y = UI.Size.percent(1, 0);
|
||||||
|
|
||||||
|
if (self.ui.signalFromBox(reset_view_button).clicked()) {
|
||||||
|
channel_rect_opts.from = channel_view.default_from;
|
||||||
|
channel_rect_opts.to = channel_view.default_to;
|
||||||
|
channel_rect_opts.min_value = channel_view.default_min_value;
|
||||||
|
channel_rect_opts.max_value = channel_view.default_max_value;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
self.showChannelViewSlider(
|
if (source == .device) {
|
||||||
&channel_view.view_rect,
|
const device_channel = source.device;
|
||||||
@floatFromInt(samples.len)
|
|
||||||
|
if (self.ni_daq) |*ni_daq| {
|
||||||
|
const record_button = self.ui.button(.text, "Record");
|
||||||
|
record_button.size.y = UI.Size.percent(1, 0);
|
||||||
|
|
||||||
|
if (device_channel.active_task != null) {
|
||||||
|
record_button.setText(.text, "Stop");
|
||||||
|
}
|
||||||
|
|
||||||
|
const signal = self.ui.signalFromBox(record_button);
|
||||||
|
if (signal.clicked()) {
|
||||||
|
if (device_channel.active_task) |task| {
|
||||||
|
try task.stop();
|
||||||
|
device_channel.active_task = null;
|
||||||
|
} else {
|
||||||
|
const channel_name = device_channel.name.buffer[0..device_channel.name.len :0];
|
||||||
|
device_channel.active_task = try self.task_pool.launchAIVoltageChannel(
|
||||||
|
ni_daq,
|
||||||
|
&device_channel.mutex,
|
||||||
|
&device_channel.samples,
|
||||||
|
.{
|
||||||
|
.continous = .{ .sample_rate = device_channel.max_sample_rate }
|
||||||
|
},
|
||||||
|
.{
|
||||||
|
.min_value = channel_view.default_min_value,
|
||||||
|
.max_value = channel_view.default_max_value,
|
||||||
|
.units = device_channel.units,
|
||||||
|
.channel = channel_name
|
||||||
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
|
channel_view.follow = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
const follow_button = self.ui.button(.text, "Follow");
|
||||||
|
follow_button.size.y = UI.Size.percent(1, 0);
|
||||||
|
if (channel_view.follow) {
|
||||||
|
follow_button.setText(.text, "Unfollow");
|
||||||
|
}
|
||||||
|
|
||||||
|
const signal = self.ui.signalFromBox(follow_button);
|
||||||
|
if (signal.clicked()) {
|
||||||
|
channel_view.follow = !channel_view.follow;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// const channel_box = self.ui.newBox(UI.Key.initNil());
|
||||||
|
// channel_box.layout_axis = .Y;
|
||||||
|
// channel_box.size.x = UI.Size.percent(1, 0);
|
||||||
|
// channel_box.size.y = UI.Size.childrenSum(1);
|
||||||
|
// self.ui.pushParent(channel_box);
|
||||||
|
// defer self.ui.popParent();
|
||||||
|
|
||||||
|
var y_axis_markers: *UI.Box = undefined;
|
||||||
|
var x_axis_markers: *UI.Box = undefined;
|
||||||
|
|
||||||
|
{
|
||||||
|
const y_axis_container = self.ui.newBox(UI.Key.initNil());
|
||||||
|
y_axis_container.layout_axis = .X;
|
||||||
|
y_axis_container.size.x = UI.Size.percent(1, 0);
|
||||||
|
y_axis_container.size.y = UI.Size.percent(1, 0);
|
||||||
|
self.ui.pushParent(y_axis_container);
|
||||||
|
defer self.ui.popParent();
|
||||||
|
|
||||||
|
y_axis_markers = self.ui.newBoxFromString("Y axis markers");
|
||||||
|
y_axis_markers.background = rl.Color.blue;
|
||||||
|
y_axis_markers.size.x = UI.Size.pixels(64, 1);
|
||||||
|
y_axis_markers.size.y = UI.Size.percent(1, 0);
|
||||||
|
|
||||||
|
try self.showChannelViewGraph(channel_view);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
{
|
||||||
|
const horizontal_container = self.ui.newBox(UI.Key.initNil());
|
||||||
|
horizontal_container.layout_axis = .X;
|
||||||
|
horizontal_container.size.x = UI.Size.childrenSum(0);
|
||||||
|
horizontal_container.size.y = UI.Size.childrenSum(1);
|
||||||
|
self.ui.pushParent(horizontal_container);
|
||||||
|
defer self.ui.popParent();
|
||||||
|
|
||||||
|
const fullscreen_button = self.ui.newBoxFromString("Fullscreen");
|
||||||
|
fullscreen_button.background = rl.Color.red;
|
||||||
|
fullscreen_button.size.x = UI.Size.pixels(y_axis_markers.computedRect().width, 1);
|
||||||
|
fullscreen_button.size.y = UI.Size.pixels(32, 1);
|
||||||
|
|
||||||
|
x_axis_markers = self.ui.newBoxFromString("X axis markers");
|
||||||
|
x_axis_markers.background = rl.Color.pink;
|
||||||
|
x_axis_markers.size.x = UI.Size.percent(1, 0);
|
||||||
|
x_axis_markers.size.y = UI.Size.pixels(32, 1);
|
||||||
|
self.ui.pushParent(x_axis_markers);
|
||||||
|
defer self.ui.popParent();
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
self.ui.pushParent(y_axis_markers);
|
||||||
|
defer self.ui.popParent();
|
||||||
|
|
||||||
|
const y_axis_rect = y_axis_markers.computedRect();
|
||||||
|
|
||||||
|
const min_gap_between_markers = 8;
|
||||||
|
|
||||||
|
const y_range = channel_rect_opts.max_value - channel_rect_opts.min_value;
|
||||||
|
|
||||||
|
var axis_marker_size = min_gap_between_markers / y_axis_rect.height * y_range;
|
||||||
|
axis_marker_size = @ceil(axis_marker_size);
|
||||||
|
|
||||||
|
var marker = utils.roundNearestUp(f64, @max(channel_rect_opts.min_value, channel_view.default_min_value), axis_marker_size);
|
||||||
|
while (marker < @min(channel_rect_opts.max_value, channel_view.default_max_value)) : (marker += axis_marker_size) {
|
||||||
|
const marker_box = self.ui.newBox(UI.Key.initNil());
|
||||||
|
marker_box.background = rl.Color.yellow;
|
||||||
|
marker_box.setFixedRect(.{
|
||||||
|
.width = y_axis_rect.width/5,
|
||||||
|
.height = 1,
|
||||||
|
.x = y_axis_rect.x + y_axis_rect.width/5*4,
|
||||||
|
.y = @floatCast(remap(
|
||||||
|
f64,
|
||||||
|
channel_rect_opts.max_value, channel_rect_opts.min_value,
|
||||||
|
y_axis_rect.y, y_axis_rect.y + y_axis_rect.height,
|
||||||
|
marker
|
||||||
|
))
|
||||||
|
});
|
||||||
|
|
||||||
|
const label_box = self.ui.newBox(UI.Key.initNil());
|
||||||
|
label_box.setFmtText(.text, "{d:.03}", .{marker});
|
||||||
|
label_box.size.x = UI.Size.text(0, 1);
|
||||||
|
label_box.size.y = UI.Size.text(0, 1);
|
||||||
|
label_box.flags.insert(.text_left_align);
|
||||||
|
label_box.setFixedRect(.{
|
||||||
|
.width = y_axis_rect.width,
|
||||||
|
.height = 1,
|
||||||
|
.x = y_axis_rect.x,
|
||||||
|
.y = @floatCast(remap(
|
||||||
|
f64,
|
||||||
|
channel_rect_opts.max_value, channel_rect_opts.min_value,
|
||||||
|
y_axis_rect.y, y_axis_rect.y + y_axis_rect.height,
|
||||||
|
marker
|
||||||
|
))
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
self.ui.pushParent(x_axis_markers);
|
||||||
|
defer self.ui.popParent();
|
||||||
|
|
||||||
|
const y_axis_rect = x_axis_markers.computedRect();
|
||||||
|
|
||||||
|
const axis_marker_size = 100000;
|
||||||
|
|
||||||
|
var marker = utils.roundNearestUp(f64, @max(channel_rect_opts.from, channel_view.default_from), axis_marker_size);
|
||||||
|
while (marker < @min(channel_rect_opts.to, channel_view.default_to)) : (marker += axis_marker_size) {
|
||||||
|
const marker_box = self.ui.newBox(UI.Key.initNil());
|
||||||
|
marker_box.background = rl.Color.yellow;
|
||||||
|
marker_box.setFixedRect(.{
|
||||||
|
.width = 1,
|
||||||
|
.height = y_axis_rect.height/2,
|
||||||
|
.x = @floatCast(remap(
|
||||||
|
f64,
|
||||||
|
channel_rect_opts.from, channel_rect_opts.to,
|
||||||
|
y_axis_rect.x, y_axis_rect.x + y_axis_rect.width,
|
||||||
|
marker
|
||||||
|
)),
|
||||||
|
.y = y_axis_rect.y,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn showChannelsWindow(self: *App) !void {
|
fn showChannelsWindow(self: *App) !void {
|
||||||
|
@ -158,7 +158,7 @@ pub fn main() !void {
|
|||||||
if (builtin.mode == .Debug) {
|
if (builtin.mode == .Debug) {
|
||||||
// try app.appendChannelFromDevice("Dev1/ai0");
|
// try app.appendChannelFromDevice("Dev1/ai0");
|
||||||
try app.appendChannelFromFile("samples/HeLa Cx37_ 40nM GFX + 35uM Propofol_18-Sep-2024_0003_I.bin");
|
try app.appendChannelFromFile("samples/HeLa Cx37_ 40nM GFX + 35uM Propofol_18-Sep-2024_0003_I.bin");
|
||||||
try app.appendChannelFromFile("samples/HeLa Cx37_ 40nM GFX + 35uM Propofol_18-Sep-2024_0003_IjStim.bin");
|
// try app.appendChannelFromFile("samples/HeLa Cx37_ 40nM GFX + 35uM Propofol_18-Sep-2024_0003_IjStim.bin");
|
||||||
// try app.appendChannelFromFile("samples/HeLa Cx37_ 40nM GFX + 35uM Propofol_18-Sep-2024_0003_IjStim.bin");
|
// try app.appendChannelFromFile("samples/HeLa Cx37_ 40nM GFX + 35uM Propofol_18-Sep-2024_0003_IjStim.bin");
|
||||||
// try app.appendChannelFromFile("samples/HeLa Cx37_ 40nM GFX + 35uM Propofol_18-Sep-2024_0003_IjStim.bin");
|
// try app.appendChannelFromFile("samples/HeLa Cx37_ 40nM GFX + 35uM Propofol_18-Sep-2024_0003_IjStim.bin");
|
||||||
}
|
}
|
||||||
|
23
src/ui.zig
23
src/ui.zig
@ -16,7 +16,7 @@ const clamp = std.math.clamp;
|
|||||||
const UI = @This();
|
const UI = @This();
|
||||||
|
|
||||||
const debug = false;
|
const debug = false;
|
||||||
const max_boxes = 512;
|
const max_boxes = 5120;
|
||||||
const max_events = 256;
|
const max_events = 256;
|
||||||
|
|
||||||
const RectFormatted = struct {
|
const RectFormatted = struct {
|
||||||
@ -176,15 +176,19 @@ pub const Event = union(enum) {
|
|||||||
pub const Signal = struct {
|
pub const Signal = struct {
|
||||||
pub const Flag = enum {
|
pub const Flag = enum {
|
||||||
left_pressed,
|
left_pressed,
|
||||||
|
middle_pressed,
|
||||||
right_pressed,
|
right_pressed,
|
||||||
|
|
||||||
left_released,
|
left_released,
|
||||||
|
middle_released,
|
||||||
right_released,
|
right_released,
|
||||||
|
|
||||||
left_clicked,
|
left_clicked,
|
||||||
|
middle_clicked,
|
||||||
right_clicked,
|
right_clicked,
|
||||||
|
|
||||||
left_dragging,
|
left_dragging,
|
||||||
|
middle_dragging,
|
||||||
right_dragging,
|
right_dragging,
|
||||||
|
|
||||||
scrolled
|
scrolled
|
||||||
@ -199,11 +203,11 @@ pub const Signal = struct {
|
|||||||
shift_modifier: bool = false,
|
shift_modifier: bool = false,
|
||||||
|
|
||||||
pub fn clicked(self: Signal) bool {
|
pub fn clicked(self: Signal) bool {
|
||||||
return self.flags.contains(.left_clicked) or self.flags.contains(.right_clicked);
|
return self.flags.contains(.left_clicked) or self.flags.contains(.right_clicked) or self.flags.contains(.middle_clicked);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn dragged(self: Signal) bool {
|
pub fn dragged(self: Signal) bool {
|
||||||
return self.flags.contains(.left_dragging) or self.flags.contains(.right_dragging);
|
return self.flags.contains(.left_dragging) or self.flags.contains(.right_dragging) or self.flags.contains(.middle_dragging);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn scrolled(self: Signal) bool {
|
pub fn scrolled(self: Signal) bool {
|
||||||
@ -215,6 +219,8 @@ pub const Signal = struct {
|
|||||||
self.flags.insert(.left_pressed);
|
self.flags.insert(.left_pressed);
|
||||||
} else if (mouse_button == .mouse_button_right) {
|
} else if (mouse_button == .mouse_button_right) {
|
||||||
self.flags.insert(.right_pressed);
|
self.flags.insert(.right_pressed);
|
||||||
|
} else if (mouse_button == .mouse_button_middle) {
|
||||||
|
self.flags.insert(.middle_pressed);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -223,6 +229,8 @@ pub const Signal = struct {
|
|||||||
self.flags.insert(.left_released);
|
self.flags.insert(.left_released);
|
||||||
} else if (mouse_button == .mouse_button_right) {
|
} else if (mouse_button == .mouse_button_right) {
|
||||||
self.flags.insert(.right_released);
|
self.flags.insert(.right_released);
|
||||||
|
} else if (mouse_button == .mouse_button_middle) {
|
||||||
|
self.flags.insert(.middle_released);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -231,6 +239,8 @@ pub const Signal = struct {
|
|||||||
self.flags.insert(.left_clicked);
|
self.flags.insert(.left_clicked);
|
||||||
} else if (mouse_button == .mouse_button_right) {
|
} else if (mouse_button == .mouse_button_right) {
|
||||||
self.flags.insert(.right_clicked);
|
self.flags.insert(.right_clicked);
|
||||||
|
} else if (mouse_button == .mouse_button_middle) {
|
||||||
|
self.flags.insert(.middle_clicked);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -239,6 +249,8 @@ pub const Signal = struct {
|
|||||||
self.flags.insert(.left_dragging);
|
self.flags.insert(.left_dragging);
|
||||||
} else if (mouse_button == .mouse_button_right) {
|
} else if (mouse_button == .mouse_button_right) {
|
||||||
self.flags.insert(.right_dragging);
|
self.flags.insert(.right_dragging);
|
||||||
|
} else if (mouse_button == .mouse_button_middle) {
|
||||||
|
self.flags.insert(.middle_dragging);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@ -856,8 +868,6 @@ fn drawBox(self: *UI, box: *Box) void {
|
|||||||
text_rect.y += (box_rect.height - text_size.y) / 2;
|
text_rect.y += (box_rect.height - text_size.y) / 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
// text_rect.y += box.persistent.active * text_rect.height*0.1;
|
|
||||||
|
|
||||||
const text_color = utils.shiftColorInHSV(text.color, value_shift);
|
const text_color = utils.shiftColorInHSV(text.color, value_shift);
|
||||||
font.drawText(text.content, .{ .x = text_rect.x, .y = text_rect.y }, text_color);
|
font.drawText(text.content, .{ .x = text_rect.x, .y = text_rect.y }, text_color);
|
||||||
|
|
||||||
@ -1387,7 +1397,8 @@ pub fn signalFromBox(self: *UI, box: *Box) Signal {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (draggable and self.mouse_delta.equals(Vec2.zero()) == 0) {
|
if (draggable and self.mouse_delta.equals(Vec2.zero()) == 0) {
|
||||||
inline for (.{ rl.MouseButton.mouse_button_left, rl.MouseButton.mouse_button_right }) |mouse_button| {
|
const mouse_buttons = [_]rl.MouseButton{ .mouse_button_left, .mouse_button_right, .mouse_button_middle };
|
||||||
|
inline for (mouse_buttons) |mouse_button| {
|
||||||
const active_box = self.active_box_keys.get(mouse_button);
|
const active_box = self.active_box_keys.get(mouse_button);
|
||||||
|
|
||||||
if (active_box != null and active_box.?.eql(key)) {
|
if (active_box != null and active_box.?.eql(key)) {
|
||||||
|
@ -53,3 +53,11 @@ pub fn remap(comptime T: type, from_min: T, from_max: T, to_min: T, to_max: T, v
|
|||||||
const t = (value - from_min) / (from_max - from_min);
|
const t = (value - from_min) / (from_max - from_min);
|
||||||
return std.math.lerp(to_min, to_max, t);
|
return std.math.lerp(to_min, to_max, t);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn roundNearestUp(comptime T: type, value: T, multiple: T) T {
|
||||||
|
return @ceil(value / multiple) * multiple;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn roundNearestDown(comptime T: type, value: T, multiple: T) T {
|
||||||
|
return @floor(value / multiple) * multiple;
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user