Skeleton of an editor. Just a window with solid toggling.

attempt/001
Elijah C. Voigt 1 year ago
parent c31801e876
commit 5c71f55363

@ -6,13 +6,13 @@ components = [
"rls",
"rustc-dev",
"rustfmt",
"wasm-bindgen-cli",
"wasm-server-runner",
# "wasm-bindgen-cli",
# "wasm-server-runner",
]
targets = [
"aarch64-apple-darwin",
"wasm32-unknown-unknown",
"x86_64-apple-darwin",
# "aarch64-apple-darwin",
# "wasm32-unknown-unknown",
# "x86_64-apple-darwin",
# "x86_64-unknown-linux-gnu",
"x86_64-pc-windows-msvc",
"x86_64-unknown-linux-gnu",
]

@ -0,0 +1,5 @@
use bevy::prelude::*;
pub(crate) fn any_component_added<T: Component>(q: Query<Entity, Added<T>>) -> bool {
!q.is_empty()
}

@ -0,0 +1,163 @@
use crate::prelude::*;
pub(crate) struct EditorPlugin;
impl Plugin for EditorPlugin {
fn build(&self, app: &mut App) {
app.init_state::<EditorState>()
.add_systems(Startup, init_editor)
.add_systems(
Update,
toggle_editor_state.run_if(input_just_pressed(KeyCode::F3)),
)
.add_systems(
OnTransition {
from: EditorState::Open,
to: EditorState::Closed,
},
toggle_editor_window,
)
.add_systems(
OnTransition {
from: EditorState::Closed,
to: EditorState::Open,
},
toggle_editor_window,
)
.add_systems(
Update,
handle_window_close.run_if(on_event::<WindowCloseRequested>()),
);
}
}
/// Tracking the open/closed state of the editor
#[derive(States, Debug, Clone, PartialEq, Eq, Hash, Default, Component)]
enum EditorState {
/// The editor is closed => the editor window is disabled
#[default]
Closed,
/// The editor is open => the editor window is visible
Open,
}
impl std::ops::Not for &EditorState {
type Output = EditorState;
fn not(self) -> Self::Output {
match self {
EditorState::Open => EditorState::Closed,
EditorState::Closed => EditorState::Open,
}
}
}
impl std::convert::From<&EditorState> for bool {
fn from(value: &EditorState) -> bool {
match value {
EditorState::Open => true,
EditorState::Closed => false,
}
}
}
/// Tag component for editor entities
#[derive(Component)]
struct EditorTag;
/// At startup initialize some editor components
fn init_editor(mut commands: Commands) {
// Editor window
let editor_window = commands
.spawn((
EditorTag,
Window {
visible: false,
title: "Editor".into(),
..default()
},
))
.id();
// Editor camera
let editor_camera = commands
.spawn((
EditorTag,
Camera3dBundle {
camera: Camera {
target: RenderTarget::Window(WindowRef::Entity(editor_window)),
..default()
},
..default()
},
))
.id();
// Editor UI elements
commands
.spawn((
EditorTag,
TargetCamera(editor_camera),
NodeBundle { ..default() },
))
.with_children(|parent| {
parent.spawn((
EditorTag,
TextBundle::from_section(
"Welcome to the editor",
TextStyle {
color: Color::WHITE,
..default()
},
),
));
});
}
fn toggle_editor_state(
curr_state: Res<State<EditorState>>,
mut next_state: ResMut<NextState<EditorState>>,
keys: Res<ButtonInput<KeyCode>>,
mut catch: Local<bool>,
) {
if keys.pressed(KeyCode::F3) && !*catch {
*catch = true;
match curr_state.get() {
EditorState::Open => next_state.set(EditorState::Closed),
EditorState::Closed => next_state.set(EditorState::Open),
}
} else {
*catch = false;
}
}
fn toggle_editor_window(
state: Res<State<EditorState>>,
mut windows: Query<&mut Window, With<EditorTag>>,
mut cameras: Query<&mut Camera, With<EditorTag>>,
) {
let curr = state.get().into();
cameras.iter_mut().for_each(|mut camera| {
camera.is_active = curr;
});
windows.iter_mut().for_each(|mut window| {
window.visible = curr;
})
}
/// Handles window close requests which are only weird because of the editor
/// When the editor window closes, just make it invisible and change the editor state to "Closed".
fn handle_window_close(
mut events: EventReader<WindowCloseRequested>,
editor_windows: Query<Entity, With<EditorTag>>,
mut editor_state: ResMut<NextState<EditorState>>,
) {
events
.read()
// Filter events down to jus those affecting the editor window
.filter_map(|WindowCloseRequested { window }| editor_windows.get(*window).ok())
// For each related close event, send out a "Close the editor" state transition
.for_each(|_| {
editor_state.set(EditorState::Closed);
});
}

