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 .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.resources.retained_ui.interaction.focused_entity = Some(entity);
383}
384
385pub fn panel_text_area(world: &mut World, panel: Entity, placeholder: &str, rows: usize) -> Entity {
388 let entity = {
389 let mut tree = UiTreeBuilder::from_parent(world, panel);
390 tree.add_text_area(placeholder, rows)
391 };
392 ui_mark_render_dirty(world);
393 entity
394}
395
396pub fn panel_text_area_with_value(
398 world: &mut World,
399 panel: Entity,
400 placeholder: &str,
401 rows: usize,
402 initial: &str,
403) -> Entity {
404 let entity = {
405 let mut tree = UiTreeBuilder::from_parent(world, panel);
406 tree.add_text_area_with_value(placeholder, rows, initial)
407 };
408 ui_mark_render_dirty(world);
409 entity
410}
411
412pub fn set_text_area(world: &mut World, area: Entity, text: &str) {
414 ui_text_area_set_value(world, area, text);
415 ui_mark_render_dirty(world);
416}
417
418pub fn panel_multi_select(world: &mut World, panel: Entity, options: &[&str]) -> Entity {
421 let entity = {
422 let mut tree = UiTreeBuilder::from_parent(world, panel);
423 tree.add_multi_select(options)
424 };
425 ui_mark_render_dirty(world);
426 entity
427}
428
429pub fn set_multi_select(world: &mut World, widget: Entity, indices: &[usize]) {
431 ui_multi_select_set_selected(world, widget, indices);
432 ui_mark_render_dirty(world);
433}
434
435pub fn panel_date_picker(
438 world: &mut World,
439 panel: Entity,
440 year: i32,
441 month: u32,
442 day: u32,
443) -> Entity {
444 let entity = {
445 let mut tree = UiTreeBuilder::from_parent(world, panel);
446 tree.add_date_picker(year, month, day)
447 };
448 ui_mark_render_dirty(world);
449 entity
450}
451
452pub fn set_date(world: &mut World, picker: Entity, year: i32, month: u32, day: u32) {
454 ui_date_picker_set_value(world, picker, year, month, day);
455 ui_mark_render_dirty(world);
456}
457
458pub fn panel_menu(world: &mut World, panel: Entity, label: &str, items: &[&str]) -> Entity {
460 let entity = {
461 let mut tree = UiTreeBuilder::from_parent(world, panel);
462 tree.add_menu(label, items)
463 };
464 ui_mark_render_dirty(world);
465 entity
466}
467
468pub fn panel_color_picker_hsv(world: &mut World, panel: Entity, initial: [f32; 4]) -> Entity {
471 let entity = {
472 let mut tree = UiTreeBuilder::from_parent(world, panel);
473 tree.add_color_picker_hsv(rgba(initial))
474 };
475 ui_mark_render_dirty(world);
476 entity
477}
478
479pub fn panel_splitter(
483 world: &mut World,
484 panel: Entity,
485 direction: SplitDirection,
486 initial_ratio: f32,
487) -> Entity {
488 let entity = {
489 let mut tree = UiTreeBuilder::from_parent(world, panel);
490 tree.add_splitter(direction, initial_ratio)
491 };
492 ui_mark_render_dirty(world);
493 entity
494}
495
496pub fn panel_breadcrumb(world: &mut World, panel: Entity, segments: &[&str]) -> Entity {
499 let entity = {
500 let mut tree = UiTreeBuilder::from_parent(world, panel);
501 tree.add_breadcrumb(segments)
502 };
503 ui_mark_render_dirty(world);
504 entity
505}
506
507pub fn panel_virtual_list(
510 world: &mut World,
511 panel: Entity,
512 item_height: f32,
513 pool_size: usize,
514) -> Entity {
515 let entity = {
516 let mut tree = UiTreeBuilder::from_parent(world, panel);
517 tree.add_virtual_list(item_height, pool_size)
518 };
519 ui_mark_render_dirty(world);
520 entity
521}
522
523pub fn panel_table(world: &mut World, panel: Entity, headers: &[&str], widths: &[f32]) -> Entity {
526 let entity = {
527 let mut tree = UiTreeBuilder::from_parent(world, panel);
528 tree.add_table(headers, widths)
529 };
530 ui_mark_render_dirty(world);
531 entity
532}
533
534pub fn panel_data_grid(
539 world: &mut World,
540 panel: Entity,
541 columns: &[(&str, f32)],
542 pool_size: usize,
543) -> Entity {
544 let grid_columns: Vec<DataGridColumn> = columns
545 .iter()
546 .map(|(header, width)| DataGridColumn::new(header, *width))
547 .collect();
548 let entity = {
549 let mut tree = UiTreeBuilder::from_parent(world, panel);
550 tree.add_data_grid(&grid_columns, pool_size)
551 };
552 ui_mark_render_dirty(world);
553 entity
554}
555
556pub fn set_data_grid_rows(world: &mut World, grid: Entity, count: usize) {
558 ui_data_grid_set_row_count(world, grid, count);
559}
560
561pub fn set_data_grid_cell(world: &mut World, grid: Entity, row: usize, column: usize, text: &str) {
563 ui_data_grid_set_cell(world, grid, row, column, text);
564}
565
566#[inline]
568pub fn data_grid_selection_changed(world: &World, grid: Entity) -> bool {
569 ui_data_grid_selection_changed(world, grid)
570}
571
572pub fn panel_command_palette(world: &mut World, panel: Entity, pool_size: usize) -> Entity {
575 let entity = {
576 let mut tree = UiTreeBuilder::from_parent(world, panel);
577 tree.add_command_palette(pool_size)
578 };
579 ui_mark_render_dirty(world);
580 entity
581}
582
583pub fn panel_property_grid(world: &mut World, panel: Entity, label_width: f32) -> Entity {
587 let entity = {
588 let mut tree = UiTreeBuilder::from_parent(world, panel);
589 tree.add_property_grid(label_width)
590 };
591 ui_mark_render_dirty(world);
592 entity
593}
594
595pub fn panel_property_row(world: &mut World, grid: Entity, label: &str) -> Entity {
598 let row = {
599 let mut tree = UiTreeBuilder::from_parent(world, grid);
600 tree.add_property_row(grid, grid, label)
601 };
602 ui_mark_render_dirty(world);
603 row
604}
605
606pub fn panel_tree_view(world: &mut World, panel: Entity, multi_select: bool) -> Entity {
609 let entity = {
610 let mut tree = UiTreeBuilder::from_parent(world, panel);
611 tree.add_tree_view(multi_select)
612 };
613 ui_mark_render_dirty(world);
614 entity
615}
616
617pub fn tree_content(world: &World, tree_view: Entity) -> Entity {
620 widget::<UiTreeViewData>(world, tree_view)
621 .map(|data| data.content_entity)
622 .unwrap_or(tree_view)
623}
624
625pub fn tree_node(
629 world: &mut World,
630 tree_view: Entity,
631 parent_container: Entity,
632 label: &str,
633 depth: usize,
634 user_data: u64,
635) -> Entity {
636 let node = {
637 let mut tree = UiTreeBuilder::from_parent(world, parent_container);
638 tree.add_tree_node(tree_view, parent_container, label, depth, user_data)
639 };
640 ui_mark_render_dirty(world);
641 node
642}
643
644pub fn tree_node_children(world: &World, node: Entity) -> Entity {
647 widget::<UiTreeNodeData>(world, node)
648 .map(|data| data.children_container)
649 .unwrap_or(node)
650}
651
652pub fn set_tree_node_expanded(world: &mut World, node: Entity, expanded: bool) {
654 ui_tree_node_set_expanded(world, node, expanded);
655 ui_mark_render_dirty(world);
656}
657
658#[inline]
660pub fn tree_view_selected(world: &World, tree_view: Entity) -> Vec<Entity> {
661 ui_tree_view_selected(world, tree_view)
662}
663
664pub fn panel_drag_value(
668 world: &mut World,
669 panel: Entity,
670 min: f32,
671 max: f32,
672 initial: f32,
673) -> Entity {
674 let entity = {
675 let mut tree = UiTreeBuilder::from_parent(world, panel);
676 tree.add_drag_value(min, max, initial)
677 };
678 ui_mark_render_dirty(world);
679 entity
680}
681
682#[inline]
684pub fn drag_value(world: &World, widget: Entity) -> f32 {
685 ui_drag_value(world, widget).unwrap_or(0.0)
686}
687
688pub fn panel_selectable(
691 world: &mut World,
692 panel: Entity,
693 text: &str,
694 group: Option<u32>,
695) -> Entity {
696 let entity = {
697 let mut tree = UiTreeBuilder::from_parent(world, panel);
698 tree.add_selectable_label(text, group)
699 };
700 ui_mark_render_dirty(world);
701 entity
702}
703
704pub fn panel_modal(
708 world: &mut World,
709 panel: Entity,
710 title: &str,
711 width: f32,
712 height: f32,
713) -> Entity {
714 let entity = {
715 let mut tree = UiTreeBuilder::from_parent(world, panel);
716 tree.add_modal_dialog(title, width, height)
717 };
718 ui_mark_render_dirty(world);
719 entity
720}
721
722pub fn panel_spinner(world: &mut World, panel: Entity) -> Entity {
724 let entity = {
725 let mut tree = UiTreeBuilder::from_parent(world, panel);
726 tree.add_spinner()
727 };
728 ui_mark_render_dirty(world);
729 entity
730}
731
732pub fn panel_separator(world: &mut World, panel: Entity) -> Entity {
734 let entity = {
735 let mut tree = UiTreeBuilder::from_parent(world, panel);
736 tree.add_separator()
737 };
738 ui_mark_render_dirty(world);
739 entity
740}
741
742pub fn panel_heading(world: &mut World, panel: Entity, text: &str) -> Entity {
744 let entity = {
745 let mut tree = UiTreeBuilder::from_parent(world, panel);
746 tree.add_heading(text)
747 };
748 ui_mark_render_dirty(world);
749 entity
750}
751
752fn panel_anchor(anchor: ScreenAnchor) -> (UiValue<Vec2>, Anchor) {
753 match anchor {
754 ScreenAnchor::TopLeft => (Ab(vec2(20.0, 20.0)).into(), Anchor::TopLeft),
755 ScreenAnchor::TopCenter => (Rl(vec2(50.0, 0.0)) + Ab(vec2(0.0, 20.0)), Anchor::TopCenter),
756 ScreenAnchor::TopRight => (
757 Rl(vec2(100.0, 0.0)) + Ab(vec2(-20.0, 20.0)),
758 Anchor::TopRight,
759 ),
760 ScreenAnchor::BottomLeft => (
761 Rl(vec2(0.0, 100.0)) + Ab(vec2(20.0, -20.0)),
762 Anchor::BottomLeft,
763 ),
764 ScreenAnchor::BottomCenter => (
765 Rl(vec2(50.0, 100.0)) + Ab(vec2(0.0, -20.0)),
766 Anchor::BottomCenter,
767 ),
768 ScreenAnchor::BottomRight => (
769 Rl(vec2(100.0, 100.0)) + Ab(vec2(-20.0, -20.0)),
770 Anchor::BottomRight,
771 ),
772 ScreenAnchor::Center => (Rl(vec2(50.0, 50.0)).into(), Anchor::Center),
773 }
774}
775
776fn anchor_base(anchor: ScreenAnchor) -> (Vec2, Anchor) {
779 match anchor {
780 ScreenAnchor::TopLeft => (vec2(0.0, 0.0), Anchor::TopLeft),
781 ScreenAnchor::TopCenter => (vec2(50.0, 0.0), Anchor::TopCenter),
782 ScreenAnchor::TopRight => (vec2(100.0, 0.0), Anchor::TopRight),
783 ScreenAnchor::BottomLeft => (vec2(0.0, 100.0), Anchor::BottomLeft),
784 ScreenAnchor::BottomCenter => (vec2(50.0, 100.0), Anchor::BottomCenter),
785 ScreenAnchor::BottomRight => (vec2(100.0, 100.0), Anchor::BottomRight),
786 ScreenAnchor::Center => (vec2(50.0, 50.0), Anchor::Center),
787 }
788}
789
790fn rgba(color: [f32; 4]) -> Vec4 {
791 Vec4::new(color[0], color[1], color[2], color[3])
792}
793
794const PANEL_BORDER: Vec4 = Vec4::new(0.12, 0.14, 0.2, 0.7);
795const PANEL_SHADOW: Vec4 = Vec4::new(0.0, 0.0, 0.0, 0.55);
796
797pub fn spawn_panel_at(
803 world: &mut World,
804 anchor: ScreenAnchor,
805 offset: Vec2,
806 size: Vec2,
807 color: [f32; 4],
808) -> Entity {
809 let root = ui_root(world);
810 let (base, anchor_kind) = anchor_base(anchor);
811 let panel = {
812 let mut tree = UiTreeBuilder::from_parent(world, root);
813 tree.add_node()
814 .window(Rl(base) + Ab(offset), Ab(size), anchor_kind)
815 .with_rect(10.0, 1.5, PANEL_BORDER)
816 .color_raw::<UiBase>(rgba(color))
817 .with_shadow(PANEL_SHADOW, vec2(0.0, 6.0), 18.0, 0.0)
818 .entity()
819 };
820 ui_mark_render_dirty(world);
821 panel
822}
823
824pub fn panel_text(
829 world: &mut World,
830 parent: Entity,
831 text: &str,
832 rect: [f32; 4],
833 font_size: f32,
834 color: [f32; 4],
835 align: TextAlignment,
836) -> Entity {
837 let label = {
838 let mut tree = UiTreeBuilder::from_parent(world, parent);
839 tree.add_node()
840 .window(
841 Ab(vec2(rect[0], rect[1])),
842 Ab(vec2(rect[2], rect[3])),
843 Anchor::TopLeft,
844 )
845 .with_text(text, font_size)
846 .with_text_alignment(align, VerticalAlignment::Middle)
847 .color_raw::<UiBase>(rgba(color))
848 .without_pointer_events()
849 .entity()
850 };
851 ui_mark_render_dirty(world);
852 label
853}
854
855pub fn panel_box(
859 world: &mut World,
860 parent: Entity,
861 offset: Vec2,
862 size: Vec2,
863 color: [f32; 4],
864) -> Entity {
865 let box_entity = {
866 let mut tree = UiTreeBuilder::from_parent(world, parent);
867 tree.add_node()
868 .window(Ab(offset), Ab(size), Anchor::TopLeft)
869 .with_rect(6.0, 0.0, Vec4::new(0.0, 0.0, 0.0, 0.0))
870 .color_raw::<UiBase>(rgba(color))
871 .without_pointer_events()
872 .entity()
873 };
874 ui_mark_render_dirty(world);
875 box_entity
876}
877
878pub fn panel_button_at(
883 world: &mut World,
884 parent: Entity,
885 label: &str,
886 offset: Vec2,
887 size: Vec2,
888) -> Entity {
889 let button = {
890 let mut tree = UiTreeBuilder::from_parent(world, parent);
891 tree.add_node()
892 .window(Ab(offset), Ab(size), Anchor::TopLeft)
893 .with_rect(8.0, 1.5, PANEL_BORDER)
894 .color_raw::<UiBase>(Vec4::new(0.05, 0.06, 0.09, 0.92))
895 .color_raw::<UiHover>(Vec4::new(0.09, 0.11, 0.17, 0.95))
896 .color_raw::<UiPressed>(Vec4::new(0.04, 0.05, 0.08, 1.0))
897 .with_transition::<UiHover>(12.0, 6.0)
898 .with_transition::<UiPressed>(18.0, 10.0)
899 .with_transition::<UiSelected>(10.0, 5.0)
900 .with_interaction()
901 .entity()
902 };
903 if !label.is_empty() {
904 let mut tree = UiTreeBuilder::from_parent(world, button);
905 tree.add_node()
906 .window(Rl(vec2(50.0, 50.0)), Ab(size), Anchor::Center)
907 .with_text(label, 14.0)
908 .with_text_alignment(TextAlignment::Center, VerticalAlignment::Middle)
909 .color_raw::<UiBase>(Vec4::new(0.92, 0.94, 1.0, 1.0))
910 .without_pointer_events()
911 .entity();
912 }
913 ui_mark_render_dirty(world);
914 button
915}
916
917pub fn set_panel_rect(world: &mut World, node: Entity, offset: Vec2, size: Vec2) {
920 if let Some(layout) = world.get_mut::<nightshade::ecs::ui::components::UiLayoutNode>(node) {
921 layout.base_layout = Some(UiLayoutType::Window(WindowLayout {
922 position: Ab(offset).into(),
923 size: Ab(size).into(),
924 anchor: Anchor::TopLeft,
925 }));
926 }
927 ui_mark_render_dirty(world);
928}
929
930pub fn set_panel_color(world: &mut World, node: Entity, color: [f32; 4]) {
932 if let Some(node_color) = world.get_mut::<nightshade::ecs::ui::components::UiNodeColor>(node) {
933 node_color.colors[UiBase::INDEX] = Some(rgba(color));
934 }
935 ui_mark_render_dirty(world);
936}
937
938pub fn set_panel_text(world: &mut World, label: Entity, text: &str) {
941 ui_set_text(world, label, text);
942}
943
944pub fn set_panel_text_color(world: &mut World, label: Entity, color: [f32; 4]) {
946 set_panel_color(world, label, color);
947}
948
949pub fn set_panel_selected(world: &mut World, button: Entity, selected: bool, accent: [f32; 4]) {
952 if let Some(node_color) = world.get_mut::<nightshade::ecs::ui::components::UiNodeColor>(button)
953 {
954 node_color.colors[UiSelected::INDEX] = Some(rgba(accent));
955 }
956 ui_set_selected(world, button, selected);
957 ui_mark_render_dirty(world);
958}
959
960pub fn set_panel_visible(world: &mut World, node: Entity, visible: bool) {
963 ui_set_visible(world, node, visible);
964 ui_mark_render_dirty(world);
965}