mirror of
https://github.com/PixelGuys/Cubyz.git
synced 2025-08-03 19:28:49 -04:00
Add a ScrollBar to the VerticalList.
This commit is contained in:
parent
ef0f9ebf67
commit
219c3214e9
@ -76,6 +76,7 @@ pub fn updateHovered(self: *TextInput, mousePosition: Vec2f) void {
|
||||
if(self.textSize[1] > self.maxHeight - 2*border) {
|
||||
const diff = self.textSize[1] - (self.maxHeight - 2*border);
|
||||
self.scrollBar.scroll(-main.Window.scrollOffset*32/diff);
|
||||
main.Window.scrollOffset = 0;
|
||||
}
|
||||
if(self.textSize[1] > self.maxHeight - 2*border) {
|
||||
self.scrollBar.pos = Vec2f{self.size[0] - border - scrollBarWidth, border};
|
||||
|
@ -10,19 +10,32 @@ const Vec2f = vec.Vec2f;
|
||||
|
||||
const gui = @import("../gui.zig");
|
||||
const GuiComponent = gui.GuiComponent;
|
||||
const ScrollBar = GuiComponent.ScrollBar;
|
||||
|
||||
const VerticalList = @This();
|
||||
|
||||
const scrollBarWidth = 5;
|
||||
const border: f32 = 3;
|
||||
|
||||
pos: Vec2f,
|
||||
size: Vec2f,
|
||||
children: std.ArrayList(GuiComponent),
|
||||
padding: f32,
|
||||
maxHeight: f32,
|
||||
childrenHeight: f32 = 0,
|
||||
scrollBar: *ScrollBar,
|
||||
scrollBarEnabled: bool = false,
|
||||
|
||||
pub fn init() Allocator.Error!*VerticalList {
|
||||
pub fn init(pos: Vec2f, maxHeight: f32, padding: f32) Allocator.Error!*VerticalList {
|
||||
const scrollBar = try ScrollBar.init(undefined, scrollBarWidth, maxHeight - 2*border, 0);
|
||||
const self = try gui.allocator.create(VerticalList);
|
||||
self.* = VerticalList {
|
||||
.children = std.ArrayList(GuiComponent).init(gui.allocator),
|
||||
.pos = undefined,
|
||||
.pos = pos,
|
||||
.size = .{0, 0},
|
||||
.padding = padding,
|
||||
.maxHeight = maxHeight,
|
||||
.scrollBar = scrollBar,
|
||||
};
|
||||
return self;
|
||||
}
|
||||
@ -31,6 +44,7 @@ pub fn deinit(self: *const VerticalList) void {
|
||||
for(self.children.items) |*child| {
|
||||
child.deinit();
|
||||
}
|
||||
self.scrollBar.deinit();
|
||||
self.children.deinit();
|
||||
gui.allocator.destroy(self);
|
||||
}
|
||||
@ -51,12 +65,12 @@ pub fn add(self: *VerticalList, _other: anytype) Allocator.Error!void {
|
||||
const added = try self.children.addOne();
|
||||
added.* = other;
|
||||
added.mutPos().*[1] += self.size[1];
|
||||
if(self.size[1] != 0) added.mutPos().*[1] += self.padding;
|
||||
self.size[1] = added.pos()[1] + added.size()[1];
|
||||
self.size[0] = @max(self.size[0], added.pos()[0] + added.size()[0]);
|
||||
}
|
||||
|
||||
pub fn finish(self: *VerticalList, pos: Vec2f, alignment: graphics.TextBuffer.Alignment) void {
|
||||
self.pos = pos;
|
||||
pub fn finish(self: *VerticalList, alignment: graphics.TextBuffer.Alignment) void {
|
||||
self.children.shrinkAndFree(self.children.items.len);
|
||||
for(self.children.items) |_child| {
|
||||
const child: GuiComponent = _child;
|
||||
@ -72,6 +86,13 @@ pub fn finish(self: *VerticalList, pos: Vec2f, alignment: graphics.TextBuffer.Al
|
||||
},
|
||||
}
|
||||
}
|
||||
if(self.size[1] > self.maxHeight) {
|
||||
self.scrollBarEnabled = true;
|
||||
self.childrenHeight = self.size[1];
|
||||
self.size[1] = self.maxHeight;
|
||||
self.scrollBar.pos = .{self.size[0] + border, border};
|
||||
self.size[0] += 2*border + scrollBarWidth;
|
||||
}
|
||||
}
|
||||
|
||||
pub fn updateSelected(self: *VerticalList) void {
|
||||
@ -81,39 +102,77 @@ pub fn updateSelected(self: *VerticalList) void {
|
||||
}
|
||||
|
||||
pub fn updateHovered(self: *VerticalList, mousePosition: Vec2f) void {
|
||||
var shiftedPos = self.pos;
|
||||
if(self.scrollBarEnabled) {
|
||||
const diff = self.childrenHeight - self.maxHeight;
|
||||
shiftedPos[1] -= diff*self.scrollBar.currentState;
|
||||
}
|
||||
var i: usize = self.children.items.len;
|
||||
while(i != 0) {
|
||||
i -= 1;
|
||||
const child = &self.children.items[i];
|
||||
if(GuiComponent.contains(child.pos() + self.pos, child.size(), mousePosition)) {
|
||||
child.updateHovered(mousePosition - self.pos);
|
||||
if(GuiComponent.contains(child.pos() + shiftedPos, child.size(), mousePosition)) {
|
||||
child.updateHovered(mousePosition - shiftedPos);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(self.scrollBarEnabled) {
|
||||
const diff = self.childrenHeight - self.maxHeight;
|
||||
self.scrollBar.scroll(-main.Window.scrollOffset*32/diff);
|
||||
main.Window.scrollOffset = 0;
|
||||
if(GuiComponent.contains(self.scrollBar.pos, self.scrollBar.size, mousePosition - self.pos)) {
|
||||
self.scrollBar.updateHovered(mousePosition - self.pos);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn render(self: *VerticalList, mousePosition: Vec2f) anyerror!void { // TODO: Remove anyerror once error union inference works in recursive loops.
|
||||
const oldTranslation = draw.setTranslation(self.pos);
|
||||
for(self.children.items) |*child| {
|
||||
try child.render(mousePosition - self.pos);
|
||||
defer draw.restoreTranslation(oldTranslation);
|
||||
const oldClip = draw.setClip(self.size);
|
||||
defer draw.restoreClip(oldClip);
|
||||
var shiftedPos = self.pos;
|
||||
if(self.scrollBarEnabled) {
|
||||
const diff = self.childrenHeight - self.maxHeight;
|
||||
shiftedPos[1] -= diff*self.scrollBar.currentState;
|
||||
try self.scrollBar.render(mousePosition - self.pos);
|
||||
}
|
||||
_ = draw.setTranslation(shiftedPos - self.pos);
|
||||
|
||||
for(self.children.items) |*child| {
|
||||
try child.render(mousePosition - shiftedPos);
|
||||
}
|
||||
draw.restoreTranslation(oldTranslation);
|
||||
}
|
||||
|
||||
pub fn mainButtonPressed(self: *VerticalList, mousePosition: Vec2f) void {
|
||||
var shiftedPos = self.pos;
|
||||
if(self.scrollBarEnabled) {
|
||||
const diff = self.childrenHeight - self.maxHeight;
|
||||
shiftedPos[1] -= diff*self.scrollBar.currentState;
|
||||
if(GuiComponent.contains(self.scrollBar.pos, self.scrollBar.size, mousePosition - self.pos)) {
|
||||
self.scrollBar.mainButtonPressed(mousePosition - self.pos);
|
||||
return;
|
||||
}
|
||||
}
|
||||
var selectedChild: ?*GuiComponent = null;
|
||||
for(self.children.items) |*child| {
|
||||
if(GuiComponent.contains(child.pos() + self.pos, child.size(), mousePosition)) {
|
||||
if(GuiComponent.contains(child.pos() + shiftedPos, child.size(), mousePosition)) {
|
||||
selectedChild = child;
|
||||
}
|
||||
}
|
||||
if(selectedChild) |child| {
|
||||
child.mainButtonPressed(mousePosition - self.pos);
|
||||
child.mainButtonPressed(mousePosition - shiftedPos);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn mainButtonReleased(self: *VerticalList, mousePosition: Vec2f) void {
|
||||
var shiftedPos = self.pos;
|
||||
if(self.scrollBarEnabled) {
|
||||
const diff = self.childrenHeight - self.maxHeight;
|
||||
shiftedPos[1] -= diff*self.scrollBar.currentState;
|
||||
self.scrollBar.mainButtonReleased(mousePosition - self.pos);
|
||||
}
|
||||
for(self.children.items) |*child| {
|
||||
child.mainButtonReleased(mousePosition - self.pos);
|
||||
child.mainButtonReleased(mousePosition - shiftedPos);
|
||||
}
|
||||
}
|
@ -44,23 +44,23 @@ fn apply() void {
|
||||
}
|
||||
|
||||
pub fn onOpen() Allocator.Error!void {
|
||||
var list = try VerticalList.init();
|
||||
var list = try VerticalList.init(.{padding, 16 + padding}, 300, 16);
|
||||
const width = 420;
|
||||
if(settings.playerName.len == 0) {
|
||||
try list.add(try Label.init(.{0, 16}, width, "Please enter your name!", .center));
|
||||
try list.add(try Label.init(.{0, 0}, width, "Please enter your name!", .center));
|
||||
} else {
|
||||
try list.add(try Label.init(.{0, 16}, width, "#ff0000Warning: #000000You loose access to your inventory data when changing the name!", .center));
|
||||
try list.add(try Label.init(.{0, 0}, width, "#ff0000Warning: #000000You loose access to your inventory data when changing the name!", .center));
|
||||
}
|
||||
try list.add(try Label.init(.{0, 16}, width, "Cubyz supports formatting your username using a markdown-like syntax:", .center));
|
||||
try list.add(try Label.init(.{0, 16}, width, "\\**italic*\\* \\*\\***bold**\\*\\* \\__underlined_\\_ \\_\\___strike-through__\\_\\_", .center));
|
||||
try list.add(try Label.init(.{0, 16}, width, "Even colors are possible, using the hexadecimal color code:", .center));
|
||||
try list.add(try Label.init(.{0, 16}, width, "\\##ff0000ff#00000000#00000000#ff0000red#000000 \\##ff0000ff#00770077#00000000#ff7700orange#000000 \\##00000000#00ff00ff#00000000#00ff00green#000000 \\##00000000#00000000#0000ffff#0000ffblue", .center));
|
||||
textComponent = try TextInput.init(.{0, 16}, width, 32, "quanturmdoelvloper");
|
||||
try list.add(try Label.init(.{0, 0}, width, "Cubyz supports formatting your username using a markdown-like syntax:", .center));
|
||||
try list.add(try Label.init(.{0, 0}, width, "\\**italic*\\* \\*\\***bold**\\*\\* \\__underlined_\\_ \\_\\___strike-through__\\_\\_", .center));
|
||||
try list.add(try Label.init(.{0, 0}, width, "Even colors are possible, using the hexadecimal color code:", .center));
|
||||
try list.add(try Label.init(.{0, 0}, width, "\\##ff0000ff#00000000#00000000#ff0000red#000000 \\##ff0000ff#00770077#00000000#ff7700orange#000000 \\##00000000#00ff00ff#00000000#00ff00green#000000 \\##00000000#00000000#0000ffff#0000ffblue", .center));
|
||||
textComponent = try TextInput.init(.{0, 0}, width, 32, "quanturmdoelvloper");
|
||||
try list.add(textComponent);
|
||||
try list.add(try Button.init(.{0, 16}, 100, "Apply", &apply));
|
||||
list.finish(.{padding, padding}, .center);
|
||||
try list.add(try Button.init(.{0, 0}, 100, "Apply", &apply));
|
||||
list.finish(.center);
|
||||
components[0] = list.toComponent();
|
||||
window.contentSize = components[0].size() + @splat(2, @as(f32, 2*padding));
|
||||
window.contentSize = components[0].pos() + components[0].size() + @splat(2, @as(f32, padding));
|
||||
gui.updateWindowPositions();
|
||||
}
|
||||
|
||||
|
@ -46,8 +46,7 @@ fn keypressListener(key: c_int, mouseButton: c_int, scancode: c_int) void {
|
||||
}
|
||||
|
||||
pub fn onOpen() Allocator.Error!void {
|
||||
var list = try VerticalList.init();
|
||||
list.size[1] = 8;
|
||||
var list = try VerticalList.init(.{padding, 16 + padding}, 300, 8);
|
||||
inline for(comptime std.meta.fieldNames(@TypeOf(main.keyboard))) |field| {
|
||||
var label = try Label.init(.{0, 0}, 128, field, .left);
|
||||
var button = if(&@field(main.keyboard, field) == selectedKey) (
|
||||
@ -58,12 +57,12 @@ pub fn onOpen() Allocator.Error!void {
|
||||
var row = try HorizontalList.init();
|
||||
try row.add(label);
|
||||
try row.add(button);
|
||||
row.finish(.{0, 8}, .center);
|
||||
row.finish(.{0, 0}, .center);
|
||||
try list.add(row);
|
||||
}
|
||||
list.finish(.{padding, padding}, .center);
|
||||
list.finish(.center);
|
||||
components[0] = list.toComponent();
|
||||
window.contentSize = components[0].size() + @splat(2, @as(f32, 2*padding));
|
||||
window.contentSize = components[0].pos() + components[0].size() + @splat(2, @as(f32, padding));
|
||||
gui.updateWindowPositions();
|
||||
}
|
||||
|
||||
|
@ -43,17 +43,17 @@ fn vsyncCallback(newValue: bool) void {
|
||||
}
|
||||
|
||||
pub fn onOpen() Allocator.Error!void {
|
||||
var list = try VerticalList.init();
|
||||
var list = try VerticalList.init(.{padding, 16 + padding}, 300, 16);
|
||||
const renderDistances = [_]u32{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12};
|
||||
try list.add(try Slider.init(.{0, 16}, 128, "#ffffffRender Distance: ", "{}", &renderDistances, settings.renderDistance - 1, &renderDistanceCallback));
|
||||
try list.add(try Slider.init(.{0, 0}, 128, "#ffffffRender Distance: ", "{}", &renderDistances, settings.renderDistance - 1, &renderDistanceCallback));
|
||||
const LODFactors = [_]f32{0.5, 1, 1.5, 2, 2.5, 3, 3.5, 4, 4.5, 5, 5.5, 6, 6.5, 7, 7.5, 8};
|
||||
try list.add(try Slider.init(.{0, 16}, 128, "#ffffffLOD Factor: ", "{d:.1}", &LODFactors, @floatToInt(u16, settings.LODFactor*2) - 1, &LODFactorCallback));
|
||||
try list.add(try Slider.init(.{0, 0}, 128, "#ffffffLOD Factor: ", "{d:.1}", &LODFactors, @floatToInt(u16, settings.LODFactor*2) - 1, &LODFactorCallback));
|
||||
// TODO: fog?
|
||||
try list.add(try CheckBox.init(.{0, 16}, 128, "Bloom", settings.bloom, &bloomCallback));
|
||||
try list.add(try CheckBox.init(.{0, 16}, 128, "Vertical Synchronization", settings.vsync, &vsyncCallback));
|
||||
list.finish(.{padding, padding}, .center);
|
||||
try list.add(try CheckBox.init(.{0, 0}, 128, "Bloom", settings.bloom, &bloomCallback));
|
||||
try list.add(try CheckBox.init(.{0, 0}, 128, "Vertical Synchronization", settings.vsync, &vsyncCallback));
|
||||
list.finish(.center);
|
||||
components[0] = list.toComponent();
|
||||
window.contentSize = components[0].size() + @splat(2, @as(f32, 2*padding));
|
||||
window.contentSize = components[0].pos() + components[0].size() + @splat(2, @as(f32, padding));
|
||||
gui.updateWindowPositions();
|
||||
}
|
||||
|
||||
|
@ -57,6 +57,7 @@ pub fn render() Allocator.Error!void {
|
||||
draw.boundImage(Vec2f{x, window.contentSize[1] - y - 16}, .{16, 16});
|
||||
x += 16;
|
||||
}
|
||||
y += 16;
|
||||
if(y != window.contentSize[1]) {
|
||||
window.contentSize[1] = y;
|
||||
gui.updateWindowPositions();
|
||||
|
@ -26,14 +26,14 @@ pub fn buttonCallbackTest() void {
|
||||
const padding: f32 = 8;
|
||||
|
||||
pub fn onOpen() Allocator.Error!void {
|
||||
var list = try VerticalList.init();
|
||||
try list.add(try Button.init(.{0, 16}, 128, "Singleplayer TODO", &buttonCallbackTest));
|
||||
try list.add(try Button.init(.{0, 16}, 128, "Multiplayer", gui.openWindowFunction("cubyz:multiplayer")));
|
||||
try list.add(try Button.init(.{0, 16}, 128, "Settings", gui.openWindowFunction("cubyz:settings")));
|
||||
try list.add(try Button.init(.{0, 16}, 128, "Exit TODO", &buttonCallbackTest));
|
||||
list.finish(.{padding, padding}, .center);
|
||||
var list = try VerticalList.init(.{padding, 16 + padding}, 300, 16);
|
||||
try list.add(try Button.init(.{0, 0}, 128, "Singleplayer TODO", &buttonCallbackTest));
|
||||
try list.add(try Button.init(.{0, 0}, 128, "Multiplayer", gui.openWindowFunction("cubyz:multiplayer")));
|
||||
try list.add(try Button.init(.{0, 0}, 128, "Settings", gui.openWindowFunction("cubyz:settings")));
|
||||
try list.add(try Button.init(.{0, 0}, 128, "Exit TODO", &buttonCallbackTest));
|
||||
list.finish(.center);
|
||||
components[0] = list.toComponent();
|
||||
window.contentSize = components[0].size() + @splat(2, @as(f32, 2*padding));
|
||||
window.contentSize = components[0].pos() + components[0].size() + @splat(2, @as(f32, padding));
|
||||
gui.updateWindowPositions();
|
||||
}
|
||||
|
||||
|
@ -88,17 +88,17 @@ fn copyIp() void {
|
||||
}
|
||||
|
||||
pub fn onOpen() Allocator.Error!void {
|
||||
var list = try VerticalList.init();
|
||||
try list.add(try Label.init(.{0, 16}, width, "Please send your IP to the host of the game and enter the host's IP below.", .center));
|
||||
// 255.255.255.255:?65536 (longest possible ip address)
|
||||
ipAddressLabel = try Label.init(.{0, 16}, width, " ", .center);
|
||||
var list = try VerticalList.init(.{padding, 16 + padding}, 300, 16);
|
||||
try list.add(try Label.init(.{0, 0}, width, "Please send your IP to the host of the game and enter the host's IP below.", .center));
|
||||
// 255.255.255.255:?65536 (longest possible ip address)
|
||||
ipAddressLabel = try Label.init(.{0, 0}, width, " ", .center);
|
||||
try list.add(ipAddressLabel);
|
||||
try list.add(try Button.init(.{0, 16}, 100, "Copy IP", ©Ip));
|
||||
try list.add(try TextInput.init(.{0, 16}, width, 32, settings.lastUsedIPAddress));
|
||||
try list.add(try Button.init(.{0, 16}, 100, "Join", &join));
|
||||
list.finish(.{padding, padding}, .center);
|
||||
try list.add(try Button.init(.{0, 0}, 100, "Copy IP", ©Ip));
|
||||
try list.add(try TextInput.init(.{0, 0}, width, 32, settings.lastUsedIPAddress));
|
||||
try list.add(try Button.init(.{0, 0}, 100, "Join", &join));
|
||||
list.finish(.center);
|
||||
components[0] = list.toComponent();
|
||||
window.contentSize = components[0].size() + @splat(2, @as(f32, 2*padding));
|
||||
window.contentSize = components[0].pos() + components[0].size() + @splat(2, @as(f32, padding));
|
||||
gui.updateWindowPositions();
|
||||
|
||||
thread = std.Thread.spawn(.{}, discoverIpAddressFromNewThread, .{}) catch |err| blk: {
|
||||
|
@ -23,14 +23,14 @@ pub var window: GuiWindow = GuiWindow {
|
||||
const padding: f32 = 8;
|
||||
|
||||
pub fn onOpen() Allocator.Error!void {
|
||||
var list = try VerticalList.init();
|
||||
try list.add(try Button.init(.{0, 16}, 128, "Graphics", gui.openWindowFunction("cubyz:graphics")));
|
||||
try list.add(try Button.init(.{0, 16}, 128, "Sound", gui.openWindowFunction("cubyz:sound")));
|
||||
try list.add(try Button.init(.{0, 16}, 128, "Controls", gui.openWindowFunction("cubyz:controls")));
|
||||
try list.add(try Button.init(.{0, 16}, 128, "Change Name", gui.openWindowFunction("cubyz:change_name")));
|
||||
list.finish(.{padding, padding}, .center);
|
||||
var list = try VerticalList.init(.{padding, 16 + padding}, 300, 16);
|
||||
try list.add(try Button.init(.{0, 0}, 128, "Graphics", gui.openWindowFunction("cubyz:graphics")));
|
||||
try list.add(try Button.init(.{0, 0}, 128, "Sound", gui.openWindowFunction("cubyz:sound")));
|
||||
try list.add(try Button.init(.{0, 0}, 128, "Controls", gui.openWindowFunction("cubyz:controls")));
|
||||
try list.add(try Button.init(.{0, 0}, 128, "Change Name", gui.openWindowFunction("cubyz:change_name")));
|
||||
list.finish(.center);
|
||||
components[0] = list.toComponent();
|
||||
window.contentSize = components[0].size() + @splat(2, @as(f32, 2*padding));
|
||||
window.contentSize = components[0].pos() + components[0].size() + @splat(2, @as(f32, padding));
|
||||
gui.updateWindowPositions();
|
||||
}
|
||||
|
||||
|
@ -23,11 +23,11 @@ pub var window = GuiWindow {
|
||||
const padding: f32 = 8;
|
||||
|
||||
pub fn onOpen() Allocator.Error!void {
|
||||
var list = try VerticalList.init();
|
||||
var list = try VerticalList.init(.{padding, 16 + padding}, 300, 16);
|
||||
// TODO
|
||||
list.finish(.{padding, padding}, .center);
|
||||
list.finish(.center);
|
||||
components[0] = list.toComponent();
|
||||
window.contentSize = components[0].size() + @splat(2, @as(f32, 2*padding));
|
||||
window.contentSize = components[0].pos() + components[0].size() + @splat(2, @as(f32, padding));
|
||||
gui.updateWindowPositions();
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user