@ -1,14 +1,26 @@
/// ECS scheduling `run_if` conditions
pub(crate) mod conditions;
/// Editor: debugging and run-time modifications to the game
pub(crate) mod editor;
/// Menu: Main and otherwise
pub(crate) mod menu;
/// Helper module containing common imports across the project
pub(crate) mod prelude;
/// Menu plugin, state, systems
pub(crate) mod menu;
/// Window handling
pub(crate) mod window;
use crate::prelude::*;
fn main() {
App::new()
.add_plugins(DefaultPlugins)
.add_plugins(DefaultPlugins.set(WindowPlugin {
// handled in crate::window::handle_window_close and crate::editor::handle_window_close
close_when_requested: false,
exit_condition: bevy::window::ExitCondition::OnPrimaryClosed,
..default()
}))
.add_plugins(menu::MenuPlugin)
.add_plugins(editor::EditorPlugin)
.add_plugins(window::WindowPlugin)
.run();
}

@ -9,23 +9,21 @@ impl Plugin for MenuPlugin {
}
fn init_menu(mut commands: Commands) {
commands.spawn(Camera3dBundle { ..default() });
commands.spawn(Camera3dBundle { ..default() });
commands
.spawn(NodeBundle {
style: Style {
max_width: Val::Percent(60.0),
max_height: Val::Percent(100.0),
..default()
},
..default()
})
style: Style {
max_width: Val::Percent(60.0),
max_height: Val::Percent(100.0),
..default()
},
..default()
})
.with_children(|parent| {
parent.spawn(TextBundle {
style: Style {
..default()
},
style: Style { ..default() },
text: Text {
justify: JustifyText::Center,
justify: JustifyText::Center,
sections: vec![
TextSection::new(
"ACTS",

@ -1 +1,9 @@
pub(crate) use bevy::app::AppExit;
pub(crate) use bevy::input::common_conditions::input_just_pressed;
pub(crate) use bevy::prelude::*;
pub(crate) use bevy::render::camera::RenderTarget;
pub(crate) use bevy::window::PrimaryWindow;
pub(crate) use bevy::window::WindowCloseRequested;
pub(crate) use bevy::window::WindowRef;
pub(crate) use crate::conditions::*;

@ -7,3 +7,9 @@ impl Plugin for UiPlugin {
app.add_systems(Startup, init_ui);
}
}
fn init_ui(
mut commands: Commands,
) {
todo!()
}

@ -0,0 +1,41 @@
use crate::prelude::*;
pub(crate) struct WindowPlugin;
impl Plugin for WindowPlugin {
fn build(&self, app: &mut App) {
app.add_systems(
Update,
setup_primary.run_if(any_component_added::<PrimaryWindow>),
)
.add_systems(
Update,
handle_window_close.run_if(on_event::<WindowCloseRequested>()),
);
}
}
fn setup_primary(mut events: Query<&mut Window, Added<PrimaryWindow>>) {
events.iter_mut().for_each(|mut window| {
window.title = "Acts of Gods".into();
});
}
/// Handles window close requests which are only weird because of the editor
/// When the primary window closes shut down the game.
fn handle_window_close(
mut events: EventReader<WindowCloseRequested>,
primary: Query<Entity, With<PrimaryWindow>>,
mut exit: EventWriter<AppExit>,
) {
events
.read()
// FilterMap this entity to the primary window
// Meaning if we get Some(entity) the event was for the primary
// If we get None it was for a different window so we skip the for_each
.filter_map(|WindowCloseRequested { window }| primary.get(*window).ok())
// If this was the primary window, send an AppExit
.for_each(|_| {
exit.send(AppExit);
});
}
Loading…
Cancel
Save