1use sge::prelude::*;
2use sge_input::gilrs::{Gamepad, GamepadId};
3
4const PRIMARY: Color = Color::WHITE;
5const SECONDARY: Color = Color::WHITE;
6
7#[main("Gamepad")]
8async fn main() -> anyhow::Result<()> {
9 let mut gamepad = None;
10
11 loop {
12 if let Some(pad) = gamepad {
13 visualize_gamepad(pad);
14 } else {
15 gamepad = choose_gamepad();
16 }
17
18 if should_quit() {
19 break;
20 }
21
22 next_frame().await;
23 }
24
25 Ok(())
26}
27
28fn choose_gamepad() -> Option<GamepadId> {
29 let input = gamepad::input();
30 let gamepads: Vec<_> = input.gamepads().collect();
31
32 use ui::prelude::*;
33 let ui = Col::with_gap(
34 10.0,
35 gamepads
36 .iter()
37 .enumerate()
38 .map(|(i, (_, pad))| flat::Button::primary_text(i, pad.name()))
39 .collect::<Vec<_>>(),
40 );
41
42 draw_ui(ui, Vec2::splat(10.0));
43
44 Some(
45 gamepads
46 .get(*all_elements_interacted_this_frame().first()?)?
47 .0,
48 )
49}
50
51fn visualize_gamepad(pad: GamepadId) {
52 let input = gamepad::input();
53 let pad = input.gamepad(pad);
54
55 draw_stick(pad.left_stick(), vec2(150.0, 150.0));
56 draw_stick(pad.right_stick(), vec2(450.0, 450.0));
57
58 draw_dpad(pad, vec2(150.0, 450.0));
59 draw_buttons(pad, vec2(450.0, 150.0));
60}
61
62fn draw_stick(val: Vec2, center: Vec2) {
63 const SIZE: f32 = 100.0;
64 let val = val.invert_y(); draw_circle_outline(center, SIZE, SECONDARY, 5.0);
67
68 let offset = val * SIZE;
69 draw_circle(center + offset, SIZE / 2.0, PRIMARY);
70
71 draw_text(
72 format!("{}, {}", val.x, val.y),
73 vec2(center.x - SIZE, center.y + SIZE + 20.0),
74 );
75}
76
77fn draw_dpad(pad: Gamepad, center: Vec2) {
79 const SIZE: f32 = 100.0;
80 const THICKNESS: f32 = 65.0;
81 const OUTLINE: f32 = 5.0;
82
83 let half = THICKNESS / 2.0;
84 let half_outline = OUTLINE / 2.0;
85 let arm = SIZE - half;
86
87 let buttons = [
88 (
89 gamepad::Button::DPadUp,
90 vec2(center.x - half, center.y - SIZE),
91 vec2(THICKNESS, arm + half_outline),
92 ),
93 (
94 gamepad::Button::DPadDown,
95 vec2(center.x - half, center.y + half - half_outline),
96 vec2(THICKNESS, arm),
97 ),
98 (
99 gamepad::Button::DPadLeft,
100 vec2(center.x - SIZE, center.y - half),
101 vec2(arm + half_outline, THICKNESS),
102 ),
103 (
104 gamepad::Button::DPadRight,
105 vec2(center.x + half - half_outline, center.y - half),
106 vec2(arm, THICKNESS),
107 ),
108 ];
109
110 let points = [
111 vec2(center.x - half, center.y - SIZE),
112 vec2(center.x + half, center.y - SIZE),
113 vec2(center.x + half, center.y - half),
114 vec2(center.x + SIZE, center.y - half),
115 vec2(center.x + SIZE, center.y + half),
116 vec2(center.x + half, center.y + half),
117 vec2(center.x + half, center.y + SIZE),
118 vec2(center.x - half, center.y + SIZE),
119 vec2(center.x - half, center.y + half),
120 vec2(center.x - SIZE, center.y + half),
121 vec2(center.x - SIZE, center.y - half),
122 vec2(center.x - half, center.y - half),
123 vec2(center.x - half, center.y - SIZE),
124 ];
125
126 draw_connected_path(&points, OUTLINE, SECONDARY);
127
128 for (button, pos, size) in buttons {
129 if pad.is_pressed(button) {
130 draw_rect(pos, size, PRIMARY);
131 }
132 }
133}
134
135fn draw_buttons(pad: Gamepad, center: Vec2) {
136 const RADIUS: f32 = 30.0;
137 const DIST: f32 = 70.0;
138 const OUTLINE: f32 = 5.0;
139
140 let buttons = [
141 (gamepad::Button::North, vec2(center.x, center.y - DIST)),
142 (gamepad::Button::South, vec2(center.x, center.y + DIST)),
143 (gamepad::Button::West, vec2(center.x - DIST, center.y)),
144 (gamepad::Button::East, vec2(center.x + DIST, center.y)),
145 ];
146
147 for (button, pos) in buttons {
148 if pad.is_pressed(button) {
149 draw_circle(pos, RADIUS + OUTLINE, PRIMARY);
150 } else {
151 draw_circle_outline(pos, RADIUS, SECONDARY, OUTLINE);
152 }
153 }
154}