Tooltip functionality
This commit is contained in:
parent
dbdd0e9bab
commit
2a302f7b1d
4 changed files with 62 additions and 11 deletions
7
TODO.MD
Normal file
7
TODO.MD
Normal file
|
|
@ -0,0 +1,7 @@
|
||||||
|
- Scale resolution
|
||||||
|
- Tooltips
|
||||||
|
- Reset zoom
|
||||||
|
- Save grid and animation data to file
|
||||||
|
- Load project
|
||||||
|
- Fix focus on submenu
|
||||||
|
- Centered justification in UI
|
||||||
|
|
@ -51,6 +51,7 @@ element_id_invalid :: proc() -> ElementId {
|
||||||
|
|
||||||
ElementConfiguration :: struct {
|
ElementConfiguration :: struct {
|
||||||
label: cstring,
|
label: cstring,
|
||||||
|
tooltip: cstring,
|
||||||
color: col,
|
color: col,
|
||||||
margin, padding: v2,
|
margin, padding: v2,
|
||||||
}
|
}
|
||||||
|
|
|
||||||
31
program.odin
31
program.odin
|
|
@ -214,6 +214,7 @@ Program :: struct {
|
||||||
ui_overlay_context: ui.Context,
|
ui_overlay_context: ui.Context,
|
||||||
ui_overlay_element_focus: ui.ElementId,
|
ui_overlay_element_focus: ui.ElementId,
|
||||||
ui_overlay_queue_focus_first: bool,
|
ui_overlay_queue_focus_first: bool,
|
||||||
|
ui_tooltip_offset: v2,
|
||||||
matrix_float_pool: []f32,
|
matrix_float_pool: []f32,
|
||||||
matrix_value_string_pool: []InputFloatField,
|
matrix_value_string_pool: []InputFloatField,
|
||||||
matrix_create_dropdown_value: HotkeyTypes,
|
matrix_create_dropdown_value: HotkeyTypes,
|
||||||
|
|
@ -305,6 +306,7 @@ program_init :: proc(allocator := context.allocator) {
|
||||||
program.ui_element_focus = ui.element_id_invalid()
|
program.ui_element_focus = ui.element_id_invalid()
|
||||||
ui.init(&program.ui_overlay_context, 200, ui_measure_text, &program.font_style, allocator)
|
ui.init(&program.ui_overlay_context, 200, ui_measure_text, &program.font_style, allocator)
|
||||||
program.ui_overlay_element_focus = ui.element_id_invalid()
|
program.ui_overlay_element_focus = ui.element_id_invalid()
|
||||||
|
program.ui_tooltip_offset = 20.0
|
||||||
|
|
||||||
animation_init(&program.animation, program.matrix_float_pool)
|
animation_init(&program.animation, program.matrix_float_pool)
|
||||||
|
|
||||||
|
|
@ -567,29 +569,31 @@ program_build_workspace_ui :: proc(ctx: ^ui.Context) ->
|
||||||
top_bar_dropdown_dimensions := ui.Dimensions {ui.Size_Pixels(160.0), ui.Size_Percentage(1.0)}
|
top_bar_dropdown_dimensions := ui.Dimensions {ui.Size_Pixels(160.0), ui.Size_Percentage(1.0)}
|
||||||
top_bar_dropdown_config := ui.ElementConfiguration {margin = top_bar_element_margin}
|
top_bar_dropdown_config := ui.ElementConfiguration {margin = top_bar_element_margin}
|
||||||
{
|
{
|
||||||
button_config := top_bar_button_config
|
button_margin := top_bar_element_margin
|
||||||
|
button_config: ui.ElementConfiguration
|
||||||
button_dimensions := top_bar_button_dimensions
|
button_dimensions := top_bar_button_dimensions
|
||||||
button_data: ^UiElementData_Button
|
button_data: ^UiElementData_Button
|
||||||
|
|
||||||
button_data = new(UiElementData_Button, context.temp_allocator)
|
button_data = new(UiElementData_Button, context.temp_allocator)
|
||||||
button_config.label = "I"
|
button_config = {margin = button_margin, label = "I", tooltip = "Add identity\nmatrix"}
|
||||||
button_data^ = {type = .AddIdentity}
|
button_data^ = {type = .AddIdentity}
|
||||||
ui.element(.Button, button_dimensions, button_config, button_data)
|
ui.element(.Button, button_dimensions, button_config, button_data)
|
||||||
|
|
||||||
button_data = new(UiElementData_Button, context.temp_allocator)
|
button_data = new(UiElementData_Button, context.temp_allocator)
|
||||||
button_config.label = "T"
|
button_config.label = "T"
|
||||||
|
button_config = {margin = button_margin, label = "T", tooltip = "Add translation\nmatrix"}
|
||||||
button_data^ = {type = .AddTranslation}
|
button_data^ = {type = .AddTranslation}
|
||||||
ui.same_line()
|
ui.same_line()
|
||||||
ui.element(.Button, button_dimensions, button_config, button_data)
|
ui.element(.Button, button_dimensions, button_config, button_data)
|
||||||
|
|
||||||
button_data = new(UiElementData_Button, context.temp_allocator)
|
button_data = new(UiElementData_Button, context.temp_allocator)
|
||||||
button_config.label = "S"
|
button_config = {margin = button_margin, label = "S", tooltip = "Add scale\nmatrix"}
|
||||||
button_data^ = {type = .AddScale}
|
button_data^ = {type = .AddScale}
|
||||||
ui.same_line()
|
ui.same_line()
|
||||||
ui.element(.Button, button_dimensions, button_config, button_data)
|
ui.element(.Button, button_dimensions, button_config, button_data)
|
||||||
|
|
||||||
button_data = new(UiElementData_Button, context.temp_allocator)
|
button_data = new(UiElementData_Button, context.temp_allocator)
|
||||||
button_config.label = "R"
|
button_config = {margin = button_margin, label = "R", tooltip = "Add rotation\nmatrix"}
|
||||||
button_data^ = {type = .AddRotation}
|
button_data^ = {type = .AddRotation}
|
||||||
ui.same_line()
|
ui.same_line()
|
||||||
ui.element(.Button, button_dimensions, button_config, button_data)
|
ui.element(.Button, button_dimensions, button_config, button_data)
|
||||||
|
|
@ -738,6 +742,9 @@ program_handle_mouse :: proc(mouse_state: MouseState, top_bar_container, matrix_
|
||||||
}
|
}
|
||||||
|
|
||||||
program_render_ui_and_handle_focus :: proc(ctx: ^ui.Context, focus_element_id: ui.ElementId, font_style: FontStyle, elements: []ui.Element) -> (focus: ui.ElementId) {
|
program_render_ui_and_handle_focus :: proc(ctx: ^ui.Context, focus_element_id: ui.ElementId, font_style: FontStyle, elements: []ui.Element) -> (focus: ui.ElementId) {
|
||||||
|
tooltip_text: cstring
|
||||||
|
tooltip_position: v2
|
||||||
|
|
||||||
scissor_container: ^ui.Element
|
scissor_container: ^ui.Element
|
||||||
render_above: ui.Element
|
render_above: ui.Element
|
||||||
render_above.id = ui.element_id_invalid()
|
render_above.id = ui.element_id_invalid()
|
||||||
|
|
@ -794,7 +801,12 @@ program_render_ui_and_handle_focus :: proc(ctx: ^ui.Context, focus_element_id: u
|
||||||
rl.GuiGroupBox(area, element.label)
|
rl.GuiGroupBox(area, element.label)
|
||||||
}
|
}
|
||||||
case .Button:
|
case .Button:
|
||||||
if (rl.GuiButton(area, element.label)) {
|
if len(element.tooltip) > 0 && rect_has_point(area, rl.GetMousePosition()) {
|
||||||
|
tooltip_text = element.tooltip
|
||||||
|
// TODO (synthas): implement keeping the rectangle within screen borders
|
||||||
|
tooltip_position = rl.GetMousePosition()
|
||||||
|
}
|
||||||
|
if rl.GuiButton(area, element.label) {
|
||||||
if element.data == nil do break
|
if element.data == nil do break
|
||||||
data := cast(^UiElementData_Button)element.data
|
data := cast(^UiElementData_Button)element.data
|
||||||
switch data.type {
|
switch data.type {
|
||||||
|
|
@ -919,6 +931,15 @@ program_render_ui_and_handle_focus :: proc(ctx: ^ui.Context, focus_element_id: u
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if len(tooltip_text) > 0 {
|
||||||
|
position := tooltip_position + program.ui_tooltip_offset
|
||||||
|
size := measure_text(tooltip_text, program.font_style)
|
||||||
|
bounds := rect_grow(rect_from(position, size), 4.0)
|
||||||
|
rl.DrawRectangleRec(bounds, rl.BLACK)
|
||||||
|
rl.DrawRectangleLinesEx(bounds, 1.0, rl.WHITE)
|
||||||
|
draw_multiline_text_centered(tooltip_text, position, program.font_style, rl.WHITE, context.temp_allocator)
|
||||||
|
}
|
||||||
|
|
||||||
return focus_element_id
|
return focus_element_id
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
34
utils.odin
34
utils.odin
|
|
@ -22,7 +22,7 @@ write_entire_file :: proc(name: string, data: []byte, truncate := true) -> (succ
|
||||||
}
|
}
|
||||||
|
|
||||||
/// ### RAYLIB DRAWING UTILS ### ///
|
/// ### RAYLIB DRAWING UTILS ### ///
|
||||||
measure_text :: proc(text: cstring, style: FontStyle) -> v2 {
|
@require_results measure_text :: proc(text: cstring, style: FontStyle) -> v2 {
|
||||||
return rl.MeasureTextEx(style.font, text, style.size, style.spacing)
|
return rl.MeasureTextEx(style.font, text, style.size, style.spacing)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -30,20 +30,42 @@ draw_text :: proc(text: cstring, position: v2, style: FontStyle, color: rl.Color
|
||||||
rl.DrawTextEx(style.font, text, position, style.size, style.spacing, color)
|
rl.DrawTextEx(style.font, text, position, style.size, style.spacing, color)
|
||||||
}
|
}
|
||||||
|
|
||||||
TextHalign :: enum {
|
draw_multiline_text_centered :: proc(text: cstring, position: v2, style: FontStyle, color: rl.Color, temp_allocator := context.temp_allocator) {
|
||||||
|
size := measure_text(text, style)
|
||||||
|
split := strings.split(strings.clone_from_cstring(text), "\n", temp_allocator)
|
||||||
|
|
||||||
|
for line, i in split {
|
||||||
|
line := strings.clone_to_cstring(line, temp_allocator)
|
||||||
|
line_size := measure_text(line, style)
|
||||||
|
offset := v2{(size.x - line_size.x) * 0.5, line_size.y * f32(i)}
|
||||||
|
draw_text(line, position + offset, style, color)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
JustificationHalign :: enum {
|
||||||
Left,
|
Left,
|
||||||
Middle,
|
Middle,
|
||||||
Right,
|
Right,
|
||||||
}
|
}
|
||||||
|
|
||||||
TextValign :: enum {
|
JustificationValign :: enum {
|
||||||
Top,
|
Top,
|
||||||
Center,
|
Center,
|
||||||
Bottom,
|
Bottom,
|
||||||
}
|
}
|
||||||
|
|
||||||
draw_text_aligned :: proc(text: cstring, position: v2, style: FontStyle, halign: TextHalign, valign: TextValign, color: rl.Color) {
|
JustificationAlign :: enum {
|
||||||
|
Shallow,
|
||||||
|
Middle,
|
||||||
|
Deep,
|
||||||
|
}
|
||||||
|
|
||||||
|
draw_text_aligned :: proc(text: cstring, position: v2, style: FontStyle, halign: JustificationHalign, valign: JustificationValign, color: rl.Color) {
|
||||||
size := measure_text(text, style)
|
size := measure_text(text, style)
|
||||||
|
draw_text(text, justify_2d(position, size, halign, valign), style, color)
|
||||||
|
}
|
||||||
|
|
||||||
|
@require_results justify_2d :: proc(position: v2, size: v2, halign: JustificationHalign, valign: JustificationValign) -> v2 {
|
||||||
position := position
|
position := position
|
||||||
switch halign {
|
switch halign {
|
||||||
case .Left:
|
case .Left:
|
||||||
|
|
@ -55,10 +77,10 @@ draw_text_aligned :: proc(text: cstring, position: v2, style: FontStyle, halign:
|
||||||
case .Center: position.y -= size.y / 2.0
|
case .Center: position.y -= size.y / 2.0
|
||||||
case .Bottom: position.y -= size.y
|
case .Bottom: position.y -= size.y
|
||||||
}
|
}
|
||||||
draw_text(text, position, style, color)
|
return position
|
||||||
}
|
}
|
||||||
|
|
||||||
draw_float_aligned :: proc(value: f32, position: v2, style: FontStyle, halign: TextHalign, valign: TextValign, color: rl.Color) {
|
draw_float_aligned :: proc(value: f32, position: v2, style: FontStyle, halign: JustificationHalign, valign: JustificationValign, color: rl.Color) {
|
||||||
fractional := fract(value)
|
fractional := fract(value)
|
||||||
text: cstring
|
text: cstring
|
||||||
if fractional == 0.0 {
|
if fractional == 0.0 {
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue