Compare commits
8 Commits
6ff9c3050d
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
| 8bea8eeda2 | |||
| 38e37dddc4 | |||
| 61b278ac8f | |||
| de7ca42f7a | |||
| f2190fb781 | |||
| f5236a9148 | |||
| df53fb0d8d | |||
| 6d5aafb78d |
40
README.md
40
README.md
@@ -115,6 +115,46 @@ and finally free the arena with a retained_capacity as the ui will more then lik
|
|||||||
_ = al.reset(.retain_capacity);
|
_ = al.reset(.retain_capacity);
|
||||||
```
|
```
|
||||||
|
|
||||||
|
## react like componets:
|
||||||
|
|
||||||
|
you can also create react like componets by creating functions blocks that return a Node, please note that this function is inlined, this is required as children from this node will be shared between all compoents that use this node.
|
||||||
|
```zig
|
||||||
|
inline fn button() UI.Node {
|
||||||
|
return UI.ElementWborder(
|
||||||
|
.{
|
||||||
|
.bottom = 2,
|
||||||
|
.left = 2,
|
||||||
|
.right = 2,
|
||||||
|
.top = 2,
|
||||||
|
},
|
||||||
|
.{
|
||||||
|
.b = 30,
|
||||||
|
},
|
||||||
|
.{
|
||||||
|
.name = "button",
|
||||||
|
.rect = .{
|
||||||
|
.h = 20,
|
||||||
|
.w = 60,
|
||||||
|
},
|
||||||
|
.on_click = .{
|
||||||
|
.func = &updateButton,
|
||||||
|
.data = &.{},
|
||||||
|
},
|
||||||
|
.on_hover = .{
|
||||||
|
.func = &hoverButton,
|
||||||
|
.data = &.{},
|
||||||
|
},
|
||||||
|
.style = .{
|
||||||
|
.background_colour = .{
|
||||||
|
.g = 255,
|
||||||
|
},
|
||||||
|
.rounded = 25,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
## adding shoots to your project
|
## adding shoots to your project
|
||||||
|
|
||||||
fetch the repo
|
fetch the repo
|
||||||
|
|||||||
9
TODO.md
9
TODO.md
@@ -5,4 +5,11 @@
|
|||||||
- rem
|
- rem
|
||||||
- percentage
|
- percentage
|
||||||
- [ ] allow text rendering to support new lines
|
- [ ] allow text rendering to support new lines
|
||||||
- [ ] possibly allow a more dearimgui approch to rendering
|
- [ ] possibly allow a more dearimgui approch to rendering
|
||||||
|
|
||||||
|
- [x] scrollable Node
|
||||||
|
- [ ] min and max width
|
||||||
|
|
||||||
|
- [ ] add ui logic to allow most of it to be hidden
|
||||||
|
- [ ] add text input fields
|
||||||
|
- [ ] fix text rendering
|
||||||
BIN
examples/raylib-example/res/image.png
Normal file
BIN
examples/raylib-example/res/image.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 233 KiB |
@@ -1,6 +1,6 @@
|
|||||||
const std = @import("std");
|
const std = @import("std");
|
||||||
const rl = @import("rl");
|
const rl = @import("rl");
|
||||||
const shoots = @import("shoots");
|
const shoots = @import("root.zig");
|
||||||
|
|
||||||
fn getTextWidth(string: []const u8, font: rl.Font) shoots.Real {
|
fn getTextWidth(string: []const u8, font: rl.Font) shoots.Real {
|
||||||
var width: c_int = 0;
|
var width: c_int = 0;
|
||||||
@@ -109,12 +109,16 @@ pub fn main() anyerror!void {
|
|||||||
rl.initWindow(screenWidth, screenHeight, "raylib-zig [core] example - basic window");
|
rl.initWindow(screenWidth, screenHeight, "raylib-zig [core] example - basic window");
|
||||||
defer rl.closeWindow(); // Close window and OpenGL context
|
defer rl.closeWindow(); // Close window and OpenGL context
|
||||||
|
|
||||||
|
const image = try rl.loadImage("res/image.png");
|
||||||
|
const image_texture = try rl.Texture.fromImage(image);
|
||||||
rl.setTargetFPS(60); // Set our game to run at 60 frames-per-second
|
rl.setTargetFPS(60); // Set our game to run at 60 frames-per-second
|
||||||
//--------------------------------------------------------------------------------------
|
//--------------------------------------------------------------------------------------
|
||||||
|
|
||||||
std.debug.print("shoots version :{s}\n", .{shoots.VERSION});
|
std.debug.print("shoots version :{s}\n", .{shoots.VERSION});
|
||||||
std.debug.print("raylib time : {}\n", .{@divTrunc(timer.lap(), std.time.ns_per_ms)});
|
std.debug.print("raylib time : {}\n", .{@divTrunc(timer.lap(), std.time.ns_per_ms)});
|
||||||
|
|
||||||
|
var scroll_offset: shoots.Pos = .{};
|
||||||
|
|
||||||
const child = &[_]UI.Node{
|
const child = &[_]UI.Node{
|
||||||
sideBar(),
|
sideBar(),
|
||||||
button(),
|
button(),
|
||||||
@@ -321,10 +325,41 @@ pub fn main() anyerror!void {
|
|||||||
}),
|
}),
|
||||||
},
|
},
|
||||||
}),
|
}),
|
||||||
button(),
|
|
||||||
button(),
|
UI.Element(.{
|
||||||
|
.name = "scrollable",
|
||||||
|
.scrollable = .{
|
||||||
|
.dir = .y,
|
||||||
|
.offset = &scroll_offset,
|
||||||
|
},
|
||||||
|
.rect = .{ .h = 250 },
|
||||||
|
.children = &[_]UI.Node{
|
||||||
|
UI.Element(
|
||||||
|
.{
|
||||||
|
.style = .{
|
||||||
|
.background_colour = .{
|
||||||
|
.r = 255,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
.children = &[_]UI.Node{
|
||||||
|
UI.Image(.{
|
||||||
|
.texture = image_texture,
|
||||||
|
.rect = .{
|
||||||
|
.h = @floatFromInt(image_texture.height),
|
||||||
|
.w = @floatFromInt(image_texture.width),
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
button(),
|
||||||
|
button(),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
),
|
||||||
|
},
|
||||||
|
}),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// root.Shoots(root.TextType(raylib.Font,(function 'getTextWidth'),(function 'getTextheight')),root.TextureType(raylib.Texture)).NodeTypes
|
||||||
|
// root.Shoots(root.TextType(raylib.Font,(function 'getTextWidth'),(function 'getTextheight')),root.TextureType(raylib.Texture)).Node
|
||||||
const root = UI.Element(.{
|
const root = UI.Element(.{
|
||||||
.name = "root",
|
.name = "root",
|
||||||
.pos = .{
|
.pos = .{
|
||||||
@@ -380,15 +415,21 @@ pub fn main() anyerror!void {
|
|||||||
.left = rl.isMouseButtonDown(.left),
|
.left = rl.isMouseButtonDown(.left),
|
||||||
.middle = rl.isMouseButtonDown(.middle),
|
.middle = rl.isMouseButtonDown(.middle),
|
||||||
.right = rl.isMouseButtonDown(.right),
|
.right = rl.isMouseButtonDown(.right),
|
||||||
|
.scroll_delta = .{
|
||||||
|
.y = rl.getMouseWheelMoveV().y,
|
||||||
|
.x = rl.getMouseWheelMoveV().x,
|
||||||
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
const commands = try UI.getRenderCommands(sized, al.allocator());
|
const commands = try UI.getRenderCommands(sized, al.allocator());
|
||||||
// std.debug.print("layout time : {}ms\n", .{
|
// std.debug.print("{f}\n", .{sized});
|
||||||
// @as(f32, @floatFromInt(timer.lap())) / @as(f32, @floatFromInt(std.time.ns_per_ms)),
|
std.debug.print("layout time : {}ms\n", .{
|
||||||
// });
|
@as(f32, @floatFromInt(timer.lap())) / @as(f32, @floatFromInt(std.time.ns_per_ms)),
|
||||||
|
});
|
||||||
|
|
||||||
for (commands.items) |command| {
|
for (commands.items) |command| {
|
||||||
// std.debug.print("command : {any}\n", .{command});
|
// std.debug.print("command : {any}\n", .{command});
|
||||||
|
rl.clearBackground(.white);
|
||||||
switch (command) {
|
switch (command) {
|
||||||
.rect => |r| {
|
.rect => |r| {
|
||||||
if (r.rounding) |rounding| {
|
if (r.rounding) |rounding| {
|
||||||
@@ -424,18 +465,51 @@ pub fn main() anyerror!void {
|
|||||||
},
|
},
|
||||||
.text => |t| {
|
.text => |t| {
|
||||||
const string = @as([:0]const u8, @ptrCast(t.text.string));
|
const string = @as([:0]const u8, @ptrCast(t.text.string));
|
||||||
rl.drawText(string, @as(i32, @intFromFloat(t.pos.x)), @as(i32, @intFromFloat(t.pos.y)), @as(i32, @intFromFloat(t.text.getTextHeight())), rl.Color.init(
|
rl.drawText(
|
||||||
t.text.colour.r,
|
string,
|
||||||
t.text.colour.g,
|
@as(i32, @intFromFloat(t.pos.x)),
|
||||||
t.text.colour.b,
|
@as(i32, @intFromFloat(t.pos.y)),
|
||||||
t.text.colour.a,
|
@as(i32, @intFromFloat(t.text.getTextHeight())),
|
||||||
));
|
rl.Color.init(
|
||||||
|
t.text.colour.r,
|
||||||
|
t.text.colour.g,
|
||||||
|
t.text.colour.b,
|
||||||
|
t.text.colour.a,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
.texture => |tex| {
|
||||||
|
// std.debug.print("{}\n", .{tex.texture.texture});
|
||||||
|
// std.debug.print("texture {}\n", .{tex});
|
||||||
|
rl.drawTexture(
|
||||||
|
tex.texture.texture,
|
||||||
|
@as(i32, @intFromFloat(tex.pos.x)),
|
||||||
|
@as(i32, @intFromFloat(tex.pos.y)),
|
||||||
|
.white,
|
||||||
|
);
|
||||||
|
},
|
||||||
|
.clip_start => |clip| {
|
||||||
|
// std.debug.print("clip {}\n", .{clip});
|
||||||
|
rl.beginScissorMode(
|
||||||
|
@as(i32, @intFromFloat(clip.pos.x)),
|
||||||
|
@as(i32, @intFromFloat(clip.pos.y)),
|
||||||
|
@as(i32, @intFromFloat(clip.rect.w)),
|
||||||
|
@as(i32, @intFromFloat(clip.rect.h)),
|
||||||
|
);
|
||||||
|
|
||||||
|
// rl.drawRectangleRec(rl.Rectangle.init(
|
||||||
|
// clip.pos.x,
|
||||||
|
// clip.pos.y,
|
||||||
|
// clip.rect.w,
|
||||||
|
// clip.rect.h,
|
||||||
|
// ), .blue);
|
||||||
|
},
|
||||||
|
.clip_end => |_| {
|
||||||
|
rl.endScissorMode();
|
||||||
},
|
},
|
||||||
.texture => continue,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
rl.clearBackground(.white);
|
|
||||||
_ = al.reset(.retain_capacity);
|
_ = al.reset(.retain_capacity);
|
||||||
// rl.drawRectangle(0, 0, 200, 100, .blue);
|
// rl.drawRectangle(0, 0, 200, 100, .blue);
|
||||||
|
|
||||||
|
|||||||
192
src/root.zig
192
src/root.zig
@@ -176,11 +176,23 @@ pub const Colour = struct {
|
|||||||
a: u8 = 255,
|
a: u8 = 255,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
pub const Scrollable = struct {
|
||||||
|
offset: *Pos,
|
||||||
|
child_size: Rect = .{},
|
||||||
|
scroll_amount: f32 = 10.0,
|
||||||
|
dir: enum {
|
||||||
|
x,
|
||||||
|
y,
|
||||||
|
// both,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
pub const MouseState = struct {
|
pub const MouseState = struct {
|
||||||
pos: Pos,
|
pos: Pos,
|
||||||
left: bool,
|
left: bool,
|
||||||
right: bool,
|
right: bool,
|
||||||
middle: bool,
|
middle: bool,
|
||||||
|
scroll_delta: Pos,
|
||||||
};
|
};
|
||||||
|
|
||||||
pub fn pointinRect(point: Pos, rect_pos: Pos, rect: Rect) bool {
|
pub fn pointinRect(point: Pos, rect_pos: Pos, rect: Rect) bool {
|
||||||
@@ -228,6 +240,11 @@ pub fn Shoots(
|
|||||||
try printWithLevel(writer, level + 1, "pos : {any},\n", .{node.element.pos});
|
try printWithLevel(writer, level + 1, "pos : {any},\n", .{node.element.pos});
|
||||||
try printWithLevel(writer, level + 1, "on_click : {?},\n", .{node.element.on_click});
|
try printWithLevel(writer, level + 1, "on_click : {?},\n", .{node.element.on_click});
|
||||||
try printWithLevel(writer, level + 1, "rect : {any},\n", .{node.element.rect});
|
try printWithLevel(writer, level + 1, "rect : {any},\n", .{node.element.rect});
|
||||||
|
try printWithLevel(writer, level + 1, "on_click : {any},\n", .{node.element.on_click});
|
||||||
|
try printWithLevel(writer, level + 1, "allow_on_click_when_occluded : {any},\n", .{node.element.allow_on_click_when_occluded});
|
||||||
|
try printWithLevel(writer, level + 1, "on_hover : {any},\n", .{node.element.on_hover});
|
||||||
|
try printWithLevel(writer, level + 1, "allow_on_hover_when_occluded : {any},\n", .{node.element.allow_on_hover_when_occluded});
|
||||||
|
try printWithLevel(writer, level + 1, "scrollable : {?},\n", .{node.element.scrollable});
|
||||||
try printWithLevel(writer, level + 1, "style : .{{\n", .{});
|
try printWithLevel(writer, level + 1, "style : .{{\n", .{});
|
||||||
try node.element.style.printStyle(writer, level + 1);
|
try node.element.style.printStyle(writer, level + 1);
|
||||||
try printWithLevel(writer, level + 1, "children : {{\n", .{});
|
try printWithLevel(writer, level + 1, "children : {{\n", .{});
|
||||||
@@ -272,6 +289,8 @@ pub fn Shoots(
|
|||||||
// the on hover call back will be ran
|
// the on hover call back will be ran
|
||||||
allow_on_hover_when_occluded: bool = true,
|
allow_on_hover_when_occluded: bool = true,
|
||||||
allow_on_click_when_occluded: bool = false,
|
allow_on_click_when_occluded: bool = false,
|
||||||
|
|
||||||
|
scrollable: ?Scrollable = null,
|
||||||
};
|
};
|
||||||
|
|
||||||
pub const Interact = struct {
|
pub const Interact = struct {
|
||||||
@@ -284,6 +303,8 @@ pub fn Shoots(
|
|||||||
rect,
|
rect,
|
||||||
text,
|
text,
|
||||||
texture,
|
texture,
|
||||||
|
clip_start,
|
||||||
|
clip_end,
|
||||||
};
|
};
|
||||||
|
|
||||||
pub const RenderCommand = union(RenderCommandType) {
|
pub const RenderCommand = union(RenderCommandType) {
|
||||||
@@ -301,20 +322,21 @@ pub fn Shoots(
|
|||||||
},
|
},
|
||||||
texture: struct {
|
texture: struct {
|
||||||
texture: Texture,
|
texture: Texture,
|
||||||
|
z_index: usize = 0,
|
||||||
|
pos: Pos,
|
||||||
|
},
|
||||||
|
clip_start: struct {
|
||||||
pos: Pos,
|
pos: Pos,
|
||||||
z_index: usize = 0,
|
z_index: usize = 0,
|
||||||
|
rect: Rect,
|
||||||
|
// might allow rounded rectangles for clipping,
|
||||||
|
// hover this would require the user to implement a
|
||||||
|
// stencil buffer and that would be annoying
|
||||||
|
// rounding: ?Real,
|
||||||
},
|
},
|
||||||
|
clip_end: struct {},
|
||||||
};
|
};
|
||||||
|
|
||||||
// focused: *Node,
|
|
||||||
|
|
||||||
// /// highly suggested that you use an area for the alloc
|
|
||||||
// pub fn init() Self {
|
|
||||||
// return Self{
|
|
||||||
// .alloc = alloc,
|
|
||||||
// };
|
|
||||||
// }
|
|
||||||
|
|
||||||
pub inline fn ElementWborder(
|
pub inline fn ElementWborder(
|
||||||
boarder_width: Padding,
|
boarder_width: Padding,
|
||||||
boarder_colour: Colour,
|
boarder_colour: Colour,
|
||||||
@@ -358,6 +380,16 @@ pub fn Shoots(
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub inline fn Image(texture: Texture) Node {
|
||||||
|
return Element(
|
||||||
|
.{
|
||||||
|
.children = &[_]Node{.{
|
||||||
|
.texture = texture,
|
||||||
|
}},
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
pub fn closeElement(node: *Node, parent: *Node) void {
|
pub fn closeElement(node: *Node, parent: *Node) void {
|
||||||
switch (node.*) {
|
switch (node.*) {
|
||||||
.element => {
|
.element => {
|
||||||
@@ -392,10 +424,50 @@ pub fn Shoots(
|
|||||||
parent.element.rect.w += node.text.getTextWidth();
|
parent.element.rect.w += node.text.getTextWidth();
|
||||||
// std.debug.print("parent.element.rect.w : {}\n", .{parent.element.rect.w});
|
// std.debug.print("parent.element.rect.w : {}\n", .{parent.element.rect.w});
|
||||||
},
|
},
|
||||||
.texture => return,
|
.texture => {
|
||||||
|
parent.element.rect.h += node.texture.rect.h;
|
||||||
|
parent.element.rect.w += node.texture.rect.w;
|
||||||
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn computeSizes(node: *Node, parent: *Node) void {
|
||||||
|
switch (node.*) {
|
||||||
|
.element => {
|
||||||
|
// std.debug.print("before {s} {}\n", .{ node.element.name, node.element.rect });
|
||||||
|
// std.debug.print("parent name : {s}\n", .{parent.element.name});
|
||||||
|
|
||||||
|
const size = node.element.rect;
|
||||||
|
|
||||||
|
for (node.element.children, 0..) |_, i| {
|
||||||
|
computeSizes(@constCast(&node.element.children[i]), node);
|
||||||
|
}
|
||||||
|
|
||||||
|
// cheaters way to beat the fence post problem
|
||||||
|
// TODO fix this
|
||||||
|
switch (node.element.style.layout) {
|
||||||
|
.right_to_left => node.element.rect.w -= node.element.style.child_gap,
|
||||||
|
.top_to_bottom => node.element.rect.h -= node.element.style.child_gap,
|
||||||
|
}
|
||||||
|
if (node.element.scrollable) |scroll| {
|
||||||
|
// have to remove the parents size
|
||||||
|
node.element.scrollable.?.child_size = node.element.rect;
|
||||||
|
node.element.scrollable.?.child_size.w -= size.w;
|
||||||
|
node.element.scrollable.?.child_size.h -= size.h;
|
||||||
|
|
||||||
|
switch (scroll.dir) {
|
||||||
|
// .both => node.element.rect = size, // retain size
|
||||||
|
.x => node.element.rect.w = size.w, // scroll in the x then the hieght stays the same
|
||||||
|
.y => node.element.rect.h = size.h, // scroll in the y then the width stays the same
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// std.debug.print("after {s} {}\n", .{ node.element.name, node.element.rect });
|
||||||
|
},
|
||||||
|
else => {},
|
||||||
|
}
|
||||||
|
closeElement(node, parent);
|
||||||
|
}
|
||||||
|
|
||||||
fn deepCloneHelper(node: Node, node_location: *Node, alloc: std.mem.Allocator) !void {
|
fn deepCloneHelper(node: Node, node_location: *Node, alloc: std.mem.Allocator) !void {
|
||||||
// std.debug.print("nodeloc : {}\n", .{node_location});
|
// std.debug.print("nodeloc : {}\n", .{node_location});
|
||||||
node_location.* = node;
|
node_location.* = node;
|
||||||
@@ -441,15 +513,26 @@ pub fn Shoots(
|
|||||||
switch (node) {
|
switch (node) {
|
||||||
.element => {
|
.element => {
|
||||||
// std.debug.print("parent name : {s}\n", .{parent.element.name});
|
// std.debug.print("parent name : {s}\n", .{parent.element.name});
|
||||||
try command_list.append(alloc, .{
|
|
||||||
.rect = .{
|
if (node.element.scrollable) |_| {
|
||||||
.colour = node.element.style.background_colour,
|
try command_list.append(alloc, .{
|
||||||
.pos = node.element.pos,
|
.clip_start = .{
|
||||||
.rect = node.element.rect,
|
.rect = node.element.rect,
|
||||||
.rounding = node.element.style.rounded,
|
.z_index = node.element.z_index,
|
||||||
.z_index = node.element.z_index,
|
.pos = node.element.pos,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
} else {
|
||||||
|
try command_list.append(alloc, .{
|
||||||
|
.rect = .{
|
||||||
|
.colour = node.element.style.background_colour,
|
||||||
|
.pos = node.element.pos,
|
||||||
|
.rect = node.element.rect,
|
||||||
|
.rounding = node.element.style.rounded,
|
||||||
|
.z_index = node.element.z_index,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
for (node.element.children, 0..) |_, i| {
|
for (node.element.children, 0..) |_, i| {
|
||||||
switch (node.element.children[i]) {
|
switch (node.element.children[i]) {
|
||||||
@@ -459,13 +542,21 @@ pub fn Shoots(
|
|||||||
.text = text,
|
.text = text,
|
||||||
.z_index = node.element.z_index,
|
.z_index = node.element.z_index,
|
||||||
} }),
|
} }),
|
||||||
.texture => |texture| try command_list.append(alloc, .{ .texture = .{
|
.texture => |texture| try command_list.append(alloc, .{
|
||||||
.pos = node.element.pos,
|
.texture = .{
|
||||||
.texture = texture,
|
.pos = node.element.pos,
|
||||||
.z_index = node.element.z_index,
|
.texture = texture,
|
||||||
} }),
|
.z_index = node.element.z_index,
|
||||||
|
},
|
||||||
|
}),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (node.element.scrollable) |_| {
|
||||||
|
try command_list.append(alloc, .{
|
||||||
|
.clip_end = .{},
|
||||||
|
});
|
||||||
|
}
|
||||||
},
|
},
|
||||||
else => return, // the commands get created above, since the text and texture need a pos
|
else => return, // the commands get created above, since the text and texture need a pos
|
||||||
// but they dont have the pos one the parent has it
|
// but they dont have the pos one the parent has it
|
||||||
@@ -478,27 +569,6 @@ pub fn Shoots(
|
|||||||
return render_commands;
|
return render_commands;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn computeSizes(node: *Node, parent: *Node) void {
|
|
||||||
switch (node.*) {
|
|
||||||
.element => {
|
|
||||||
// std.debug.print("parent name : {s}\n", .{parent.element.name});
|
|
||||||
|
|
||||||
for (node.element.children, 0..) |_, i| {
|
|
||||||
computeSizes(@constCast(&node.element.children[i]), node);
|
|
||||||
}
|
|
||||||
|
|
||||||
// cheaters way to beat the fence post problem
|
|
||||||
// TODO fix this
|
|
||||||
switch (node.element.style.layout) {
|
|
||||||
.right_to_left => node.element.rect.w -= node.element.style.child_gap,
|
|
||||||
.top_to_bottom => node.element.rect.h -= node.element.style.child_gap,
|
|
||||||
}
|
|
||||||
},
|
|
||||||
else => {},
|
|
||||||
}
|
|
||||||
closeElement(node, parent);
|
|
||||||
}
|
|
||||||
|
|
||||||
fn filterGrowableChildren(index: *usize, node: Node) ?*Ele {
|
fn filterGrowableChildren(index: *usize, node: Node) ?*Ele {
|
||||||
switch (node) {
|
switch (node) {
|
||||||
.element => {
|
.element => {
|
||||||
@@ -724,6 +794,14 @@ pub fn Shoots(
|
|||||||
fn computeChildernsPostions(ele: *Ele) void {
|
fn computeChildernsPostions(ele: *Ele) void {
|
||||||
const layout_style = ele.style.layout;
|
const layout_style = ele.style.layout;
|
||||||
var children = @constCast(ele.children);
|
var children = @constCast(ele.children);
|
||||||
|
const scroll_offset: Pos = blk: {
|
||||||
|
if (ele.scrollable) |scroll| {
|
||||||
|
const scroll_offset = scroll.offset.*;
|
||||||
|
break :blk scroll_offset;
|
||||||
|
}
|
||||||
|
|
||||||
|
break :blk .{};
|
||||||
|
};
|
||||||
|
|
||||||
switch (layout_style) {
|
switch (layout_style) {
|
||||||
.right_to_left => {
|
.right_to_left => {
|
||||||
@@ -733,8 +811,8 @@ pub fn Shoots(
|
|||||||
switch (ele.children[i]) {
|
switch (ele.children[i]) {
|
||||||
.element => {
|
.element => {
|
||||||
// off set it by the parent
|
// off set it by the parent
|
||||||
children[i].element.pos.x += ele.pos.x + ele.style.padding.left + off_set_left;
|
children[i].element.pos.x += ele.pos.x + ele.style.padding.left + off_set_left - scroll_offset.x;
|
||||||
children[i].element.pos.y += ele.pos.y + ele.style.padding.top;
|
children[i].element.pos.y += ele.pos.y + ele.style.padding.top - scroll_offset.y;
|
||||||
off_set_left += children[i].element.rect.w + child_gap;
|
off_set_left += children[i].element.rect.w + child_gap;
|
||||||
// add
|
// add
|
||||||
},
|
},
|
||||||
@@ -749,8 +827,8 @@ pub fn Shoots(
|
|||||||
switch (ele.children[i]) {
|
switch (ele.children[i]) {
|
||||||
.element => {
|
.element => {
|
||||||
// off set it by the parent
|
// off set it by the parent
|
||||||
children[i].element.pos.x += ele.pos.x + ele.style.padding.left;
|
children[i].element.pos.x += ele.pos.x + ele.style.padding.left - scroll_offset.x;
|
||||||
children[i].element.pos.y += ele.pos.y + ele.style.padding.top + offset_top;
|
children[i].element.pos.y += ele.pos.y + ele.style.padding.top + offset_top - scroll_offset.y;
|
||||||
offset_top += children[i].element.rect.h + child_gap;
|
offset_top += children[i].element.rect.h + child_gap;
|
||||||
// add
|
// add
|
||||||
},
|
},
|
||||||
@@ -809,6 +887,22 @@ pub fn Shoots(
|
|||||||
.element => |e| {
|
.element => |e| {
|
||||||
// std.debug.print("clicked : {} hovered node name : {s}\n", .{ clicked, e.name });
|
// std.debug.print("clicked : {} hovered node name : {s}\n", .{ clicked, e.name });
|
||||||
|
|
||||||
|
// TODO fix when another scrollable contaier occludes the other one
|
||||||
|
if (current_node.element.scrollable) |scroll| {
|
||||||
|
current_node.element.scrollable.?.offset.x += mouse_state.scroll_delta.x * scroll.child_size.w / current_node.element.rect.w;
|
||||||
|
current_node.element.scrollable.?.offset.y += mouse_state.scroll_delta.y * scroll.child_size.h / current_node.element.rect.h;
|
||||||
|
|
||||||
|
// fixes being able to scroll past the min value
|
||||||
|
if (scroll.offset.x < 0) current_node.element.scrollable.?.offset.x = 0;
|
||||||
|
if (scroll.offset.y < 0) current_node.element.scrollable.?.offset.y = 0;
|
||||||
|
|
||||||
|
// fixes being able to scroll past the max value
|
||||||
|
if (scroll.offset.x > scroll.child_size.w - current_node.element.rect.w)
|
||||||
|
current_node.element.scrollable.?.offset.x = scroll.child_size.w - current_node.element.rect.w;
|
||||||
|
if (scroll.offset.y > scroll.child_size.h - current_node.element.rect.h)
|
||||||
|
current_node.element.scrollable.?.offset.y = scroll.child_size.h - current_node.element.rect.h;
|
||||||
|
}
|
||||||
|
|
||||||
if (e.on_hover != null and e.allow_on_hover_when_occluded) {
|
if (e.on_hover != null and e.allow_on_hover_when_occluded) {
|
||||||
needs_redraw |= node.element.on_hover.?.func(&node.element, mouse_state, node.element.on_click.?.data);
|
needs_redraw |= node.element.on_hover.?.func(&node.element, mouse_state, node.element.on_click.?.data);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user