From 2e3a7e10756954dc5a99d617a1c0eef327d3adbb Mon Sep 17 00:00:00 2001 From: San Jacobs Date: Sun, 15 Oct 2023 14:37:29 +0200 Subject: Normalized timelines and editor for spacing and sizing --- src/ui_implementation.odin | 168 +++++++++++++++++++++++++++++++++++++++------ 1 file changed, 147 insertions(+), 21 deletions(-) (limited to 'src/ui_implementation.odin') diff --git a/src/ui_implementation.odin b/src/ui_implementation.odin index e4b4f80..6839b57 100644 --- a/src/ui_implementation.odin +++ b/src/ui_implementation.odin @@ -10,6 +10,8 @@ Theme :: struct { background: rl.Color, background_bar: rl.Color, button: rl.Color, + button_hover: rl.Color, + button_click: rl.Color, base: rl.Color, slider_bar: rl.Color, text: rl.Color, @@ -23,6 +25,8 @@ theme : Theme = { background = {25 , 27 , 29 , 255,}, background_bar = {43 , 43 , 48 , 255,}, button = {91 , 91 , 204, 255,}, + button_hover = {91 , 91 , 204, 255,}, + button_click = {91 , 91 , 204, 255,}, base = {60 , 60 , 60 , 255,}, slider_bar = {91 , 91 , 204, 255,}, text = {255, 255, 255, 252,}, @@ -32,9 +36,28 @@ theme : Theme = { price_300 = {240, 30 , 240, 255,}, } -DAY_HEIGHT :: 35 -TIMELINE_START :: 175 -TIMELINE_END :: -85 +Sizings :: struct { + date: int, + call: int, + wrap: int, + price: int, + lunch: int, + timeline: int, + inter_timeline: int, +} +sizings : Sizings = { + date = 110, + call = 85, + wrap = 90, + price = 100, + lunch = 100, + timeline = 32, + inter_timeline = 5, +} + +DAY_HEIGHT :: 35 // Only here for legacy UI +TIMELINE_START :: 175 // Only here for legacy UI +TIMELINE_END :: -85 // Only here for legacy UI Item :: oui.Item Call :: oui.Call @@ -42,10 +65,12 @@ Call :: oui.Call Data_Element :: enum int { Panel, Button, - Slider, + SliderU8, + SliderInt, Label, Text_Input, Timeblock, + Timeline, // ... } @@ -64,7 +89,15 @@ Data_Button :: struct { selected: bool, } -Data_Slider :: struct { +Data_SliderInt :: struct { + using _: Data_Head, + text: string, + value: ^int, + min: int, + max: int, +} + +Data_SliderU8 :: struct { using _: Data_Head, text: string, value: ^u8, @@ -78,6 +111,11 @@ Data_Label :: struct { alignment: Text_Alignment, } +Data_Timeline :: struct { + using _: Data_Head, + day: ^Workday, +} + panel :: proc(color : rl.Color = rl.RED) -> ^Item { item := oui.item_make(c0) @@ -129,21 +167,50 @@ button_callback :: proc(ctxt: ^oui.Context, item: ^Item, event: Call) -> int { return -1 } -slider :: proc(id: string, text: string, width: int, value: ^u8) -> ^Item { +slider_int :: proc(id: string, text: string, width: int, value: ^int, min: int, max: int) -> ^Item { + item := oui.item_make(c0) + item.layout_size = {width, 25} + item.id = oui.gen_id(c0, id) + item.callback = slider_int_callback + + data := oui.alloc_typed(c0, item, Data_SliderInt) + data.subtype = .SliderInt + data.text = text + data.value = value + data.min = min + data.max = max + + return item +} +slider_int_callback :: proc(ctxt: ^oui.Context, item: ^Item, event: Call) -> int { + data := cast(^Data_SliderInt) item.handle + rect := item.bounds + + #partial switch event { + case .Left_Capture: + cursor_position := clamp(oui.get_cursor(c0).x, rect.l, rect.r) + + data.value^ = int(f32(data.min) + (f32(data.max - data.min) * (f32(cursor_position - rect.l) / f32(rect.r - rect.l)))) + } + + return -1 +} + +slider_u8 :: proc(id: string, text: string, width: int, value: ^u8) -> ^Item { item := oui.item_make(c0) item.layout_size = {width, 25} item.id = oui.gen_id(c0, id) - item.callback = slider_callback + item.callback = slider_u8_callback - data := oui.alloc_typed(c0, item, Data_Slider) - data.subtype = .Slider + data := oui.alloc_typed(c0, item, Data_SliderU8) + data.subtype = .SliderU8 data.text = text data.value = value return item } -slider_callback :: proc(ctxt: ^oui.Context, item: ^Item, event: Call) -> int { - data := cast(^Data_Slider) item.handle +slider_u8_callback :: proc(ctxt: ^oui.Context, item: ^Item, event: Call) -> int { + data := cast(^Data_SliderU8) item.handle rect := item.bounds #partial switch event { @@ -157,10 +224,21 @@ slider_callback :: proc(ctxt: ^oui.Context, item: ^Item, event: Call) -> int { } color_sliders :: proc(parent: ^Item, color: ^rl.Color) { width :: 167 - oui.item_insert(parent, slider("slider_r", fmt.tprintf("%d", color.r), width, &color.r)) - oui.item_insert(parent, slider("slider_g", fmt.tprintf("%d", color.g), width, &color.g)) - oui.item_insert(parent, slider("slider_b", fmt.tprintf("%d", color.b), width, &color.b)) - oui.item_insert(parent, slider("slider_a", fmt.tprintf("%d", color.a), width, &color.a)) + oui.item_insert(parent, slider_u8("slider_r", fmt.tprintf("%d", color.r), width, &color.r)) + oui.item_insert(parent, slider_u8("slider_g", fmt.tprintf("%d", color.g), width, &color.g)) + oui.item_insert(parent, slider_u8("slider_b", fmt.tprintf("%d", color.b), width, &color.b)) + oui.item_insert(parent, slider_u8("slider_a", fmt.tprintf("%d", color.a), width, &color.a)) +} + +timeline :: proc(parent: ^Item, day: ^Workday) -> ^Item { + item := oui.item_make(c0) + + data := oui.alloc_typed(c0, item, Data_Timeline) + data.subtype = .Timeline + data.day = day + + oui.item_insert(parent, item) + return item } Text_Alignment :: enum int { @@ -181,9 +259,9 @@ label :: proc(text: string, font: rl.Font, width: int = 150, alignment: Text_Ali return item } -calculate_text_alignment :: proc(text: cstring, font: rl.Font, alignment: Text_Alignment, rect: oui.RectI) -> (output: [2]int) { +calculate_text_alignment :: proc(text: cstring, font: rl.Font, alignment: Text_Alignment, rect: oui.RectI, spacing: f32 = 0) -> (output: [2]int) { - measurement := rl.MeasureTextEx(font, text, f32(font.baseSize), 0.0) + measurement := rl.MeasureTextEx(font, text, f32(font.baseSize), spacing) switch alignment { case .Left: @@ -229,17 +307,28 @@ ui_draw :: proc(item: ^oui.Item) { // ... render any type of item case .Button: data := cast(^Data_Button) item.handle + text_spacing := clamp(item.anim.hot - item.anim.active, 0, item.anim.hot)*2 rl.DrawRectangle(i32(rect.l), i32(rect.t), i32(rect.r-rect.l), i32(rect.b-rect.t), theme.button) text := strings.clone_to_cstring(data.text, context.temp_allocator) - position := calculate_text_alignment(text, font, .Center, rect) + position := calculate_text_alignment(text, font, .Center, rect, text_spacing) - rl.DrawTextEx(font, text, i2f(position), f32(font.baseSize), 0.0, theme.text); + rl.DrawTextEx(font, text, i2f(position), f32(font.baseSize), text_spacing, theme.text); //fmt.println(item.anim) - case .Slider: - data := cast(^Data_Slider) head + case .SliderInt: + data := cast(^Data_SliderInt) head + rl.DrawRectangle(i32(rect.l), i32(rect.t), i32(rect.r-rect.l), i32(rect.b-rect.t), theme.base) + rl.DrawRectangle(i32(rect.l+1), i32(rect.t+1), i32(f32(rect.r-rect.l)*(f32(data.value^)/f32(data.max))-2), i32(rect.b-rect.t-2), theme.slider_bar) + + text := strings.clone_to_cstring(data.text, context.temp_allocator) + position := calculate_text_alignment(text, font, .Center, rect) + + rl.DrawTextEx(font, text, i2f(position), f32(font.baseSize), 0.0, theme.text); + + case .SliderU8: + data := cast(^Data_SliderU8) head rl.DrawRectangle(i32(rect.l), i32(rect.t), i32(rect.r-rect.l), i32(rect.b-rect.t), theme.base) rl.DrawRectangle(i32(rect.l+1), i32(rect.t+1), i32(f32(rect.r-rect.l)*(f32(data.value^)/255)-2), i32(rect.b-rect.t-2), theme.slider_bar) @@ -259,5 +348,42 @@ ui_draw :: proc(item: ^oui.Item) { position := calculate_text_alignment(text, data.font, data.alignment, rect) rl.DrawTextEx(data.font, text, i2f(position), f32(data.font.baseSize), 0.0, theme.text); + + case .Timeline: + data := cast(^Data_Timeline) item.handle + + width := int(f32(rect.r - rect.l)/(FRACT_MAX - FRACT_MIN)) + + for fracts, i in data.day.fractions { + + color := theme.price_100 + value := data.day.blocks[i].value + + switch { + case value>2.1: + color = theme.price_300 + case value>1.6: + color = theme.price_200 + case value>1.1: + color = theme.price_150 + } + + + + rl.DrawRectangle(i32(rect.l + int(f32(width)*fracts.start) - int(f32(width)*FRACT_MIN)), + i32(rect.t), + i32(f32(width) * (fracts.end - fracts.start)+0.99), + i32(rect.b - rect.t), + color) + // Dark middle of blocks, glowing edge. Disabled for now. + /*rl.DrawRectangle(i32(rect.l + int(f32(width)*fracts.start) - int(f32(width)*FRACT_MIN) + 1), + i32(rect.t) + 1, + i32(f32(width+1) * (fracts.end - fracts.start)-1.01), + i32(rect.b - rect.t)-2, + {0,0,0,100})*/ + if i+1 == data.day.total_timeblocks { + break + } + } } } \ No newline at end of file -- cgit v1.2.1