Skip to content

Commit

Permalink
Merge pull request #176 from janhohenheim/editor-window
Browse files Browse the repository at this point in the history
Former-commit-id: fc120bc
  • Loading branch information
janhohenheim authored Feb 20, 2023
2 parents c1c7d92 + a32bf35 commit df8749d
Show file tree
Hide file tree
Showing 5 changed files with 89 additions and 50 deletions.
8 changes: 4 additions & 4 deletions readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,16 +13,16 @@ be good enough for others to find inspiration, copy parts they like or troublesh
- A 3D character controller
- Physics via `bevy_rapier`
- Audio via `bevy_kira_audio`
- Pathfinding via `bevy_pathmesh`
- bevy_editor_pls from the `dev` feature
- Custom editor that can be opened with 'Q' from the `dev` feature
- Pathfinding via `oxidized_navigation`
- `bevy_editor_pls` in the `dev` feature, bound to 'Q'
- Custom editor for the game state found in the windows for `bevy_editor_pls`.
- Saving / loading levels
- Saving / loading the game state
- Animations
- A custom dialog system
- Shaders
- GLTF imports, including colliders and navmeshes
- dynamic builds via the `dynamic` feature
- dynamic builds in the `native-dev` feature

## Usage

Expand Down
23 changes: 19 additions & 4 deletions src/dev.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
use crate::dev::scene_editor::SceneEditorPlugin;
use crate::dev::dev_editor::DevEditorPlugin;
use bevy::diagnostic::{FrameTimeDiagnosticsPlugin, LogDiagnosticsPlugin};
use bevy::prelude::*;
use bevy_editor_pls::prelude::*;
use bevy_prototype_debug_lines::DebugLinesPlugin;
use bevy_rapier3d::prelude::*;

pub mod scene_editor;
pub mod dev_editor;

