coordinate space math fixes, got resize handles working in settings menu prototype
will eventually lift to its own generic widget I still need to implement the corner resize..
This commit is contained in:
@ -4,6 +4,23 @@ import "core:fmt"
|
||||
|
||||
import rl "vendor:raylib"
|
||||
|
||||
draw_rectangle :: #force_inline proc "contextless" ( rect : rl.Rectangle, style : UI_Style ) {
|
||||
if style.layout.corner_radii[0] > 0 {
|
||||
rl.DrawRectangleRounded( rect, style.layout.corner_radii[0], 9, style.bg_color )
|
||||
}
|
||||
else {
|
||||
rl.DrawRectangleRec( rect, style.bg_color )
|
||||
}
|
||||
}
|
||||
|
||||
draw_rectangle_lines :: #force_inline proc "contextless" ( rect : rl.Rectangle, style : UI_Style, color : Color, thickness : f32 ) {
|
||||
if style.layout.corner_radii[0] > 0 {
|
||||
rl.DrawRectangleRoundedLines( rect, style.layout.corner_radii[0], 9, thickness, color )
|
||||
}
|
||||
else {
|
||||
rl.DrawRectangleLinesEx( rect, thickness, color )
|
||||
}
|
||||
}
|
||||
|
||||
render :: proc()
|
||||
{
|
||||
@ -15,124 +32,34 @@ render :: proc()
|
||||
rl.BeginDrawing()
|
||||
rl.ClearBackground( Color_BG )
|
||||
|
||||
render_mode_2d()
|
||||
render_mode_2d_workspace()
|
||||
render_mode_screenspace()
|
||||
|
||||
rl.EndDrawing()
|
||||
}
|
||||
|
||||
render_mode_screenspace :: proc ()
|
||||
// Experimental 3d viewport, not really the focus of this prototype
|
||||
// Until we can have a native or interpreted program render to it its not very useful.
|
||||
// Note(Ed): Other usecase could be 3d vis notes & math/graphical debug
|
||||
render_mode_3d :: proc()
|
||||
{
|
||||
profile("Render Screenspace")
|
||||
profile(#procedure)
|
||||
|
||||
state := get_state(); using state
|
||||
replay := & Memory_App.replay
|
||||
cam := & project.workspace.cam
|
||||
win_extent := state.app_window.extent
|
||||
|
||||
//region App UI
|
||||
Render_App_UI:
|
||||
{
|
||||
profile("App UI")
|
||||
ui := & state.app_ui
|
||||
root := ui.root
|
||||
if root.num_children == 0 {
|
||||
break Render_App_UI
|
||||
}
|
||||
rl.BeginDrawing()
|
||||
rl.BeginTextureMode( debug.viewport_rt )
|
||||
rl.BeginMode3D( debug.cam_vp )
|
||||
rl.ClearBackground( Color_3D_BG )
|
||||
|
||||
current := root.first
|
||||
for ; current != nil; current = ui_box_tranverse_next( current )
|
||||
{
|
||||
// profile("Box")
|
||||
parent := current.parent
|
||||
|
||||
style := current.style
|
||||
computed := & current.computed
|
||||
|
||||
computed_size := computed.bounds.p1 - computed.bounds.p0
|
||||
}
|
||||
}
|
||||
//endregion App UI
|
||||
|
||||
screen_top_left : Vec2 = {
|
||||
-win_extent.x + cam.target.x,
|
||||
-win_extent.y + cam.target.y,
|
||||
}
|
||||
|
||||
fps_msg := str_fmt_tmp( "FPS: %f", fps_avg)
|
||||
fps_msg_width := measure_text_size( fps_msg, default_font, 16.0, 0.0 ).x
|
||||
fps_msg_pos := screen_get_corners().top_right - { fps_msg_width, 0 }
|
||||
debug_draw_text( fps_msg, fps_msg_pos, 16.0, color = rl.GREEN )
|
||||
|
||||
debug_text :: proc( format : string, args : ..any )
|
||||
{
|
||||
@static draw_text_scratch : [Kilobyte * 64]u8
|
||||
|
||||
state := get_state(); using state
|
||||
if debug.draw_debug_text_y > 800 {
|
||||
debug.draw_debug_text_y = 50
|
||||
}
|
||||
|
||||
cam := & project.workspace.cam
|
||||
screen_corners := screen_get_corners()
|
||||
|
||||
position := screen_corners.top_right
|
||||
position.x -= 800
|
||||
position.y += debug.draw_debug_text_y
|
||||
|
||||
content := str_fmt_buffer( draw_text_scratch[:], format, ..args )
|
||||
debug_draw_text( content, position, 14.0 )
|
||||
|
||||
debug.draw_debug_text_y += 14
|
||||
}
|
||||
|
||||
// Debug Text
|
||||
{
|
||||
// debug_text( "Screen Width : %v", rl.GetScreenWidth () )
|
||||
// debug_text( "Screen Height: %v", rl.GetScreenHeight() )
|
||||
debug_text( "frametime_target_ms : %f ms", frametime_target_ms )
|
||||
debug_text( "frametime : %f ms", frametime_delta_ms )
|
||||
// debug_text( "frametime_last_elapsed_ms : %f ms", frametime_elapsed_ms )
|
||||
if replay.mode == ReplayMode.Record {
|
||||
debug_text( "Recording Input")
|
||||
}
|
||||
if replay.mode == ReplayMode.Playback {
|
||||
debug_text( "Replaying Input")
|
||||
}
|
||||
}
|
||||
|
||||
debug_text("Zoom Target: %v", project.workspace.zoom_target)
|
||||
|
||||
if debug.mouse_vis {
|
||||
debug_text( "Mouse Vertical Wheel: %v", input.mouse.vertical_wheel )
|
||||
debug_text( "Mouse Position (Screen): %v", input.mouse.pos )
|
||||
debug_text("Mouse Position (World): %v", screen_to_world(input.mouse.pos) )
|
||||
cursor_pos := transmute(Vec2) state.app_window.extent + input.mouse.pos
|
||||
rl.DrawCircleV( cursor_pos, 10, Color_White_A125 )
|
||||
}
|
||||
|
||||
ui := & project.workspace.ui
|
||||
|
||||
// debug_text("Box Count: %v", ui.built_box_count )
|
||||
|
||||
hot_box := ui_box_from_key( ui.curr_cache, ui.hot )
|
||||
active_box := ui_box_from_key( ui.curr_cache, ui.active )
|
||||
if hot_box != nil {
|
||||
debug_text("Hot Box : %v", hot_box.label.str )
|
||||
// debug_text("Hot Range2: %v", hot_box.computed.bounds.pts)
|
||||
}
|
||||
if active_box != nil{
|
||||
// debug_text("Active Box: %v", active_box.label.str )
|
||||
}
|
||||
// debug_text("Active Resizing: %v", ui.active_start_signal.resizing)
|
||||
|
||||
view := view_get_bounds()
|
||||
// debug_text("View Bounds (World): %v", view.pts )
|
||||
|
||||
debug.draw_debug_text_y = 50
|
||||
rl.EndMode3D()
|
||||
rl.EndTextureMode()
|
||||
rl.EndDrawing()
|
||||
}
|
||||
|
||||
render_mode_2d :: proc()
|
||||
// TODO(Ed): Eventually this needs to become a 'viewport within a UI'
|
||||
// This would allow the user to have more than one workspace open at the same time
|
||||
render_mode_2d_workspace :: proc()
|
||||
{
|
||||
profile(#procedure)
|
||||
state := get_state(); using state
|
||||
@ -164,8 +91,8 @@ render_mode_2d :: proc()
|
||||
when false
|
||||
{
|
||||
render_view := Range2 { pts = {
|
||||
world_to_screen_pos(view_bounds.min),
|
||||
world_to_screen_pos(view_bounds.max),
|
||||
world_to_screen_pos( view_bounds.min),
|
||||
world_to_screen_pos( view_bounds.max),
|
||||
}}
|
||||
view_rect := rl.Rectangle {
|
||||
render_view.min.x,
|
||||
@ -205,24 +132,24 @@ render_mode_2d :: proc()
|
||||
|
||||
// profile_begin("Calculating Raylib rectangles")
|
||||
render_anchors := range2(
|
||||
world_to_screen_pos(computed.anchors.min),
|
||||
world_to_screen_pos(computed.anchors.max),
|
||||
ws_view_to_render_pos(computed.anchors.min),
|
||||
ws_view_to_render_pos(computed.anchors.max),
|
||||
)
|
||||
render_margins := range2(
|
||||
world_to_screen_pos(computed.margins.min),
|
||||
world_to_screen_pos(computed.margins.max),
|
||||
ws_view_to_render_pos(computed.margins.min),
|
||||
ws_view_to_render_pos(computed.margins.max),
|
||||
)
|
||||
render_bounds := range2(
|
||||
world_to_screen_pos(computed.bounds.min),
|
||||
world_to_screen_pos(computed.bounds.max),
|
||||
ws_view_to_render_pos(computed.bounds.min),
|
||||
ws_view_to_render_pos(computed.bounds.max),
|
||||
)
|
||||
render_padding := range2(
|
||||
world_to_screen_pos(computed.padding.min),
|
||||
world_to_screen_pos(computed.padding.max),
|
||||
ws_view_to_render_pos(computed.padding.min),
|
||||
ws_view_to_render_pos(computed.padding.max),
|
||||
)
|
||||
render_content := range2(
|
||||
world_to_screen_pos(computed.content.min),
|
||||
world_to_screen_pos(computed.content.max),
|
||||
ws_view_to_render_pos(computed.content.min),
|
||||
ws_view_to_render_pos(computed.content.max),
|
||||
)
|
||||
|
||||
rect_anchors := range2_to_rl_rect( render_anchors )
|
||||
@ -232,24 +159,6 @@ render_mode_2d :: proc()
|
||||
rect_content := range2_to_rl_rect( render_content )
|
||||
// profile_end()
|
||||
|
||||
draw_rectangle :: #force_inline proc "contextless" ( rect : rl.Rectangle, style : UI_Style ) {
|
||||
if style.layout.corner_radii[0] > 0 {
|
||||
rl.DrawRectangleRounded( rect, style.layout.corner_radii[0], 9, style.bg_color )
|
||||
}
|
||||
else {
|
||||
rl.DrawRectangleRec( rect, style.bg_color )
|
||||
}
|
||||
}
|
||||
|
||||
draw_rectangle_lines :: #force_inline proc "contextless" ( rect : rl.Rectangle, style : UI_Style, color : Color, thickness : f32 ) {
|
||||
if style.layout.corner_radii[0] > 0 {
|
||||
rl.DrawRectangleRoundedLines( rect, style.layout.corner_radii[0], 9, thickness, color )
|
||||
}
|
||||
else {
|
||||
rl.DrawRectangleLinesEx( rect, thickness, color )
|
||||
}
|
||||
}
|
||||
|
||||
// profile_begin("rl.DrawRectangleRounded( rect_bounds, style.layout.corner_radii[0], 9, style.bg_color )")
|
||||
if style.bg_color.a != 0
|
||||
{
|
||||
@ -281,8 +190,8 @@ render_mode_2d :: proc()
|
||||
{ -resize_percent_width.x, resize_percent_width.x }))
|
||||
|
||||
render_resize := range2(
|
||||
world_to_screen_pos(resize_border_non_range.min),
|
||||
world_to_screen_pos(resize_border_non_range.max),
|
||||
ws_view_to_render_pos(resize_border_non_range.min),
|
||||
ws_view_to_render_pos(resize_border_non_range.max),
|
||||
)
|
||||
rect_resize := rl.Rectangle {
|
||||
render_resize.min.x,
|
||||
@ -307,7 +216,7 @@ render_mode_2d :: proc()
|
||||
// profile_end()
|
||||
|
||||
if len(current.text.str) > 0 {
|
||||
draw_text( current.text, world_to_screen_pos(computed.text_pos), style.font_size, style.text_color )
|
||||
ws_view_draw_text( current.text, ws_view_to_render_pos(computed.text_pos * {1, -1}), style.font_size, style.text_color )
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -315,8 +224,8 @@ render_mode_2d :: proc()
|
||||
|
||||
|
||||
if debug.mouse_vis {
|
||||
cursor_world_pos := screen_to_world(input.mouse.pos)
|
||||
rl.DrawCircleV( world_to_screen_pos(cursor_world_pos), 5, Color_GreyRed )
|
||||
cursor_world_pos := surface_to_ws_view_pos(input.mouse.pos)
|
||||
rl.DrawCircleV( ws_view_to_render_pos(cursor_world_pos), 5, Color_GreyRed )
|
||||
}
|
||||
|
||||
rl.DrawCircleV( { 0, 0 }, 1 * cam_zoom_ratio, Color_White )
|
||||
@ -324,18 +233,208 @@ render_mode_2d :: proc()
|
||||
rl.EndMode2D()
|
||||
}
|
||||
|
||||
render_mode_3d :: proc()
|
||||
render_mode_screenspace :: proc ()
|
||||
{
|
||||
profile("Render Screenspace")
|
||||
|
||||
state := get_state(); using state
|
||||
replay := & Memory_App.replay
|
||||
cam := & project.workspace.cam
|
||||
win_extent := state.app_window.extent
|
||||
|
||||
render_app_ui()
|
||||
|
||||
fps_msg := str_fmt_tmp( "FPS: %f", fps_avg)
|
||||
fps_msg_width := measure_text_size( fps_msg, default_font, 16.0, 0.0 ).x
|
||||
fps_msg_pos := screen_get_corners().top_right - { fps_msg_width, 0 } - { 5, 5 }
|
||||
debug_draw_text( fps_msg, fps_msg_pos, 16.0, color = rl.GREEN )
|
||||
|
||||
debug_text :: proc( format : string, args : ..any )
|
||||
{
|
||||
@static draw_text_scratch : [Kilobyte * 64]u8
|
||||
|
||||
state := get_state(); using state
|
||||
if debug.draw_debug_text_y > 800 {
|
||||
debug.draw_debug_text_y = 0
|
||||
}
|
||||
|
||||
cam := & project.workspace.cam
|
||||
screen_corners := screen_get_corners()
|
||||
|
||||
position := screen_corners.top_right
|
||||
position.x -= app_window.extent.x
|
||||
position.y -= debug.draw_debug_text_y
|
||||
|
||||
content := str_fmt_buffer( draw_text_scratch[:], format, ..args )
|
||||
debug_draw_text( content, position, 14.0 )
|
||||
|
||||
debug.draw_debug_text_y += 14
|
||||
}
|
||||
|
||||
// Debug Text
|
||||
{
|
||||
// debug_text( "Screen Width : %v", rl.GetScreenWidth () )
|
||||
// debug_text( "Screen Height: %v", rl.GetScreenHeight() )
|
||||
debug_text( "frametime_target_ms : %f ms", frametime_target_ms )
|
||||
debug_text( "frametime : %f ms", frametime_delta_ms )
|
||||
// debug_text( "frametime_last_elapsed_ms : %f ms", frametime_elapsed_ms )
|
||||
if replay.mode == ReplayMode.Record {
|
||||
debug_text( "Recording Input")
|
||||
}
|
||||
if replay.mode == ReplayMode.Playback {
|
||||
debug_text( "Replaying Input")
|
||||
}
|
||||
}
|
||||
|
||||
debug_text("Zoom Target: %v", project.workspace.zoom_target)
|
||||
|
||||
if debug.mouse_vis {
|
||||
debug_text("Mouse Vertical Wheel: %v", input.mouse.vertical_wheel )
|
||||
debug_text("Mouse Position (Render) : %v", input.mouse.raw_pos )
|
||||
debug_text("Mouse Position (Surface) : %v", input.mouse.pos )
|
||||
debug_text("Mouse Position (Workspace View): %v", surface_to_ws_view_pos(input.mouse.pos) )
|
||||
rl.DrawCircleV( input.mouse.raw_pos, 10, Color_White_A125 )
|
||||
rl.DrawCircleV( surface_to_render_pos(input.mouse.pos), 2, Color_BG )
|
||||
}
|
||||
|
||||
ui := & project.workspace.ui
|
||||
|
||||
// debug_text("Box Count: %v", ui.built_box_count )
|
||||
|
||||
hot_box := ui_box_from_key( ui.curr_cache, ui.hot )
|
||||
active_box := ui_box_from_key( ui.curr_cache, ui.active )
|
||||
if hot_box != nil {
|
||||
debug_text("Hot Box : %v", hot_box.label.str )
|
||||
// debug_text("Hot Range2: %v", hot_box.computed.bounds.pts)
|
||||
}
|
||||
if active_box != nil{
|
||||
// debug_text("Active Box: %v", active_box.label.str )
|
||||
}
|
||||
// debug_text("Active Resizing: %v", ui.active_start_signal.resizing)
|
||||
|
||||
view := view_get_bounds()
|
||||
// debug_text("View Bounds (World): %v", view.pts )
|
||||
|
||||
debug.draw_debug_text_y = 14
|
||||
}
|
||||
|
||||
// A non-zoomable static-view for ui
|
||||
// Only a scalar factor may be applied to the size of widgets & fonts
|
||||
// 'Window tiled' panels reside here
|
||||
render_app_ui :: proc()
|
||||
{
|
||||
profile(#procedure)
|
||||
|
||||
state := get_state(); using state
|
||||
using state := get_state()
|
||||
|
||||
rl.BeginDrawing()
|
||||
rl.BeginTextureMode( debug.viewport_rt )
|
||||
rl.BeginMode3D( debug.cam_vp )
|
||||
rl.ClearBackground( Color_3D_BG )
|
||||
//region App UI
|
||||
Render_App_UI:
|
||||
{
|
||||
profile("App UI")
|
||||
ui := & state.app_ui
|
||||
root := ui.root
|
||||
if root.num_children == 0 {
|
||||
break Render_App_UI
|
||||
}
|
||||
|
||||
rl.EndMode3D()
|
||||
rl.EndTextureMode()
|
||||
rl.EndDrawing()
|
||||
current := root.first
|
||||
for ; current != nil; current = ui_box_tranverse_next( current )
|
||||
{
|
||||
// profile("Box")
|
||||
parent := current.parent
|
||||
|
||||
style := current.style
|
||||
computed := & current.computed
|
||||
|
||||
computed_size := computed.bounds.p1 - computed.bounds.p0
|
||||
|
||||
render_anchors := range2(
|
||||
surface_to_render_pos(computed.anchors.min),
|
||||
surface_to_render_pos(computed.anchors.max),
|
||||
)
|
||||
render_margins := range2(
|
||||
surface_to_render_pos(computed.margins.min),
|
||||
surface_to_render_pos(computed.margins.max),
|
||||
)
|
||||
render_bounds := range2(
|
||||
surface_to_render_pos(computed.bounds.min),
|
||||
surface_to_render_pos(computed.bounds.max),
|
||||
)
|
||||
render_padding := range2(
|
||||
surface_to_render_pos(computed.padding.min),
|
||||
surface_to_render_pos(computed.padding.max),
|
||||
)
|
||||
render_content := range2(
|
||||
surface_to_render_pos(computed.content.min),
|
||||
surface_to_render_pos(computed.content.max),
|
||||
)
|
||||
rect_anchors := range2_to_rl_rect( render_anchors )
|
||||
rect_margins := range2_to_rl_rect( render_margins )
|
||||
rect_bounds := range2_to_rl_rect( render_bounds )
|
||||
rect_padding := range2_to_rl_rect( render_padding )
|
||||
rect_content := range2_to_rl_rect( render_content )
|
||||
// profile_end()
|
||||
|
||||
// profile_begin("rl.DrawRectangleRounded( rect_bounds, style.layout.corner_radii[0], 9, style.bg_color )")
|
||||
if style.bg_color.a != 0
|
||||
{
|
||||
draw_rectangle( rect_bounds, style )
|
||||
}
|
||||
if style.border_width > 0 {
|
||||
draw_rectangle_lines( rect_bounds, style, style.border_color, style.border_width )
|
||||
}
|
||||
// profile_end()
|
||||
|
||||
line_thickness : f32 = 1
|
||||
|
||||
// profile_begin("rl.DrawRectangleRoundedLines: padding & content")
|
||||
if equal_range2(computed.content, computed.padding) {
|
||||
// draw_rectangle_lines( rect_padding, style, Color_Debug_UI_Padding_Bounds, line_thickness )
|
||||
}
|
||||
else {
|
||||
// draw_rectangle_lines( rect_content, style, Color_Debug_UI_Content_Bounds, line_thickness )
|
||||
}
|
||||
// profile_end()
|
||||
|
||||
if .Mouse_Resizable in current.flags
|
||||
{
|
||||
// profile("Resize Bounds")
|
||||
resize_border_width := cast(f32) get_state().config.ui_resize_border_width
|
||||
resize_percent_width := computed_size * (resize_border_width * 1.0/ 200.0)
|
||||
resize_border_non_range := add(current.computed.bounds, range2(
|
||||
{ resize_percent_width.x, -resize_percent_width.x },
|
||||
{ -resize_percent_width.x, resize_percent_width.x }))
|
||||
|
||||
render_resize := range2(
|
||||
resize_border_non_range.min,
|
||||
resize_border_non_range.max,
|
||||
)
|
||||
rect_resize := rl.Rectangle {
|
||||
render_resize.min.x,
|
||||
render_resize.min.y,
|
||||
render_resize.max.x - render_resize.min.x,
|
||||
render_resize.max.y - render_resize.min.y,
|
||||
}
|
||||
draw_rectangle_lines( rect_padding, style, Color_Red, line_thickness )
|
||||
}
|
||||
|
||||
point_radius : f32 = 3
|
||||
|
||||
// profile_begin("circles")
|
||||
// center := Vec2 {
|
||||
// render_bounds.p0.x + computed_size.x * 0.5,
|
||||
// render_bounds.p0.y - computed_size.y * 0.5,
|
||||
// }
|
||||
// rl.DrawCircleV( center, point_radius, Color_White )
|
||||
|
||||
// rl.DrawCircleV( render_bounds.p0, point_radius, Color_Red )
|
||||
// rl.DrawCircleV( render_bounds.p1, point_radius, Color_Blue )
|
||||
// profile_end()
|
||||
|
||||
if len(current.text.str) > 0 {
|
||||
draw_text_screenspace( current.text, surface_to_render_pos(computed.text_pos), style.font_size, style.text_color )
|
||||
}
|
||||
}
|
||||
}
|
||||
//endregion App UI
|
||||
}
|
||||
|
Reference in New Issue
Block a user