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.plugin_resource_mut::<EguiState>().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 .get::<nightshade::ecs::ui::components::UiNodeInteraction>(button)
299 .is_some_and(|interaction| interaction.hovered)
300}
301
302#[inline]
304pub fn despawn_panel(world: &mut World, panel: Entity) {
305 despawn_recursive_immediate(world, panel);
306 ui_mark_render_dirty(world);
307}
308
309pub fn panel_row(world: &mut World, panel: Entity, height: f32) -> Entity {
313 let row = {
314 let mut tree = UiTreeBuilder::from_parent(world, panel);
315 tree.add_node()
316 .flow_child(Rl(vec2(100.0, 0.0)) + Ab(vec2(0.0, height)))
317 .flow(FlowDirection::Horizontal, 0.0, 8.0)
318 .entity()
319 };
320 ui_mark_render_dirty(world);
321 row
322}
323
324pub fn panel_grid(
328 world: &mut World,
329 panel: Entity,
330 columns: usize,
331 row_height: f32,
332 height: f32,
333) -> Entity {
334 let grid = {
335 let mut tree = UiTreeBuilder::from_parent(world, panel);
336 tree.add_node()
337 .flow_child(Rl(vec2(100.0, 0.0)) + Ab(vec2(0.0, height)))
338 .grid(columns, row_height, 0.0, 8.0, 8.0)
339 .entity()
340 };
341 ui_mark_render_dirty(world);
342 grid
343}
344
345pub fn panel_scroll(world: &mut World, panel: Entity, height: f32) -> Entity {
350 let content = {
351 let mut tree = UiTreeBuilder::from_parent(world, panel);
352 let area = tree.add_scroll_area(vec2(0.0, height));
353 widget::<UiScrollAreaData>(tree.world_mut(), area)
354 .map(|data| data.content_entity)
355 .unwrap_or(area)
356 };
357 ui_mark_render_dirty(world);
358 content
359}
360
361pub fn set_scroll_offset(world: &mut World, scroll_area: Entity, offset: f32) {
364 ui_scroll_area_set_offset(world, scroll_area, offset);
365 ui_mark_render_dirty(world);
366}
367
368pub fn set_focus_order(world: &mut World, entity: Entity, order: i32) {
372 if let Some(interaction) =
373 world.get_mut::<nightshade::ecs::ui::components::UiNodeInteraction>(entity)
374 {
375 interaction.tab_index = Some(order);
376 }
377}
378
379pub fn focus_widget(world: &mut World, entity: Entity) {
382 world
383 .res_mut::<nightshade::ecs::ui::resources::RetainedUiState>()
384 .interaction
385 .focused_entity = Some(entity);
386}
387
388pub fn panel_text_area(world: &mut World, panel: Entity, placeholder: &str, rows: usize) -> Entity {
391 let entity = {
392 let mut tree = UiTreeBuilder::from_parent(world, panel);
393 tree.add_text_area(placeholder, rows)
394 };
395 ui_mark_render_dirty(world);
396 entity
397}
398
399pub fn panel_text_area_with_value(
401 world: &mut World,
402 panel: Entity,
403 placeholder: &str,
404 rows: usize,
405 initial: &str,
406) -> Entity {
407 let entity = {
408 let mut tree = UiTreeBuilder::from_parent(world, panel);
409 tree.add_text_area_with_value(placeholder, rows, initial)
410 };
411 ui_mark_render_dirty(world);
412 entity
413}
414
415pub fn set_text_area(world: &mut World, area: Entity, text: &str) {
417 ui_text_area_set_value(world, area, text);
418 ui_mark_render_dirty(world);
419}
420
421pub fn panel_multi_select(world: &mut World, panel: Entity, options: &[&str]) -> Entity {
424 let entity = {
425 let mut tree = UiTreeBuilder::from_parent(world, panel);
426 tree.add_multi_select(options)
427 };
428 ui_mark_render_dirty(world);
429 entity
430}
431
432pub fn set_multi_select(world: &mut World, widget: Entity, indices: &[usize]) {
434 ui_multi_select_set_selected(world, widget, indices);
435 ui_mark_render_dirty(world);
436}
437
438pub fn panel_date_picker(
441 world: &mut World,
442 panel: Entity,
443 year: i32,
444 month: u32,
445 day: u32,
446) -> Entity {
447 let entity = {
448 let mut tree = UiTreeBuilder::from_parent(world, panel);
449 tree.add_date_picker(year, month, day)
450 };
451 ui_mark_render_dirty(world);
452 entity
453}
454
455pub fn set_date(world: &mut World, picker: Entity, year: i32, month: u32, day: u32) {
457 ui_date_picker_set_value(world, picker, year, month, day);
458 ui_mark_render_dirty(world);
459}
460
461pub fn panel_menu(world: &mut World, panel: Entity, label: &str, items: &[&str]) -> Entity {
463 let entity = {
464 let mut tree = UiTreeBuilder::from_parent(world, panel);
465 tree.add_menu(label, items)
466 };
467 ui_mark_render_dirty(world);
468 entity
469}
470
471pub fn panel_color_picker_hsv(world: &mut World, panel: Entity, initial: [f32; 4]) -> Entity {
474 let entity = {
475 let mut tree = UiTreeBuilder::from_parent(world, panel);
476 tree.add_color_picker_hsv(rgba(initial))
477 };
478 ui_mark_render_dirty(world);
479 entity
480}
481
482pub fn panel_splitter(
486 world: &mut World,
487 panel: Entity,
488 direction: SplitDirection,
489 initial_ratio: f32,
490) -> Entity {
491 let entity = {
492 let mut tree = UiTreeBuilder::from_parent(world, panel);
493 tree.add_splitter(direction, initial_ratio)
494 };
495 ui_mark_render_dirty(world);
496 entity
497}
498
499pub fn panel_breadcrumb(world: &mut World, panel: Entity, segments: &[&str]) -> Entity {
502 let entity = {
503 let mut tree = UiTreeBuilder::from_parent(world, panel);
504 tree.add_breadcrumb(segments)
505 };
506 ui_mark_render_dirty(world);
507 entity
508}
509
510pub fn panel_virtual_list(
513 world: &mut World,
514 panel: Entity,
515 item_height: f32,
516 pool_size: usize,
517) -> Entity {
518 let entity = {
519 let mut tree = UiTreeBuilder::from_parent(world, panel);
520 tree.add_virtual_list(item_height, pool_size)
521 };
522 ui_mark_render_dirty(world);
523 entity
524}
525
526pub fn panel_table(world: &mut World, panel: Entity, headers: &[&str], widths: &[f32]) -> Entity {
529 let entity = {
530 let mut tree = UiTreeBuilder::from_parent(world, panel);
531 tree.add_table(headers, widths)
532 };
533 ui_mark_render_dirty(world);
534 entity
535}
536
537pub fn panel_data_grid(
542 world: &mut World,
543 panel: Entity,
544 columns: &[(&str, f32)],
545 pool_size: usize,
546) -> Entity {
547 let grid_columns: Vec<DataGridColumn> = columns
548 .iter()
549 .map(|(header, width)| DataGridColumn::new(header, *width))
550 .collect();
551 let entity = {
552 let mut tree = UiTreeBuilder::from_parent(world, panel);
553 tree.add_data_grid(&grid_columns, pool_size)
554 };
555 ui_mark_render_dirty(world);
556 entity
557}
558
559pub fn set_data_grid_rows(world: &mut World, grid: Entity, count: usize) {
561 ui_data_grid_set_row_count(world, grid, count);
562}
563
564pub fn set_data_grid_cell(world: &mut World, grid: Entity, row: usize, column: usize, text: &str) {
566 ui_data_grid_set_cell(world, grid, row, column, text);
567}
568
569#[inline]
571pub fn data_grid_selection_changed(world: &World, grid: Entity) -> bool {
572 ui_data_grid_selection_changed(world, grid)
573}
574
575pub fn panel_command_palette(world: &mut World, panel: Entity, pool_size: usize) -> Entity {
578 let entity = {
579 let mut tree = UiTreeBuilder::from_parent(world, panel);
580 tree.add_command_palette(pool_size)
581 };
582 ui_mark_render_dirty(world);
583 entity
584}
585
586pub fn panel_property_grid(world: &mut World, panel: Entity, label_width: f32) -> Entity {
590 let entity = {
591 let mut tree = UiTreeBuilder::from_parent(world, panel);
592 tree.add_property_grid(label_width)
593 };
594 ui_mark_render_dirty(world);
595 entity
596}
597
598pub fn panel_property_row(world: &mut World, grid: Entity, label: &str) -> Entity {
601 let row = {
602 let mut tree = UiTreeBuilder::from_parent(world, grid);
603 tree.add_property_row(grid, grid, label)
604 };
605 ui_mark_render_dirty(world);
606 row
607}
608
609pub fn panel_tree_view(world: &mut World, panel: Entity, multi_select: bool) -> Entity {
612 let entity = {
613 let mut tree = UiTreeBuilder::from_parent(world, panel);
614 tree.add_tree_view(multi_select)
615 };
616 ui_mark_render_dirty(world);
617 entity
618}
619
620pub fn tree_content(world: &World, tree_view: Entity) -> Entity {
623 widget::<UiTreeViewData>(world, tree_view)
624 .map(|data| data.content_entity)
625 .unwrap_or(tree_view)
626}
627
628pub fn tree_node(
632 world: &mut World,
633 tree_view: Entity,
634 parent_container: Entity,
635 label: &str,
636 depth: usize,
637 user_data: u64,
638) -> Entity {
639 let node = {
640 let mut tree = UiTreeBuilder::from_parent(world, parent_container);
641 tree.add_tree_node(tree_view, parent_container, label, depth, user_data)
642 };
643 ui_mark_render_dirty(world);
644 node
645}
646
647pub fn tree_node_children(world: &World, node: Entity) -> Entity {
650 widget::<UiTreeNodeData>(world, node)
651 .map(|data| data.children_container)
652 .unwrap_or(node)
653}
654
655pub fn set_tree_node_expanded(world: &mut World, node: Entity, expanded: bool) {
657 ui_tree_node_set_expanded(world, node, expanded);
658 ui_mark_render_dirty(world);
659}
660
661#[inline]
663pub fn tree_view_selected(world: &World, tree_view: Entity) -> Vec<Entity> {
664 ui_tree_view_selected(world, tree_view)
665}
666
667pub fn panel_drag_value(
671 world: &mut World,
672 panel: Entity,
673 min: f32,
674 max: f32,
675 initial: f32,
676) -> Entity {
677 let entity = {
678 let mut tree = UiTreeBuilder::from_parent(world, panel);
679 tree.add_drag_value(min, max, initial)
680 };
681 ui_mark_render_dirty(world);
682 entity
683}
684
685#[inline]
687pub fn drag_value(world: &World, widget: Entity) -> f32 {
688 ui_drag_value(world, widget).unwrap_or(0.0)
689}
690
691pub fn panel_selectable(
694 world: &mut World,
695 panel: Entity,
696 text: &str,
697 group: Option<u32>,
698) -> Entity {
699 let entity = {
700 let mut tree = UiTreeBuilder::from_parent(world, panel);
701 tree.add_selectable_label(text, group)
702 };
703 ui_mark_render_dirty(world);
704 entity
705}
706
707pub fn panel_modal(
711 world: &mut World,
712 panel: Entity,
713 title: &str,
714 width: f32,
715 height: f32,
716) -> Entity {
717 let entity = {
718 let mut tree = UiTreeBuilder::from_parent(world, panel);
719 tree.add_modal_dialog(title, width, height)
720 };
721 ui_mark_render_dirty(world);
722 entity
723}
724
725pub fn panel_spinner(world: &mut World, panel: Entity) -> Entity {
727 let entity = {
728 let mut tree = UiTreeBuilder::from_parent(world, panel);
729 tree.add_spinner()
730 };
731 ui_mark_render_dirty(world);
732 entity
733}
734
735pub fn panel_separator(world: &mut World, panel: Entity) -> Entity {
737 let entity = {
738 let mut tree = UiTreeBuilder::from_parent(world, panel);
739 tree.add_separator()
740 };
741 ui_mark_render_dirty(world);
742 entity
743}
744
745pub fn panel_heading(world: &mut World, panel: Entity, text: &str) -> Entity {
747 let entity = {
748 let mut tree = UiTreeBuilder::from_parent(world, panel);
749 tree.add_heading(text)
750 };
751 ui_mark_render_dirty(world);
752 entity
753}
754
755fn panel_anchor(anchor: ScreenAnchor) -> (UiValue<Vec2>, Anchor) {
756 match anchor {
757 ScreenAnchor::TopLeft => (Ab(vec2(20.0, 20.0)).into(), Anchor::TopLeft),
758 ScreenAnchor::TopCenter => (Rl(vec2(50.0, 0.0)) + Ab(vec2(0.0, 20.0)), Anchor::TopCenter),
759 ScreenAnchor::TopRight => (
760 Rl(vec2(100.0, 0.0)) + Ab(vec2(-20.0, 20.0)),
761 Anchor::TopRight,
762 ),
763 ScreenAnchor::BottomLeft => (
764 Rl(vec2(0.0, 100.0)) + Ab(vec2(20.0, -20.0)),
765 Anchor::BottomLeft,
766 ),
767 ScreenAnchor::BottomCenter => (
768 Rl(vec2(50.0, 100.0)) + Ab(vec2(0.0, -20.0)),
769 Anchor::BottomCenter,
770 ),
771 ScreenAnchor::BottomRight => (
772 Rl(vec2(100.0, 100.0)) + Ab(vec2(-20.0, -20.0)),
773 Anchor::BottomRight,
774 ),
775 ScreenAnchor::Center => (Rl(vec2(50.0, 50.0)).into(), Anchor::Center),
776 }
777}
778
779fn anchor_base(anchor: ScreenAnchor) -> (Vec2, Anchor) {
782 match anchor {
783 ScreenAnchor::TopLeft => (vec2(0.0, 0.0), Anchor::TopLeft),
784 ScreenAnchor::TopCenter => (vec2(50.0, 0.0), Anchor::TopCenter),
785 ScreenAnchor::TopRight => (vec2(100.0, 0.0), Anchor::TopRight),
786 ScreenAnchor::BottomLeft => (vec2(0.0, 100.0), Anchor::BottomLeft),
787 ScreenAnchor::BottomCenter => (vec2(50.0, 100.0), Anchor::BottomCenter),
788 ScreenAnchor::BottomRight => (vec2(100.0, 100.0), Anchor::BottomRight),
789 ScreenAnchor::Center => (vec2(50.0, 50.0), Anchor::Center),
790 }
791}
792
793fn rgba(color: [f32; 4]) -> Vec4 {
794 Vec4::new(color[0], color[1], color[2], color[3])
795}
796
797const PANEL_BORDER: Vec4 = Vec4::new(0.12, 0.14, 0.2, 0.7);
798const PANEL_SHADOW: Vec4 = Vec4::new(0.0, 0.0, 0.0, 0.55);
799
800pub fn spawn_panel_at(
806 world: &mut World,
807 anchor: ScreenAnchor,
808 offset: Vec2,
809 size: Vec2,
810 color: [f32; 4],
811) -> Entity {
812 let root = ui_root(world);
813 let (base, anchor_kind) = anchor_base(anchor);
814 let panel = {
815 let mut tree = UiTreeBuilder::from_parent(world, root);
816 tree.add_node()
817 .window(Rl(base) + Ab(offset), Ab(size), anchor_kind)
818 .with_rect(10.0, 1.5, PANEL_BORDER)
819 .color_raw::<UiBase>(rgba(color))
820 .with_shadow(PANEL_SHADOW, vec2(0.0, 6.0), 18.0, 0.0)
821 .entity()
822 };
823 ui_mark_render_dirty(world);
824 panel
825}
826
827pub fn panel_text(
832 world: &mut World,
833 parent: Entity,
834 text: &str,
835 rect: [f32; 4],
836 font_size: f32,
837 color: [f32; 4],
838 align: TextAlignment,
839) -> Entity {
840 let label = {
841 let mut tree = UiTreeBuilder::from_parent(world, parent);
842 tree.add_node()
843 .window(
844 Ab(vec2(rect[0], rect[1])),
845 Ab(vec2(rect[2], rect[3])),
846 Anchor::TopLeft,
847 )
848 .with_text(text, font_size)
849 .with_text_alignment(align, VerticalAlignment::Middle)
850 .color_raw::<UiBase>(rgba(color))
851 .without_pointer_events()
852 .entity()
853 };
854 ui_mark_render_dirty(world);
855 label
856}
857
858pub fn panel_box(
862 world: &mut World,
863 parent: Entity,
864 offset: Vec2,
865 size: Vec2,
866 color: [f32; 4],
867) -> Entity {
868 let box_entity = {
869 let mut tree = UiTreeBuilder::from_parent(world, parent);
870 tree.add_node()
871 .window(Ab(offset), Ab(size), Anchor::TopLeft)
872 .with_rect(6.0, 0.0, Vec4::new(0.0, 0.0, 0.0, 0.0))
873 .color_raw::<UiBase>(rgba(color))
874 .without_pointer_events()
875 .entity()
876 };
877 ui_mark_render_dirty(world);
878 box_entity
879}
880
881pub fn panel_button_at(
886 world: &mut World,
887 parent: Entity,
888 label: &str,
889 offset: Vec2,
890 size: Vec2,
891) -> Entity {
892 let button = {
893 let mut tree = UiTreeBuilder::from_parent(world, parent);
894 tree.add_node()
895 .window(Ab(offset), Ab(size), Anchor::TopLeft)
896 .with_rect(8.0, 1.5, PANEL_BORDER)
897 .color_raw::<UiBase>(Vec4::new(0.05, 0.06, 0.09, 0.92))
898 .color_raw::<UiHover>(Vec4::new(0.09, 0.11, 0.17, 0.95))
899 .color_raw::<UiPressed>(Vec4::new(0.04, 0.05, 0.08, 1.0))
900 .with_transition::<UiHover>(12.0, 6.0)
901 .with_transition::<UiPressed>(18.0, 10.0)
902 .with_transition::<UiSelected>(10.0, 5.0)
903 .with_interaction()
904 .entity()
905 };
906 if !label.is_empty() {
907 let mut tree = UiTreeBuilder::from_parent(world, button);
908 tree.add_node()
909 .window(Rl(vec2(50.0, 50.0)), Ab(size), Anchor::Center)
910 .with_text(label, 14.0)
911 .with_text_alignment(TextAlignment::Center, VerticalAlignment::Middle)
912 .color_raw::<UiBase>(Vec4::new(0.92, 0.94, 1.0, 1.0))
913 .without_pointer_events()
914 .entity();
915 }
916 ui_mark_render_dirty(world);
917 button
918}
919
920pub fn set_panel_rect(world: &mut World, node: Entity, offset: Vec2, size: Vec2) {
923 if let Some(layout) = world.get_mut::<nightshade::ecs::ui::components::UiLayoutNode>(node) {
924 layout.base_layout = Some(UiLayoutType::Window(WindowLayout {
925 position: Ab(offset).into(),
926 size: Ab(size).into(),
927 anchor: Anchor::TopLeft,
928 }));
929 }
930 ui_mark_render_dirty(world);
931}
932
933pub fn set_panel_color(world: &mut World, node: Entity, color: [f32; 4]) {
935 if let Some(node_color) = world.get_mut::<nightshade::ecs::ui::components::UiNodeColor>(node) {
936 node_color.colors[UiBase::INDEX] = Some(rgba(color));
937 }
938 ui_mark_render_dirty(world);
939}
940
941pub fn set_panel_text(world: &mut World, label: Entity, text: &str) {
944 ui_set_text(world, label, text);
945}
946
947pub fn set_panel_text_color(world: &mut World, label: Entity, color: [f32; 4]) {
949 set_panel_color(world, label, color);
950}
951
952pub fn set_panel_selected(world: &mut World, button: Entity, selected: bool, accent: [f32; 4]) {
955 if let Some(node_color) = world.get_mut::<nightshade::ecs::ui::components::UiNodeColor>(button)
956 {
957 node_color.colors[UiSelected::INDEX] = Some(rgba(accent));
958 }
959 ui_set_selected(world, button, selected);
960 ui_mark_render_dirty(world);
961}
962
963pub fn set_panel_visible(world: &mut World, node: Entity, visible: bool) {
966 ui_set_visible(world, node, visible);
967 ui_mark_render_dirty(world);
968}