1use bevy::prelude::*;
2use press_here::{
3 Add, And, AppExt, AxisBinding, AxisBindingBuilder, AxisVisualizer, Clamp, Deadzone, Divide,
4 Invert, MouseWheel, MouseY, Multiply, Normalize, Not, Pair, RateLimit, Remap, Smooth, Subtract,
5 Transformation, Trigger, TriggerBinding, WithCurve, WithTriggerBinding,
6};
7use std::time::Duration;
8
9fn main() {
10 let _super_complex_axis_binding = WithTriggerBinding(
13 Smooth::new(
14 Deadzone(
15 (
16 Pair(KeyCode::KeyA, GamepadAxis::LeftStickX),
17 Multiply(32.0, GamepadAxis::LeftStickX),
18 ),
19 0.1,
20 ),
21 0.2,
22 ),
23 MouseButton::Left,
24 );
25
26 let _super_complex_axis_binding_built_different = (
30 Pair(KeyCode::KeyA, GamepadAxis::LeftStickX),
31 32.0.mult(GamepadAxis::LeftStickX),
32 )
33 .deadzone(0.1)
34 .smooth(0.2)
35 .with_trigger_binding(MouseButton::Left);
36
37 App::new()
41 .add_plugins(DefaultPlugins)
42 .add_axis::<EmptyAxis>(()) .add_axis::<ConstantAxis>(1.0) .add_axis::<KeyCodeAxis>(KeyCode::Space) .add_axis::<MouseButtonAxis>(MouseButton::Left) .add_axis::<GamepadButtonAxis>(GamepadButton::South) .add_axis::<GamepadAxisAxis>(GamepadAxis::LeftStickX) .add_axis::<MouseMovementAxis>(MouseY) .add_axis::<MouseWheelAxis>(MouseWheel::default()) .add_axis::<BoxedAxis>(Box::new(KeyCode::KeyW) as Box<dyn AxisBinding>) .add_axis::<TupleAxis>((KeyCode::KeyW, GamepadAxis::LeftStickX)) .add_axis::<VecAxis>(vec![KeyCode::KeyW, KeyCode::ArrowUp]) .add_axis::<PairAxis>(Pair(KeyCode::KeyS, KeyCode::KeyW)) .add_axis::<WithTriggerAxis>(WithTriggerBinding(MouseY, MouseButton::Left)) .add_axis::<DeadzoneAxis>(Deadzone(GamepadAxis::LeftStickX, 0.2)) .add_axis::<SmoothAxis>(Smooth::new(GamepadAxis::LeftStickX, 0.1)) .add_axis::<NormalizeAxis>(Normalize(GamepadAxis::LeftStickX, GamepadAxis::LeftStickY)) .add_axis::<RateLimitAxis>(RateLimit::new(GamepadAxis::LeftStickX, 1.0)) .add_axis::<ClampAxis>(Clamp(GamepadAxis::LeftStickX, -0.5, 0.5)) .add_axis::<MultiplyAxis>(Multiply(GamepadAxis::LeftStickX, 0.5)) .add_axis::<DivideAxis>(Divide(GamepadAxis::LeftStickX, 2.0)) .add_axis::<AddAxis>(Add(GamepadAxis::LeftStickX, 0.5)) .add_axis::<SubtractAxis>(Subtract(GamepadAxis::LeftStickX, 0.5)) .add_axis::<InvertAxis>(Invert(GamepadAxis::LeftStickX)) .add_axis::<WithCurveAxis>(WithCurve(GamepadAxis::LeftStickX, EaseFunction::BounceIn)) .add_axis::<TransformationAxis>(Transformation(GamepadAxis::LeftStickX, |v| v * v)) .add_axis::<RemapAxis>(Remap(GamepadAxis::LeftStickX, -1.0, 1.0, 0.0, 1.0)) .add_trigger::<EmptyTrigger>(()) .add_trigger::<ConstantTrigger>(true) .add_trigger::<KeyCodeTrigger>(KeyCode::Space) .add_trigger::<MouseButtonTrigger>(MouseButton::Left) .add_trigger::<GamepadButtonTrigger>(GamepadButton::South) .add_trigger::<BoxedTrigger>(Box::new(KeyCode::KeyW) as Box<dyn TriggerBinding>) .add_trigger::<TupleTrigger>((KeyCode::KeyW, GamepadButton::South)) .add_trigger::<VecTrigger>(vec![KeyCode::KeyW, KeyCode::ArrowUp]) .add_trigger::<AndTrigger>(And(KeyCode::KeyW, GamepadButton::South)) .add_trigger::<NotTrigger>(Not(KeyCode::KeyW)) .add_systems(
92 Update,
93 (
94 visualize_basic,
95 visualize_combinators,
96 visualize_filters,
97 visualize_modifiers,
98 draw_triggers,
99 ),
100 )
101 .add_systems(Startup, setup)
102 .insert_resource(ClearColor(Color::WHITE))
103 .run();
104}
105
106struct EmptyAxis;
107struct ConstantAxis;
108struct KeyCodeAxis;
109struct MouseButtonAxis;
110struct GamepadButtonAxis;
111struct GamepadAxisAxis;
112struct MouseMovementAxis;
113struct MouseWheelAxis;
114struct BoxedAxis;
115
116struct TupleAxis;
117struct VecAxis;
118struct PairAxis;
119struct WithTriggerAxis;
120
121struct DeadzoneAxis;
122struct SmoothAxis;
123struct NormalizeAxis;
124struct RateLimitAxis;
125struct ClampAxis;
126
127struct MultiplyAxis;
128struct DivideAxis;
129struct AddAxis;
130struct SubtractAxis;
131struct InvertAxis;
132struct WithCurveAxis;
133struct TransformationAxis;
134struct RemapAxis;
135
136struct EmptyTrigger;
137struct ConstantTrigger;
138struct KeyCodeTrigger;
139struct MouseButtonTrigger;
140struct GamepadButtonTrigger;
141struct BoxedTrigger;
142
143struct TupleTrigger;
144struct VecTrigger;
145struct AndTrigger;
146
147struct NotTrigger;
148
149#[allow(clippy::too_many_arguments)]
150fn visualize_basic(
151 mut empty: AxisVisualizer<EmptyAxis>,
152 mut constant: AxisVisualizer<ConstantAxis>,
153 mut keycode: AxisVisualizer<KeyCodeAxis>,
154 mut mouse_button: AxisVisualizer<MouseButtonAxis>,
155 mut gamepad_button: AxisVisualizer<GamepadButtonAxis>,
156 mut gamepad_axis: AxisVisualizer<GamepadAxisAxis>,
157 mut mouse_movement: AxisVisualizer<MouseMovementAxis>,
158 mut mouse_wheel: AxisVisualizer<MouseWheelAxis>,
159 mut boxed: AxisVisualizer<BoxedAxis>,
160) {
161 graph(&mut empty, 0, 0, SCALE);
162 graph(&mut constant, 1, 0, SCALE);
163 graph(&mut keycode, 2, 0, SCALE);
164 graph(&mut mouse_button, 3, 0, SCALE);
165 graph(&mut gamepad_button, 4, 0, SCALE);
166 graph(&mut gamepad_axis, 5, 0, SCALE);
167 graph(&mut mouse_movement, 6, 0, 1.0);
168 graph(&mut mouse_wheel, 7, 0, 1.0);
169 graph(&mut boxed, 8, 0, SCALE);
170}
171
172fn visualize_combinators(
173 mut tuple: AxisVisualizer<TupleAxis>,
174 mut vec: AxisVisualizer<VecAxis>,
175 mut pair: AxisVisualizer<PairAxis>,
176 mut with_trigger: AxisVisualizer<WithTriggerAxis>,
177) {
178 graph(&mut tuple, 0, 1, SCALE);
179 graph(&mut vec, 1, 1, SCALE);
180 graph(&mut pair, 2, 1, SCALE);
181 graph(&mut with_trigger, 3, 1, 1.0);
182}
183
184fn visualize_filters(
185 mut deadzone: AxisVisualizer<DeadzoneAxis>,
186 mut smooth: AxisVisualizer<SmoothAxis>,
187 mut normalize: AxisVisualizer<NormalizeAxis>,
188 mut rate_limit: AxisVisualizer<RateLimitAxis>,
189 mut clamp: AxisVisualizer<ClampAxis>,
190) {
191 graph(&mut deadzone, 0, 2, SCALE);
192 graph(&mut smooth, 1, 2, SCALE);
193 graph(&mut normalize, 2, 2, SCALE);
194 graph(&mut rate_limit, 3, 2, SCALE);
195 graph(&mut clamp, 4, 2, SCALE);
196}
197
198#[allow(clippy::too_many_arguments)]
199fn visualize_modifiers(
200 mut multiply: AxisVisualizer<MultiplyAxis>,
201 mut divide: AxisVisualizer<DivideAxis>,
202 mut add: AxisVisualizer<AddAxis>,
203 mut subtract: AxisVisualizer<SubtractAxis>,
204 mut invert: AxisVisualizer<InvertAxis>,
205 mut with_curve: AxisVisualizer<WithCurveAxis>,
206 mut transformation: AxisVisualizer<TransformationAxis>,
207 mut remap: AxisVisualizer<RemapAxis>,
208) {
209 graph(&mut multiply, 0, 3, SCALE);
210 graph(&mut divide, 1, 3, SCALE);
211 graph(&mut add, 2, 3, SCALE);
212 graph(&mut subtract, 3, 3, SCALE);
213 graph(&mut invert, 4, 3, SCALE);
214 graph(&mut with_curve, 5, 3, SCALE);
215 graph(&mut transformation, 6, 3, SCALE);
216 graph(&mut remap, 7, 3, SCALE);
217}
218
219#[allow(clippy::too_many_arguments)]
220fn draw_triggers(
221 mut gizmos: Gizmos,
222 empty: Res<Trigger<EmptyTrigger>>,
223 constant: Res<Trigger<ConstantTrigger>>,
224 keycode: Res<Trigger<KeyCodeTrigger>>,
225 mouse_button: Res<Trigger<MouseButtonTrigger>>,
226 gamepad_button: Res<Trigger<GamepadButtonTrigger>>,
227 boxed: Res<Trigger<BoxedTrigger>>,
228 tuple: Res<Trigger<TupleTrigger>>,
229 vec: Res<Trigger<VecTrigger>>,
230 and: Res<Trigger<AndTrigger>>,
231 not: Res<Trigger<NotTrigger>>,
232) {
233 draw_trigger(&mut gizmos, &empty, 0);
234 draw_trigger(&mut gizmos, &constant, 1);
235 draw_trigger(&mut gizmos, &keycode, 2);
236 draw_trigger(&mut gizmos, &mouse_button, 3);
237 draw_trigger(&mut gizmos, &gamepad_button, 4);
238 draw_trigger(&mut gizmos, &boxed, 5);
239 draw_trigger(&mut gizmos, &tuple, 6);
240 draw_trigger(&mut gizmos, &vec, 7);
241 draw_trigger(&mut gizmos, &and, 8);
242 draw_trigger(&mut gizmos, ¬, 9);
243}
244
245fn setup(mut commands: Commands) {
246 commands.spawn(Camera2d);
247}
248
249const SCALE: f32 = 32.0;
250const MAX_COLUMNS: u32 = 9;
251const MAX_ROWS: u32 = 4;
252const TRIGGER_COUNT: u32 = 10;
253
254fn graph<A: Send + Sync + 'static>(visualizer: &mut AxisVisualizer<A>, x: i32, y: i32, scale: f32) {
255 let timespan = Duration::from_secs(5);
256 let margin = 32.0;
257 let size = 64.0;
258
259 let width = MAX_COLUMNS as f32 * (size + margin) - margin;
260 let height = MAX_ROWS as f32 * (size + margin) - margin;
261
262 let pos = Vec2::new(
263 -width / 2.0 + x as f32 * (size + margin) + size / 2.0,
264 height / 2.0 - y as f32 * (size + margin) - size / 2.0,
265 );
266 let color = Color::srgb(
267 x as f32 / MAX_COLUMNS as f32,
268 y as f32 / MAX_ROWS as f32,
269 1.0 - (x as f32 / MAX_COLUMNS as f32),
270 );
271
272 visualizer.graph_x(timespan, pos, scale, Vec2::splat(size), color);
273}
274
275fn draw_trigger<T: Send + Sync + 'static>(
276 gizmos: &mut Gizmos,
277 trigger: &Res<Trigger<T>>,
278 index: u32,
279) {
280 let is_pressed = trigger.pressed();
281 let color = if is_pressed {
282 Srgba::RED
283 } else {
284 Srgba::gray(0.4)
285 };
286
287 let size = 8.0;
288 let margin = 32.0;
289
290 let width = TRIGGER_COUNT as f32 * (size + margin) - margin;
291
292 let pos = Vec2::new(
293 -width / 2.0 + index as f32 * (size + margin) + size / 2.0,
294 -240.0,
295 );
296
297 gizmos.circle_2d(pos, size, color);
298}