WIP: Stuff related to working on the settings menu + more
Moved core ui to its own folder. Worked on theming (proper light and dark theme) Began to work on the scroll box widget and input box constructions I added back a script for flattening the codebase: gen_flattened_codebase.ps1
This commit is contained in:
		| @@ -52,12 +52,13 @@ ui_screen_menu_bar :: proc( captures : rawptr = nil ) -> (should_raise : b32 = f | ||||
| 	{ | ||||
| 		@static theme : UI_Theme | ||||
| 		@static loaded : b32 = false | ||||
| 		if true && ! loaded | ||||
| 		if ! loaded | ||||
| 		{ | ||||
| 			app_color := app_color_theme() | ||||
| 			layout := UI_Layout { | ||||
| 				flags          = {}, | ||||
| 				anchor         = range2({},{}), | ||||
| 				alignment      = {0.5, 0.5}, | ||||
| 				// alignment      = UI_Align_Presets.text_centered, | ||||
| 				text_alignment = {0.0, 1.5}, | ||||
| 				font_size      = 12, | ||||
| 				margins        = {0, 0, 0, 0}, | ||||
| @@ -67,34 +68,30 @@ ui_screen_menu_bar :: proc( captures : rawptr = nil ) -> (should_raise : b32 = f | ||||
| 				size           = range2({},{}) | ||||
| 			} | ||||
| 			style := UI_Style { | ||||
| 				bg_color     = Color_ThmDark_BG, | ||||
| 				border_color = Color_ThmDark_Border_Default, | ||||
| 				bg_color     = app_color.bg, | ||||
| 				border_color = app_color.border_default, | ||||
| 				corner_radii = {}, | ||||
| 				blur_size    = 0, | ||||
| 				font         = get_state().default_font, | ||||
| 				text_color   = Color_ThmDark_Text_Default, | ||||
| 				text_color   = app_color.text_default, | ||||
| 				cursor       = {}, | ||||
| 			} | ||||
|  | ||||
| 			// loaded = true | ||||
| 			layout_combo := to_ui_layout_combo(layout) | ||||
| 			style_combo  := to_ui_style_combo(style) | ||||
| 			{ | ||||
| 			Hot: { | ||||
| 				using layout_combo.hot | ||||
| 				using style_combo.hot | ||||
| 				bg_color   = Color_ThmDark_Btn_BG_Hot | ||||
| 				text_color = Color_ThmDark_Text_Hot | ||||
| 				bg_color   = app_color.btn_bg_hot | ||||
| 				text_color = app_color.text_hot | ||||
| 			} | ||||
| 			{ | ||||
| 			Active: { | ||||
| 				using layout_combo.active | ||||
| 				using style_combo.active | ||||
| 				bg_color   = Color_ThmDark_Btn_BG_Active | ||||
| 				text_color = Color_ThmDark_Text_Active | ||||
| 			} | ||||
|  | ||||
| 			theme = UI_Theme { | ||||
| 				layout_combo, style_combo | ||||
| 				bg_color   = app_color.btn_bg_active | ||||
| 				text_color = app_color.text_active | ||||
| 			} | ||||
| 			theme = UI_Theme { layout_combo, style_combo } | ||||
| 			loaded = true | ||||
| 		} | ||||
| 		ui_layout_push(theme.layout) | ||||
| 		ui_style_push(theme.style) | ||||
| @@ -105,7 +102,8 @@ ui_screen_menu_bar :: proc( captures : rawptr = nil ) -> (should_raise : b32 = f | ||||
| 	{ | ||||
| 		using screen_ui.menu_bar | ||||
| 		ui_theme_app_menu_bar_default() | ||||
| 		container = ui_hbox( .Left_To_Right, "Menu Bar" ) | ||||
| 		container = ui_hbox_begin( .Left_To_Right, "Menu Bar" ) | ||||
| 		ui_parent(container) | ||||
| 		{ | ||||
| 			using container | ||||
| 			layout.flags = {.Fixed_Position_X, .Fixed_Position_Y, .Fixed_Width, .Fixed_Height, .Origin_At_Anchor_Center} | ||||
| @@ -114,7 +112,7 @@ ui_screen_menu_bar :: proc( captures : rawptr = nil ) -> (should_raise : b32 = f | ||||
| 			text = str_intern("menu_bar") | ||||
| 		} | ||||
|  | ||||
| 		ui_theme_btn_default() | ||||
| 		ui_theme_btn() | ||||
| 		move_box := ui_button("Move Box"); | ||||
| 		{ | ||||
| 			using move_box | ||||
| @@ -122,7 +120,7 @@ ui_screen_menu_bar :: proc( captures : rawptr = nil ) -> (should_raise : b32 = f | ||||
| 				pos += input.mouse.delta | ||||
| 				should_raise = true | ||||
| 			} | ||||
| 			layout.anchor.ratio.x = 0.4 | ||||
| 			layout.anchor.ratio.x = 1.0 | ||||
| 		} | ||||
|  | ||||
| 		spacer := ui_spacer("Menu Bar: Move Spacer") | ||||
| @@ -135,17 +133,18 @@ ui_screen_menu_bar :: proc( captures : rawptr = nil ) -> (should_raise : b32 = f | ||||
| 			using settings_btn | ||||
| 			text = str_intern("Settings") | ||||
| 			layout.flags = { | ||||
| 				// .Scale_Width_By_Height_Ratio, | ||||
| 				.Fixed_Width | ||||
| 				.Scale_Width_By_Height_Ratio, | ||||
| 				// .Fixed_Width | ||||
| 			} | ||||
| 			layout.size.min.x = 100 | ||||
| 			layout.size.ratio.x = 2.0 | ||||
| 			if pressed { | ||||
| 				screen_ui.settings_menu.is_open = true | ||||
| 			} | ||||
| 		} | ||||
|  | ||||
| 		spacer = ui_spacer("Menu Bar: End Spacer") | ||||
| 		spacer.layout.anchor.ratio.x = 1.0 | ||||
| 		spacer.layout.anchor.ratio.x = 2.0 | ||||
|  | ||||
| 		ui_hbox_end(container, compute_layout = false) | ||||
| 	} | ||||
| 	return | ||||
| } | ||||
| @@ -156,22 +155,18 @@ ui_screen_settings_menu :: proc( captures : rawptr = nil ) -> ( should_raise : b | ||||
| 	using state := get_state() | ||||
| 	using state.screen_ui | ||||
| 	if ! settings_menu.is_open do return | ||||
| 	app_color := app_color_theme() | ||||
|  | ||||
| 	using settings_menu | ||||
| 	if size.x < min_size.x do size.x = min_size.x | ||||
| 	if size.y < min_size.y do size.y = min_size.y | ||||
|  | ||||
| 	ui_theme_transparent() | ||||
| 	container = ui_widget("Settings Menu", {}) | ||||
| 	{ | ||||
| 	ui_theme_window_panel() | ||||
| 	container = ui_widget("Settings Menu", {}); 	{ | ||||
| 		using container | ||||
| 		layout.flags        = { .Fixed_Width, .Fixed_Height, .Fixed_Position_X, .Fixed_Position_Y, .Origin_At_Anchor_Center } | ||||
| 		style.bg_color      = Color_ThmDark_Translucent_Panel | ||||
| 		style.border_color  = { 0, 0, 0, 200 } | ||||
| 		layout.alignment    = {0.0, 0.0} | ||||
| 		layout.border_width = 1.0 | ||||
| 		layout.pos          = pos | ||||
| 		layout.size         = range2( size, {}) | ||||
| 		layout.flags = { .Fixed_Width, .Fixed_Height, .Fixed_Position_X, .Fixed_Position_Y, .Origin_At_Anchor_Center } | ||||
| 		layout.pos   = pos | ||||
| 		layout.size  = range2( size, {}) | ||||
| 	} | ||||
| 	ui_parent(container) | ||||
| 	if settings_menu.is_maximized { | ||||
| @@ -179,54 +174,27 @@ ui_screen_settings_menu :: proc( captures : rawptr = nil ) -> ( should_raise : b | ||||
| 		layout.flags = {.Origin_At_Anchor_Center } | ||||
| 		layout.pos   = {} | ||||
| 	} | ||||
| 	should_raise |= ui_resizable_handles( & container, & pos, & size/*, compute_layout = true*/) | ||||
| 	// ui_box_compute_layout(container) | ||||
| 	should_raise |= ui_resizable_handles( & container, & pos, & size) | ||||
|  | ||||
| 	vbox := ui_vbox_begin( .Top_To_Bottom, "Settings Menu: VBox", {.Mouse_Clickable}, compute_layout = true) | ||||
| 	{ | ||||
| 		should_raise |= b32(vbox.active) | ||||
| 		ui_parent(vbox) | ||||
|  | ||||
| 		ui_layout( UI_Layout { | ||||
| 		// 	font_size = 16, | ||||
| 			// alignment = {0, 1}, | ||||
| 		}) | ||||
| 		ui_style( UI_Style { | ||||
| 			// bg_color   = Color_Transparent, | ||||
| 			font       = default_font, | ||||
| 			text_color = Color_White, | ||||
| 		}) | ||||
| 		ui_style_ref().hot.bg_color = Color_Blue | ||||
| 		frame_bar := ui_hbox_begin(.Left_To_Right, "Settings Menu: Frame Bar", { .Mouse_Clickable, .Focusable, .Click_To_Focus }) | ||||
| 		ui_theme_window_bar() | ||||
| 		frame_bar := ui_hbox_begin(.Left_To_Right, "Settings Menu: Frame Bar", { .Mouse_Clickable }) | ||||
| 		{ | ||||
| 			frame_bar.layout.flags      = {.Fixed_Height} | ||||
| 			frame_bar.layout.size.min.y = 50 | ||||
| 			ui_parent(frame_bar) | ||||
|  | ||||
| 			ui_layout( UI_Layout { | ||||
| 				font_size = 18, | ||||
| 			}) | ||||
| 			title := ui_text("Settings Menu: Title", str_intern("Settings Menu"), {.Disabled}) | ||||
| 			{ | ||||
| 			ui_theme_text() | ||||
| 			title := ui_text("Settings Menu: Title", str_intern("Settings Menu"), {.Disabled}); { | ||||
| 				using title | ||||
| 				layout.anchor.ratio.x = 1.0 | ||||
| 				layout.margins        = { 0, 0, 15, 0} | ||||
| 				layout.text_alignment = {0 , 0.5} | ||||
| 				layout.anchor.ratio.x = 1.0 | ||||
| 				layout.font_size      = 16 | ||||
| 			} | ||||
|  | ||||
| 			ui_layout( UI_Layout { | ||||
| 				font_size = 16, | ||||
| 			}) | ||||
|  | ||||
| 			ui_style(ui_style_peek()) | ||||
| 			style := ui_style_ref() | ||||
| 			maximize_btn := ui_button("Settings Menu: Maximize Btn") | ||||
| 			{ | ||||
| 			ui_theme_window_bar_btn() | ||||
| 			maximize_btn := ui_button("Settings Menu: Maximize Btn"); { | ||||
| 				using maximize_btn | ||||
| 				layout.flags          = {.Fixed_Width} | ||||
| 				layout.size.min       = {50, 50} | ||||
| 				layout.text_alignment = {0.5, 0.5} | ||||
| 				layout.anchor.ratio.x = 1.0 | ||||
| 				if maximize_btn.pressed { | ||||
| 					settings_menu.is_maximized = ~settings_menu.is_maximized | ||||
| 					should_raise = true | ||||
| @@ -234,19 +202,12 @@ ui_screen_settings_menu :: proc( captures : rawptr = nil ) -> ( should_raise : b | ||||
| 				if settings_menu.is_maximized do text = str_intern("min") | ||||
| 				else do text = str_intern("max") | ||||
| 			} | ||||
| 			close_btn := ui_button("Settings Menu: Close Btn") | ||||
| 			{ | ||||
| 			close_btn := ui_button("Settings Menu: Close Btn"); { | ||||
| 				using close_btn | ||||
| 				text = str_intern("close") | ||||
| 				layout.flags          = {.Fixed_Width} | ||||
| 				layout.size.min       = {50, 0} | ||||
| 				layout.text_alignment = {0.5, 0.5} | ||||
| 				layout.anchor.ratio.x = 1.0 | ||||
| 				if close_btn.pressed { | ||||
| 					settings_menu.is_open = false | ||||
| 				} | ||||
| 				if close_btn.hot     do style.bg_color =  app_color.window_btn_close_bg_hot | ||||
| 				if close_btn.pressed do settings_menu.is_open = false | ||||
| 			} | ||||
|  | ||||
| 			ui_hbox_end(frame_bar, compute_layout = true) | ||||
| 		} | ||||
| 		if frame_bar.active { | ||||
| @@ -254,66 +215,109 @@ ui_screen_settings_menu :: proc( captures : rawptr = nil ) -> ( should_raise : b | ||||
| 			should_raise = true | ||||
| 		} | ||||
|  | ||||
| 		// Populate settings with values from config (hardcoded for now) | ||||
| 		ui_layout(UI_Layout { | ||||
| 			flags = { | ||||
| 				// .Origin_At_Anchor_Center, | ||||
| 				// .Fixed_Height, | ||||
| 			}, | ||||
| 			// pos = {0, 50}, | ||||
| 			// size = range2({100, 100},{}), | ||||
| 			// alignment = {0,0}, | ||||
| 		}) | ||||
| 		ui_style( UI_Style { | ||||
| 				// bg_color = Color_GreyRed | ||||
| 		}) | ||||
| 		drop_down_bar := ui_hbox_begin(.Left_To_Right, "settings_menu.vbox: config drop_down_bar", {.Mouse_Clickable}) | ||||
| 		btn : UI_Widget | ||||
| 		@static config_drop_down_open := false | ||||
| 		ui_theme_drop_down() | ||||
| 		drop_down_bar := ui_hbox_begin(.Left_To_Right, "settings_menu.vbox: config drop_down_bar", {.Mouse_Clickable }) | ||||
| 		{ | ||||
| 			drop_down_bar.layout.anchor.ratio.y = 0.1 | ||||
| 			ui_parent_push(drop_down_bar) | ||||
| 			{ | ||||
| 				using drop_down_bar | ||||
| 				text = str_intern("drop_down_bar") | ||||
| 				// style.bg_color        = { 55, 55, 55, 100 } | ||||
| 				style.font            = default_font | ||||
| 				style.text_color      = Color_White | ||||
| 				layout.flags          = {.Fixed_Height} | ||||
| 				layout.font_size      = 12 | ||||
| 				layout.text_alignment = {1, 0} | ||||
| 				layout.size.min.y     = 35 | ||||
| 				layout.anchor.ratio.y = 1.0 | ||||
| 			} | ||||
| 			ui_parent(drop_down_bar) | ||||
|  | ||||
| 			btn = ui_text("pls", str_intern("Lets figure this out...")) | ||||
| 			{ | ||||
| 				using btn | ||||
| 				text = str_intern("Config") | ||||
| 				style.font            = default_font | ||||
| 				style.text_color      = Color_White | ||||
| 				// layout.flags          = {.Origin_At_Anchor_Center} | ||||
| 			ui_theme_text() | ||||
| 			title := ui_text("drop_down_bar.btn", str_intern("drop_down_bar.btn")); { | ||||
| 				using title | ||||
| 				text = str_intern("App Config") | ||||
| 				style.text_color      = drop_down_bar.style.text_color | ||||
| 				layout.alignment      = {0.0, 0.0} | ||||
| 				layout.text_alignment = {0.0, 0.5} | ||||
| 				layout.anchor.ratio.x = 1.0 | ||||
| 				layout.font_size      = 12 | ||||
| 				layout.margins        = {0,0, 15, 0} | ||||
| 				layout.size.min.y     = 35 | ||||
| 			} | ||||
| 			um := ui_spacer("um...") | ||||
| 			um.layout.anchor.ratio.x = 1.0 | ||||
| 			ui_parent_pop() | ||||
| 			ui_hbox_end(drop_down_bar, compute_layout = true) | ||||
| 			if drop_down_bar.pressed do config_drop_down_open = !config_drop_down_open | ||||
| 		} | ||||
|  | ||||
| 		// ui_layout(UI_Layout { | ||||
| 		if config_drop_down_open | ||||
| 		{ | ||||
| 			{ | ||||
| 				ui_theme_table_row(is_even = false) | ||||
| 				hb := ui_hbox(.Left_To_Right, "settings_menu.engine_refresh_hz.hb"); { using hb | ||||
| 					layout.size.min = {0, 30} | ||||
| 					layout.flags = {.Fixed_Height} | ||||
| 					layout.padding = to_ui_layout_side(4) | ||||
| 				} | ||||
| 				ui_theme_text(); title := ui_text("settings_menu.engine_refresh_hz.title", str_intern("Engine Refresh Hz")); { using title | ||||
| 					layout.anchor.ratio.x = 1.0 | ||||
| 					layout.margins.left = 10 | ||||
| 					layout.text_alignment = {0, 0.5} | ||||
|  | ||||
| 		// }) | ||||
| 		// ui_style( UI_Style { | ||||
| 				} | ||||
| 				input_box := ui_widget("settings_menu.engine_refresh.input_box", {.Mouse_Clickable, .Focusable, .Click_To_Focus}); { using input_box | ||||
| 					layout.flags = {.Fixed_Width} | ||||
| 					layout.margins.left = 5 | ||||
| 					layout.padding.right = 10 | ||||
| 					layout.size.min.x = 80 | ||||
| 					if input_box.active do style.bg_color = app_color.input_box_bg_active | ||||
| 					else if input_box.hot do style.bg_color = app_color.input_box_bg_hot | ||||
| 					else do style.bg_color = app_color.input_box_bg | ||||
| 					style.corner_radii[0] = 0.35 | ||||
| 				} | ||||
| 				@static value_str : Array(rune) | ||||
| 				if value_str.data == nil { | ||||
| 					error : AllocatorError | ||||
| 					value_str, error = array_init_reserve(rune, persistent_slab_allocator(), Kilo) | ||||
| 					ensure(error != AllocatorError.None, "Failed to allocate array for value_str of input_box") | ||||
| 					array_append( & value_str, rune('_')) | ||||
| 				} | ||||
| 				if input_box.active { | ||||
| 					array_append( & value_str, input.keyboard_events.chars_pressed ) | ||||
| 					array_clear( input.keyboard_events.chars_pressed ) | ||||
| 				} | ||||
| 				else if input_box.was_active { | ||||
|  | ||||
| 		// }) | ||||
| 		// res_width_hbox := ui_hbox_begin(.Left_To_Right, "settings_menu.vbox: config.resolution_width: hbox", {}) | ||||
| 		// ui_parent(res_width_hbox) | ||||
|  | ||||
| 		spacer := ui_spacer("Settings Menu: Spacer") | ||||
| 		spacer.layout.anchor.ratio.y = 1.0 | ||||
| 				} | ||||
| 				else { | ||||
| 					array_clear( value_str) | ||||
| 					array_append( & value_str, to_runes(str_fmt_alloc("%v", config.engine_refresh_hz))) | ||||
| 				} | ||||
| 				// input_box | ||||
| 				{ | ||||
| 					ui_parent(input_box) | ||||
| 					value_txt := ui_text("settings_menu.engine_refresh.refresh_value", to_str_runes_pair(value_str)) | ||||
| 					value_txt.layout.text_alignment = vec2(1, 0.5) | ||||
| 				} | ||||
|  | ||||
| 				spacer := ui_spacer("settings_menu.engine_refresh.end_spacer") | ||||
| 				spacer.layout.flags = {.Fixed_Width} | ||||
| 				spacer.layout.size.min.x = 10 | ||||
| 				// input_text := ui_text("settings_menu.engine_refresh", str_fmt_alloc(value_str)) | ||||
| 			} | ||||
| 			{ | ||||
| 				ui_theme_table_row(is_even = true) | ||||
| 				hb := ui_hbox(.Left_To_Right, "settings_menu.cam_min_zoom.hb"); { using hb | ||||
| 					layout.size.min = {0, 30} | ||||
| 					layout.flags = {.Fixed_Height} | ||||
| 				} | ||||
| 				ui_theme_text(); title := ui_text("settings_menu.cam_min_zoom.title", str_intern("Camera: Min Zoom")); { using title | ||||
| 					layout.anchor.ratio.x = 1.0 | ||||
| 					layout.margins.left   = 10 | ||||
| 				} | ||||
| 			} | ||||
| 			{ | ||||
| 				ui_theme_table_row(is_even = false) | ||||
| 				hb := ui_hbox(.Left_To_Right, "settings_menu.cam_max_zoom.hb"); { using hb | ||||
| 					layout.size.min = {0, 30} | ||||
| 					layout.flags = {.Fixed_Height} | ||||
| 				} | ||||
| 				ui_theme_text(); title := ui_text("settings_menu.cam_max_zoom.title", str_intern("Camera: Max Zoom")); { using title | ||||
| 					layout.anchor.ratio.x = 1.0 | ||||
| 					layout.margins.left   = 10 | ||||
| 				} | ||||
| 			} | ||||
| 		} | ||||
| 		ui_vbox_end(vbox, compute_layout = false ) | ||||
| 	} | ||||
| 	return | ||||
|   | ||||
| @@ -159,6 +159,8 @@ AppConfig :: struct { | ||||
| 	timing_fps_moving_avg_alpha : f32, | ||||
|  | ||||
| 	ui_resize_border_width : f32, | ||||
|  | ||||
| 	color_theme : AppColorTheme, | ||||
| } | ||||
|  | ||||
| AppWindow :: struct { | ||||
| @@ -257,4 +259,7 @@ get_state :: #force_inline proc "contextless" () -> ^ State { | ||||
| // 	return get_state().frametime | ||||
| // } | ||||
|  | ||||
| app_config      :: #force_inline proc "contextless" () -> AppConfig     { return get_state().config } | ||||
| app_color_theme :: #force_inline proc "contextless" () -> AppColorTheme { return get_state().config.color_theme } | ||||
|  | ||||
| #endregion("State") | ||||
|   | ||||
							
								
								
									
										473
									
								
								code/sectr/app/ui_theme.odin
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										473
									
								
								code/sectr/app/ui_theme.odin
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,473 @@ | ||||
| package sectr | ||||
|  | ||||
| /* | ||||
| UI Themes: Comprise of UI_Box's layout & style | ||||
|  | ||||
| Provides presets for themes and their interface for manipulating the combo stacks in UI_State in pairs | ||||
| */ | ||||
| // TODO(Ed): Eventually this will have a configuration wizard, and we'll save the presets | ||||
|  | ||||
| @(deferred_none = ui_theme_pop) | ||||
| ui_theme_btn :: proc() | ||||
| { | ||||
| 	@static theme  : UI_Theme | ||||
| 	@static loaded : b32 = false | ||||
| 	if ! loaded | ||||
| 	{ | ||||
| 		app_color := app_color_theme() | ||||
| 		layout := UI_Layout { | ||||
| 			flags          = {}, | ||||
| 			anchor         = range2_zero, | ||||
| 			alignment      = {0, 0}, | ||||
| 			text_alignment = {0.5, 0.5}, | ||||
| 			font_size      = 16, | ||||
| 			margins        = {0, 0, 0, 0}, | ||||
| 			padding        = {0, 0, 0, 0}, | ||||
| 			border_width   = 1, | ||||
| 			pos            = {0, 0}, | ||||
| 			size           = range2_zero, | ||||
| 		} | ||||
| 		style := UI_Style { | ||||
| 			bg_color     = app_color.btn_bg_default, | ||||
| 			border_color = app_color.border_default, | ||||
| 			corner_radii = {}, | ||||
| 			blur_size    = 0, | ||||
| 			font         = get_state().default_font, | ||||
| 			text_color   = app_color.text_default, | ||||
| 			cursor       = {}, | ||||
| 		} | ||||
| 		layout_combo := to_ui_layout_combo(layout) | ||||
| 		style_combo  := to_ui_style_combo(style) | ||||
| 		Hot: { | ||||
| 			using layout_combo.hot | ||||
| 			using style_combo.hot | ||||
| 			bg_color   = app_color.btn_bg_hot | ||||
| 			text_color = app_color.text_hot | ||||
| 		} | ||||
| 		Active: { | ||||
| 			using layout_combo.active | ||||
| 			using style_combo.active | ||||
| 			bg_color   = app_color.btn_bg_active | ||||
| 			text_color = app_color.text_active | ||||
| 			margins    = {2, 2, 2, 2} | ||||
| 		} | ||||
| 		theme  = UI_Theme { layout_combo, style_combo } | ||||
| 		loaded = true | ||||
| 	} | ||||
| 	ui_layout_push(theme.layout) | ||||
| 	ui_style_push(theme.style) | ||||
| } | ||||
|  | ||||
| @(deferred_none = ui_theme_pop) | ||||
| ui_theme_drop_down :: proc() | ||||
| { | ||||
| 	@static theme  : UI_Theme | ||||
| 	@static loaded : b32 = false | ||||
| 	if ! loaded | ||||
| 	{ | ||||
| 		app_color := app_color_theme() | ||||
| 		layout := UI_Layout { | ||||
| 			flags          = {.Fixed_Height}, | ||||
| 			anchor         = range2({0, 0},{}), | ||||
| 			alignment      = {0, 0}, | ||||
| 			text_alignment = {0.5, 0.5}, | ||||
| 			font_size      = 14, | ||||
| 			margins        = {0, 0, 0, 0}, | ||||
| 			padding        = {0, 0, 0, 0}, | ||||
| 			border_width   = 1, | ||||
| 			pos            = {0, 0}, | ||||
| 			size           = range2({0,20},{}) | ||||
| 		} | ||||
| 		style := UI_Style { | ||||
| 			bg_color     = app_color.btn_bg_default, | ||||
| 			border_color = app_color.border_default, | ||||
| 			corner_radii = {}, | ||||
| 			blur_size    = 0, | ||||
| 			font         = get_state().default_font, | ||||
| 			text_color   = app_color.text_default, | ||||
| 			cursor       = {}, | ||||
| 		} | ||||
| 		layout_combo := to_ui_layout_combo(layout) | ||||
| 		style_combo  := to_ui_style_combo(style) | ||||
| 		Hot: { | ||||
| 			using layout_combo.hot | ||||
| 			using style_combo.hot | ||||
| 			bg_color   = app_color.btn_bg_hot | ||||
| 			text_color = app_color.text_hot | ||||
| 			margins    = {2, 2, 2, 2} | ||||
| 		} | ||||
| 		Active: { | ||||
| 			using layout_combo.active | ||||
| 			using style_combo.active | ||||
| 			bg_color   = app_color.btn_bg_active | ||||
| 			text_color = app_color.text_active | ||||
| 			margins    = {2, 2, 2, 2} | ||||
| 		} | ||||
| 		theme  = UI_Theme { layout_combo, style_combo } | ||||
| 		loaded = true | ||||
| 	} | ||||
| 	ui_layout_push(theme.layout) | ||||
| 	ui_style_push(theme.style) | ||||
| } | ||||
|  | ||||
| @(deferred_none = ui_theme_pop) | ||||
| ui_theme_table_row :: proc(is_even : bool) | ||||
| { | ||||
| 	@static theme  : UI_Theme | ||||
| 	@static loaded : b32 = false | ||||
| 	// if ! loaded | ||||
| 	{ | ||||
| 		app_color := app_color_theme() | ||||
| 		table_bg : Color | ||||
| 		if is_even { | ||||
| 			table_bg = app_color.table_even_bg_color | ||||
| 		} | ||||
| 		else { | ||||
| 			table_bg = app_color.table_odd_bg_color | ||||
| 		} | ||||
| 		layout := UI_Layout { | ||||
| 			flags          = {}, | ||||
| 			anchor         = range2({},{}), | ||||
| 			alignment      = {0, 0}, | ||||
| 			text_alignment = {0.0, 0.0}, | ||||
| 			font_size      = 16, | ||||
| 			margins        = {0, 0, 0, 0}, | ||||
| 			padding        = {0, 0, 0, 0}, | ||||
| 			border_width   = 0, | ||||
| 			pos            = {0, 0}, | ||||
| 			size           = range2({},{}) | ||||
| 		} | ||||
| 		style := UI_Style { | ||||
| 			bg_color     = table_bg, | ||||
| 			border_color = Color_Transparent, | ||||
| 			corner_radii = {}, | ||||
| 			blur_size    = 0, | ||||
| 			font         = get_state().default_font, | ||||
| 			text_color   = app_color_theme().text_default, | ||||
| 			cursor       = {}, | ||||
| 		} | ||||
| 		layout_combo := to_ui_layout_combo(layout) | ||||
| 		style_combo  := to_ui_style_combo(style) | ||||
| 		Hot: { | ||||
| 			using layout_combo.disabled | ||||
| 			using style_combo.disabled | ||||
| 		} | ||||
| 		Active: { | ||||
| 			using layout_combo.hot | ||||
| 			using style_combo.hot | ||||
| 		} | ||||
| 		{ | ||||
| 			using layout_combo.active | ||||
| 			using style_combo.active | ||||
| 		} | ||||
| 		theme  = UI_Theme { layout_combo, style_combo } | ||||
| 		loaded = true | ||||
| 	} | ||||
| 	ui_layout_push(theme.layout) | ||||
| 	ui_style_push(theme.style) | ||||
| } | ||||
|  | ||||
| @(deferred_none = ui_theme_pop) | ||||
| ui_theme_window_bar :: proc() | ||||
| { | ||||
| 	@static theme  : UI_Theme | ||||
| 	@static loaded : b32 = false | ||||
| 	if ! loaded || true | ||||
| 	{ | ||||
| 		app_color := app_color_theme() | ||||
| 		layout := UI_Layout { | ||||
| 			flags          = {.Fixed_Height}, | ||||
| 			anchor         = range2({},{}), | ||||
| 			alignment      = {0, 0}, | ||||
| 			text_alignment = {0.0, 0.0}, | ||||
| 			font_size      = 16, | ||||
| 			margins        = {0, 0, 0, 0}, | ||||
| 			padding        = {0, 0, 0, 0}, | ||||
| 			border_width   = 0.0, | ||||
| 			pos            = {0, 0}, | ||||
| 			size           = range2({0, 35},{}) | ||||
| 		} | ||||
| 		style := UI_Style { | ||||
| 			bg_color     = app_color.window_bar_bg, | ||||
| 			border_color = Color_Transparent, | ||||
| 			corner_radii = {}, | ||||
| 			blur_size    = 0, | ||||
| 			font         = get_state().default_font, | ||||
| 			text_color   = app_color.text_default, | ||||
| 			cursor       = {}, | ||||
| 		} | ||||
| 		layout_combo := to_ui_layout_combo(layout) | ||||
| 		style_combo  := to_ui_style_combo(style) | ||||
| 		Disabled : { | ||||
| 			using layout_combo.disabled | ||||
| 			using style_combo.disabled | ||||
| 		} | ||||
| 		Hot: { | ||||
| 			using layout_combo.hot | ||||
| 			using style_combo.hot | ||||
| 			border_color = app_color.window_bar_border | ||||
| 			border_width = 1.0 | ||||
| 		} | ||||
| 		Active: { | ||||
| 			using layout_combo.active | ||||
| 			using style_combo.active | ||||
| 			border_color = app_color.window_bar_border | ||||
| 			border_width = 2.0 | ||||
| 		} | ||||
| 		theme  = UI_Theme { layout_combo, style_combo } | ||||
| 		loaded = true | ||||
| 	} | ||||
| 	ui_layout_push(theme.layout) | ||||
| 	ui_style_push(theme.style) | ||||
| } | ||||
|  | ||||
| @(deferred_none = ui_theme_pop) | ||||
| ui_theme_window_bar_title :: proc() | ||||
| { | ||||
| 	@static theme  : UI_Theme | ||||
| 	@static loaded : b32 = false | ||||
| 	if ! loaded | ||||
| 	{ | ||||
| 		app_color := app_color_theme() | ||||
| 		layout := UI_Layout { | ||||
| 			flags          = {}, | ||||
| 			anchor         = range2({},{}), | ||||
| 			alignment      = {0, 0}, | ||||
| 			text_alignment = {0.0, 0.0}, | ||||
| 			font_size      = 16, | ||||
| 			margins        = {0, 0, 0, 0}, | ||||
| 			padding        = {0, 0, 0, 0}, | ||||
| 			border_width   = 0, | ||||
| 			pos            = {0, 0}, | ||||
| 			size           = range2({},{}) | ||||
| 		} | ||||
| 		style := UI_Style { | ||||
| 			bg_color     = Color_Transparent, | ||||
| 			border_color = Color_Transparent, | ||||
| 			corner_radii = {}, | ||||
| 			blur_size    = 0, | ||||
| 			font         = get_state().default_font, | ||||
| 			text_color   = app_color.text_default, | ||||
| 			cursor       = {}, | ||||
| 		} | ||||
| 		layout_combo := to_ui_layout_combo(layout) | ||||
| 		style_combo  := to_ui_style_combo(style) | ||||
| 		Disabed: { | ||||
| 			using layout_combo.disabled | ||||
| 			using style_combo.disabled | ||||
| 		} | ||||
| 		Hot: { | ||||
| 			using layout_combo.hot | ||||
| 			using style_combo.hot | ||||
| 		} | ||||
| 		Active: { | ||||
| 			using layout_combo.active | ||||
| 			using style_combo.active | ||||
| 		} | ||||
| 		theme  = UI_Theme { layout_combo, style_combo } | ||||
| 		loaded = true | ||||
| 	} | ||||
| 	ui_layout_push(theme.layout) | ||||
| 	ui_style_push(theme.style) | ||||
| } | ||||
|  | ||||
| @(deferred_none = ui_theme_pop) | ||||
| ui_theme_window_bar_btn :: proc() | ||||
| { | ||||
| 	@static theme  : UI_Theme | ||||
| 	@static loaded : b32 = false | ||||
| 	if ! loaded | ||||
| 	{ | ||||
| 		app_color := app_color_theme() | ||||
| 		layout := UI_Layout { | ||||
| 			flags          = {.Fixed_Width}, | ||||
| 			anchor         = range2({1, 0},{}), | ||||
| 			alignment      = {0, 0}, | ||||
| 			text_alignment = {0.5, 0.5}, | ||||
| 			font_size      = 16, | ||||
| 			margins        = {0, 0, 0, 0}, | ||||
| 			padding        = {0, 0, 0, 0}, | ||||
| 			border_width   = 1, | ||||
| 			pos            = {0, 0}, | ||||
| 			size           = range2({50,0},{}) | ||||
| 		} | ||||
| 		style := UI_Style { | ||||
| 			bg_color     = app_color.btn_bg_default, | ||||
| 			border_color = app_color.border_default, | ||||
| 			corner_radii = {}, | ||||
| 			blur_size    = 0, | ||||
| 			font         = get_state().default_font, | ||||
| 			text_color   = app_color.text_default, | ||||
| 			cursor       = {}, | ||||
| 		} | ||||
| 		layout_combo := to_ui_layout_combo(layout) | ||||
| 		style_combo  := to_ui_style_combo(style) | ||||
| 		Hot: { | ||||
| 			using layout_combo.hot | ||||
| 			using style_combo.hot | ||||
| 			bg_color   = app_color.btn_bg_hot | ||||
| 			text_color = app_color.text_hot | ||||
| 		} | ||||
| 		Active: { | ||||
| 			using layout_combo.active | ||||
| 			using style_combo.active | ||||
| 			bg_color   = app_color.btn_bg_active | ||||
| 			text_color = app_color.text_active | ||||
| 			margins    = {2, 2, 2, 2} | ||||
| 		} | ||||
| 		theme  = UI_Theme { layout_combo, style_combo } | ||||
| 		loaded = true | ||||
| 	} | ||||
| 	ui_layout_push(theme.layout) | ||||
| 	ui_style_push(theme.style) | ||||
| } | ||||
|  | ||||
| @(deferred_none = ui_theme_pop) | ||||
| ui_theme_window_panel :: proc() | ||||
| { | ||||
| 	@static theme  : UI_Theme | ||||
| 	@static loaded : b32 = false | ||||
| 	if ! loaded | ||||
| 	{ | ||||
| 		app_color := app_color_theme() | ||||
| 		layout := UI_Layout { | ||||
| 			flags          = {}, | ||||
| 			anchor         = range2({},{}), | ||||
| 			alignment      = {0, 0}, | ||||
| 			text_alignment = {0.0, 0.0}, | ||||
| 			font_size      = 16, | ||||
| 			margins        = {0, 0, 0, 0}, | ||||
| 			padding        = {0, 0, 0, 0}, | ||||
| 			border_width   = 1, | ||||
| 			pos            = {0, 0}, | ||||
| 			size           = range2({},{}) | ||||
| 		} | ||||
| 		style := UI_Style { | ||||
| 			bg_color     = app_color.window_panel_bg, | ||||
| 			border_color = app_color.window_panel_border, | ||||
| 			corner_radii = {}, | ||||
| 			blur_size    = 0, | ||||
| 			font         = get_state().default_font, | ||||
| 			text_color   = app_color.text_default, | ||||
| 			cursor       = {}, | ||||
| 		} | ||||
| 		layout_combo := to_ui_layout_combo(layout) | ||||
| 		style_combo  := to_ui_style_combo(style) | ||||
| 		Disabled: { | ||||
| 			using layout_combo.disabled | ||||
| 			using style_combo.disabled | ||||
| 		} | ||||
| 		Hot: { | ||||
| 			using layout_combo.hot | ||||
| 			using style_combo.hot | ||||
| 		} | ||||
| 		Active: { | ||||
| 			using layout_combo.active | ||||
| 			using style_combo.active | ||||
| 		} | ||||
| 		theme  = UI_Theme { layout_combo, style_combo } | ||||
| 		loaded = true | ||||
| 	} | ||||
| 	ui_layout_push(theme.layout) | ||||
| 	ui_style_push(theme.style) | ||||
| } | ||||
|  | ||||
| @(deferred_none = ui_theme_pop) | ||||
| ui_theme_transparent :: proc() | ||||
| { | ||||
| 	@static theme  : UI_Theme | ||||
| 	@static loaded : b32 = false | ||||
| 	if ! loaded | ||||
| 	{ | ||||
| 		app_color := app_color_theme() | ||||
| 		layout := UI_Layout { | ||||
| 			flags          = {}, | ||||
| 			anchor         = range2({},{}), | ||||
| 			alignment      = {0, 0}, | ||||
| 			text_alignment = {0.0, 0.0}, | ||||
| 			font_size      = 16, | ||||
| 			margins        = {0, 0, 0, 0}, | ||||
| 			padding        = {0, 0, 0, 0}, | ||||
| 			border_width   = 0, | ||||
| 			pos            = {0, 0}, | ||||
| 			size           = range2({},{}) | ||||
| 		} | ||||
| 		style := UI_Style { | ||||
| 			bg_color     = Color_Transparent, | ||||
| 			border_color = Color_Transparent, | ||||
| 			corner_radii = {}, | ||||
| 			blur_size    = 0, | ||||
| 			font         = get_state().default_font, | ||||
| 			text_color   = app_color.text_default, | ||||
| 			cursor       = {}, | ||||
| 		} | ||||
| 		layout_combo := to_ui_layout_combo(layout) | ||||
| 		style_combo  := to_ui_style_combo(style) | ||||
| 		{ | ||||
| 			using layout_combo.disabled | ||||
| 			using style_combo.disabled | ||||
| 		} | ||||
| 		{ | ||||
| 			using layout_combo.hot | ||||
| 			using style_combo.hot | ||||
| 		} | ||||
| 		{ | ||||
| 			using layout_combo.active | ||||
| 			using style_combo.active | ||||
| 		} | ||||
| 		theme  = UI_Theme { layout_combo, style_combo } | ||||
| 		loaded = true | ||||
| 	} | ||||
| 	ui_layout_push(theme.layout) | ||||
| 	ui_style_push(theme.style) | ||||
| } | ||||
|  | ||||
| @(deferred_none = ui_theme_pop) | ||||
| ui_theme_text :: proc() | ||||
| { | ||||
| 	@static theme  : UI_Theme | ||||
| 	@static loaded : b32 = false | ||||
| 	if ! loaded | ||||
| 	{ | ||||
| 		app_color := app_color_theme() | ||||
| 		layout := UI_Layout { | ||||
| 			flags          = {}, | ||||
| 			anchor         = range2({},{}), | ||||
| 			alignment      = {0, 0}, | ||||
| 			text_alignment = {0.0, 0.5}, | ||||
| 			font_size      = 14, | ||||
| 			margins        = {0, 0, 0, 0}, | ||||
| 			padding        = {0, 0, 0, 0}, | ||||
| 			border_width   = 0, | ||||
| 			pos            = {0, 0}, | ||||
| 			size           = range2({},{}) | ||||
| 		} | ||||
| 		style := UI_Style { | ||||
| 			bg_color     = Color_Transparent, | ||||
| 			border_color = Color_Transparent, | ||||
| 			corner_radii = {}, | ||||
| 			blur_size    = 0, | ||||
| 			font         = get_state().default_font, | ||||
| 			text_color   = app_color.text_default, | ||||
| 			cursor       = {}, | ||||
| 		} | ||||
| 		layout_combo := to_ui_layout_combo(layout) | ||||
| 		style_combo  := to_ui_style_combo(style) | ||||
| 		{ | ||||
| 			using layout_combo.disabled | ||||
| 			using style_combo.disabled | ||||
| 		} | ||||
| 		{ | ||||
| 			using layout_combo.hot | ||||
| 			using style_combo.hot | ||||
| 		} | ||||
| 		{ | ||||
| 			using layout_combo.active | ||||
| 			using style_combo.active | ||||
| 		} | ||||
| 		theme  = UI_Theme { layout_combo, style_combo } | ||||
| 		loaded = true | ||||
| 	} | ||||
| 	ui_layout_push(theme.layout) | ||||
| 	ui_style_push(theme.style) | ||||
| } | ||||
| @@ -1,114 +0,0 @@ | ||||
| package sectr | ||||
|  | ||||
| /* | ||||
| UI Themes: Comprise of UI_Box's layout & style | ||||
|  | ||||
| Provides presets for themes and their interface for manipulating the combo stacks in UI_State in pairs | ||||
| */ | ||||
| // TODO(Ed): Eventually this will have a configuration wizard, and we'll save the presets | ||||
|  | ||||
| @(deferred_none = ui_theme_pop) | ||||
| ui_theme_btn_default :: proc() | ||||
| { | ||||
| 	@static theme : UI_Theme | ||||
| 	@static loaded : b32 = false | ||||
| 	if ! loaded | ||||
| 	{ | ||||
| 		layout := UI_Layout { | ||||
| 			flags          = {}, | ||||
| 			anchor         = range2({},{}), | ||||
| 			alignment      = {0, 0}, | ||||
| 			text_alignment = {0.5, 0.5}, | ||||
| 			font_size      = 16, | ||||
| 			margins        = {0, 0, 0, 0}, | ||||
| 			padding        = {0, 0, 0, 0}, | ||||
| 			border_width   = 1, | ||||
| 			pos            = {0, 0}, | ||||
| 			size           = range2({},{}) | ||||
| 		} | ||||
| 		style := UI_Style { | ||||
| 			bg_color     = Color_ThmDark_Btn_BG_Default, | ||||
| 			border_color = Color_ThmDark_Border_Default, | ||||
| 			corner_radii = {}, | ||||
| 			blur_size    = 0, | ||||
| 			font         = get_state().default_font, | ||||
| 			text_color   = Color_ThmDark_Text_Default, | ||||
| 			cursor       = {}, | ||||
| 		} | ||||
| 		layout_combo := to_ui_layout_combo(layout) | ||||
| 		style_combo  := to_ui_style_combo(style) | ||||
| 		{ | ||||
| 			using layout_combo.hot | ||||
| 			using style_combo.hot | ||||
| 			bg_color   = Color_ThmDark_Btn_BG_Hot | ||||
| 			text_color = Color_ThmDark_Text_Hot | ||||
| 			margins    = {2, 2, 2, 2} | ||||
| 		} | ||||
| 		{ | ||||
| 			using layout_combo.active | ||||
| 			using style_combo.active | ||||
| 			bg_color   = Color_ThmDark_Btn_BG_Active | ||||
| 			text_color = Color_ThmDark_Text_Active | ||||
| 			margins    = {2, 2, 2, 2} | ||||
| 		} | ||||
| 		theme = UI_Theme { | ||||
| 			layout_combo, style_combo | ||||
| 		} | ||||
| 		loaded = true | ||||
| 	} | ||||
| 	ui_layout_push(theme.layout) | ||||
| 	ui_style_push(theme.style) | ||||
| } | ||||
|  | ||||
| @(deferred_none = ui_theme_pop) | ||||
| ui_theme_transparent :: proc() | ||||
| { | ||||
| 	@static theme : UI_Theme | ||||
| 	@static loaded : b32 = false | ||||
| 	if ! loaded || true | ||||
| 	{ | ||||
| 		layout := UI_Layout { | ||||
| 			flags          = {}, | ||||
| 			anchor         = range2({},{}), | ||||
| 			alignment      = {0, 0}, | ||||
| 			text_alignment = {0.0, 0.0}, | ||||
| 			font_size      = 16, | ||||
| 			margins        = {0, 0, 0, 0}, | ||||
| 			padding        = {0, 0, 0, 0}, | ||||
| 			border_width   = 0, | ||||
| 			pos            = {0, 0}, | ||||
| 			size           = range2({},{}) | ||||
| 		} | ||||
| 		style := UI_Style { | ||||
| 			bg_color     = Color_Transparent, | ||||
| 			border_color = Color_Transparent, | ||||
| 			corner_radii = {}, | ||||
| 			blur_size    = 0, | ||||
| 			font         = get_state().default_font, | ||||
| 			text_color   = Color_ThmDark_Text_Default, | ||||
| 			cursor       = {}, | ||||
| 		} | ||||
|  | ||||
| 		layout_combo := to_ui_layout_combo(layout) | ||||
| 		style_combo  := to_ui_style_combo(style) | ||||
| 		{ | ||||
| 			using layout_combo.disabled | ||||
| 			using style_combo.disabled | ||||
| 		} | ||||
| 		{ | ||||
| 			using layout_combo.hot | ||||
| 			using style_combo.hot | ||||
| 		} | ||||
| 		{ | ||||
| 			using layout_combo.active | ||||
| 			using style_combo.active | ||||
| 		} | ||||
|  | ||||
| 		theme = UI_Theme { | ||||
| 			layout_combo, style_combo | ||||
| 		} | ||||
| 		loaded = true | ||||
| 	} | ||||
| 	ui_layout_push(theme.layout) | ||||
| 	ui_style_push(theme.style) | ||||
| } | ||||
| @@ -31,32 +31,114 @@ Color_Debug_UI_Content_Bounds :: Color { 170, 120, 240, 160 } | ||||
| // TODO(Ed): The entire rendering pass should be post-processed by a tone curve configurable for the user | ||||
| // This is how you properly support any tonality of light or dark themes and not have it be base don the monitors raw output. | ||||
|  | ||||
| // Dark Theme | ||||
| AppColorTheme :: struct { | ||||
| 	light_limit, | ||||
| 	dark_limit, | ||||
|  | ||||
| // Brightest value limited to (text is the only exception): | ||||
| Color_ThmDark_BrightLimit :: Color {230, 230, 230, 255} | ||||
| // Darkness value limited to (text is the only exception): | ||||
| Color_ThmDark_DarkLimit   :: Color {10, 10, 10, 255} | ||||
| 	bg, | ||||
|  | ||||
| 	border_default, | ||||
|  | ||||
| Color_ThmDark_BG :: Color {33, 33, 33, 255} | ||||
| 	btn_bg_default, | ||||
| 	btn_bg_hot, | ||||
| 	btn_bg_active, | ||||
|  | ||||
| Color_ThmDark_Translucent_Panel :: Color { 0, 0, 0, 60} | ||||
| 	input_box_bg, | ||||
| 	input_box_bg_hot, | ||||
| 	input_box_bg_active, | ||||
|  | ||||
| Color_ThmDark_ResizeHandle_Default :: Color_Transparent | ||||
| Color_ThmDark_ResizeHandle_Hot     :: Color { 72, 72, 72, 90} | ||||
| Color_ThmDark_ResizeHandle_Active  :: Color { 88, 88, 88, 90} | ||||
| 	resize_hndl_default, | ||||
| 	resize_hndl_hot, | ||||
| 	resize_hndl_active, | ||||
|  | ||||
| Color_ThmDark_Border_Default :: Color { 64, 64, 64, 255} | ||||
| 	table_even_bg_color, | ||||
| 	table_odd_bg_color, | ||||
|  | ||||
| Color_ThmDark_Btn_BG_Default :: Color { 40,  40,  40, 255} | ||||
| Color_ThmDark_Btn_BG_Hot     :: Color { 60,  60,  70, 255} | ||||
| Color_ThmDark_Btn_BG_Active  :: Color { 90, 100, 130, 255} | ||||
| 	text_default, | ||||
| 	text_hot, | ||||
| 	text_active, | ||||
|  | ||||
| Color_ThmDark_Text_Default :: Color {120, 117, 115, 255} | ||||
| Color_ThmDark_Text_Hot     :: Color {180, 180, 180, 255} | ||||
| Color_ThmDark_Text_Active  :: Color {240, 240, 240, 255} | ||||
| 	translucent_panel, | ||||
|  | ||||
| // Light Theme | ||||
| 	window_bar_border, | ||||
| 	window_bar_bg, | ||||
| 	window_btn_close_bg_hot, | ||||
|  | ||||
| // LightTheme_BG :: Color { 120, 120, 120, 255 } | ||||
| 	window_panel_bg, | ||||
| 	window_panel_border \ | ||||
| 	: Color | ||||
| } | ||||
|  | ||||
| App_Thm_Dusk :: AppColorTheme { | ||||
| 	light_limit = Color {125, 125, 125, 255}, | ||||
| 	dark_limit  = Color { 10, 10, 10, 255}, | ||||
|  | ||||
| 	bg = Color {33, 33, 33, 255}, | ||||
|  | ||||
| 	border_default = Color { 64, 64, 64, 255}, | ||||
|  | ||||
| 	btn_bg_default = Color { 40,  40,  40, 255}, | ||||
| 	btn_bg_hot     = Color { 60,  60,  70, 255}, | ||||
| 	btn_bg_active  = Color { 90, 100, 130, 255}, | ||||
|  | ||||
| 	input_box_bg        = Color { 20, 20, 20, 255}, | ||||
| 	input_box_bg_hot    = Color { 25, 25, 25, 255}, | ||||
| 	input_box_bg_active = Color { 15, 15, 15, 255}, | ||||
|  | ||||
| 	resize_hndl_default = Color_Transparent, | ||||
| 	resize_hndl_hot     = Color { 72, 72, 72, 90}, | ||||
| 	resize_hndl_active  = Color { 88, 88, 88, 90}, | ||||
|  | ||||
| 	table_even_bg_color = Color { 35, 35, 35, 255}, | ||||
| 	table_odd_bg_color  = Color { 30, 30, 30, 255}, | ||||
|  | ||||
| 	text_default = Color {120, 117, 115, 255}, | ||||
| 	text_hot     = Color {180, 180, 180, 255}, | ||||
| 	text_active  = Color {240, 240, 240, 255}, | ||||
|  | ||||
| 	translucent_panel = Color { 10, 10, 10, 50}, | ||||
|  | ||||
| 	window_bar_border       = Color { 64, 64, 64, 255}, // border_default | ||||
| 	window_bar_bg           = Color{35, 35, 35, 255}, | ||||
| 	window_btn_close_bg_hot = Color{45, 35, 35, 255}, | ||||
|  | ||||
| 	window_panel_bg     = Color { 10, 10, 10, 50}, // translucent_panel | ||||
| 	window_panel_border = Color{24, 24, 24, 255}, | ||||
| } | ||||
|  | ||||
| App_Thm_Light :: AppColorTheme { | ||||
| 	light_limit = Color {195, 195, 195, 255}, | ||||
| 	dark_limit  = Color { 60,  60,  60, 255}, | ||||
|  | ||||
| 	bg = Color {135, 135, 135, 255}, | ||||
|  | ||||
| 	border_default = Color { 174, 174, 174, 255}, | ||||
|  | ||||
| 	btn_bg_default = Color { 160, 160, 160, 255}, | ||||
| 	btn_bg_hot     = Color { 145, 145, 155, 255}, | ||||
| 	btn_bg_active  = Color { 124, 124, 136, 255}, | ||||
|  | ||||
| 	input_box_bg        = Color {115, 115, 115, 255}, | ||||
| 	input_box_bg_hot    = Color {125, 125, 125, 255}, | ||||
| 	input_box_bg_active = Color {105, 105, 105, 255}, | ||||
|  | ||||
| 	resize_hndl_default = Color_Transparent, | ||||
| 	resize_hndl_hot     = Color { 95, 95, 95, 90}, | ||||
| 	resize_hndl_active  = Color { 80, 80, 80, 90}, | ||||
|  | ||||
| 	table_even_bg_color = Color {150, 150, 150, 255}, | ||||
| 	table_odd_bg_color  = Color {160, 160, 160, 255}, | ||||
|  | ||||
| 	text_default = Color { 55,  55,  55, 255}, | ||||
| 	text_hot     = Color { 85,  85,  85, 255}, | ||||
| 	text_active  = Color { 45,  45,  49, 255}, | ||||
|  | ||||
| 	translucent_panel = Color { 110, 110, 110, 50}, | ||||
|  | ||||
| 	window_bar_border       = Color{ 174, 174, 174, 255}, // border_default | ||||
| 	window_bar_bg           = Color{ 155, 155, 155, 255}, | ||||
| 	window_btn_close_bg_hot = Color{ 145, 135, 135, 255}, | ||||
|  | ||||
| 	window_panel_bg     = Color {135, 135, 135, 50}, // translucent_panel | ||||
| 	window_panel_border = Color{184, 184, 184, 255}, | ||||
| } | ||||
|   | ||||
| @@ -60,7 +60,7 @@ startup :: proc( prof : ^SpallProfiler, persistent_mem, frame_mem, transient_mem | ||||
| 	Memory_App.state = state | ||||
| 	using state | ||||
|  | ||||
| 	// Setup Persistent Slab | ||||
| 	// Setup Persistent Slabs & String Cache | ||||
| 	{ | ||||
| 		alignment := uint(mem.DEFAULT_ALIGNMENT) | ||||
|  | ||||
| @@ -93,14 +93,24 @@ startup :: proc( prof : ^SpallProfiler, persistent_mem, frame_mem, transient_mem | ||||
| 		verify( alloc_error == .None, "Failed to allocate transient slab" ) | ||||
|  | ||||
| 		transient_clear_time = 120 // Seconds, 2 Minutes | ||||
|  | ||||
| 		string_cache = str_cache_init() | ||||
| 	} | ||||
|  | ||||
| 	string_cache = str_cache_init() | ||||
|  | ||||
| 	// Setup input frame poll references | ||||
| 	input      = & input_data[1] | ||||
| 	input_prev = & input_data[0] | ||||
| 	for & input in input_data { | ||||
| 		using input | ||||
| 		error : AllocatorError | ||||
| 		keyboard_events.keys_pressed, error  = array_init_reserve(KeyboardKey, persistent_slab_allocator(), Kilo) | ||||
| 		ensure(error == AllocatorError.None, "Failed to allocate input.keyboard_events.keys_pressed array") | ||||
| 		keyboard_events.chars_pressed, error = array_init_reserve(rune, persistent_slab_allocator(), Kilo) | ||||
| 		ensure(error == AllocatorError.None, "Failed to allocate input.keyboard_events.chars_pressed array") | ||||
| 	} | ||||
|  | ||||
| 	// Configuration Load | ||||
| 	// TODO(Ed): Make this actually load from an ini | ||||
| 	{ | ||||
| 		using config | ||||
| 		resolution_width  = 1000 | ||||
| @@ -119,6 +129,8 @@ startup :: proc( prof : ^SpallProfiler, persistent_mem, frame_mem, transient_mem | ||||
| 		timing_fps_moving_avg_alpha = 0.9 | ||||
|  | ||||
| 		ui_resize_border_width = 5 | ||||
|  | ||||
| 		color_theme = App_Thm_Dusk | ||||
| 	} | ||||
|  | ||||
| 	Desired_OS_Scheduler_MS :: 1 | ||||
| @@ -182,6 +194,7 @@ startup :: proc( prof : ^SpallProfiler, persistent_mem, frame_mem, transient_mem | ||||
| 	} | ||||
|  | ||||
| 	// Demo project setup | ||||
| 	// TODO(Ed): This will eventually have to occur when the user either creates or loads a workspace. I don't know  | ||||
| 	{ | ||||
| 		using project | ||||
| 		path           = str_intern("./") | ||||
| @@ -318,10 +331,12 @@ tick :: proc( host_delta_time : f64, host_delta_ns : Duration ) -> b32 | ||||
|  | ||||
| 		rl.PollInputEvents() | ||||
|  | ||||
| 		debug.draw_ui_box_bounds_points = true | ||||
| 		debug.draw_ui_box_bounds_points = false | ||||
| 		debug.draw_UI_padding_bounds = false | ||||
| 		debug.draw_ui_content_bounds = true | ||||
| 		debug.draw_ui_content_bounds = false | ||||
|  | ||||
| 		config.color_theme = App_Thm_Light | ||||
| 		// config.color_theme = App_Thm_Dusk | ||||
| 		should_close = update( host_delta_time ) | ||||
| 		render() | ||||
|  | ||||
|   | ||||
| @@ -43,7 +43,7 @@ render :: proc() | ||||
| 	render_mode_3d() | ||||
|  | ||||
| 	rl.BeginDrawing() | ||||
| 	rl.ClearBackground( Color_ThmDark_BG ) | ||||
| 	rl.ClearBackground( app_color_theme().bg ) | ||||
|  | ||||
| 	render_mode_2d_workspace() | ||||
| 	render_mode_screenspace() | ||||
| @@ -252,7 +252,7 @@ render_mode_screenspace :: proc () | ||||
| 	{ | ||||
| 		// 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_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 { | ||||
| @@ -261,10 +261,9 @@ render_mode_screenspace :: proc () | ||||
| 		if replay.mode == ReplayMode.Playback { | ||||
| 			debug_text( "Replaying Input") | ||||
| 		} | ||||
| 		// debug_text("Zoom Target: %v", project.workspace.zoom_target) | ||||
| 	} | ||||
|  | ||||
| 	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 Delta                    : %v", input.mouse.delta ) | ||||
| @@ -277,34 +276,39 @@ render_mode_screenspace :: proc () | ||||
|  | ||||
| 	ui := & project.workspace.ui | ||||
|  | ||||
| 	debug_text("Box Count (Workspace): %v", ui.built_box_count ) | ||||
| 	if false | ||||
| 	{ | ||||
| 		debug_text("Box Count (Workspace): %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("Worksapce Hot    Box   : %v", hot_box.label.str ) | ||||
| 		debug_text("Workspace Hot    Range2: %v", hot_box.computed.bounds.pts) | ||||
| 	} | ||||
| 	if active_box != nil{ | ||||
| 		debug_text("Workspace Active Box: %v", active_box.label.str ) | ||||
| 		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("Worksapce Hot    Box   : %v", hot_box.label.str ) | ||||
| 			debug_text("Workspace Hot    Range2: %v", hot_box.computed.bounds.pts) | ||||
| 		} | ||||
| 		if active_box != nil{ | ||||
| 			debug_text("Workspace Active Box: %v", active_box.label.str ) | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	ui = & screen_ui | ||||
|  | ||||
| 	debug_text("Box Count: %v", ui.built_box_count ) | ||||
| 	if true | ||||
| 	{ | ||||
| 		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 ) | ||||
| 		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 ) | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	view := view_get_bounds() | ||||
|  | ||||
| 	debug.draw_debug_text_y = 14 | ||||
|  | ||||
| 	 // Define the triangle vertices and colors | ||||
|   | ||||
| @@ -239,7 +239,7 @@ update :: proc( delta_time : f64 ) -> b32 | ||||
| 		// test_hover_n_click() | ||||
| 		// test_draggable() | ||||
| 		// test_text_box() | ||||
| 		test_parenting( & default_layout, & frame_style_default ) | ||||
| 		// test_parenting( & default_layout, & frame_style_default ) | ||||
| 		// test_whitespace_ast( & default_layout, & frame_style_default ) | ||||
| 	} | ||||
| 	//endregion Workspace Imgui Tick | ||||
|   | ||||
| @@ -75,7 +75,7 @@ array_init_reserve :: proc | ||||
| 	return | ||||
| } | ||||
|  | ||||
| array_append :: proc( self : ^Array( $ Type), value : Type ) -> AllocatorError | ||||
| array_append_value :: proc( self : ^Array( $ Type), value : Type ) -> AllocatorError | ||||
| { | ||||
| 	// profile(#procedure) | ||||
| 	if self.header.num == self.header.capacity | ||||
| @@ -91,11 +91,11 @@ array_append :: proc( self : ^Array( $ Type), value : Type ) -> AllocatorError | ||||
| 	return AllocatorError.None | ||||
| } | ||||
|  | ||||
| array_append_slice :: proc( using self : ^Array( $ Type ), items : []Type ) -> AllocatorError | ||||
| array_append_array :: proc( using self: ^Array( $ Type), other : Array(Type)) -> AllocatorError | ||||
| { | ||||
| 	if num + len(items) > capacity | ||||
| 	if num + other.num > capacity | ||||
| 	{ | ||||
| 		grow_result := array_grow( self, capacity ) | ||||
| 		grow_result := array_grow( self, num + other.num ) | ||||
| 		if grow_result != AllocatorError.None { | ||||
| 			return grow_result | ||||
| 		} | ||||
| @@ -106,9 +106,31 @@ array_append_slice :: proc( using self : ^Array( $ Type ), items : []Type ) -> A | ||||
|  | ||||
| 	// TODO(Ed) : VERIFY VIA DEBUG THIS COPY IS FINE. | ||||
| 	target := ptr_offset( data, num ) | ||||
| 	copy( slice_ptr(target, capacity - num), items ) | ||||
| 	copy( slice_ptr(target, int(capacity - num)), array_to_slice(other) ) | ||||
|  | ||||
| 	num += len(items) | ||||
| 	num += other.num | ||||
| 	return AllocatorError.None | ||||
| } | ||||
|  | ||||
| array_append_slice :: proc( using self : ^Array( $ Type ), items : []Type ) -> AllocatorError | ||||
| { | ||||
| 	items_num :=u64(len(items)) | ||||
| 	if num + items_num > capacity | ||||
| 	{ | ||||
| 		grow_result := array_grow( self, num + items_num ) | ||||
| 		if grow_result != AllocatorError.None { | ||||
| 			return grow_result | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	// Note(Ed) : Original code from gencpp | ||||
| 	// libc.memcpy( ptr_offset(data, num), raw_data(items), len(items) * size_of(Type) ) | ||||
|  | ||||
| 	// TODO(Ed) : VERIFY VIA DEBUG THIS COPY IS FINE. | ||||
| 	target := ptr_offset( data, num ) | ||||
| 	copy( slice_ptr(target, int(capacity - num)), items ) | ||||
|  | ||||
| 	num += items_num | ||||
| 	return AllocatorError.None | ||||
| } | ||||
|  | ||||
|   | ||||
| @@ -107,6 +107,12 @@ add :: proc { | ||||
| 	add_range2, | ||||
| } | ||||
|  | ||||
| array_append :: proc { | ||||
| 	array_append_value, | ||||
| 	array_append_array, | ||||
| 	array_append_slice, | ||||
| } | ||||
|  | ||||
| bivec3 :: proc { | ||||
| 	bivec3_via_f32s, | ||||
| 	vec3_to_bivec3, | ||||
|   | ||||
| @@ -1 +1 @@ | ||||
| package sectr | ||||
| package sectr | ||||
|   | ||||
| @@ -281,221 +281,13 @@ mouse_world_delta :: #force_inline proc "contextless" () -> Vec2 { | ||||
|  | ||||
| InputState :: struct { | ||||
| 	keyboard : KeyboardState, | ||||
| 	mouse    : MouseState | ||||
| 	mouse    : MouseState, | ||||
|  | ||||
| 	keyboard_events : KeyboardEvents, | ||||
| } | ||||
|  | ||||
| import    "core:os" | ||||
| import c  "core:c/libc" | ||||
| import rl "vendor:raylib" | ||||
|  | ||||
| poll_input :: proc( old, new : ^ InputState ) | ||||
| { | ||||
| 	profile(#procedure) | ||||
| 	input_process_digital_btn :: proc( old_state, new_state : ^ DigitalBtn, is_down : b32 ) | ||||
| 	{ | ||||
| 		new_state.ended_down = is_down | ||||
| 		had_transition := old_state.ended_down != new_state.ended_down | ||||
| 		if had_transition { | ||||
| 			new_state.half_transitions += 1 | ||||
| 		} | ||||
| 		else { | ||||
| 			new_state.half_transitions = 0 | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	// Keyboard | ||||
| 	{ | ||||
| 		// profile("Keyboard") | ||||
| 		check_range :: proc( old, new : ^ InputState, start, end : i32 ) | ||||
| 		{ | ||||
| 			for id := start; id < end; id += 1 | ||||
| 			{ | ||||
| 				// TODO(Ed) : LOOK OVER THIS... | ||||
| 				entry_old := & old.keyboard.keys[id - 1] | ||||
| 				entry_new := & new.keyboard.keys[id - 1] | ||||
|  | ||||
| 				key_id := cast(KeyboardKey) id | ||||
|  | ||||
| 				is_down := cast(b32) rl.IsKeyDown( to_raylib_key(id) ) | ||||
| 				input_process_digital_btn( entry_old, entry_new, is_down ) | ||||
| 			} | ||||
| 		} | ||||
|  | ||||
| 		DeadBound_1 :: 0x0A | ||||
| 		DeadBound_2 :: 0x2E | ||||
| 		DeadBound_3 :: 0x19 | ||||
| 		DeadBound_4 :: 0x3F | ||||
| 		check_range( old, new, cast(i32) KeyboardKey.enter,     DeadBound_1 ) | ||||
| 		check_range( old, new, cast(i32) KeyboardKey.caps_lock, DeadBound_2 ) | ||||
| 		check_range( old, new, cast(i32) KeyboardKey.escape,    DeadBound_3 ) | ||||
| 		check_range( old, new, cast(i32) KeyboardKey.backtick,  DeadBound_4 ) | ||||
| 		check_range( old, new, cast(i32) KeyboardKey.A,         cast(i32) KeyboardKey.count ) | ||||
| 	} | ||||
|  | ||||
| 	// Mouse | ||||
| 	{ | ||||
| 		// profile("Mouse") | ||||
| 		// Process Buttons | ||||
| 		for id : i32 = 0; id < i32(MouseBtn.count); id += 1 | ||||
| 		{ | ||||
| 			old_btn := & old.mouse.btns[id] | ||||
| 			new_btn := & new.mouse.btns[id] | ||||
|  | ||||
| 			mouse_id := cast(MouseBtn) id | ||||
|  | ||||
| 			is_down := cast(b32) rl.IsMouseButtonDown( to_raylib_mouse_btn(id) ) | ||||
| 			input_process_digital_btn( old_btn, new_btn, is_down ) | ||||
| 		} | ||||
|  | ||||
| 		new.mouse.raw_pos        = rl.GetMousePosition() | ||||
| 		new.mouse.pos            = render_to_screen_pos(new.mouse.raw_pos) | ||||
| 		new.mouse.delta          = rl.GetMouseDelta() * {1, -1} | ||||
| 		new.mouse.vertical_wheel = rl.GetMouseWheelMove() | ||||
| 	} | ||||
| } | ||||
|  | ||||
| record_input :: proc( replay_file : os.Handle, input : ^ InputState ) { | ||||
| 	raw_data := slice_ptr( transmute(^ byte) input, size_of(InputState) ) | ||||
| 	file_write( replay_file, raw_data ) | ||||
| } | ||||
|  | ||||
| play_input :: proc( replay_file : os.Handle, input : ^ InputState ) { | ||||
| 	raw_data := slice_ptr( transmute(^ byte) input, size_of(InputState) ) | ||||
| 	total_read, result_code := file_read( replay_file, raw_data ) | ||||
| 	if result_code == os.ERROR_HANDLE_EOF { | ||||
| 		file_rewind( replay_file ) | ||||
| 		load_snapshot( & Memory_App.snapshot ) | ||||
| 	} | ||||
| } | ||||
|  | ||||
| to_raylib_key :: proc( key : i32 ) -> rl.KeyboardKey { | ||||
| 	@static raylib_key_lookup_table := [?] rl.KeyboardKey { | ||||
| 		rl.KeyboardKey.KEY_NULL, | ||||
| 		rl.KeyboardKey.ENTER, | ||||
| 		rl.KeyboardKey.TAB, | ||||
| 		rl.KeyboardKey.SPACE, | ||||
| 		rl.KeyboardKey.LEFT_BRACKET, | ||||
| 		rl.KeyboardKey.RIGHT_BRACKET, | ||||
| 		rl.KeyboardKey.SEMICOLON, | ||||
| 		rl.KeyboardKey.APOSTROPHE, | ||||
| 		rl.KeyboardKey.COMMA, | ||||
| 		rl.KeyboardKey.PERIOD, | ||||
| 		cast(rl.KeyboardKey) 0, // 0x0A | ||||
| 		cast(rl.KeyboardKey) 0, // 0x0B | ||||
| 		cast(rl.KeyboardKey) 0, // 0x0C | ||||
| 		cast(rl.KeyboardKey) 0, // 0x0D | ||||
| 		cast(rl.KeyboardKey) 0, // 0x0E | ||||
| 		cast(rl.KeyboardKey) 0, // 0x0F | ||||
| 		rl.KeyboardKey.CAPS_LOCK, | ||||
| 		rl.KeyboardKey.SCROLL_LOCK, | ||||
| 		rl.KeyboardKey.NUM_LOCK, | ||||
| 		rl.KeyboardKey.LEFT_ALT, | ||||
| 		rl.KeyboardKey.LEFT_SHIFT, | ||||
| 		rl.KeyboardKey.LEFT_CONTROL, | ||||
| 		rl.KeyboardKey.RIGHT_ALT, | ||||
| 		rl.KeyboardKey.RIGHT_SHIFT, | ||||
| 		rl.KeyboardKey.RIGHT_CONTROL, | ||||
| 		cast(rl.KeyboardKey) 0, // 0x0F | ||||
| 		cast(rl.KeyboardKey) 0, // 0x0F | ||||
| 		cast(rl.KeyboardKey) 0, // 0x0F | ||||
| 		cast(rl.KeyboardKey) 0, // 0x0F | ||||
| 		cast(rl.KeyboardKey) 0, // 0x0F | ||||
| 		cast(rl.KeyboardKey) 0, // 0x0F | ||||
| 		cast(rl.KeyboardKey) 0, // 0x0F | ||||
| 		rl.KeyboardKey.ESCAPE, | ||||
| 		rl.KeyboardKey.F1, | ||||
| 		rl.KeyboardKey.F2, | ||||
| 		rl.KeyboardKey.F3, | ||||
| 		rl.KeyboardKey.F4, | ||||
| 		rl.KeyboardKey.F5, | ||||
| 		rl.KeyboardKey.F7, | ||||
| 		rl.KeyboardKey.F8, | ||||
| 		rl.KeyboardKey.F9, | ||||
| 		rl.KeyboardKey.F10, | ||||
| 		rl.KeyboardKey.F11, | ||||
| 		rl.KeyboardKey.F12, | ||||
| 		rl.KeyboardKey.PRINT_SCREEN, | ||||
| 		rl.KeyboardKey.PAUSE, | ||||
| 		cast(rl.KeyboardKey) 0, // 0x2E | ||||
| 		rl.KeyboardKey.GRAVE, | ||||
| 		cast(rl.KeyboardKey) '0', | ||||
| 		cast(rl.KeyboardKey) '1', | ||||
| 		cast(rl.KeyboardKey) '2', | ||||
| 		cast(rl.KeyboardKey) '3', | ||||
| 		cast(rl.KeyboardKey) '4', | ||||
| 		cast(rl.KeyboardKey) '5', | ||||
| 		cast(rl.KeyboardKey) '6', | ||||
| 		cast(rl.KeyboardKey) '7', | ||||
| 		cast(rl.KeyboardKey) '8', | ||||
| 		cast(rl.KeyboardKey) '9', | ||||
| 		rl.KeyboardKey.MINUS, | ||||
| 		rl.KeyboardKey.EQUAL, | ||||
| 		rl.KeyboardKey.BACKSPACE, | ||||
| 		rl.KeyboardKey.BACKSLASH, | ||||
| 		rl.KeyboardKey.SLASH, | ||||
| 		cast(rl.KeyboardKey) 0, // 0x3F | ||||
| 		cast(rl.KeyboardKey) 0, // 0x40 | ||||
| 		rl.KeyboardKey.A, | ||||
| 		rl.KeyboardKey.B, | ||||
| 		rl.KeyboardKey.C, | ||||
| 		rl.KeyboardKey.D, | ||||
| 		rl.KeyboardKey.E, | ||||
| 		rl.KeyboardKey.F, | ||||
| 		rl.KeyboardKey.G, | ||||
| 		rl.KeyboardKey.H, | ||||
| 		rl.KeyboardKey.I, | ||||
| 		rl.KeyboardKey.J, | ||||
| 		rl.KeyboardKey.K, | ||||
| 		rl.KeyboardKey.L, | ||||
| 		rl.KeyboardKey.M, | ||||
| 		rl.KeyboardKey.N, | ||||
| 		rl.KeyboardKey.O, | ||||
| 		rl.KeyboardKey.P, | ||||
| 		rl.KeyboardKey.Q, | ||||
| 		rl.KeyboardKey.R, | ||||
| 		rl.KeyboardKey.S, | ||||
| 		rl.KeyboardKey.T, | ||||
| 		rl.KeyboardKey.U, | ||||
| 		rl.KeyboardKey.V, | ||||
| 		rl.KeyboardKey.W, | ||||
| 		rl.KeyboardKey.X, | ||||
| 		rl.KeyboardKey.Y, | ||||
| 		rl.KeyboardKey.Z, | ||||
| 		rl.KeyboardKey.INSERT, | ||||
| 		rl.KeyboardKey.DELETE, | ||||
| 		rl.KeyboardKey.HOME, | ||||
| 		rl.KeyboardKey.END, | ||||
| 		rl.KeyboardKey.PAGE_UP, | ||||
| 		rl.KeyboardKey.PAGE_DOWN, | ||||
| 		rl.KeyboardKey.KP_0, | ||||
| 		rl.KeyboardKey.KP_1, | ||||
| 		rl.KeyboardKey.KP_2, | ||||
| 		rl.KeyboardKey.KP_3, | ||||
| 		rl.KeyboardKey.KP_4, | ||||
| 		rl.KeyboardKey.KP_5, | ||||
| 		rl.KeyboardKey.KP_6, | ||||
| 		rl.KeyboardKey.KP_7, | ||||
| 		rl.KeyboardKey.KP_8, | ||||
| 		rl.KeyboardKey.KP_9, | ||||
| 		rl.KeyboardKey.KP_DECIMAL, | ||||
| 		rl.KeyboardKey.KP_EQUAL, | ||||
| 		rl.KeyboardKey.KP_ADD, | ||||
| 		rl.KeyboardKey.KP_SUBTRACT, | ||||
| 		rl.KeyboardKey.KP_MULTIPLY, | ||||
| 		rl.KeyboardKey.KP_DIVIDE, | ||||
| 		rl.KeyboardKey.KP_ENTER } | ||||
| 	return raylib_key_lookup_table[ key ] | ||||
| } | ||||
|  | ||||
| to_raylib_mouse_btn :: proc( btn : i32 ) -> rl.MouseButton { | ||||
| 	@static raylib_mouse_btn_lookup_table := [?] rl.MouseButton { | ||||
| 		rl.MouseButton.LEFT, | ||||
| 		rl.MouseButton.MIDDLE, | ||||
| 		rl.MouseButton.RIGHT, | ||||
| 		rl.MouseButton.SIDE, | ||||
| 		rl.MouseButton.FORWARD, | ||||
| 		rl.MouseButton.BACK, | ||||
| 		rl.MouseButton.EXTRA, | ||||
| 	} | ||||
| 	return raylib_mouse_btn_lookup_table[ btn ] | ||||
| // TODO(Ed): Whats the lifetime of these events? (So far we're picking per full-frame) | ||||
| KeyboardEvents :: struct { | ||||
| 	keys_pressed  : Array(KeyboardKey), | ||||
| 	chars_pressed : Array(rune), | ||||
| } | ||||
|   | ||||
							
								
								
									
										350
									
								
								code/sectr/input/input_raylib.odin
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										350
									
								
								code/sectr/input/input_raylib.odin
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,350 @@ | ||||
| package sectr | ||||
|  | ||||
| import    "base:runtime" | ||||
| import    "core:os" | ||||
| import c  "core:c/libc" | ||||
| import rl "vendor:raylib" | ||||
|  | ||||
| poll_input :: proc( old, new : ^ InputState ) | ||||
| { | ||||
| 	profile(#procedure) | ||||
| 	input_process_digital_btn :: proc( old_state, new_state : ^ DigitalBtn, is_down : b32 ) | ||||
| 	{ | ||||
| 		new_state.ended_down = is_down | ||||
| 		had_transition := old_state.ended_down != new_state.ended_down | ||||
| 		if had_transition { | ||||
| 			new_state.half_transitions += 1 | ||||
| 		} | ||||
| 		else { | ||||
| 			new_state.half_transitions = 0 | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	// Keyboard | ||||
| 	{ | ||||
| 		// profile("Keyboard") | ||||
| 		check_range :: proc( old, new : ^ InputState, start, end : i32 ) | ||||
| 		{ | ||||
| 			for id := start; id < end; id += 1 | ||||
| 			{ | ||||
| 				// TODO(Ed) : LOOK OVER THIS... | ||||
| 				entry_old := & old.keyboard.keys[id - 1] | ||||
| 				entry_new := & new.keyboard.keys[id - 1] | ||||
|  | ||||
| 				key_id := cast(KeyboardKey) id | ||||
|  | ||||
| 				is_down := cast(b32) rl.IsKeyDown( to_raylib_key(id) ) | ||||
| 				input_process_digital_btn( entry_old, entry_new, is_down ) | ||||
| 			} | ||||
| 		} | ||||
|  | ||||
| 		DeadBound_1 :: 0x0A | ||||
| 		DeadBound_2 :: 0x2E | ||||
| 		DeadBound_3 :: 0x19 | ||||
| 		DeadBound_4 :: 0x3F | ||||
| 		check_range( old, new, cast(i32) KeyboardKey.enter,     DeadBound_1 ) | ||||
| 		check_range( old, new, cast(i32) KeyboardKey.caps_lock, DeadBound_2 ) | ||||
| 		check_range( old, new, cast(i32) KeyboardKey.escape,    DeadBound_3 ) | ||||
| 		check_range( old, new, cast(i32) KeyboardKey.backtick,  DeadBound_4 ) | ||||
| 		check_range( old, new, cast(i32) KeyboardKey.A,         cast(i32) KeyboardKey.count ) | ||||
|  | ||||
| 		swap( & old.keyboard_events.keys_pressed, & new.keyboard_events.keys_pressed ) | ||||
| 		swap( & old.keyboard_events.chars_pressed, & new.keyboard_events.chars_pressed ) | ||||
|  | ||||
| 		array_clear( new.keyboard_events.keys_pressed ) | ||||
| 		array_clear( new.keyboard_events.chars_pressed ) | ||||
|  | ||||
| 		for key_pressed := rl.GetKeyPressed(); key_pressed != rl.KeyboardKey.KEY_NULL; key_pressed = rl.GetKeyPressed() { | ||||
| 			array_append( & new.keyboard_events.keys_pressed, to_key_from_raylib(key_pressed)) | ||||
| 		} | ||||
| 		for char_pressed := rl.GetCharPressed(); char_pressed != cast(rune)0; char_pressed = rl.GetCharPressed() { | ||||
| 			array_append( & new.keyboard_events.chars_pressed, char_pressed) | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	// Mouse | ||||
| 	{ | ||||
| 		// profile("Mouse") | ||||
| 		// Process Buttons | ||||
| 		for id : i32 = 0; id < i32(MouseBtn.count); id += 1 | ||||
| 		{ | ||||
| 			old_btn := & old.mouse.btns[id] | ||||
| 			new_btn := & new.mouse.btns[id] | ||||
|  | ||||
| 			mouse_id := cast(MouseBtn) id | ||||
|  | ||||
| 			is_down := cast(b32) rl.IsMouseButtonDown( to_raylib_mouse_btn(id) ) | ||||
| 			input_process_digital_btn( old_btn, new_btn, is_down ) | ||||
| 		} | ||||
|  | ||||
| 		new.mouse.raw_pos        = rl.GetMousePosition() | ||||
| 		new.mouse.pos            = render_to_screen_pos(new.mouse.raw_pos) | ||||
| 		new.mouse.delta          = rl.GetMouseDelta() * {1, -1} | ||||
| 		new.mouse.vertical_wheel = rl.GetMouseWheelMove() | ||||
| 	} | ||||
| } | ||||
|  | ||||
| record_input :: proc( replay_file : os.Handle, input : ^ InputState ) { | ||||
| 	raw_data := slice_ptr( transmute(^ byte) input, size_of(InputState) ) | ||||
| 	file_write( replay_file, raw_data ) | ||||
| } | ||||
|  | ||||
| play_input :: proc( replay_file : os.Handle, input : ^ InputState ) { | ||||
| 	raw_data := slice_ptr( transmute(^ byte) input, size_of(InputState) ) | ||||
| 	total_read, result_code := file_read( replay_file, raw_data ) | ||||
| 	if result_code == os.ERROR_HANDLE_EOF { | ||||
| 		file_rewind( replay_file ) | ||||
| 		load_snapshot( & Memory_App.snapshot ) | ||||
| 	} | ||||
| } | ||||
|  | ||||
| to_key_from_raylib :: proc( key : rl.KeyboardKey ) -> KeyboardKey { | ||||
| 	@static lookup_table := [?] KeyboardKey { | ||||
| 		KeyboardKey.null, | ||||
| 		KeyboardKey.enter, | ||||
| 		KeyboardKey.tab, | ||||
| 		KeyboardKey.space, | ||||
| 		KeyboardKey.bracket_open, | ||||
| 		KeyboardKey.bracket_close, | ||||
| 		KeyboardKey.semicolon, | ||||
| 		KeyboardKey.apostrophe, | ||||
| 		KeyboardKey.comma, | ||||
| 		KeyboardKey.period, | ||||
| 		cast(KeyboardKey) 0, // 0x0A | ||||
| 		cast(KeyboardKey) 0, // 0x0B | ||||
| 		cast(KeyboardKey) 0, // 0x0C | ||||
| 		cast(KeyboardKey) 0, // 0x0D | ||||
| 		cast(KeyboardKey) 0, // 0x0E | ||||
| 		cast(KeyboardKey) 0, // 0x0F | ||||
| 		KeyboardKey.caps_lock, | ||||
| 		KeyboardKey.scroll_lock, | ||||
| 		KeyboardKey.num_lock, | ||||
| 		KeyboardKey.left_alt, | ||||
| 		KeyboardKey.left_shit, | ||||
| 		KeyboardKey.left_control, | ||||
| 		KeyboardKey.right_alt, | ||||
| 		KeyboardKey.right_shift, | ||||
| 		KeyboardKey.right_control, | ||||
| 		cast(KeyboardKey) 0, // 0x0F | ||||
| 		cast(KeyboardKey) 0, // 0x0F | ||||
| 		cast(KeyboardKey) 0, // 0x0F | ||||
| 		cast(KeyboardKey) 0, // 0x0F | ||||
| 		cast(KeyboardKey) 0, // 0x0F | ||||
| 		cast(KeyboardKey) 0, // 0x0F | ||||
| 		cast(KeyboardKey) 0, // 0x0F | ||||
| 		KeyboardKey.escape, | ||||
| 		KeyboardKey.F1, | ||||
| 		KeyboardKey.F2, | ||||
| 		KeyboardKey.F3, | ||||
| 		KeyboardKey.F4, | ||||
| 		KeyboardKey.F5, | ||||
| 		KeyboardKey.F7, | ||||
| 		KeyboardKey.F8, | ||||
| 		KeyboardKey.F9, | ||||
| 		KeyboardKey.F10, | ||||
| 		KeyboardKey.F11, | ||||
| 		KeyboardKey.F12, | ||||
| 		KeyboardKey.print_screen, | ||||
| 		KeyboardKey.pause, | ||||
| 		cast(KeyboardKey) 0, // 0x2E | ||||
| 		KeyboardKey.backtick, | ||||
| 		KeyboardKey.nrow_0, | ||||
| 		KeyboardKey.nrow_1, | ||||
| 		KeyboardKey.nrow_2, | ||||
| 		KeyboardKey.nrow_3, | ||||
| 		KeyboardKey.nrow_4, | ||||
| 		KeyboardKey.nrow_5, | ||||
| 		KeyboardKey.nrow_6, | ||||
| 		KeyboardKey.nrow_7, | ||||
| 		KeyboardKey.nrow_8, | ||||
| 		KeyboardKey.nrow_9, | ||||
| 		KeyboardKey.hyphen, | ||||
| 		KeyboardKey.equals, | ||||
| 		KeyboardKey.backspace, | ||||
| 		KeyboardKey.backslash, | ||||
| 		KeyboardKey.slash, | ||||
| 		cast(KeyboardKey) 0, // 0x3F | ||||
| 		cast(KeyboardKey) 0, // 0x40 | ||||
| 		KeyboardKey.A, | ||||
| 		KeyboardKey.B, | ||||
| 		KeyboardKey.C, | ||||
| 		KeyboardKey.D, | ||||
| 		KeyboardKey.E, | ||||
| 		KeyboardKey.F, | ||||
| 		KeyboardKey.G, | ||||
| 		KeyboardKey.H, | ||||
| 		KeyboardKey.I, | ||||
| 		KeyboardKey.J, | ||||
| 		KeyboardKey.K, | ||||
| 		KeyboardKey.L, | ||||
| 		KeyboardKey.M, | ||||
| 		KeyboardKey.N, | ||||
| 		KeyboardKey.O, | ||||
| 		KeyboardKey.P, | ||||
| 		KeyboardKey.Q, | ||||
| 		KeyboardKey.R, | ||||
| 		KeyboardKey.S, | ||||
| 		KeyboardKey.T, | ||||
| 		KeyboardKey.U, | ||||
| 		KeyboardKey.V, | ||||
| 		KeyboardKey.W, | ||||
| 		KeyboardKey.X, | ||||
| 		KeyboardKey.Y, | ||||
| 		KeyboardKey.Z, | ||||
| 		KeyboardKey.insert, | ||||
| 		KeyboardKey.delete, | ||||
| 		KeyboardKey.home, | ||||
| 		KeyboardKey.end, | ||||
| 		KeyboardKey.page_up, | ||||
| 		KeyboardKey.page_down, | ||||
| 		KeyboardKey.npad_0, | ||||
| 		KeyboardKey.npad_1, | ||||
| 		KeyboardKey.npad_2, | ||||
| 		KeyboardKey.npad_3, | ||||
| 		KeyboardKey.npad_4, | ||||
| 		KeyboardKey.npad_5, | ||||
| 		KeyboardKey.npad_6, | ||||
| 		KeyboardKey.npad_7, | ||||
| 		KeyboardKey.npad_8, | ||||
| 		KeyboardKey.npad_9, | ||||
| 		KeyboardKey.npad_decimal, | ||||
| 		KeyboardKey.npad_equals, | ||||
| 		KeyboardKey.npad_plus, | ||||
| 		KeyboardKey.npad_minus, | ||||
| 		KeyboardKey.npad_multiply, | ||||
| 		KeyboardKey.npad_divide, | ||||
| 		KeyboardKey.npad_enter, } | ||||
| 		return lookup_table[key] | ||||
| } | ||||
|  | ||||
| to_raylib_key :: proc( key : i32 ) -> rl.KeyboardKey | ||||
| { | ||||
| 	@static raylib_key_lookup_table := [?] rl.KeyboardKey { | ||||
| 		rl.KeyboardKey.KEY_NULL, | ||||
| 		rl.KeyboardKey.ENTER, | ||||
| 		rl.KeyboardKey.TAB, | ||||
| 		rl.KeyboardKey.SPACE, | ||||
| 		rl.KeyboardKey.LEFT_BRACKET, | ||||
| 		rl.KeyboardKey.RIGHT_BRACKET, | ||||
| 		rl.KeyboardKey.SEMICOLON, | ||||
| 		rl.KeyboardKey.APOSTROPHE, | ||||
| 		rl.KeyboardKey.COMMA, | ||||
| 		rl.KeyboardKey.PERIOD, | ||||
| 		cast(rl.KeyboardKey) 0, // 0x0A | ||||
| 		cast(rl.KeyboardKey) 0, // 0x0B | ||||
| 		cast(rl.KeyboardKey) 0, // 0x0C | ||||
| 		cast(rl.KeyboardKey) 0, // 0x0D | ||||
| 		cast(rl.KeyboardKey) 0, // 0x0E | ||||
| 		cast(rl.KeyboardKey) 0, // 0x0F | ||||
| 		rl.KeyboardKey.CAPS_LOCK, | ||||
| 		rl.KeyboardKey.SCROLL_LOCK, | ||||
| 		rl.KeyboardKey.NUM_LOCK, | ||||
| 		rl.KeyboardKey.LEFT_ALT, | ||||
| 		rl.KeyboardKey.LEFT_SHIFT, | ||||
| 		rl.KeyboardKey.LEFT_CONTROL, | ||||
| 		rl.KeyboardKey.RIGHT_ALT, | ||||
| 		rl.KeyboardKey.RIGHT_SHIFT, | ||||
| 		rl.KeyboardKey.RIGHT_CONTROL, | ||||
| 		cast(rl.KeyboardKey) 0, // 0x0F | ||||
| 		cast(rl.KeyboardKey) 0, // 0x0F | ||||
| 		cast(rl.KeyboardKey) 0, // 0x0F | ||||
| 		cast(rl.KeyboardKey) 0, // 0x0F | ||||
| 		cast(rl.KeyboardKey) 0, // 0x0F | ||||
| 		cast(rl.KeyboardKey) 0, // 0x0F | ||||
| 		cast(rl.KeyboardKey) 0, // 0x0F | ||||
| 		rl.KeyboardKey.ESCAPE, | ||||
| 		rl.KeyboardKey.F1, | ||||
| 		rl.KeyboardKey.F2, | ||||
| 		rl.KeyboardKey.F3, | ||||
| 		rl.KeyboardKey.F4, | ||||
| 		rl.KeyboardKey.F5, | ||||
| 		rl.KeyboardKey.F7, | ||||
| 		rl.KeyboardKey.F8, | ||||
| 		rl.KeyboardKey.F9, | ||||
| 		rl.KeyboardKey.F10, | ||||
| 		rl.KeyboardKey.F11, | ||||
| 		rl.KeyboardKey.F12, | ||||
| 		rl.KeyboardKey.PRINT_SCREEN, | ||||
| 		rl.KeyboardKey.PAUSE, | ||||
| 		cast(rl.KeyboardKey) 0, // 0x2E | ||||
| 		rl.KeyboardKey.GRAVE, | ||||
| 		cast(rl.KeyboardKey) '0', | ||||
| 		cast(rl.KeyboardKey) '1', | ||||
| 		cast(rl.KeyboardKey) '2', | ||||
| 		cast(rl.KeyboardKey) '3', | ||||
| 		cast(rl.KeyboardKey) '4', | ||||
| 		cast(rl.KeyboardKey) '5', | ||||
| 		cast(rl.KeyboardKey) '6', | ||||
| 		cast(rl.KeyboardKey) '7', | ||||
| 		cast(rl.KeyboardKey) '8', | ||||
| 		cast(rl.KeyboardKey) '9', | ||||
| 		rl.KeyboardKey.MINUS, | ||||
| 		rl.KeyboardKey.EQUAL, | ||||
| 		rl.KeyboardKey.BACKSPACE, | ||||
| 		rl.KeyboardKey.BACKSLASH, | ||||
| 		rl.KeyboardKey.SLASH, | ||||
| 		cast(rl.KeyboardKey) 0, // 0x3F | ||||
| 		cast(rl.KeyboardKey) 0, // 0x40 | ||||
| 		rl.KeyboardKey.A, | ||||
| 		rl.KeyboardKey.B, | ||||
| 		rl.KeyboardKey.C, | ||||
| 		rl.KeyboardKey.D, | ||||
| 		rl.KeyboardKey.E, | ||||
| 		rl.KeyboardKey.F, | ||||
| 		rl.KeyboardKey.G, | ||||
| 		rl.KeyboardKey.H, | ||||
| 		rl.KeyboardKey.I, | ||||
| 		rl.KeyboardKey.J, | ||||
| 		rl.KeyboardKey.K, | ||||
| 		rl.KeyboardKey.L, | ||||
| 		rl.KeyboardKey.M, | ||||
| 		rl.KeyboardKey.N, | ||||
| 		rl.KeyboardKey.O, | ||||
| 		rl.KeyboardKey.P, | ||||
| 		rl.KeyboardKey.Q, | ||||
| 		rl.KeyboardKey.R, | ||||
| 		rl.KeyboardKey.S, | ||||
| 		rl.KeyboardKey.T, | ||||
| 		rl.KeyboardKey.U, | ||||
| 		rl.KeyboardKey.V, | ||||
| 		rl.KeyboardKey.W, | ||||
| 		rl.KeyboardKey.X, | ||||
| 		rl.KeyboardKey.Y, | ||||
| 		rl.KeyboardKey.Z, | ||||
| 		rl.KeyboardKey.INSERT, | ||||
| 		rl.KeyboardKey.DELETE, | ||||
| 		rl.KeyboardKey.HOME, | ||||
| 		rl.KeyboardKey.END, | ||||
| 		rl.KeyboardKey.PAGE_UP, | ||||
| 		rl.KeyboardKey.PAGE_DOWN, | ||||
| 		rl.KeyboardKey.KP_0, | ||||
| 		rl.KeyboardKey.KP_1, | ||||
| 		rl.KeyboardKey.KP_2, | ||||
| 		rl.KeyboardKey.KP_3, | ||||
| 		rl.KeyboardKey.KP_4, | ||||
| 		rl.KeyboardKey.KP_5, | ||||
| 		rl.KeyboardKey.KP_6, | ||||
| 		rl.KeyboardKey.KP_7, | ||||
| 		rl.KeyboardKey.KP_8, | ||||
| 		rl.KeyboardKey.KP_9, | ||||
| 		rl.KeyboardKey.KP_DECIMAL, | ||||
| 		rl.KeyboardKey.KP_EQUAL, | ||||
| 		rl.KeyboardKey.KP_ADD, | ||||
| 		rl.KeyboardKey.KP_SUBTRACT, | ||||
| 		rl.KeyboardKey.KP_MULTIPLY, | ||||
| 		rl.KeyboardKey.KP_DIVIDE, | ||||
| 		rl.KeyboardKey.KP_ENTER, } | ||||
| 	return raylib_key_lookup_table[ key ] | ||||
| } | ||||
|  | ||||
| to_raylib_mouse_btn :: proc( btn : i32 ) -> rl.MouseButton { | ||||
| 	@static raylib_mouse_btn_lookup_table := [?] rl.MouseButton { | ||||
| 		rl.MouseButton.LEFT, | ||||
| 		rl.MouseButton.MIDDLE, | ||||
| 		rl.MouseButton.RIGHT, | ||||
| 		rl.MouseButton.SIDE, | ||||
| 		rl.MouseButton.FORWARD, | ||||
| 		rl.MouseButton.BACK, | ||||
| 		rl.MouseButton.EXTRA, } | ||||
| 	return raylib_mouse_btn_lookup_table[ btn ] | ||||
| } | ||||
| @@ -101,6 +101,8 @@ Range2 :: struct #raw_union { | ||||
|  | ||||
| UnitRange2 :: distinct Range2 | ||||
|  | ||||
| range2_zero :: Range2 {} | ||||
|  | ||||
| range2 :: #force_inline proc "contextless" ( a, b : Vec2 ) -> Range2 { | ||||
| 	result := Range2 { pts = { a, b } } | ||||
| 	return result | ||||
|   | ||||
							
								
								
									
										7
									
								
								code/sectr/ui/core/Readme.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										7
									
								
								code/sectr/ui/core/Readme.md
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,7 @@ | ||||
| # Plans | ||||
|  | ||||
| Eventually want to generalize this core UI as its own library.   | ||||
| This will keep track of here whats needed for it to work wihtout the rest of this codebase.   | ||||
|  | ||||
| * Provide UI input state in its own data stucture at the beginning of `ui_build_graph`: | ||||
| *  | ||||
| @@ -15,6 +15,10 @@ UI_BoxFlag :: enum u64 | ||||
| UI_BoxFlags :: bit_set[UI_BoxFlag; u64] | ||||
| // UI_BoxFlag_Scroll :: UI_BoxFlags { .Scroll_X, .Scroll_Y } | ||||
| 
 | ||||
| UI_NavLinks :: struct { | ||||
| 	left, right, up, down : ^UI_Box, | ||||
| } | ||||
| 
 | ||||
| UI_RenderBoxInfo :: struct { | ||||
| 	using computed : UI_Computed, | ||||
| 	using style    : UI_Style, | ||||
| @@ -26,12 +30,15 @@ UI_RenderBoxInfo :: struct { | ||||
| UI_Box :: struct { | ||||
| 	// Cache ID | ||||
| 	key   : UI_Key, | ||||
| 	// label : string, | ||||
| 	label : StrRunesPair, | ||||
| 	text  : StrRunesPair, | ||||
| 
 | ||||
| 	// Regenerated per frame. | ||||
| 
 | ||||
| 	nav : UI_NavLinks, | ||||
| 	// signal_callback : #type proc(), | ||||
| 
 | ||||
| 
 | ||||
| 	// first, last : The first and last child of this box | ||||
| 	// prev, next  : The adjacent neighboring boxes who are children of to the same parent | ||||
| 	using links   : DLL_NodeFull( UI_Box ), | ||||
| @@ -129,7 +136,7 @@ ui_box_tranverse_next :: proc "contextless" ( box : ^ UI_Box ) -> (^ UI_Box) | ||||
| 	{ | ||||
| 		// Check to make sure parent is present on the screen, if its not don't bother. | ||||
| 		is_app_ui := ui_context == & screen_ui | ||||
| 		if intersects_range2( view_get_bounds(), box.computed.bounds) | ||||
| 		if intersects_range2( ui_view_bounds(), box.computed.bounds) | ||||
| 		{ | ||||
| 			return box.first | ||||
| 		} | ||||
| @@ -16,13 +16,17 @@ LayoutAlign_OriginTL_Bottom       :: Vec2{0.5,   1} | ||||
| LayoutAlign_OriginTL_BottomLeft   :: Vec2{  0,   1} | ||||
| LayoutAlign_OriginTL_BottomRight  :: Vec2{  1,   1} | ||||
| 
 | ||||
| // LayoutAlign_OriginTL_ | ||||
| 
 | ||||
| Layout_OriginCenter_Centered :: Vec2{0.5, 0.5} | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| UI_Align_Presets_Struct :: struct { | ||||
| 	origin_tl_centered : Vec2, | ||||
| 	text_centered  : Vec2, | ||||
| } | ||||
| UI_Align_Presets :: UI_Align_Presets_Struct { | ||||
| 	origin_tl_centered = {0.5, 0.5}, | ||||
| 	text_centered      = {0.5, 0.5}, | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| // The UI_Box's actual positioning and sizing | ||||
| @@ -85,9 +85,16 @@ ui_box_compute_layout :: proc( box : ^UI_Box, | ||||
| 	if .Scale_Width_By_Height_Ratio in layout.flags { | ||||
| 		adjusted_size.x = adjusted_size.y * layout.size.min.x | ||||
| 	} | ||||
| 	else if .Fixed_Width in layout.flags { | ||||
| 		adjusted_size.x = layout.size.min.x | ||||
| 	} | ||||
| 
 | ||||
| 	if .Scale_Height_By_Width_Ratio in layout.flags { | ||||
| 		adjusted_size.y = adjusted_size.x * layout.size.min.y | ||||
| 	} | ||||
| 	else if .Fixed_Height in layout.flags { | ||||
| 		adjusted_size.y = layout.size.min.y | ||||
| 	} | ||||
| 
 | ||||
| 	if .Size_To_Content in layout.flags { | ||||
| 		// Preemtively traverse the children of this parent and have them compute their layout. | ||||
| @@ -97,14 +104,6 @@ ui_box_compute_layout :: proc( box : ^UI_Box, | ||||
| 		//ui_compute_children_bounding_area(box) | ||||
| 	} | ||||
| 
 | ||||
| 	// TODO(Ed): Should this force override all of the previous auto-sizing possible? | ||||
| 	if .Fixed_Width in layout.flags { | ||||
| 		adjusted_size.x = layout.size.min.x | ||||
| 	} | ||||
| 	if .Fixed_Height in layout.flags { | ||||
| 		adjusted_size.y = layout.size.min.y | ||||
| 	} | ||||
| 
 | ||||
| 	// 5. Determine relative position | ||||
| 
 | ||||
| 	origin_center   := margined_bounds_origin | ||||
| @@ -186,34 +185,3 @@ ui_box_compute_layout_children :: proc( box : ^UI_Box ) | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| ui_core_compute_layout :: proc( ui : ^UI_State ) | ||||
| { | ||||
| 	profile(#procedure) | ||||
| 	state := get_state() | ||||
| 
 | ||||
| 	root := ui.root | ||||
| 	{ | ||||
| 		computed := & root.computed | ||||
| 		style    := root.style | ||||
| 		layout   := & root.layout | ||||
| 		if ui == & state.screen_ui { | ||||
| 			computed.bounds.min = transmute(Vec2) state.app_window.extent * -1 | ||||
| 			computed.bounds.max = transmute(Vec2) state.app_window.extent | ||||
| 		} | ||||
| 		computed.content    = computed.bounds | ||||
| 	} | ||||
| 
 | ||||
| 	for current := root.first; current != nil; current = ui_box_tranverse_next( current ) | ||||
| 	{ | ||||
| 		if ! current.computed.fresh { | ||||
| 			ui_box_compute_layout( current ) | ||||
| 		} | ||||
| 		array_append( & ui.render_queue, UI_RenderBoxInfo { | ||||
| 			current.computed, | ||||
| 			current.style, | ||||
| 			current.text, | ||||
| 			current.layout.font_size, | ||||
| 			current.layout.border_width, | ||||
| 		}) | ||||
| 	} | ||||
| } | ||||
| @@ -70,13 +70,13 @@ ui_signal_from_box :: proc ( box : ^ UI_Box, update_style := true, update_deltas | ||||
| 
 | ||||
| 	mouse_clickable    := UI_BoxFlag.Mouse_Clickable    in box.flags | ||||
| 	keyboard_clickable := UI_BoxFlag.Keyboard_Clickable in box.flags | ||||
| 	is_focusable       := .Focusable in box.flags | ||||
| 
 | ||||
| 	was_hot      := (box.hot_delta    > 0) | ||||
| 	was_active   := (ui.active == box.key) && (box.active_delta > 0) | ||||
| 	was_hot      := (box.hot_delta    > 0) | ||||
| 	was_disabled := box.disabled_delta > 0 | ||||
| 	// if was_hot { | ||||
| 		// runtime.debug_trap() | ||||
| 	// } | ||||
| 
 | ||||
| 	is_focused_locked := is_focusable ? was_active : false | ||||
| 
 | ||||
| 	// Check to see if this box is active | ||||
| 	if mouse_clickable && signal.cursor_over && left_pressed && was_hot | ||||
| @@ -93,14 +93,14 @@ ui_signal_from_box :: proc ( box : ^ UI_Box, update_style := true, update_deltas | ||||
| 		// TODO(Ed) : Support double-click detection | ||||
| 	} | ||||
| 
 | ||||
| 	if mouse_clickable && ! signal.cursor_over && left_released | ||||
| 	if ! is_focused_locked && was_active && mouse_clickable && ! signal.cursor_over && left_released | ||||
| 	{ | ||||
| 		box.active_delta = 0 | ||||
| 
 | ||||
| 		ui.active = UI_Key(0) | ||||
| 		ui.active_mouse[MouseBtn.Left] = UI_Key(0) | ||||
| 
 | ||||
| 		signal.released     = true | ||||
| 		signal.released = true | ||||
| 	} | ||||
| 
 | ||||
| 	if keyboard_clickable | ||||
| @@ -109,6 +109,7 @@ ui_signal_from_box :: proc ( box : ^ UI_Box, update_style := true, update_deltas | ||||
| 	} | ||||
| 
 | ||||
| 	// TODO(Ed): Should panning and scrolling get supported here? (problably not...) | ||||
| 	// We can just report the scroll amount in the signal and have the scrollbox widget handle it | ||||
| 	// TODO(Ed) : Add scrolling support | ||||
| 	// if UI_BoxFlag.Scroll_X in box.flags { | ||||
| 
 | ||||
| @@ -123,39 +124,7 @@ ui_signal_from_box :: proc ( box : ^ UI_Box, update_style := true, update_deltas | ||||
| 	// if UI_BoxFlag.Pan_Y in box.flags { | ||||
| 	// } | ||||
| 
 | ||||
| 	is_disabled := UI_BoxFlag.Disabled in box.flags | ||||
| 	is_hot      := ui.hot    == box.key | ||||
| 	is_active   := ui.active == box.key | ||||
| 
 | ||||
| 	// TODO(Ed): It should be able to enter hot without mouse_clickable | ||||
| 	if mouse_clickable && signal.cursor_over && ! is_disabled | ||||
| 	{ | ||||
| 		hot_vacant    := ui.hot    == UI_Key(0) | ||||
| 		active_vacant := ui.active == UI_Key(0) | ||||
| 			//  (active_vacant  is_active) | ||||
| 		if signal.cursor_over && active_vacant | ||||
| 		{ | ||||
| 			if ! hot_vacant { | ||||
| 				prev := ui_box_from_key( ui.curr_cache, ui.hot ) | ||||
| 				prev.hot_delta = 0 | ||||
| 			} | ||||
| 			// prev_hot := zpl_hmap_get( ui.prev_cache, u64(ui.hot) ) | ||||
| 			// prev_hot_label := prev_hot != nil ? prev_hot.label.str : "" | ||||
| 			// log( str_fmt_tmp("Detected HOT via CURSOR OVER: %v is_hot: %v is_active: %v prev_hot: %v", box.label.str, is_hot, is_active, prev_hot_label )) | ||||
| 			ui.hot = box.key | ||||
| 			is_hot = true | ||||
| 
 | ||||
| 			ui.hot_start_style = box.style | ||||
| 		} | ||||
| 	} | ||||
| 	else if ! signal.cursor_over && was_hot | ||||
| 	{ | ||||
| 		ui.hot        = UI_Key(0) | ||||
| 		is_hot        = false | ||||
| 		box.hot_delta = 0 | ||||
| 	} | ||||
| 
 | ||||
| 	if mouse_clickable && signal.cursor_over && left_released | ||||
| 	if ! is_focused_locked && was_active && mouse_clickable && signal.cursor_over && left_released | ||||
| 	{ | ||||
| 		box.active_delta = 0 | ||||
| 
 | ||||
| @@ -169,6 +138,39 @@ ui_signal_from_box :: proc ( box : ^ UI_Box, update_style := true, update_deltas | ||||
| 			ui.last_clicked     = box.key | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	is_disabled := UI_BoxFlag.Disabled in box.flags | ||||
| 	is_hot      := ui.hot    == box.key | ||||
| 	is_active   := ui.active == box.key | ||||
| 
 | ||||
| 	// TODO(Ed): It should be able to enter hot without mouse_clickable | ||||
| 	if mouse_clickable && signal.cursor_over && ! is_disabled | ||||
| 	{ | ||||
| 		hot_vacant    := ui.hot == UI_Key(0) | ||||
| 		// active_vacant := ui.active == UI_Key(0) | ||||
| 		if signal.cursor_over //&& active_vacant | ||||
| 		{ | ||||
| 			if ! hot_vacant { | ||||
| 				prev := ui_box_from_key( ui.curr_cache, ui.hot ) | ||||
| 				prev.hot_delta = 0 | ||||
| 			} | ||||
| 			// prev_hot := zpl_hmap_get( ui.prev_cache, u64(ui.hot) ) | ||||
| 			// prev_hot_label := prev_hot != nil ? prev_hot.label.str : "" | ||||
| 			// log( str_fmt_tmp("Detected HOT via CURSOR OVER: %v is_hot: %v is_active: %v prev_hot: %v", box.label.str, is_hot, is_active, prev_hot_label )) | ||||
| 			ui.hot = box.key | ||||
| 			is_hot = true | ||||
| 
 | ||||
| 			ui.hot_start_style = box.style | ||||
| 			signal.hot = true | ||||
| 		} | ||||
| 	} | ||||
| 	else if ! signal.cursor_over && was_hot | ||||
| 	{ | ||||
| 		ui.hot        = UI_Key(0) | ||||
| 		is_hot        = false | ||||
| 		box.hot_delta = 0 | ||||
| 	} | ||||
| 
 | ||||
| 	// profile_end() | ||||
| 
 | ||||
| 	// State Deltas update | ||||
| @@ -206,14 +206,55 @@ ui_graph_build_begin :: proc( ui : ^ UI_State, bounds : Vec2 = {} ) | ||||
| 	ui_parent_push(root) | ||||
| } | ||||
| 
 | ||||
| ui_core_compute_layout :: proc( ui : ^UI_State ) | ||||
| { | ||||
| 	profile(#procedure) | ||||
| 	state := get_state() | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| ui_graph_build_end :: proc( ui : ^UI_State ) | ||||
| { | ||||
| 	profile(#procedure) | ||||
| 	state := get_state() | ||||
| 
 | ||||
| 	ui_parent_pop() // Should be ui_context.root | ||||
| 
 | ||||
| 	// Regenerate the computed layout if dirty | ||||
| 	ui_compute_layout( ui ) | ||||
| 	Post_Build_Graph_Traversal: | ||||
| 	{ | ||||
| 		root := ui.root | ||||
| 		{ | ||||
| 			computed := & root.computed | ||||
| 			style    := root.style | ||||
| 			layout   := & root.layout | ||||
| 			if ui == & state.screen_ui { | ||||
| 				computed.bounds.min = transmute(Vec2) state.app_window.extent * -1 | ||||
| 				computed.bounds.max = transmute(Vec2) state.app_window.extent | ||||
| 			} | ||||
| 			computed.content    = computed.bounds | ||||
| 		} | ||||
| 		for current := root.first; current != nil; current = ui_box_tranverse_next( current ) | ||||
| 		{ | ||||
| 			 | ||||
| 
 | ||||
| 			if ! current.computed.fresh { | ||||
| 				ui_box_compute_layout( current ) | ||||
| 			} | ||||
| 
 | ||||
| 			// Enqueue for rendering | ||||
| 			array_append( & ui.render_queue, UI_RenderBoxInfo { | ||||
| 				current.computed, | ||||
| 				current.style, | ||||
| 				current.text, | ||||
| 				current.layout.font_size, | ||||
| 				current.layout.border_width, | ||||
| 			}) | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	get_state().ui_context = nil | ||||
| } | ||||
| @@ -259,4 +300,14 @@ ui_top_ancestor :: #force_inline proc "contextless" ( box : ^UI_Box ) -> (^UI_Bo | ||||
| 	return ancestor | ||||
| } | ||||
| 
 | ||||
| ui_view_bounds :: #force_inline proc "contextless" () -> (range : Range2) { | ||||
| 	using state := get_state(); | ||||
| 	if ui_context == & screen_ui { | ||||
| 		return screen_get_bounds() | ||||
| 	} | ||||
| 	else { | ||||
| 		return view_get_bounds() | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| ui_context :: #force_inline proc() -> ^UI_State { return get_state().ui_context } | ||||
| @@ -117,20 +117,6 @@ ui_floating_build :: proc() | ||||
| 		} | ||||
| 		lookup.queued = true | ||||
| 		dll_full_push_back(floating, lookup, nil ) | ||||
| 	// 	if first == nil { | ||||
| 	// 		first = lookup | ||||
| 	// 		last  = lookup | ||||
| 	// 		continue | ||||
| 	// 	} | ||||
| 	// 	if first == last { | ||||
| 	// 		last       = lookup | ||||
| 	// 		last.prev  = first | ||||
| 	// 		first.next = last | ||||
| 	// 		continue | ||||
| 	// 	} | ||||
| 	// 	last.next   = lookup | ||||
| 	// 	lookup.prev = last | ||||
| 	// 	last        = lookup | ||||
| 	} | ||||
| 	array_clear(build_queue) | ||||
|  | ||||
| @@ -140,28 +126,7 @@ ui_floating_build :: proc() | ||||
| 		if ! entry.queued | ||||
| 		{ | ||||
| 			ensure(false, "There should be no queue failures yet") | ||||
|  | ||||
| 			if entry == first | ||||
| 			{ | ||||
| 				first      = entry.next | ||||
| 				entry.next = nil | ||||
| 				continue | ||||
| 			} | ||||
| 			if entry == last | ||||
| 			{ | ||||
| 				last       = last.prev | ||||
| 				last.prev  = nil | ||||
| 				entry.prev = nil | ||||
| 				continue | ||||
| 			} | ||||
|  | ||||
| 			left  := entry.prev | ||||
| 			right := entry.next | ||||
|  | ||||
| 			left.next  = right | ||||
| 			right.prev = left | ||||
| 			entry.prev = nil | ||||
| 			entry.next = nil | ||||
| 			dll_full_pop(to_raise, floating) | ||||
| 		} | ||||
|  | ||||
| 		if entry.builder( entry.captures ) && entry != last && to_raise == nil | ||||
|   | ||||
| @@ -1,5 +1,7 @@ | ||||
| package sectr | ||||
|  | ||||
| import "base:runtime" | ||||
|  | ||||
| /* | ||||
| Widget Layout Ops | ||||
| */ | ||||
| @@ -13,6 +15,7 @@ ui_layout_children_horizontally :: proc( container : ^UI_Box, direction : UI_Lay | ||||
| 	else { | ||||
| 		container_width = container.computed.content.max.x - container.computed.content.min.x | ||||
| 	} | ||||
| 	container_height := container.computed.content.max.y - container.computed.content.min.y | ||||
|  | ||||
| 	// do layout calculations for the children | ||||
| 	total_stretch_ratio : f32 = 0.0 | ||||
| @@ -21,16 +24,13 @@ ui_layout_children_horizontally :: proc( container : ^UI_Box, direction : UI_Lay | ||||
| 	{ | ||||
| 		using child.layout | ||||
| 		scaled_width_by_height : b32 = b32(.Scale_Width_By_Height_Ratio in flags) | ||||
| 		if .Scale_Width_By_Height_Ratio in flags | ||||
| 		{ | ||||
| 			size_req_children += size.min.x * container_height | ||||
| 			continue | ||||
| 		} | ||||
| 		if .Fixed_Width in flags | ||||
| 		{ | ||||
| 			if scaled_width_by_height { | ||||
| 				height := size.max.y != 0 ? size.max.y : container_width | ||||
| 				width  := height * size.min.x | ||||
|  | ||||
| 				size_req_children += width | ||||
| 				continue | ||||
| 			} | ||||
|  | ||||
| 			size_req_children += size.min.x | ||||
| 			continue | ||||
| 		} | ||||
| @@ -40,32 +40,45 @@ ui_layout_children_horizontally :: proc( container : ^UI_Box, direction : UI_Lay | ||||
|  | ||||
| 	avail_flex_space := container_width - size_req_children | ||||
|  | ||||
| 	allocate_space :: proc( child : ^UI_Box, total_stretch_ratio, avail_flex_space : f32 ) | ||||
| 	allocate_space :: proc( child : ^UI_Box, total_stretch_ratio, avail_flex_space, container_height : f32 ) -> (space_allocated : f32) | ||||
| 	{ | ||||
| 		using child.layout | ||||
| 		if ! (.Fixed_Width in flags) { | ||||
| 			size.min.x = anchor.ratio.x * (1 / total_stretch_ratio) * avail_flex_space - child.layout.margins.left - child.layout.margins.right | ||||
| 		if .Scale_Width_By_Height_Ratio in flags { | ||||
| 			size.min.y      = container_height | ||||
| 			space_allocated = size.min.x * container_height | ||||
| 		} | ||||
| 		else if ! (.Fixed_Width in flags) { | ||||
| 			size.min.x      = anchor.ratio.x * (1 / total_stretch_ratio) * avail_flex_space | ||||
| 			space_allocated = size.min.x | ||||
| 		} | ||||
| 		else { | ||||
| 			space_allocated = size.min.x | ||||
| 		} | ||||
| 		space_allocated -= child.layout.margins.left - child.layout.margins.right | ||||
| 		size.min.x      -= child.layout.margins.left - child.layout.margins.right | ||||
| 		flags |= {.Fixed_Width} | ||||
| 		return | ||||
| 	} | ||||
|  | ||||
| 	space_used : f32 = 0.0 | ||||
| 	switch direction{ | ||||
| 		case .Right_To_Left: | ||||
| 			for child := container.last; child != nil; child = child.prev { | ||||
| 				allocate_space(child, total_stretch_ratio, avail_flex_space) | ||||
| 				using child.layout | ||||
| 				anchor      = range2({0, 0}, {0, 0}) | ||||
| 				pos.x       = space_used | ||||
| 				space_used += size.min.x + child.layout.margins.left + child.layout.margins.right | ||||
| 				child_width := allocate_space(child, total_stretch_ratio, avail_flex_space, container_height) | ||||
| 				anchor       = range2({0, 0}, {0, 0}) | ||||
| 				width : f32 | ||||
| 				pos.x        = space_used | ||||
| 				space_used  += child_width + child.layout.margins.left + child.layout.margins.right | ||||
| 			} | ||||
| 		case .Left_To_Right: | ||||
| 			for child := container.first; child != nil; child = child.next { | ||||
| 				allocate_space(child, total_stretch_ratio, avail_flex_space) | ||||
| 				using child.layout | ||||
| 				anchor      = range2({0, 0}, {0, 0}) | ||||
| 				pos.x       = space_used | ||||
| 				space_used += size.min.x + child.layout.margins.left + child.layout.margins.right | ||||
| 				child_width := allocate_space(child, total_stretch_ratio, avail_flex_space, container_height) | ||||
| 				anchor       = range2({0, 0}, {0, 0}) | ||||
| 				width : f32 | ||||
| 				pos.x        = space_used | ||||
| 				space_used  += child_width + child.layout.margins.left + child.layout.margins.right | ||||
| 			} | ||||
| 	} | ||||
| } | ||||
| @@ -123,9 +136,8 @@ ui_layout_children_vertically :: proc( container : ^UI_Box, direction : UI_Layou | ||||
| 				allocate_space(child, total_stretch_ratio, avail_flex_space) | ||||
| 				using child.layout | ||||
| 				anchor      = range2({0,0}, {0, 0}) | ||||
| 				// alignment   = {0, 0} | ||||
| 				pos.y       = -space_used | ||||
| 				space_used += size.min.y | ||||
| 				space_used += size.min.y + child.layout.margins.top + child.layout.margins.bottom | ||||
| 				size.min.x  = container.computed.content.max.x + container.computed.content.min.x | ||||
| 			} | ||||
| 		case .Top_To_Bottom: | ||||
| @@ -133,9 +145,8 @@ ui_layout_children_vertically :: proc( container : ^UI_Box, direction : UI_Layou | ||||
| 				allocate_space(child, total_stretch_ratio, avail_flex_space) | ||||
| 				using child.layout | ||||
| 				anchor      = range2({0, 0}, {0, 0}) | ||||
| 				// alignment   = {0, 0} | ||||
| 				pos.y       = -space_used | ||||
| 				space_used += size.min.y | ||||
| 				space_used += size.min.y + child.layout.margins.top + child.layout.margins.bottom | ||||
| 				size.min.x  = container.computed.content.max.x - container.computed.content.min.x | ||||
| 			} | ||||
| 	} | ||||
|   | ||||
| @@ -17,7 +17,7 @@ ui_widget :: proc( label : string, flags : UI_BoxFlags ) -> (widget : UI_Widget) | ||||
|  | ||||
| ui_button :: proc( label : string, flags : UI_BoxFlags = {} ) -> (btn : UI_Widget) | ||||
| { | ||||
| 	btn_flags := UI_BoxFlags { .Mouse_Clickable, .Focusable, .Click_To_Focus } | ||||
| 	btn_flags := UI_BoxFlags { .Mouse_Clickable } | ||||
| 	btn.box    = ui_box_make( btn_flags | flags, label ) | ||||
| 	btn.signal = ui_signal_from_box( btn.box ) | ||||
| 	return | ||||
| @@ -197,6 +197,7 @@ ui_resizable_handles :: proc( parent : ^UI_Widget, pos : ^Vec2, size : ^Vec2, | ||||
| 		} | ||||
| 		else | ||||
| 		{ | ||||
| 			app_color := app_color_theme() | ||||
| 			layout := UI_Layout { | ||||
| 				flags          = flags, | ||||
| 				anchor         = range2({},{}), | ||||
| @@ -215,7 +216,7 @@ ui_resizable_handles :: proc( parent : ^UI_Widget, pos : ^Vec2, size : ^Vec2, | ||||
| 				corner_radii = {5, 0, 0, 0}, | ||||
| 				blur_size    = 0, | ||||
| 				font         = get_state().default_font, | ||||
| 				text_color   = Color_ThmDark_Text_Default, | ||||
| 				text_color   = app_color.text_default, | ||||
| 				cursor       = {}, | ||||
| 			} | ||||
| 			layout_combo = to_ui_layout_combo(layout) | ||||
| @@ -223,12 +224,12 @@ ui_resizable_handles :: proc( parent : ^UI_Widget, pos : ^Vec2, size : ^Vec2, | ||||
| 			{ | ||||
| 				using layout_combo.hot | ||||
| 				using style_combo.hot | ||||
| 				bg_color = Color_ThmDark_ResizeHandle_Hot | ||||
| 				bg_color = app_color.resize_hndl_hot | ||||
| 			} | ||||
| 			{ | ||||
| 				using layout_combo.active | ||||
| 				using style_combo.active | ||||
| 				bg_color = Color_ThmDark_ResizeHandle_Active | ||||
| 				bg_color = app_color.resize_hndl_active | ||||
| 			} | ||||
| 		} | ||||
| 		theme := UI_Theme { | ||||
| @@ -364,7 +365,7 @@ ui_resizable_handles :: proc( parent : ^UI_Widget, pos : ^Vec2, size : ^Vec2, | ||||
| 			} | ||||
| 			was_dragging = true | ||||
| 		} | ||||
| 		else if released && was_dragging | ||||
| 		else if released// && was_dragging | ||||
| 		{ | ||||
| 			// This needed to be added as for some reason, this was getting called in screen_ui even when we were resizing with a handle in a worksapce | ||||
| 			if active_context != ui do return false | ||||
|   | ||||
		Reference in New Issue
	
	Block a user