1use crate::text::ScreenAnchor;
6use crate::text::ui_root;
7use nightshade::ecs::ui::layout_types::FlowDirection;
8use nightshade::ecs::ui::units::UiValue;
9use nightshade::prelude::*;
10
11#[cfg(feature = "egui")]
28pub fn enable_egui(world: &mut World) {
29 world.resources.egui.enabled = true;
30}
31
32pub fn spawn_panel(world: &mut World, anchor: ScreenAnchor, width: f32, height: f32) -> Entity {
36 let root = ui_root(world);
37 let (position, anchor_kind) = panel_anchor(anchor);
38 let panel = {
39 let mut tree = UiTreeBuilder::from_parent(world, root);
40 tree.add_node()
41 .window(position, Ab(vec2(width, height)), anchor_kind)
42 .with_rect(8.0, 1.0, Vec4::new(1.0, 1.0, 1.0, 0.1))
43 .color_raw::<UiBase>(Vec4::new(0.05, 0.05, 0.08, 0.85))
44 .flow(FlowDirection::Vertical, 12.0, 8.0)
45 .entity()
46 };
47 ui_mark_render_dirty(world);
48 panel
49}
50
51pub fn panel_button(world: &mut World, panel: Entity, text: &str) -> Entity {
54 let button = {
55 let mut tree = UiTreeBuilder::from_parent(world, panel);
56 tree.add_button(text)
57 };
58 ui_mark_render_dirty(world);
59 button
60}
61
62pub fn panel_label(world: &mut World, panel: Entity, text: &str) -> Entity {
67 let label = {
68 let mut tree = UiTreeBuilder::from_parent(world, panel);
69 tree.add_node()
70 .flow_child(Rl(vec2(100.0, 0.0)) + Ab(vec2(0.0, 24.0)))
71 .with_text(text, 18.0)
72 .color_raw::<UiBase>(Vec4::new(1.0, 1.0, 1.0, 1.0))
73 .entity()
74 };
75 ui_mark_render_dirty(world);
76 label
77}
78
79pub fn panel_checkbox(world: &mut World, panel: Entity, label: &str, initial: bool) -> Entity {
82 let entity = {
83 let mut tree = UiTreeBuilder::from_parent(world, panel);
84 tree.add_checkbox(label, initial)
85 };
86 ui_mark_render_dirty(world);
87 entity
88}
89
90#[inline]
92pub fn checkbox_value(world: &World, checkbox: Entity) -> bool {
93 ui_checkbox_value(world, checkbox).unwrap_or(false)
94}
95
96pub fn panel_slider(world: &mut World, panel: Entity, min: f32, max: f32, initial: f32) -> Entity {
99 let entity = {
100 let mut tree = UiTreeBuilder::from_parent(world, panel);
101 tree.add_slider(min, max, initial)
102 };
103 ui_mark_render_dirty(world);
104 entity
105}
106
107#[inline]
109pub fn slider_value(world: &World, slider: Entity) -> f32 {
110 ui_slider_value(world, slider).unwrap_or(0.0)
111}
112
113pub fn set_slider_value(world: &mut World, slider: Entity, value: f32) {
115 ui_slider_set_value(world, slider, value);
116 ui_mark_render_dirty(world);
117}
118
119pub fn panel_text_input(world: &mut World, panel: Entity, placeholder: &str) -> Entity {
122 let entity = {
123 let mut tree = UiTreeBuilder::from_parent(world, panel);
124 tree.add_text_input(placeholder)
125 };
126 ui_mark_render_dirty(world);
127 entity
128}
129
130#[inline]
132pub fn text_input_changed(world: &World, input: Entity) -> Option<String> {
133 ui_text_input_changed(world, input).map(str::to_string)
134}
135
136pub fn panel_dropdown(
139 world: &mut World,
140 panel: Entity,
141 options: &[&str],
142 initial: usize,
143) -> Entity {
144 let entity = {
145 let mut tree = UiTreeBuilder::from_parent(world, panel);
146 tree.add_dropdown(options, initial)
147 };
148 ui_mark_render_dirty(world);
149 entity
150}
151
152#[inline]
154pub fn dropdown_selected(world: &World, dropdown: Entity) -> Option<usize> {
155 ui_dropdown_selected_changed(world, dropdown)
156}
157
158pub fn panel_progress_bar(world: &mut World, panel: Entity, initial: f32) -> Entity {
161 let entity = {
162 let mut tree = UiTreeBuilder::from_parent(world, panel);
163 tree.add_progress_bar(initial)
164 };
165 ui_mark_render_dirty(world);
166 entity
167}
168
169pub fn set_progress(world: &mut World, bar: Entity, value: f32) {
171 ui_progress_bar_set_value(world, bar, value);
172 ui_mark_render_dirty(world);
173}
174
175pub fn panel_toggle(world: &mut World, panel: Entity, initial: bool) -> Entity {
178 let entity = {
179 let mut tree = UiTreeBuilder::from_parent(world, panel);
180 tree.add_toggle(initial)
181 };
182 ui_mark_render_dirty(world);
183 entity
184}
185
186#[inline]
188pub fn toggle_value(world: &World, toggle: Entity) -> bool {
189 ui_toggle_value(world, toggle).unwrap_or(false)
190}
191
192pub fn panel_radio(
196 world: &mut World,
197 panel: Entity,
198 label: &str,
199 group_id: u32,
200 option_index: usize,
201) -> Entity {
202 let entity = {
203 let mut tree = UiTreeBuilder::from_parent(world, panel);
204 tree.add_radio(label, group_id, option_index)
205 };
206 ui_mark_render_dirty(world);
207 entity
208}
209
210#[inline]
212pub fn radio_selected(world: &World, group_id: u32) -> Option<usize> {
213 ui_radio_group_value(world, group_id)
214}
215
216pub fn panel_range_slider(
219 world: &mut World,
220 panel: Entity,
221 min: f32,
222 max: f32,
223 low: f32,
224 high: f32,
225) -> Entity {
226 let entity = {
227 let mut tree = UiTreeBuilder::from_parent(world, panel);
228 tree.add_range_slider(min, max, low, high)
229 };
230 ui_mark_render_dirty(world);
231 entity
232}
233
234pub fn set_range(world: &mut World, slider: Entity, low: f32, high: f32) {
236 ui_range_slider_set_values(world, slider, low, high);
237 ui_mark_render_dirty(world);
238}
239
240pub fn panel_tabs(world: &mut World, panel: Entity, labels: &[&str], initial: usize) -> Entity {
243 let entity = {
244 let mut tree = UiTreeBuilder::from_parent(world, panel);
245 tree.add_tab_bar(labels, initial)
246 };
247 ui_mark_render_dirty(world);
248 entity
249}
250
251pub fn set_tab(world: &mut World, tabs: Entity, index: usize) {
253 ui_tab_bar_set_value(world, tabs, index);
254 ui_mark_render_dirty(world);
255}
256
257pub fn panel_collapsing(world: &mut World, panel: Entity, label: &str, open: bool) -> Entity {
261 let entity = {
262 let mut tree = UiTreeBuilder::from_parent(world, panel);
263 tree.add_collapsing_header(label, open)
264 };
265 ui_mark_render_dirty(world);
266 entity
267}
268
269pub fn panel_color_picker(world: &mut World, panel: Entity, initial: [f32; 4]) -> Entity {
272 let entity = {
273 let mut tree = UiTreeBuilder::from_parent(world, panel);
274 tree.add_color_picker(Vec4::new(initial[0], initial[1], initial[2], initial[3]))
275 };
276 ui_mark_render_dirty(world);
277 entity
278}
279
280pub fn color_value(world: &World, picker: Entity) -> [f32; 4] {
282 ui_color_picker_color(world, picker)
283 .map(|color| [color.x, color.y, color.z, color.w])
284 .unwrap_or([1.0, 1.0, 1.0, 1.0])
285}
286
287#[inline]
290pub fn button_clicked(world: &World, button: Entity) -> bool {
291 ui_clicked(world, button)
292}
293
294#[inline]
296pub fn button_hovered(world: &World, button: Entity) -> bool {
297 world
298 .ui
299 .get_ui_node_interaction(button)
300 .is_some_and(|interaction| interaction.hovered)
301}
302
303#[inline]
305pub fn despawn_panel(world: &mut World, panel: Entity) {
306 despawn_recursive_immediate(world, panel);
307 ui_mark_render_dirty(world);
308}
309
310pub fn panel_row(world: &mut World, panel: Entity, height: f32) -> Entity {
314 let row = {
315 let mut tree = UiTreeBuilder::from_parent(world, panel);
316 tree.add_node()
317 .flow_child(Rl(vec2(100.0, 0.0)) + Ab(vec2(0.0, height)))
318 .flow(FlowDirection::Horizontal, 0.0, 8.0)
319 .entity()
320 };
321 ui_mark_render_dirty(world);
322 row
323}
324
325pub fn panel_grid(
329 world: &mut World,
330 panel: Entity,
331 columns: usize,
332 row_height: f32,
333 height: f32,
334) -> Entity {
335 let grid = {
336 let mut tree = UiTreeBuilder::from_parent(world, panel);
337 tree.add_node()
338 .flow_child(Rl(vec2(100.0, 0.0)) + Ab(vec2(0.0, height)))
339 .grid(columns, row_height, 0.0, 8.0, 8.0)
340 .entity()
341 };
342 ui_mark_render_dirty(world);
343 grid
344}
345
346pub fn panel_scroll(world: &mut World, panel: Entity, height: f32) -> Entity {
351 let content = {
352 let mut tree = UiTreeBuilder::from_parent(world, panel);
353 let area = tree.add_scroll_area(vec2(0.0, height));
354 widget::<UiScrollAreaData>(tree.world_mut(), area)
355 .map(|data| data.content_entity)
356 .unwrap_or(area)
357 };
358 ui_mark_render_dirty(world);
359 content
360}
361
362pub fn set_scroll_offset(world: &mut World, scroll_area: Entity, offset: f32) {
365 ui_scroll_area_set_offset(world, scroll_area, offset);
366 ui_mark_render_dirty(world);
367}
368
369pub fn set_focus_order(world: &mut World, entity: Entity, order: i32) {
373 if let Some(interaction) = world.ui.get_ui_node_interaction_mut(entity) {
374 interaction.tab_index = Some(order);
375 }
376}
377
378pub fn focus_widget(world: &mut World, entity: Entity) {
381 world.resources.retained_ui.interaction.focused_entity = Some(entity);
382}
383
384pub fn panel_text_area(world: &mut World, panel: Entity, placeholder: &str, rows: usize) -> Entity {
387 let entity = {
388 let mut tree = UiTreeBuilder::from_parent(world, panel);
389 tree.add_text_area(placeholder, rows)
390 };
391 ui_mark_render_dirty(world);
392 entity
393}
394
395pub fn panel_text_area_with_value(
397 world: &mut World,
398 panel: Entity,
399 placeholder: &str,
400 rows: usize,
401 initial: &str,
402) -> Entity {
403 let entity = {
404 let mut tree = UiTreeBuilder::from_parent(world, panel);
405 tree.add_text_area_with_value(placeholder, rows, initial)
406 };
407 ui_mark_render_dirty(world);
408 entity
409}
410
411pub fn set_text_area(world: &mut World, area: Entity, text: &str) {
413 ui_text_area_set_value(world, area, text);
414 ui_mark_render_dirty(world);
415}
416
417pub fn panel_multi_select(world: &mut World, panel: Entity, options: &[&str]) -> Entity {
420 let entity = {
421 let mut tree = UiTreeBuilder::from_parent(world, panel);
422 tree.add_multi_select(options)
423 };
424 ui_mark_render_dirty(world);
425 entity
426}
427
428pub fn set_multi_select(world: &mut World, widget: Entity, indices: &[usize]) {
430 ui_multi_select_set_selected(world, widget, indices);
431 ui_mark_render_dirty(world);
432}
433
434pub fn panel_date_picker(
437 world: &mut World,
438 panel: Entity,
439 year: i32,
440 month: u32,
441 day: u32,
442) -> Entity {
443 let entity = {
444 let mut tree = UiTreeBuilder::from_parent(world, panel);
445 tree.add_date_picker(year, month, day)
446 };
447 ui_mark_render_dirty(world);
448 entity
449}
450
451pub fn set_date(world: &mut World, picker: Entity, year: i32, month: u32, day: u32) {
453 ui_date_picker_set_value(world, picker, year, month, day);
454 ui_mark_render_dirty(world);
455}
456
457pub fn panel_menu(world: &mut World, panel: Entity, label: &str, items: &[&str]) -> Entity {
459 let entity = {
460 let mut tree = UiTreeBuilder::from_parent(world, panel);
461 tree.add_menu(label, items)
462 };
463 ui_mark_render_dirty(world);
464 entity
465}
466
467pub fn panel_color_picker_hsv(world: &mut World, panel: Entity, initial: [f32; 4]) -> Entity {
470 let entity = {
471 let mut tree = UiTreeBuilder::from_parent(world, panel);
472 tree.add_color_picker_hsv(rgba(initial))
473 };
474 ui_mark_render_dirty(world);
475 entity
476}
477
478pub fn panel_splitter(
482 world: &mut World,
483 panel: Entity,
484 direction: SplitDirection,
485 initial_ratio: f32,
486) -> Entity {
487 let entity = {
488 let mut tree = UiTreeBuilder::from_parent(world, panel);
489 tree.add_splitter(direction, initial_ratio)
490 };
491 ui_mark_render_dirty(world);
492 entity
493}
494
495pub fn panel_breadcrumb(world: &mut World, panel: Entity, segments: &[&str]) -> Entity {
498 let entity = {
499 let mut tree = UiTreeBuilder::from_parent(world, panel);
500 tree.add_breadcrumb(segments)
501 };
502 ui_mark_render_dirty(world);
503 entity
504}
505
506pub fn panel_virtual_list(
509 world: &mut World,
510 panel: Entity,
511 item_height: f32,
512 pool_size: usize,
513) -> Entity {
514 let entity = {
515 let mut tree = UiTreeBuilder::from_parent(world, panel);
516 tree.add_virtual_list(item_height, pool_size)
517 };
518 ui_mark_render_dirty(world);
519 entity
520}
521
522pub fn panel_table(world: &mut World, panel: Entity, headers: &[&str], widths: &[f32]) -> Entity {
525 let entity = {
526 let mut tree = UiTreeBuilder::from_parent(world, panel);
527 tree.add_table(headers, widths)
528 };
529 ui_mark_render_dirty(world);
530 entity
531}
532
533pub fn panel_data_grid(
538 world: &mut World,
539 panel: Entity,
540 columns: &[(&str, f32)],
541 pool_size: usize,
542) -> Entity {
543 let grid_columns: Vec<DataGridColumn> = columns
544 .iter()
545 .map(|(header, width)| DataGridColumn::new(header, *width))
546 .collect();
547 let entity = {
548 let mut tree = UiTreeBuilder::from_parent(world, panel);
549 tree.add_data_grid(&grid_columns, pool_size)
550 };
551 ui_mark_render_dirty(world);
552 entity
553}
554
555pub fn set_data_grid_rows(world: &mut World, grid: Entity, count: usize) {
557 ui_data_grid_set_row_count(world, grid, count);
558}
559
560pub fn set_data_grid_cell(world: &mut World, grid: Entity, row: usize, column: usize, text: &str) {
562 ui_data_grid_set_cell(world, grid, row, column, text);
563}
564
565#[inline]
567pub fn data_grid_selection_changed(world: &World, grid: Entity) -> bool {
568 ui_data_grid_selection_changed(world, grid)
569}
570
571pub fn panel_command_palette(world: &mut World, panel: Entity, pool_size: usize) -> Entity {
574 let entity = {
575 let mut tree = UiTreeBuilder::from_parent(world, panel);
576 tree.add_command_palette(pool_size)
577 };
578 ui_mark_render_dirty(world);
579 entity
580}
581
582pub fn panel_property_grid(world: &mut World, panel: Entity, label_width: f32) -> Entity {
586 let entity = {
587 let mut tree = UiTreeBuilder::from_parent(world, panel);
588 tree.add_property_grid(label_width)
589 };
590 ui_mark_render_dirty(world);
591 entity
592}
593
594pub fn panel_property_row(world: &mut World, grid: Entity, label: &str) -> Entity {
597 let row = {
598 let mut tree = UiTreeBuilder::from_parent(world, grid);
599 tree.add_property_row(grid, grid, label)
600 };
601 ui_mark_render_dirty(world);
602 row
603}
604
605pub fn panel_tree_view(world: &mut World, panel: Entity, multi_select: bool) -> Entity {
608 let entity = {
609 let mut tree = UiTreeBuilder::from_parent(world, panel);
610 tree.add_tree_view(multi_select)
611 };
612 ui_mark_render_dirty(world);
613 entity
614}
615
616pub fn tree_content(world: &World, tree_view: Entity) -> Entity {
619 widget::<UiTreeViewData>(world, tree_view)
620 .map(|data| data.content_entity)
621 .unwrap_or(tree_view)
622}
623
624pub fn tree_node(
628 world: &mut World,
629 tree_view: Entity,
630 parent_container: Entity,
631 label: &str,
632 depth: usize,
633 user_data: u64,
634) -> Entity {
635 let node = {
636 let mut tree = UiTreeBuilder::from_parent(world, parent_container);
637 tree.add_tree_node(tree_view, parent_container, label, depth, user_data)
638 };
639 ui_mark_render_dirty(world);
640 node
641}
642
643pub fn tree_node_children(world: &World, node: Entity) -> Entity {
646 widget::<UiTreeNodeData>(world, node)
647 .map(|data| data.children_container)
648 .unwrap_or(node)
649}
650
651pub fn set_tree_node_expanded(world: &mut World, node: Entity, expanded: bool) {
653 ui_tree_node_set_expanded(world, node, expanded);
654 ui_mark_render_dirty(world);
655}
656
657#[inline]
659pub fn tree_view_selected(world: &World, tree_view: Entity) -> Vec<Entity> {
660 ui_tree_view_selected(world, tree_view)
661}
662
663pub fn panel_drag_value(
667 world: &mut World,
668 panel: Entity,
669 min: f32,
670 max: f32,
671 initial: f32,
672) -> Entity {
673 let entity = {
674 let mut tree = UiTreeBuilder::from_parent(world, panel);
675 tree.add_drag_value(min, max, initial)
676 };
677 ui_mark_render_dirty(world);
678 entity
679}
680
681#[inline]
683pub fn drag_value(world: &World, widget: Entity) -> f32 {
684 ui_drag_value(world, widget).unwrap_or(0.0)
685}
686
687pub fn panel_selectable(
690 world: &mut World,
691 panel: Entity,
692 text: &str,
693 group: Option<u32>,
694) -> Entity {
695 let entity = {
696 let mut tree = UiTreeBuilder::from_parent(world, panel);
697 tree.add_selectable_label(text, group)
698 };
699 ui_mark_render_dirty(world);
700 entity
701}
702
703pub fn panel_modal(
707 world: &mut World,
708 panel: Entity,
709 title: &str,
710 width: f32,
711 height: f32,
712) -> Entity {
713 let entity = {
714 let mut tree = UiTreeBuilder::from_parent(world, panel);
715 tree.add_modal_dialog(title, width, height)
716 };
717 ui_mark_render_dirty(world);
718 entity
719}
720
721pub fn panel_spinner(world: &mut World, panel: Entity) -> Entity {
723 let entity = {
724 let mut tree = UiTreeBuilder::from_parent(world, panel);
725 tree.add_spinner()
726 };
727 ui_mark_render_dirty(world);
728 entity
729}
730
731pub fn panel_separator(world: &mut World, panel: Entity) -> Entity {
733 let entity = {
734 let mut tree = UiTreeBuilder::from_parent(world, panel);
735 tree.add_separator()
736 };
737 ui_mark_render_dirty(world);
738 entity
739}
740
741pub fn panel_heading(world: &mut World, panel: Entity, text: &str) -> Entity {
743 let entity = {
744 let mut tree = UiTreeBuilder::from_parent(world, panel);
745 tree.add_heading(text)
746 };
747 ui_mark_render_dirty(world);
748 entity
749}
750
751fn panel_anchor(anchor: ScreenAnchor) -> (UiValue<Vec2>, Anchor) {
752 match anchor {
753 ScreenAnchor::TopLeft => (Ab(vec2(20.0, 20.0)).into(), Anchor::TopLeft),
754 ScreenAnchor::TopCenter => (Rl(vec2(50.0, 0.0)) + Ab(vec2(0.0, 20.0)), Anchor::TopCenter),
755 ScreenAnchor::TopRight => (
756 Rl(vec2(100.0, 0.0)) + Ab(vec2(-20.0, 20.0)),
757 Anchor::TopRight,
758 ),
759 ScreenAnchor::BottomLeft => (
760 Rl(vec2(0.0, 100.0)) + Ab(vec2(20.0, -20.0)),
761 Anchor::BottomLeft,
762 ),
763 ScreenAnchor::BottomCenter => (
764 Rl(vec2(50.0, 100.0)) + Ab(vec2(0.0, -20.0)),
765 Anchor::BottomCenter,
766 ),
767 ScreenAnchor::BottomRight => (
768 Rl(vec2(100.0, 100.0)) + Ab(vec2(-20.0, -20.0)),
769 Anchor::BottomRight,
770 ),
771 ScreenAnchor::Center => (Rl(vec2(50.0, 50.0)).into(), Anchor::Center),
772 }
773}
774
775fn anchor_base(anchor: ScreenAnchor) -> (Vec2, Anchor) {
778 match anchor {
779 ScreenAnchor::TopLeft => (vec2(0.0, 0.0), Anchor::TopLeft),
780 ScreenAnchor::TopCenter => (vec2(50.0, 0.0), Anchor::TopCenter),
781 ScreenAnchor::TopRight => (vec2(100.0, 0.0), Anchor::TopRight),
782 ScreenAnchor::BottomLeft => (vec2(0.0, 100.0), Anchor::BottomLeft),
783 ScreenAnchor::BottomCenter => (vec2(50.0, 100.0), Anchor::BottomCenter),
784 ScreenAnchor::BottomRight => (vec2(100.0, 100.0), Anchor::BottomRight),
785 ScreenAnchor::Center => (vec2(50.0, 50.0), Anchor::Center),
786 }
787}
788
789fn rgba(color: [f32; 4]) -> Vec4 {
790 Vec4::new(color[0], color[1], color[2], color[3])
791}
792
793const PANEL_BORDER: Vec4 = Vec4::new(0.12, 0.14, 0.2, 0.7);
794const PANEL_SHADOW: Vec4 = Vec4::new(0.0, 0.0, 0.0, 0.55);
795
796pub fn spawn_panel_at(
802 world: &mut World,
803 anchor: ScreenAnchor,
804 offset: Vec2,
805 size: Vec2,
806 color: [f32; 4],
807) -> Entity {
808 let root = ui_root(world);
809 let (base, anchor_kind) = anchor_base(anchor);
810 let panel = {
811 let mut tree = UiTreeBuilder::from_parent(world, root);
812 tree.add_node()
813 .window(Rl(base) + Ab(offset), Ab(size), anchor_kind)
814 .with_rect(10.0, 1.5, PANEL_BORDER)
815 .color_raw::<UiBase>(rgba(color))
816 .with_shadow(PANEL_SHADOW, vec2(0.0, 6.0), 18.0, 0.0)
817 .entity()
818 };
819 ui_mark_render_dirty(world);
820 panel
821}
822
823pub fn panel_text(
828 world: &mut World,
829 parent: Entity,
830 text: &str,
831 rect: [f32; 4],
832 font_size: f32,
833 color: [f32; 4],
834 align: TextAlignment,
835) -> Entity {
836 let label = {
837 let mut tree = UiTreeBuilder::from_parent(world, parent);
838 tree.add_node()
839 .window(
840 Ab(vec2(rect[0], rect[1])),
841 Ab(vec2(rect[2], rect[3])),
842 Anchor::TopLeft,
843 )
844 .with_text(text, font_size)
845 .with_text_alignment(align, VerticalAlignment::Middle)
846 .color_raw::<UiBase>(rgba(color))
847 .without_pointer_events()
848 .entity()
849 };
850 ui_mark_render_dirty(world);
851 label
852}
853
854pub fn panel_box(
858 world: &mut World,
859 parent: Entity,
860 offset: Vec2,
861 size: Vec2,
862 color: [f32; 4],
863) -> Entity {
864 let box_entity = {
865 let mut tree = UiTreeBuilder::from_parent(world, parent);
866 tree.add_node()
867 .window(Ab(offset), Ab(size), Anchor::TopLeft)
868 .with_rect(6.0, 0.0, Vec4::new(0.0, 0.0, 0.0, 0.0))
869 .color_raw::<UiBase>(rgba(color))
870 .without_pointer_events()
871 .entity()
872 };
873 ui_mark_render_dirty(world);
874 box_entity
875}
876
877pub fn panel_button_at(
882 world: &mut World,
883 parent: Entity,
884 label: &str,
885 offset: Vec2,
886 size: Vec2,
887) -> Entity {
888 let button = {
889 let mut tree = UiTreeBuilder::from_parent(world, parent);
890 tree.add_node()
891 .window(Ab(offset), Ab(size), Anchor::TopLeft)
892 .with_rect(8.0, 1.5, PANEL_BORDER)
893 .color_raw::<UiBase>(Vec4::new(0.05, 0.06, 0.09, 0.92))
894 .color_raw::<UiHover>(Vec4::new(0.09, 0.11, 0.17, 0.95))
895 .color_raw::<UiPressed>(Vec4::new(0.04, 0.05, 0.08, 1.0))
896 .with_transition::<UiHover>(12.0, 6.0)
897 .with_transition::<UiPressed>(18.0, 10.0)
898 .with_transition::<UiSelected>(10.0, 5.0)
899 .with_interaction()
900 .entity()
901 };
902 if !label.is_empty() {
903 let mut tree = UiTreeBuilder::from_parent(world, button);
904 tree.add_node()
905 .window(Rl(vec2(50.0, 50.0)), Ab(size), Anchor::Center)
906 .with_text(label, 14.0)
907 .with_text_alignment(TextAlignment::Center, VerticalAlignment::Middle)
908 .color_raw::<UiBase>(Vec4::new(0.92, 0.94, 1.0, 1.0))
909 .without_pointer_events()
910 .entity();
911 }
912 ui_mark_render_dirty(world);
913 button
914}
915
916pub fn set_panel_rect(world: &mut World, node: Entity, offset: Vec2, size: Vec2) {
919 if let Some(layout) = world.ui.get_ui_layout_node_mut(node) {
920 layout.base_layout = Some(UiLayoutType::Window(WindowLayout {
921 position: Ab(offset).into(),
922 size: Ab(size).into(),
923 anchor: Anchor::TopLeft,
924 }));
925 }
926 ui_mark_render_dirty(world);
927}
928
929pub fn set_panel_color(world: &mut World, node: Entity, color: [f32; 4]) {
931 if let Some(node_color) = world.ui.get_ui_node_color_mut(node) {
932 node_color.colors[UiBase::INDEX] = Some(rgba(color));
933 }
934 ui_mark_render_dirty(world);
935}
936
937pub fn set_panel_text(world: &mut World, label: Entity, text: &str) {
940 ui_set_text(world, label, text);
941}
942
943pub fn set_panel_text_color(world: &mut World, label: Entity, color: [f32; 4]) {
945 set_panel_color(world, label, color);
946}
947
948pub fn set_panel_selected(world: &mut World, button: Entity, selected: bool, accent: [f32; 4]) {
951 if let Some(node_color) = world.ui.get_ui_node_color_mut(button) {
952 node_color.colors[UiSelected::INDEX] = Some(rgba(accent));
953 }
954 ui_set_selected(world, button, selected);
955 ui_mark_render_dirty(world);
956}
957
958pub fn set_panel_visible(world: &mut World, node: Entity, visible: bool) {
961 ui_set_visible(world, node, visible);
962 ui_mark_render_dirty(world);
963}