veloren_voxygen/hud/
buttons.rs

1use super::{
2    BLACK, TEXT_COLOR,
3    img_ids::{Imgs, ImgsRot},
4};
5use crate::{
6    GlobalState,
7    game_input::GameInput,
8    ui::{ImageFrame, Tooltip, TooltipManager, Tooltipable, fonts::Fonts},
9    window::KeyMouse,
10};
11use conrod_core::{
12    Color, Colorable, Positionable, Sizeable, UiCell, Widget, WidgetCommon,
13    widget::{self, Button, Text, UpdateArgs},
14    widget_ids,
15};
16use i18n::Localization;
17widget_ids! {
18    struct Ids {
19        bag_show_map,
20        map_button,
21        map_text,
22        map_text_bg,
23        settings_button,
24        settings_text,
25        settings_text_bg,
26        social_button,
27        social_button_bg,
28        social_text,
29        social_text_bg,
30        spellbook_button,
31        spellbook_button_bg,
32        spellbook_text,
33        spellbook_text_bg,
34        crafting_button,
35        crafting_button_bg,
36        crafting_text,
37        crafting_text_bg,
38        group_button,
39        sp_arrow,
40        sp_arrow_txt_bg,
41        sp_arrow_txt,
42    }
43}
44#[derive(WidgetCommon)]
45pub struct Buttons<'a> {
46    imgs: &'a Imgs,
47    fonts: &'a Fonts,
48    #[conrod(common_builder)]
49    common: widget::CommonBuilder,
50    global_state: &'a GlobalState,
51    rot_imgs: &'a ImgsRot,
52    tooltip_manager: &'a mut TooltipManager,
53    localized_strings: &'a Localization,
54}
55
56impl<'a> Buttons<'a> {
57    pub fn new(
58        imgs: &'a Imgs,
59        fonts: &'a Fonts,
60        global_state: &'a GlobalState,
61        rot_imgs: &'a ImgsRot,
62        tooltip_manager: &'a mut TooltipManager,
63        localized_strings: &'a Localization,
64    ) -> Self {
65        Self {
66            imgs,
67            fonts,
68            common: widget::CommonBuilder::default(),
69            global_state,
70            rot_imgs,
71            tooltip_manager,
72            localized_strings,
73        }
74    }
75}
76
77pub struct State {
78    ids: Ids,
79}
80
81#[expect(clippy::enum_variant_names)] //think about renaming to ToggleEvent
82pub enum Event {
83    ToggleSettings,
84    ToggleMap,
85    ToggleSocial,
86    ToggleCrafting,
87}
88
89impl Widget for Buttons<'_> {
90    type Event = Option<Event>;
91    type State = State;
92    type Style = ();
93
94    fn init_state(&self, id_gen: widget::id::Generator) -> Self::State {
95        State {
96            ids: Ids::new(id_gen),
97        }
98    }
99
100    fn style(&self) -> Self::Style {}
101
102    fn update(self, args: UpdateArgs<Self>) -> Self::Event {
103        common_base::prof_span!("Buttons::update");
104        let UpdateArgs { state, ui, .. } = args;
105        let localized_strings = self.localized_strings;
106
107        let button_tooltip = Tooltip::new({
108            // Edge images [t, b, r, l]
109            // Corner images [tr, tl, br, bl]
110            let edge = &self.rot_imgs.tt_side;
111            let corner = &self.rot_imgs.tt_corner;
112            ImageFrame::new(
113                [edge.cw180, edge.none, edge.cw270, edge.cw90],
114                [corner.none, corner.cw270, corner.cw90, corner.cw180],
115                Color::Rgba(0.08, 0.07, 0.04, 1.0),
116                5.0,
117            )
118        })
119        .title_font_size(self.fonts.cyri.scale(15))
120        .parent(ui.window)
121        .desc_font_size(self.fonts.cyri.scale(12))
122        .font_id(self.fonts.cyri.conrod_id)
123        .desc_text_color(TEXT_COLOR);
124
125        // Settings
126        if Button::image(self.imgs.settings)
127            .w_h(29.0, 25.0)
128            .bottom_right_with_margins_on(ui.window, 5.0, 5.0)
129            .hover_image(self.imgs.settings_hover)
130            .press_image(self.imgs.settings_press)
131            .with_tooltip(
132                self.tooltip_manager,
133                &localized_strings.get_msg("common-settings"),
134                "",
135                &button_tooltip,
136                TEXT_COLOR,
137            )
138            .set(state.ids.settings_button, ui)
139            .was_clicked()
140        {
141            return Some(Event::ToggleSettings);
142        };
143        if let Some(settings) = &self
144            .global_state
145            .settings
146            .controls
147            .get_binding(GameInput::Settings)
148        {
149            self.create_new_button_with_shadow(
150                ui,
151                settings,
152                state.ids.settings_button,
153                state.ids.settings_text_bg,
154                state.ids.settings_text,
155            );
156        };
157
158        // Social
159        if Button::image(self.imgs.social)
160            .w_h(25.0, 25.0)
161            .left_from(state.ids.settings_button, 10.0)
162            .hover_image(self.imgs.social_hover)
163            .press_image(self.imgs.social_press)
164            .with_tooltip(
165                self.tooltip_manager,
166                &localized_strings.get_msg("hud-social"),
167                "",
168                &button_tooltip,
169                TEXT_COLOR,
170            )
171            .set(state.ids.social_button, ui)
172            .was_clicked()
173        {
174            return Some(Event::ToggleSocial);
175        }
176        if let Some(social) = &self
177            .global_state
178            .settings
179            .controls
180            .get_binding(GameInput::Social)
181        {
182            self.create_new_button_with_shadow(
183                ui,
184                social,
185                state.ids.social_button,
186                state.ids.social_text_bg,
187                state.ids.social_text,
188            );
189        };
190        // Map
191        if Button::image(self.imgs.map_button)
192            .w_h(22.0, 25.0)
193            .left_from(state.ids.social_button, 10.0)
194            .hover_image(self.imgs.map_hover)
195            .press_image(self.imgs.map_press)
196            .with_tooltip(
197                self.tooltip_manager,
198                &localized_strings.get_msg("hud-map-map_title"),
199                "",
200                &button_tooltip,
201                TEXT_COLOR,
202            )
203            .set(state.ids.map_button, ui)
204            .was_clicked()
205        {
206            return Some(Event::ToggleMap);
207        };
208        if let Some(map) = &self
209            .global_state
210            .settings
211            .controls
212            .get_binding(GameInput::Map)
213        {
214            self.create_new_button_with_shadow(
215                ui,
216                map,
217                state.ids.map_button,
218                state.ids.map_text_bg,
219                state.ids.map_text,
220            );
221        }
222
223        // Crafting
224        if Button::image(self.imgs.crafting_icon)
225            .w_h(25.0, 25.0)
226            .left_from(state.ids.map_button, 10.0)
227            .hover_image(self.imgs.crafting_icon_hover)
228            .press_image(self.imgs.crafting_icon_press)
229            .with_tooltip(
230                self.tooltip_manager,
231                &localized_strings.get_msg("hud-crafting"),
232                "",
233                &button_tooltip,
234                TEXT_COLOR,
235            )
236            .set(state.ids.crafting_button, ui)
237            .was_clicked()
238        {
239            return Some(Event::ToggleCrafting);
240        }
241        if let Some(crafting) = &self
242            .global_state
243            .settings
244            .controls
245            .get_binding(GameInput::Crafting)
246        {
247            self.create_new_button_with_shadow(
248                ui,
249                crafting,
250                state.ids.crafting_button,
251                state.ids.crafting_text_bg,
252                state.ids.crafting_text,
253            );
254        }
255
256        None
257    }
258}
259
260impl Buttons<'_> {
261    fn create_new_button_with_shadow(
262        &self,
263        ui: &mut UiCell,
264        key_mouse: &KeyMouse,
265        button_identifier: widget::Id,
266        text_background: widget::Id,
267        text: widget::Id,
268    ) {
269        let key_layout = &self.global_state.window.key_layout;
270        let key_desc = key_mouse.display_shortest(key_layout);
271
272        //Create shadow
273        Text::new(&key_desc)
274            .bottom_right_with_margins_on(button_identifier, 0.0, 0.0)
275            .font_size(10)
276            .font_id(self.fonts.cyri.conrod_id)
277            .color(BLACK)
278            .set(text_background, ui);
279
280        //Create button
281        Text::new(&key_desc)
282            .bottom_right_with_margins_on(text_background, 1.0, 1.0)
283            .font_size(10)
284            .font_id(self.fonts.cyri.conrod_id)
285            .color(TEXT_COLOR)
286            .set(text, ui);
287    }
288}