Skip to content

Commit

Permalink
better controls!
Browse files Browse the repository at this point in the history
  • Loading branch information
lee-orr committed Jan 7, 2023
1 parent fb9bd92 commit 58b912c
Show file tree
Hide file tree
Showing 4 changed files with 192 additions and 9 deletions.
113 changes: 113 additions & 0 deletions src/camera_control.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
use crate::app_state::*;
use bevy::{
input::mouse::{MouseMotion, MouseScrollUnit, MouseWheel},
prelude::*,
};
use iyes_loopless::prelude::{AppLooplessStateExt, IntoConditionalSystem};
use smooth_bevy_cameras::{
controllers::orbit::{ControlEvent, OrbitCameraController},
LookTransform,
};

pub struct CameraControlPlugin;

impl Plugin for CameraControlPlugin {
fn build(&self, app: &mut App) {
app.add_enter_system(AppState::InGame, reset_camera)
.add_exit_system(AppState::InGame, freeze_camera)
.add_system(control_camera.run_in_state(AppState::InGame));
}
}

fn reset_camera(mut query: Query<(&mut OrbitCameraController, &mut LookTransform)>) {
for (mut orbit, mut look) in query.iter_mut() {
orbit.enabled = true;
look.target = Vec3::default();
look.eye = Vec3::new(5., 10., 5.);
}
}

fn freeze_camera(mut query: Query<(&mut OrbitCameraController, &mut LookTransform)>) {
for (mut orbit, mut look) in query.iter_mut() {
orbit.enabled = false;
look.target = Vec3::default();
look.eye = Vec3::new(5., 10., 5.);
}
}

fn control_camera(
mut events: EventWriter<ControlEvent>,
keys: Res<Input<KeyCode>>,
mut mouse_wheel: EventReader<MouseWheel>,
mouse_buttons: Res<Input<MouseButton>>,
mut mouse_motion_events: EventReader<MouseMotion>,
controllers: Query<&OrbitCameraController>,
) {
let controller = if let Some(controller) = controllers.iter().find(|c| c.enabled) {
controller
} else {
return;
};

let mut cursor_delta = Vec2::ZERO;
for event in mouse_motion_events.iter() {
cursor_delta += event.delta;
}

if keys.any_pressed([KeyCode::LControl, KeyCode::RControl]) {
// Orbit Mode
if keys.any_pressed([KeyCode::Left, KeyCode::A]) {
events.send(ControlEvent::Orbit(Vec2::new(1., 0.)));
}
if keys.any_pressed([KeyCode::Right, KeyCode::D]) {
events.send(ControlEvent::Orbit(Vec2::new(-1., 0.)));
}
if keys.any_pressed([KeyCode::Up, KeyCode::W]) {
events.send(ControlEvent::Orbit(Vec2::new(0., 1.)));
}
if keys.any_pressed([KeyCode::Down, KeyCode::S]) {
events.send(ControlEvent::Orbit(Vec2::new(0., -1.)));
}
} else {
// Move Mode
if keys.any_pressed([KeyCode::Left, KeyCode::A]) {
events.send(ControlEvent::TranslateTarget(Vec2::new(1., 0.)));
}
if keys.any_pressed([KeyCode::Right, KeyCode::D]) {
events.send(ControlEvent::TranslateTarget(Vec2::new(-1., 0.)));
}
if keys.any_pressed([KeyCode::Up, KeyCode::W]) {
events.send(ControlEvent::TranslateTarget(Vec2::new(0., 1.)));
}
if keys.any_pressed([KeyCode::Down, KeyCode::S]) {
events.send(ControlEvent::TranslateTarget(Vec2::new(0., -1.)));
}
}

if keys.any_pressed([KeyCode::NumpadSubtract, KeyCode::Minus]) {
events.send(ControlEvent::Zoom(1.01));
}
if keys.any_pressed([KeyCode::NumpadAdd, KeyCode::Equals]) {
events.send(ControlEvent::Zoom(0.99));
}

if mouse_buttons.pressed(MouseButton::Middle) {
events.send(ControlEvent::TranslateTarget(
controller.mouse_translate_sensitivity * cursor_delta,
));
}

if mouse_buttons.pressed(MouseButton::Right) {
events.send(ControlEvent::Orbit(
controller.mouse_rotate_sensitivity * cursor_delta,
));
}

for ev in mouse_wheel.iter() {
let mut scalar = ev.y * controller.mouse_wheel_zoom_sensitivity;
if ev.unit == MouseScrollUnit::Line {
scalar /= controller.pixels_per_line;
}
events.send(ControlEvent::Zoom(1. - scalar));
}
}
53 changes: 53 additions & 0 deletions src/custom_picking_plugin.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
use bevy::{ecs::schedule::ShouldRun, prelude::*};
use bevy_mod_picking::{
mesh_events_system, mesh_focus, pause_for_picking_blockers, CustomHighlightPlugin,
DefaultHighlighting, PausedForBlockers, PickingEvent, PickingPlugin, PickingPluginsState,
PickingSystem,
};

