Scroll container

This commit is contained in:
Synthasmagoria 2026-07-31 14:05:19 +02:00
commit 2026024949
2 changed files with 63 additions and 6 deletions

View file

@ -7,11 +7,13 @@ import "core:fmt"
UiContainerType :: enum { UiContainerType :: enum {
Normal, Normal,
Matrix, Matrix,
Scroll,
} }
UiElementData_Container :: struct { UiElementData_Container :: struct {
type: UiContainerType, type: UiContainerType,
thickness: f32, thickness: f32,
scroll: f32,
} }
UiElementData_Slider :: struct { UiElementData_Slider :: struct {
@ -61,6 +63,8 @@ Program :: struct {
matrix_float_pool: []f32, matrix_float_pool: []f32,
matrix_value_string_pool: []InputFloatField, matrix_value_string_pool: []InputFloatField,
matrix_count: int, matrix_count: int,
matrix_scroll: f32,
matrix_scroll_speed: f32,
grid: Grid, grid: Grid,
font_style: FontStyle, font_style: FontStyle,
state: ProgramState, state: ProgramState,
@ -87,6 +91,7 @@ matrix_pool_get_mat3 :: proc() -> ^mat3 {
program_init :: proc(allocator := context.allocator) { program_init :: proc(allocator := context.allocator) {
program.matrix_float_pool = make(type_of(program.matrix_float_pool), MATRIX_POOL_SIZE) program.matrix_float_pool = make(type_of(program.matrix_float_pool), MATRIX_POOL_SIZE)
program.matrix_value_string_pool = make(type_of(program.matrix_value_string_pool), MATRIX_POOL_SIZE) program.matrix_value_string_pool = make(type_of(program.matrix_value_string_pool), MATRIX_POOL_SIZE)
program.matrix_scroll_speed = 32.0
program.font_style = { program.font_style = {
font = rl.GetFontDefault(), font = rl.GetFontDefault(),
size = 16.0, size = 16.0,
@ -129,7 +134,9 @@ program_build_ui :: proc() -> []ui.Element {
ui.container_end() ui.container_end()
side_bar_container_config := ui.ElementConfiguration {margin = V2_ONE * 4.0} side_bar_container_config := ui.ElementConfiguration {margin = V2_ONE * 4.0}
ui.container_begin({ui.Size_Percentage(0.2), ui.Size_PercentageRemainder(1.0)}, side_bar_container_config) side_bar_container_data := new(UiElementData_Container, context.temp_allocator)
side_bar_container_data^ = {type = .Scroll, scroll = program.matrix_scroll}
matrix_container := ui.container_begin({ui.Size_Percentage(0.2), ui.Size_PercentageRemainder(1.0)}, side_bar_container_config, side_bar_container_data)
for i in 0..<program.matrix_count { for i in 0..<program.matrix_count {
container_config := ui.ElementConfiguration{margin = V2_ONE * 8.0, label = fmt.ctprintf("Matrix %d", i)} container_config := ui.ElementConfiguration{margin = V2_ONE * 8.0, label = fmt.ctprintf("Matrix %d", i)}
container_dimensions := ui.Dimensions {ui.Size_Percentage(1.0), ui.Size_Pixels(112.0)} container_dimensions := ui.Dimensions {ui.Size_Percentage(1.0), ui.Size_Pixels(112.0)}
@ -138,7 +145,14 @@ program_build_ui :: proc() -> []ui.Element {
ui_mat3(mat, value_strings, container_dimensions, container_config) ui_mat3(mat, value_strings, container_dimensions, container_config)
} }
ui.container_end() ui.container_end()
return ui.end() elements := ui.end()
mouse := rl.GetMousePosition()
if rect_has_point(rect2(matrix_container.area), mouse) {
program.matrix_scroll = max(0, program.matrix_scroll - rl.GetMouseWheelMove() * program.matrix_scroll_speed)
}
return elements
} }
ui_mat3 :: proc(mat: []f32, value_strings: []InputFloatField, dimensions: ui.Dimensions, config: ui.ElementConfiguration, allocator := context.temp_allocator) { ui_mat3 :: proc(mat: []f32, value_strings: []InputFloatField, dimensions: ui.Dimensions, config: ui.ElementConfiguration, allocator := context.temp_allocator) {
@ -161,8 +175,27 @@ ui_mat3 :: proc(mat: []f32, value_strings: []InputFloatField, dimensions: ui.Dim
} }
program_render_ui :: proc(ctx: ^ui.Context, elements: []ui.Element) { program_render_ui :: proc(ctx: ^ui.Context, elements: []ui.Element) {
for element in elements { scissor_container: ^ui.Element
area := rl.Rectangle(element.area)
defer {
if scissor_container != nil {
rl.EndScissorMode()
scissor_container = nil
}
}
for &element in elements {
offset: v2
if scissor_container != nil {
if element.id.container_index < scissor_container.id.container_index {
rl.EndScissorMode()
scissor_container = nil
} else {
offset.y = -(cast(^UiElementData_Container)scissor_container.data).scroll
}
}
area := rect_translate(rl.Rectangle(element.area), offset)
switch element.type { switch element.type {
case .Container: case .Container:
dim := rl.Color {0, 0, 0, 192} dim := rl.Color {0, 0, 0, 192}
@ -173,8 +206,7 @@ program_render_ui :: proc(ctx: ^ui.Context, elements: []ui.Element) {
rl.DrawRectangleRounded(area, 0.1, 4.0, dim) rl.DrawRectangleRounded(area, 0.1, 4.0, dim)
rl.GuiGroupBox(area, element.label) rl.GuiGroupBox(area, element.label)
case .Matrix: case .Matrix:
matrix_area := ui.rect_grow(ui.rect2(area), element.margin / 2.0)
matrix_area := ui.rect_grow(element.area, element.margin / 2.0)
tl, tr, br, bl := ui.rect_get_corners(matrix_area) tl, tr, br, bl := ui.rect_get_corners(matrix_area)
col := rl.WHITE col := rl.WHITE
hook_length: f32 = 4.0 hook_length: f32 = 4.0
@ -184,6 +216,11 @@ program_render_ui :: proc(ctx: ^ui.Context, elements: []ui.Element) {
rl.DrawLineEx(tr, br, data.thickness, col) rl.DrawLineEx(tr, br, data.thickness, col)
rl.DrawLineEx(tr, tr + V2_LEFT * hook_length, data.thickness, col) rl.DrawLineEx(tr, tr + V2_LEFT * hook_length, data.thickness, col)
rl.DrawLineEx(br, br + V2_LEFT * hook_length, data.thickness, col) rl.DrawLineEx(br, br + V2_LEFT * hook_length, data.thickness, col)
case .Scroll:
rl.DrawRectangleRounded(area, 0.1, 4.0, dim)
rl.GuiGroupBox(area, element.label)
scissor_container = &element
rl.BeginScissorMode(**rect2_to_irect2(area))
} }
} else { } else {
rl.DrawRectangleRounded(area, 0.1, 4.0, dim) rl.DrawRectangleRounded(area, 0.1, 4.0, dim)

View file

@ -91,6 +91,26 @@ enum_to_raygui_options_string :: proc($T: typeid, allocator: mem.Allocator) -> c
/// ### RECTANGLES ### /// /// ### RECTANGLES ### ///
rect2_to_irect2 :: proc "contextless" (rect: rect2) -> irect2 {
return {i32(rect.x), i32(rect.y), i32(rect.width), i32(rect.height)}
}
irect2_to_rect2 :: proc "contextless" (rect: irect2) -> rect2 {
return {f32(rect.x), f32(rect.y), f32(rect.width), f32(rect.height)}
}
rect_has_point :: proc {rect2_has_point, irect2_has_point}
@(private="file") rect2_has_point :: proc "contextless" (rect: rect2, p: v2) -> bool {
return p.x >= rect.x && p.x < rect.x + rect.width && p.y >= rect.y && p.y < rect.y + rect.height
}
@(private="file") irect2_has_point :: proc "contextless" (rect: irect2, p: iv2) -> bool {
return p.x >= rect.x && p.x < rect.x + rect.width && p.y >= rect.y && p.y < rect.y + rect.height
}
rect_translate :: proc {rect2_translate, irect2_translate} rect_translate :: proc {rect2_translate, irect2_translate}
@(private="file") rect2_translate :: proc "contextless" (rect: rect2, translation: v2) -> rect2 { @(private="file") rect2_translate :: proc "contextless" (rect: rect2, translation: v2) -> rect2 {