/// Plugin with debugging utility intended for use during development only.
/// Don't include this in a release build.
Expand All @@ -14,10 +14,11 @@ pub struct DevPlugin;
impl Plugin for DevPlugin {
fn build(&self, app: &mut App) {
{
app.add_plugin(EditorPlugin)
app.insert_resource(default_editor_controls())
.add_plugin(EditorPlugin)
.add_plugin(FrameTimeDiagnosticsPlugin::default())
.add_plugin(DebugLinesPlugin::default())
.add_plugin(SceneEditorPlugin)
.add_plugin(DevEditorPlugin)
.add_plugin(LogDiagnosticsPlugin::filtered(vec![]))
.add_plugin(RapierDebugRenderPlugin {
enabled: false,
Expand All @@ -26,3 +27,17 @@ impl Plugin for DevPlugin {
}
}
}

fn default_editor_controls() -> bevy_editor_pls::controls::EditorControls {
use bevy_editor_pls::controls::*;
let mut editor_controls = EditorControls::default_bindings();
editor_controls.unbind(Action::PlayPauseEditor);
editor_controls.insert(
Action::PlayPauseEditor,
Binding {
input: UserInput::Single(Button::Keyboard(KeyCode::Q)),
conditions: vec![BindingCondition::ListeningForText(false)],
},
);
editor_controls
}
86 changes: 47 additions & 39 deletions src/dev/scene_editor.rs → src/dev/dev_editor.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
use crate::file_system_interaction::game_state_serialization::{GameLoadRequest, GameSaveRequest};
use crate::file_system_interaction::level_serialization::{WorldLoadRequest, WorldSaveRequest};
use crate::level_instantiation::spawning::{DelayedSpawnEvent, GameObject, SpawnEvent};
use crate::player_control::camera::ForceCursorGrabMode;
use crate::GameState;
use anyhow::Result;
use bevy::prelude::*;
use bevy::window::CursorGrabMode;
use bevy_editor_pls::editor_window::EditorWindow;
use bevy_editor_pls::{AddEditorWindow, Editor};
use bevy_editor_pls::{AddEditorWindow, Editor, EditorEvent};
use bevy_egui::egui;
use bevy_egui::egui::ScrollArea;
use bevy_prototype_debug_lines::DebugLines;
Expand All @@ -13,22 +16,37 @@ use oxidized_navigation::NavMesh;
use serde::{Deserialize, Serialize};
use strum::IntoEnumIterator;

pub struct SceneEditorPlugin;
pub struct DevEditorPlugin;

pub struct FoxtrotDevWindow;
impl Plugin for DevEditorPlugin {
fn build(&self, app: &mut App) {
app.init_resource::<DevEditorState>()
.add_editor_window::<DevEditorWindow>()
.add_system_set(
SystemSet::on_update(GameState::Playing)
.with_system(handle_debug_render)
.with_system(handle_navmesh_render)
.with_system(set_cursor_grab_mode),
);
}
}

impl EditorWindow for FoxtrotDevWindow {
const DEFAULT_SIZE: (f32, f32) = (200., 150.);
pub struct DevEditorWindow;

impl EditorWindow for DevEditorWindow {
type State = DevEditorState;
const NAME: &'static str = "Foxtrot Dev";
type State = SceneEditorState;
const DEFAULT_SIZE: (f32, f32) = (200., 150.);
fn ui(
world: &mut World,
mut cx: bevy_editor_pls::editor_window::EditorWindowContext,
ui: &mut egui::Ui,
) {
let state = cx
.state_mut::<FoxtrotDevWindow>()
.expect("Window State Loaded");
.state_mut::<DevEditorWindow>()
.expect("Failed to get dev window state");

state.open = true;
ui.heading("Debug Rendering");
ui.checkbox(&mut state.collider_render_enabled, "Colliders");
ui.checkbox(&mut state.navmesh_render_enabled, "Navmeshes");
Expand Down Expand Up @@ -104,53 +122,57 @@ impl EditorWindow for FoxtrotDevWindow {

#[derive(Debug, Clone, Eq, PartialEq, Resource, Reflect, Serialize, Deserialize)]
#[reflect(Resource, Serialize, Deserialize)]
pub struct SceneEditorState {
pub struct DevEditorState {
pub open: bool,
pub level_name: String,
pub save_name: String,
pub spawn_item: GameObject,
pub collider_render_enabled: bool,
pub navmesh_render_enabled: bool,
}

impl Default for SceneEditorState {
impl Default for DevEditorState {
fn default() -> Self {
Self {
level_name: "old_town".to_owned(),
save_name: default(),
spawn_item: default(),
collider_render_enabled: false,
navmesh_render_enabled: false,
open: false,
}
}
}

impl Plugin for SceneEditorPlugin {
fn build(&self, app: &mut App) {
app.init_resource::<SceneEditorState>()
.add_editor_window::<FoxtrotDevWindow>()
.insert_resource(default_editor_controls())
.add_system_set(
SystemSet::on_update(GameState::Playing)
.with_system(handle_debug_render)
.with_system(handle_navmesh_render),
);
}
}

fn handle_debug_render(state: Res<Editor>, mut debug_render_context: ResMut<DebugRenderContext>) {
debug_render_context.enabled = state
.window_state::<FoxtrotDevWindow>()
.window_state::<DevEditorWindow>()
.expect("Window State Loaded")
.collider_render_enabled;
}

fn set_cursor_grab_mode(
mut events: EventReader<EditorEvent>,
mut force_cursor_grab: ResMut<ForceCursorGrabMode>,
) {
for event in events.iter() {
if let EditorEvent::Toggle { now_active } = event {
if *now_active {
force_cursor_grab.0 = Some(CursorGrabMode::None);
} else {
force_cursor_grab.0 = None;
}
}
}
}

fn handle_navmesh_render(
state: Res<Editor>,
nav_mesh: Res<NavMesh>,
mut lines: ResMut<DebugLines>,
) {
if !state
.window_state::<FoxtrotDevWindow>()
.window_state::<DevEditorWindow>()
.expect("Window State Loaded")
.navmesh_render_enabled
{
Expand Down Expand Up @@ -183,17 +205,3 @@ fn handle_navmesh_render(
}
}
}

fn default_editor_controls() -> bevy_editor_pls::controls::EditorControls {
use bevy_editor_pls::controls::*;
let mut start = EditorControls::default_bindings();
start.unbind(Action::PlayPauseEditor);
start.insert(
Action::PlayPauseEditor,
Binding {
input: UserInput::Single(Button::Keyboard(KeyCode::Q)),
conditions: vec![BindingCondition::ListeningForText(false)],
},
);
start
}
10 changes: 7 additions & 3 deletions src/movement/navigation.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
#[cfg(feature = "dev")]
use crate::dev::scene_editor::FoxtrotDevWindow;
use crate::dev::dev_editor::DevEditorWindow;
use crate::movement::general_movement::{apply_walking, reset_movement_components, Walking};
use crate::player_control::player_embodiment::Player;
use crate::util::log_error::log_errors;
use crate::util::trait_extension::{F32Ext, Vec3Ext};
use crate::GameState;
use anyhow::Result;
use anyhow::{Context, Result};
use bevy::prelude::*;
use bevy_prototype_debug_lines::DebugLines;
use bevy_rapier3d::prelude::*;
Expand Down Expand Up @@ -99,7 +99,11 @@ fn query_mesh(
};
if let Some(path) = path {
#[cfg(feature = "dev")]
if editor_state.window_state::<FoxtrotDevWindow>().expect("Window Is Loaded").navmesh_render_enabled {
if editor_state
.window_state::<DevEditorWindow>()
.context("Failed to get dev window state")?
.navmesh_render_enabled
{
draw_path(&path, &mut lines, Color::RED);
}
let dir = path
Expand Down
12 changes: 12 additions & 0 deletions src/player_control/camera.rs
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,9 @@ impl Plugin for CameraPlugin {
.register_type::<ThirdPersonCamera>()
.register_type::<IngameCamera>()
.register_type::<IngameCameraKind>()
.register_type::<FirstPersonCamera>()
.register_type::<FixedAngleCamera>()
.init_resource::<ForceCursorGrabMode>()
.add_startup_system(spawn_ui_camera)
.add_system_set(SystemSet::on_enter(GameState::Playing).with_system(despawn_ui_camera))
.add_system_set(
Expand Down Expand Up @@ -223,13 +226,22 @@ fn move_skydome(
}
}

#[derive(Debug, Clone, Copy, Resource, Serialize, Deserialize, Default)]
pub struct ForceCursorGrabMode(pub Option<CursorGrabMode>);

fn cursor_grab_system(
mut windows: ResMut<Windows>,
actions_frozen: Res<ActionsFrozen>,
force_cursor_grab: Res<ForceCursorGrabMode>,
) -> Result<()> {
let window = windows
.get_primary_mut()
.context("Failed to get primary window")?;
if let Some(mode) = force_cursor_grab.0 {
window.set_cursor_grab_mode(mode);
window.set_cursor_visibility(mode != CursorGrabMode::Locked);
return Ok(());
}
if actions_frozen.is_frozen() {
window.set_cursor_grab_mode(CursorGrabMode::None);
window.set_cursor_visibility(true);
Expand Down

0 comments on commit df8749d

Please sign in to comment.