pub struct CustomPickingPlugin;

fn simple_criteria(flag: bool) -> ShouldRun {
if flag {
ShouldRun::Yes
} else {
ShouldRun::No
}
}

impl Plugin for CustomPickingPlugin {
fn build(&self, app: &mut App) {
app.add_plugin(PickingPlugin)
.add_plugin(CustomHighlightPlugin::<StandardMaterial> {
highlighting_default: |mut assets| DefaultHighlighting {
hovered: assets.add(Color::rgb(0.35, 0.35, 0.35).into()),
pressed: assets.add(Color::rgb(0.35, 0.75, 0.35).into()),
selected: assets.add(Color::rgb(0.35, 0.35, 0.75).into()),
},
})
.add_event::<PickingEvent>()
.init_resource::<PausedForBlockers>()
.add_system_set_to_stage(
CoreStage::First,
SystemSet::new()
.with_run_criteria(|state: Res<PickingPluginsState>| {
simple_criteria(state.enable_interacting)
})
.with_system(
pause_for_picking_blockers
.label(PickingSystem::PauseForBlockers)
.after(PickingSystem::UpdateIntersections),
)
.with_system(
mesh_focus
.label(PickingSystem::Focus)
.after(PickingSystem::PauseForBlockers),
)
.with_system(
mesh_events_system
.label(PickingSystem::Events)
.after(PickingSystem::Selection),
),
);
}
}
14 changes: 12 additions & 2 deletions src/game/in_game_ui.rs
Original file line number Diff line number Diff line change
Expand Up @@ -93,10 +93,20 @@ fn display_ui(mut commands: Commands, level: Res<Level>, asset: Res<CanalManiaAs
.size(Size::new(Val::Px(200.), Val::Auto))
.with_children(|parent| {
parent.text(text).size(15.);
parent.div().padding(2.);
parent.text("Right-click and drag to pan, Ctrl and move the mouse to orbit, Scroll to zoom.").size(15.);
});
}
parent.div().padding(20.);
parent
.div()
.opaque()
.size(Size::new(Val::Px(200.), Val::Auto))
.with_children(|parent| {
parent.text("Drag Midde Mouse Button, Arrow Keys or WSAD to move the camera").size(15.);
parent.div().padding(3.);
parent.text("Drag Right Mouse Button, Control + Arrow Keys or WSAD to orbit the camera").size(15.);
parent.div().padding(3.);
parent.text("Scroll Wheel, + or - Keys to zoom").size(15.);
});
});

#[cfg(feature = "dev")]
Expand Down
21 changes: 14 additions & 7 deletions src/main.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
mod app_state;
mod assets;
mod camera_control;
mod choose_level;
mod credits;
mod custom_picking_plugin;
mod game;
mod menu;
mod ui;
Expand All @@ -11,10 +13,12 @@ use bevy::prelude::*;
use bevy_asset_loader::prelude::*;
use bevy_common_assets::{json::JsonAssetPlugin, yaml::YamlAssetPlugin};

use bevy_mod_picking::{DefaultPickingPlugins, PickingCameraBundle};
use bevy_mod_picking::PickingCameraBundle;

use camera_control::CameraControlPlugin;
use choose_level::ChooseLevelPlugin;
use credits::CreditsPlugin;
use custom_picking_plugin::CustomPickingPlugin;
use game::{
level::{Level, LevelList},
GamePlugin,
Expand Down Expand Up @@ -51,9 +55,10 @@ fn main() {
}),
)
.add_plugin(NoisyShaderPlugin)
.add_plugins(DefaultPickingPlugins)
.add_plugin(LookTransformPlugin)
.add_plugin(OrbitCameraPlugin::default())
.add_plugin(OrbitCameraPlugin {
override_input_system: true,
})
.add_plugin(JsonAssetPlugin::<Level>::new(&["lvl.json"]))
.add_plugin(YamlAssetPlugin::<LevelList>::new(&["levels.yml"]));

Expand All @@ -74,12 +79,11 @@ fn main() {
.add_plugin(ChooseLevelPlugin)
.add_plugin(CreditsPlugin)
.add_plugin(GamePlugin)
.add_plugin(CameraControlPlugin)
.add_plugin(CustomPickingPlugin)
.add_startup_system(setup)
.add_enter_system(AppLoadingState::Loaded, on_loaded);

// #[cfg(feature = "dev")]
// app.add_plugin(bevy_inspector_egui::quick::WorldInspectorPlugin);

app.run();
}

Expand All @@ -90,7 +94,10 @@ fn setup(mut commands: Commands) {
.spawn(Camera3dBundle::default())
.insert(OrbitCameraBundle::new(
OrbitCameraController {
enabled: true,
enabled: false,
mouse_translate_sensitivity: Vec2::splat(0.5),
mouse_rotate_sensitivity: Vec2::splat(0.08),
mouse_wheel_zoom_sensitivity: 1.5,
..Default::default()
},
eye,
Expand Down

0 comments on commit 58b912c

Please sign in to comment.