veloren_voxygen/hud/
controller_icons.rs

1use super::img_ids::Imgs;
2use crate::{GlobalState, game_input::GameInput, settings::Button, window::ControllerType};
3use conrod_core::{
4    Positionable, Sizeable, UiCell, Widget,
5    image::Id as ConrodImageId,
6    widget::{Id as WidgetId, Image},
7};
8use gilrs::Button as GilButton;
9
10/// stores the current maximum number of controller inputs for a single action
11pub struct LayerIconIds {
12    pub main: WidgetId,
13    pub modifier1: WidgetId,
14    pub modifier2: WidgetId,
15}
16
17pub struct IconHandler<'a> {
18    global_state: &'a GlobalState,
19    imgs: &'a Imgs,
20}
21
22/// returns the left trigger (dark) icon based on controller type
23pub fn fetch_skillbar_gamepad_left(ctrl_type: ControllerType, imgs: &Imgs) -> ConrodImageId {
24    match ctrl_type {
25        ControllerType::Xbox => imgs.left_trigger_xbox_dark,
26        ControllerType::Nintendo => imgs.left_trigger_nin_dark,
27        ControllerType::Playstation => imgs.left_trigger_ps_dark,
28        _ => imgs.m1_ico,
29    }
30}
31
32/// returns the right trigger (dark) icon based on controller type
33pub fn fetch_skillbar_gamepad_right(ctrl_type: ControllerType, imgs: &Imgs) -> ConrodImageId {
34    match ctrl_type {
35        ControllerType::Xbox => imgs.right_trigger_xbox_dark,
36        ControllerType::Nintendo => imgs.right_trigger_nin_dark,
37        ControllerType::Playstation => imgs.right_trigger_ps_dark,
38        _ => imgs.m2_ico,
39    }
40}
41
42impl<'a> IconHandler<'a> {
43    pub fn new(global_state: &'a GlobalState, imgs: &'a Imgs) -> Self {
44        Self { global_state, imgs }
45    }
46
47    /// when no icon needs to be displayed, uses the widgets to generate
48    /// transparant objects to prevent issues with conrod
49    ///
50    /// input:
51    /// `size` - size of icon to be rendered
52    /// `target_id` - conrod id of text that icon is rendered next to
53    /// `current_id` - collection of conrod ids reserved for icons (stored in
54    /// LayerIconIds) `ui` - UiCell object
55    pub fn set_controller_icons_left_none(
56        &self,
57        size: f64,
58        target_id: WidgetId,
59        current_id: &LayerIconIds,
60        ui: &mut UiCell,
61    ) {
62        // draw invisible placeholders for all widgets
63        let mut anchor_id = target_id;
64        let ids = [current_id.main, current_id.modifier1, current_id.modifier2];
65        for &icon_id in ids.iter() {
66            Image::new(self.imgs.transparant_button)
67                .w_h(size, size)
68                .mid_left_with_margin_on(anchor_id, -21.0)
69                .set(icon_id, ui);
70            anchor_id = icon_id;
71        }
72    }
73
74    /// renders the controller icons for a given GameInput positioned left of
75    /// the given widget
76    ///
77    /// input:
78    /// `input` - which input is being displayed
79    /// `size` - size of icon
80    /// `target_id` - conrod id of text that icon is rendered next to
81    /// `current_id` - collection of conrod ids reserved for icons (stored in
82    /// LayerIconIds) `ui` - UiCell object
83    pub fn set_controller_icons_left(
84        &self,
85        input: GameInput,
86        size: f64,
87        target_id: WidgetId,
88        current_id: &LayerIconIds,
89        ui: &mut UiCell,
90    ) -> u8 {
91        let main_id = current_id.main;
92        let mod1_id = current_id.modifier1;
93        let mod2_id = current_id.modifier2;
94
95        let mut icon_draw_list: Vec<(WidgetId, Button)> = Vec::with_capacity(3);
96        let unknown = Button::Simple(GilButton::Unknown);
97        let mut count: u8 = 0; // # of valid icons displayed
98
99        // prioritize game layers over game buttons
100        if let Some(layer_input) = self
101            .global_state
102            .settings
103            .controller
104            .get_layer_button_binding(input)
105        {
106            // draw main layer button
107            icon_draw_list.push((main_id, layer_input.button));
108            count += 1;
109
110            // draw modifier buttons if any
111            let mod1 = layer_input.mod1;
112            let mut mod1_valid = false;
113            let mod2 = layer_input.mod2;
114            let mut mod2_valid = false;
115
116            // place valid buttons first, then place invalid buttons after
117            if mod1 != unknown {
118                icon_draw_list.push((mod1_id, mod1));
119                mod1_valid = true;
120                count += 1;
121            }
122            if mod2 != unknown {
123                icon_draw_list.push((mod2_id, mod2));
124                mod2_valid = true;
125                count += 1;
126            }
127
128            // invalid buttons will be rendered as an empty widget because conrod needs all
129            // defined widgets to be used (or it will cause issues)
130            if !mod1_valid {
131                icon_draw_list.push((mod1_id, unknown));
132            }
133            if !mod2_valid {
134                icon_draw_list.push((mod2_id, unknown));
135            }
136        } else if let Some(button_input) = self
137            .global_state
138            .settings
139            .controller
140            .get_game_button_binding(input)
141        {
142            // draw only button
143            icon_draw_list.push((main_id, button_input));
144            count += 1;
145
146            // modifiers will be a transparant object to consume conrod modifier widget IDs
147            icon_draw_list.push((mod1_id, Button::Simple(GilButton::Unknown)));
148            icon_draw_list.push((mod2_id, Button::Simple(GilButton::Unknown)));
149        }
150
151        // draw transparant objects if no icons were rendered
152        if icon_draw_list.is_empty() {
153            self.set_controller_icons_left_none(size, target_id, current_id, ui);
154        } else {
155            // draw icons
156            let mut anchor_id = target_id;
157            for (icon_id, button) in icon_draw_list.iter() {
158                // draw invisibile placeholder if button is unknown
159                if *button == unknown {
160                    Image::new(self.imgs.transparant_button)
161                        .w_h(size, size)
162                        .mid_left_with_margin_on(anchor_id, -21.0)
163                        .set(*icon_id, ui);
164                } else {
165                    Image::new(self.get_controller_icon_id(*button))
166                        .w_h(size, size)
167                        .mid_left_with_margin_on(anchor_id, -21.0)
168                        .set(*icon_id, ui);
169                }
170                anchor_id = *icon_id;
171            }
172        }
173
174        count
175    }
176
177    fn get_controller_icon_id(&self, binding: Button) -> ConrodImageId {
178        let controller_type = self.global_state.window.controller_type();
179
180        let icon_id: ConrodImageId = match binding {
181            Button::Simple(GilButton::South) => self.get_south(controller_type),
182            Button::Simple(GilButton::East) => self.get_east(controller_type),
183            Button::Simple(GilButton::West) => self.get_west(controller_type),
184            Button::Simple(GilButton::North) => self.get_north(controller_type),
185            Button::Simple(GilButton::LeftThumb) => self.get_left_axis_button(),
186            Button::Simple(GilButton::RightThumb) => self.get_right_axis_button(),
187            Button::Simple(GilButton::LeftTrigger) => self.get_left_shoulder(controller_type),
188            Button::Simple(GilButton::RightTrigger) => self.get_right_shoulder(controller_type),
189            Button::Simple(GilButton::LeftTrigger2) => self.get_left_trigger(controller_type),
190            Button::Simple(GilButton::RightTrigger2) => self.get_right_trigger(controller_type),
191            Button::Simple(GilButton::DPadDown) => self.get_dpad_down(controller_type),
192            Button::Simple(GilButton::DPadLeft) => self.get_dpad_left(controller_type),
193            Button::Simple(GilButton::DPadRight) => self.get_dpad_right(controller_type),
194            Button::Simple(GilButton::DPadUp) => self.get_dpad_up(controller_type),
195            Button::Simple(GilButton::Start) => self.get_start(controller_type),
196            Button::Simple(GilButton::Select) => self.get_select(controller_type),
197            _ => self.imgs.no_button,
198        };
199
200        icon_id
201    }
202
203    fn get_south(&self, controller_type: ControllerType) -> ConrodImageId {
204        match controller_type {
205            ControllerType::Nintendo => self.imgs.south_button_a,
206            ControllerType::Playstation => self.imgs.south_button_ps_cross,
207            _ => self.imgs.south_button_a,
208        }
209    }
210
211    fn get_east(&self, controller_type: ControllerType) -> ConrodImageId {
212        match controller_type {
213            ControllerType::Nintendo => self.imgs.east_button_b,
214            ControllerType::Playstation => self.imgs.east_button_ps_circle,
215            _ => self.imgs.east_button_b,
216        }
217    }
218
219    fn get_west(&self, controller_type: ControllerType) -> ConrodImageId {
220        match controller_type {
221            ControllerType::Nintendo => self.imgs.west_button_x,
222            ControllerType::Playstation => self.imgs.west_button_ps_square,
223            _ => self.imgs.west_button_x,
224        }
225    }
226
227    fn get_north(&self, controller_type: ControllerType) -> ConrodImageId {
228        match controller_type {
229            ControllerType::Nintendo => self.imgs.north_button_y,
230            ControllerType::Playstation => self.imgs.north_button_ps_triangle,
231            _ => self.imgs.north_button_y,
232        }
233    }
234
235    //fn get_left_axis(&self) -> ConrodImageId { self.imgs.left_axis }
236
237    fn get_left_axis_button(&self) -> ConrodImageId { self.imgs.left_axis_button }
238
239    //fn get_right_axis(&self) -> ConrodImageId { self.imgs.right_axis }
240
241    fn get_right_axis_button(&self) -> ConrodImageId { self.imgs.right_axis_button }
242
243    fn get_left_shoulder(&self, controller_type: ControllerType) -> ConrodImageId {
244        match controller_type {
245            ControllerType::Nintendo => self.imgs.left_shoulder_nin_l,
246            ControllerType::Playstation => self.imgs.left_shoulder_ps_l1,
247            _ => self.imgs.left_shoulder_xbox_lb,
248        }
249    }
250
251    fn get_right_shoulder(&self, controller_type: ControllerType) -> ConrodImageId {
252        match controller_type {
253            ControllerType::Nintendo => self.imgs.right_shoulder_nin_r,
254            ControllerType::Playstation => self.imgs.right_shoulder_ps_r1,
255            _ => self.imgs.right_shoulder_xbox_rb,
256        }
257    }
258
259    fn get_left_trigger(&self, controller_type: ControllerType) -> ConrodImageId {
260        match controller_type {
261            ControllerType::Nintendo => self.imgs.left_trigger_nin_zl,
262            ControllerType::Playstation => self.imgs.left_trigger_ps_l2,
263            _ => self.imgs.left_trigger_xbox_lt,
264        }
265    }
266
267    fn get_right_trigger(&self, controller_type: ControllerType) -> ConrodImageId {
268        match controller_type {
269            ControllerType::Nintendo => self.imgs.right_trigger_nin_zr,
270            ControllerType::Playstation => self.imgs.right_trigger_ps_r2,
271            _ => self.imgs.right_trigger_xbox_rt,
272        }
273    }
274
275    fn get_dpad_down(&self, controller_type: ControllerType) -> ConrodImageId {
276        match controller_type {
277            ControllerType::Nintendo => self.imgs.dpad_down,
278            ControllerType::Playstation => self.imgs.dpad_down_ps,
279            _ => self.imgs.dpad_down,
280        }
281    }
282
283    fn get_dpad_left(&self, controller_type: ControllerType) -> ConrodImageId {
284        match controller_type {
285            ControllerType::Nintendo => self.imgs.dpad_left,
286            ControllerType::Playstation => self.imgs.dpad_left_ps,
287            _ => self.imgs.dpad_left,
288        }
289    }
290
291    fn get_dpad_right(&self, controller_type: ControllerType) -> ConrodImageId {
292        match controller_type {
293            ControllerType::Nintendo => self.imgs.dpad_right,
294            ControllerType::Playstation => self.imgs.dpad_right_ps,
295            _ => self.imgs.dpad_right,
296        }
297    }
298
299    fn get_dpad_up(&self, controller_type: ControllerType) -> ConrodImageId {
300        match controller_type {
301            ControllerType::Nintendo => self.imgs.dpad_up,
302            ControllerType::Playstation => self.imgs.dpad_up_ps,
303            _ => self.imgs.dpad_up,
304        }
305    }
306
307    fn get_start(&self, controller_type: ControllerType) -> ConrodImageId {
308        match controller_type {
309            ControllerType::Nintendo => self.imgs.start_button_nin,
310            ControllerType::Playstation => self.imgs.start_button_ps,
311            _ => self.imgs.start_button_xbox,
312        }
313    }
314
315    fn get_select(&self, controller_type: ControllerType) -> ConrodImageId {
316        match controller_type {
317            ControllerType::Xbox => self.imgs.select_button_xbox,
318            ControllerType::Nintendo => self.imgs.select_button_nin,
319            ControllerType::Playstation => self.imgs.select_button_ps,
320            _ => self.imgs.select_button_xbox,
321        }
322    }
323}