1use crate::*;
4use std::collections::HashMap;
5
6#[derive(Debug, Clone)]
7pub struct Binding {
9 pub controller: u32,
11 pub config: Option<String>,
13 pub element: NodeId,
15 pub name: String,
17}
18
19#[derive(Debug, Clone)]
20pub struct DialogInstance {
22 pub root: NodeId,
24 pub bindings: Vec<Binding>,
26 pub dialogs: Vec<String>,
28 pub background: Option<SpriteRef>,
30}
31
32impl DialogInstance {
33 pub fn dispatch(&self, ui: &Ui, event: Event, mut handler: impl FnMut(&Binding, Event)) {
36 let source = input::event_node(event);
37 for b in &self.bindings {
38 if ui.descendant(b.element, source) {
39 handler(b, event);
40 }
41 }
42 }
43}
44
45impl Ui {
46 pub fn instantiate_dialog(&mut self, reference: &str) -> Option<DialogInstance> {
48 let d = banished_formats::ui::dialog(&self.res.archive.read_ref(reference).ok()?).ok()?;
49 let overrides: HashMap<_, _> = d
52 .named
53 .iter()
54 .map(|(r, name)| (name.clone(), r.clone()))
55 .collect();
56 self.overrides.push(overrides);
57 let root = d.root.as_deref().and_then(|r| self.instantiate(r));
58 self.overrides.pop();
59 let root = root?;
60 for (name, key) in [("buttonOk", 13), ("buttonCancel", 27)] {
61 if let Some(id) = self.find(root, name) {
62 self.set_shortcut(id, key);
63 }
64 }
65 let mut bindings = Vec::new();
66 for b in d.bindings {
67 let element = if b.name.is_empty() {
68 Some(root)
69 } else {
70 self.find(root, &b.name)
71 };
72 let Some(element) = element else {
73 log::warn!("unresolved dialog controller host: {}", b.name);
74 continue;
75 };
76 let attached = if let Some(reference) = b.source.as_deref() {
79 if let Some(c) = self.instantiate(reference) {
80 self.add_child(element, c);
81 c
82 } else {
83 element
84 }
85 } else {
86 element
87 };
88 bindings.push(Binding {
89 controller: b.unknown,
90 config: b.target,
91 element: attached,
92 name: b.name,
93 });
94 }
95 let background = self
96 .res
97 .sprite(d.background_sheet.as_deref(), &d.background_sprite);
98 Some(DialogInstance {
99 root,
100 bindings,
101 dialogs: d.dialogs.into_iter().flatten().collect(),
102 background,
103 })
104 }
105
106 pub fn descendant(&self, root: NodeId, node: NodeId) -> bool {
108 root == node
109 || self
110 .child_ids(root)
111 .into_iter()
112 .any(|child| self.descendant(child, node))
113 }
114}