diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index f65ed0a..634528e 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -8,6 +8,12 @@ need [mise](https://mise.jdx.dev/), an environment manager and task runner. Once you install mise, run `mise install` and `mise run` to get all the necessary tools and view the available actions. +## Why a monorepo? + +These crates are all very closely related. It's likely that if you edit one, +you'll need to edit another. Additionally, they all use the same build tooling, +so overall it's more convenient to have them all in the same place. + ## Testing Tests are handled diff --git a/crates/cmd_prompt/README.md b/crates/cmd_prompt/README.md index c58e19c..1dbcda3 100644 --- a/crates/cmd_prompt/README.md +++ b/crates/cmd_prompt/README.md @@ -1,8 +1,8 @@
-Logo - 'q command prompt' over a sketch of a green magpie +Logo - 'q command prompt' over a sketch of a green magpie
-[![Coveralls](https://img.shields.io/coverallsCoverage/github/ada-x64/qproj?branch=q_cmd_prompt)](https://coveralls.io/github/ada-x64/qproj?branch=main) +[![Coveralls](https://img.shields.io/coverallsCoverage/github/ada-x64/qproj?branch=q_cmd_prompt)](https://coveralls.io/github/ada-x64/qproj?branch=q_cmd_prompt) This is an attempt at a `bevy_ui`-native dev console. diff --git a/crates/screens/README.md b/crates/screens/README.md index 18ba735..39d4211 100644 --- a/crates/screens/README.md +++ b/crates/screens/README.md @@ -1,9 +1,9 @@
-Illustration of a bowerbird with text 'q_screens' +Illustration of a bowerbird with text 'q_screens'
-[![Coveralls](https://img.shields.io/coverallsCoverage/github/ada-x64/qproj?branch=q_screens)](https://coveralls.io/github/ada-x64/qproj?branch=main) +[![Coveralls](https://img.shields.io/coverallsCoverage/github/ada-x64/qproj?branch=q_screens)](https://coveralls.io/github/ada-x64/qproj?branch=q_screens) Screen implementation for Bevy. diff --git a/crates/screens/src/data.rs b/crates/screens/src/data.rs index a4d1939..ccbd1fb 100644 --- a/crates/screens/src/data.rs +++ b/crates/screens/src/data.rs @@ -16,6 +16,8 @@ mod general_api { /// [SwitchToScreenMsg] with the screen's [ComponentId]. #[derive(Event, Debug, PartialEq, Eq, Clone, Deref, Default)] pub struct SwitchToScreen(PhantomData); + + /// See [SwitchToScreen] pub fn switch_to_screen() -> SwitchToScreen { SwitchToScreen::::default() } @@ -31,6 +33,8 @@ mod general_api { /// screen is not currently loading. #[derive(Event, Debug, PartialEq, Eq, Clone, Deref, Default)] pub struct FinishLoading(PhantomData); + + /// See [FinishLoading] pub fn finish_loading() -> FinishLoading { FinishLoading::::default() } @@ -39,13 +43,15 @@ mod general_api { /// screen is not currently unloading. #[derive(Event, Debug, PartialEq, Eq, Clone, Deref, Default)] pub struct FinishUnloading(PhantomData); + + /// See [FinishUnloading] pub fn finish_unloading() -> FinishUnloading { FinishUnloading::::default() } /// Scopes an entity to the current screen. The entity will be cleaned up when - /// the [Screens] state changes. By default, all entities _except_ those listed - /// in the [module documentation](crate::framework::screen) are screen-scoped. + /// the [Screen] state changes. By default, all entities _except_ top-level + /// [Observer] and [Window] components are screen-scoped. /// /// Note: This is effectively used to skip the propagation of the /// [Persistent] component. Since screen scoping is the default behavior, it @@ -55,8 +61,7 @@ mod general_api { /// Marks an entity as screen-persistent, i.e., this entity will _not_ be /// automatically cleaned up when the screen changes. By default, all entites - /// _except_ those listed in the [module - /// documentation](crate::framework::screen) are screen-scoped. + /// _except_ top-level [Observer] and [Window] components and are screen-scoped. /// /// In order to mark the children of this component as Persistent, you should /// use the [Propagate](bevy::app::Propagate) component. @@ -68,9 +73,11 @@ mod general_api { #[derive(Resource, Default, Debug, Deref)] pub struct InitialScreen(Option); impl InitialScreen { + #[allow(missing_docs)] pub fn new() -> Self { Self(Some(S::name())) } + #[allow(missing_docs)] pub fn from_name(name: String) -> Self { Self(Some(name)) } @@ -113,6 +120,7 @@ mod screens { skip_unload: bool, } impl ScreenData { + #[allow(missing_docs)] pub fn new(id: ComponentId, tick: Tick) -> Self { Self { name: S::name(), @@ -174,54 +182,67 @@ mod screens { } } + #[allow(missing_docs)] pub fn load_strategy(&self) -> LoadStrategy { self.load_strategy } + #[allow(missing_docs)] pub fn skip_load(&self) -> bool { self.skip_load } + #[allow(missing_docs)] pub fn skip_unload(&self) -> bool { self.skip_unload } + #[allow(missing_docs)] pub fn set_skip_unload(&mut self, skip_unload: bool) { self.skip_unload = skip_unload; } + #[allow(missing_docs)] pub fn set_skip_load(&mut self, skip_load: bool) { self.skip_load = skip_load; } + #[allow(missing_docs)] pub fn set_load_strategy(&mut self, load_strategy: LoadStrategy) { self.load_strategy = load_strategy; } + #[allow(missing_docs)] pub fn initialized(&self) -> bool { self.initialized } + #[allow(missing_docs)] pub fn changed_at(&self) -> Tick { self.changed_at } + #[allow(missing_docs)] pub fn needs_update(&self) -> bool { self.needs_update } + #[allow(missing_docs)] pub fn type_id(&self) -> TypeId { self.type_id } + #[allow(missing_docs)] pub fn state(&self) -> ScreenState { self.state } + #[allow(missing_docs)] pub fn id(&self) -> ComponentId { self.id } + #[allow(missing_docs)] pub fn name(&self) -> &str { &self.name } @@ -231,15 +252,18 @@ pub use screens::*; mod schedules { use super::*; - /// Describes a screen's [Schedule]. All systems added to this schedule, using the - /// [ScreenScope] below, will be scoped to this screen's lifetime. That is, - /// they will only run when the screen is in [ScreenStatus::Ready]. + /// Describes a screen's [Schedule]. All systems added to this schedule + /// will be scoped to this screen's lifetime. /// To use as a schedule, wrap it with [ScreenScheduleLabel]. #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, strum::EnumIter)] pub enum ScreenSchedule { + /// Runs on [Update] when the screen has [ScreenState::Ready] Update, + /// Runs on [FixedUpdate] when the screen has [ScreenState::Ready] FixedUpdate, + /// Runs on [Update] when the screen has [ScreenState::Loading] Loading, + /// Runs on [Update] when the screen has [ScreenState::Unloading] Unloading, /// Can also be specified as [on_screen_load] OnLoad, @@ -258,12 +282,14 @@ mod schedules { kind: ScreenSchedule, } impl ScreenScheduleLabel { + #[allow(missing_docs)] pub fn new(kind: ScreenSchedule) -> Self { Self { id: TypeId::of::(), kind, } } + #[allow(missing_docs)] pub fn from_id(kind: ScreenSchedule, id: TypeId) -> Self { Self { id, kind } } @@ -306,6 +332,7 @@ mod system_params { _ghost: PhantomData, } impl<'w, S: Screen> ScreenDataRef<'w, S> { + #[allow(missing_docs)] pub fn data(&self) -> &'w ScreenData { self.data } @@ -373,6 +400,7 @@ mod system_params { let tick = self.change_tick; self.data_mut().finish_unloading(tick); } + #[allow(missing_docs)] pub fn data(&self) -> &ScreenData { self.registry.get(&self.cid).unwrap() } @@ -444,6 +472,8 @@ mod helpers { /// Label of a schedule which fires when the screen has begun to load. #[derive(ScheduleLabel, Debug, PartialEq, Eq, Hash, Clone, Copy)] pub struct OnScreenLoad(pub TypeId); + + /// See [OnScreenLoad] pub fn on_screen_load() -> impl ScheduleLabel { OnScreenLoad(TypeId::of::()) } @@ -451,6 +481,8 @@ mod helpers { /// Label of a schedule which fires when the screen has finished loading. #[derive(ScheduleLabel, Debug, PartialEq, Eq, Hash, Clone, Copy)] pub struct OnScreenReady(pub TypeId); + + /// See [OnScreenReady] pub fn on_screen_ready() -> impl ScheduleLabel { OnScreenReady(TypeId::of::()) } @@ -458,6 +490,8 @@ mod helpers { /// Label of a schedule which fires when the screen is beginning to unload. Not to be confused with [OnScreenUnloaded]. #[derive(ScheduleLabel, Debug, PartialEq, Eq, Hash, Clone, Copy)] pub struct OnScreenUnload(pub TypeId); + + /// See [OnScreenUnload] pub fn on_screen_unload() -> impl ScheduleLabel { OnScreenUnload(TypeId::of::()) } @@ -465,6 +499,8 @@ mod helpers { /// Label of a schedule which fires when the screen has finished unloading and is no longer active. #[derive(ScheduleLabel, Debug, PartialEq, Eq, Hash, Clone, Copy)] pub struct OnScreenUnloaded(pub TypeId); + + /// See [OnScreenUnloaded] pub fn on_screen_unloaded() -> impl ScheduleLabel { OnScreenUnloaded(TypeId::of::()) } diff --git a/crates/screens/src/doc.md b/crates/screens/src/doc.md deleted file mode 100644 index 45a2c2a..0000000 --- a/crates/screens/src/doc.md +++ /dev/null @@ -1,30 +0,0 @@ -# Screens - -The [Screen] trait - -## Screen scoping - -First, let's go over some terminology to make sure we have a clear conceptual -understanding. - -| term | definition | -| ------------- | -------------------------------------------------------------------------------------------------------------------------- | -| Screen | A type of world-state which can help determine behavior. | -| Screen-scoped | This entity will be despawned when the screen changes. | -| Persistent | This entity will _not_ be despawned when the screen changes. | -| Propagate | A propogating component will descend the parent/child hierarchy and clone its inner component onto its recursive children. | -| Top-level | An entity without any parents. | - -By default, all entities are screen-scoped. This means that, whenever the screen -changes, all entities are removed from the world. However, there are some -exceptions to this rule. First, there are a few built-in components that mark -an entity as persistent. They are listed below: - -- [Window] -- [Observer] [^1] - -[^1]: These components are persistent _only if_ they are top-level. - -Second, there is the explicitly-marked [Persistent] component. This component -is designed to make screen-persistent interfaces, such as UI and global -settings. diff --git a/crates/screens/src/lib.rs b/crates/screens/src/lib.rs index af1b890..d7e0d02 100644 --- a/crates/screens/src/lib.rs +++ b/crates/screens/src/lib.rs @@ -1,14 +1,21 @@ +#![doc = include_str!("../README.md")] #![feature(register_tool)] #![register_tool(bevy)] #![allow(bevy::panicking_methods)] -#![doc = include_str!("./doc.md")] +#![deny(missing_docs)] -mod data; +#[allow(unused_imports, reason = "used in docs")] +use prelude::*; +/// Resources, components, states, etc. +pub mod data; mod plugin; -mod scope; +/// The [ScreenScopeBuilder] and friends. +pub mod scope; mod systems; -mod trait_impl; +/// The [Screen] trait. +pub mod trait_impl; +/// The main export. pub mod prelude { pub use super::data::*; pub use super::plugin::*; diff --git a/crates/screens/src/scope.rs b/crates/screens/src/scope.rs index df32aad..172ebfc 100644 --- a/crates/screens/src/scope.rs +++ b/crates/screens/src/scope.rs @@ -2,18 +2,32 @@ pub use crate::prelude::*; use bevy::{ecs::system::ScheduleSystem, platform::collections::HashMap}; use strum::IntoEnumIterator; +#[allow(missing_docs)] pub trait RegisterScreen { /// Registers a [Screen] to the application. fn register_screen(&mut self) -> &mut Self; } impl RegisterScreen for App { fn register_screen(&mut self) -> &mut Self { - S::builder(ScreenScopeBuilder::::new()).build(self); + S::builder(ScreenScopeBuilder::::default()).build(self); self } } -// TODO: DOCUMENT ME +/// The [ScreenScopeBuilder] is the main entrypoint for screen registration. +/// Use it to add scoped systems to your screen. These scoped systems will only run +/// when the screen is in the [ScreenState] analgous to the specified [ScreenSchedule]. +/// +/// When a screen is unloaded, it will clean up all entities marked as non-[Persistent] entities. +/// Entities can be marked as [ScreenScoped] to opt out of persistence. This is primarily useful +/// when propagating entity persistence, using [Propagate(Persistence).](bevy::app::Propagate) +/// +/// Be aware that loading is _disabled by default,_ unless you specify +/// a system to run in [ScreenSchedule::Loading], or you +/// manually specify [Self::with_skip_load]. The same is true for unloading. +/// +/// If you want to allow the screen to run its [Update] schedule while it is in +/// [ScreenState::Loading], set [Self::with_load_strategy] to [LoadStrategy::Nonblocking]. pub struct ScreenScopeBuilder where S: Screen, @@ -54,7 +68,7 @@ where self.skip_unload = Some(val); self } - /// Sets the [LoadingStrategy]. By default, this is Blocking. + /// Sets the [LoadStrategy]. By default, this is Blocking. pub fn with_load_strategy(&mut self, val: LoadStrategy) -> &mut Self { self.load_strategy = val; self diff --git a/crates/screens/src/systems.rs b/crates/screens/src/systems.rs index 9249d8a..2dab051 100644 --- a/crates/screens/src/systems.rs +++ b/crates/screens/src/systems.rs @@ -24,7 +24,7 @@ fn handle_switch_msg( } } /// NOTE: This is registered in scope.rs -pub fn on_switch_screen( +pub(crate) fn on_switch_screen( _trigger: On>, id: ComponentIdFor, mut commands: Commands, @@ -32,10 +32,13 @@ pub fn on_switch_screen( commands.write_message(SwitchToScreenMsg(id.get())); } -pub fn on_finish_loading(_trigger: On>, mut data: ScreenDataMut) { +pub(crate) fn on_finish_loading( + _trigger: On>, + mut data: ScreenDataMut, +) { data.finish_loading(); } -pub fn on_finish_unloading( +pub(crate) fn on_finish_unloading( _trigger: On>, mut data: ScreenDataMut, ) { @@ -132,7 +135,7 @@ fn run_fixed_schedules(registry: ResMut, mut commands: Commands) } } -pub fn initial_screen( +pub(crate) fn initial_screen( mut commands: Commands, initial_screen: Res, registry: Res, @@ -150,7 +153,7 @@ pub fn initial_screen( } } -pub fn plugin(app: &mut App) { +pub(crate) fn plugin(app: &mut App) { app.add_systems(Startup, initial_screen); app.add_systems(PostUpdate, handle_switch_msg); app.add_systems(Update, run_schedules); diff --git a/crates/template/README.md b/crates/template/README.md index 2a7d031..74714fd 100644 --- a/crates/template/README.md +++ b/crates/template/README.md @@ -1,5 +1,5 @@
-Illustration of a tufted titmouse with text, 'tfw - bevy template framework' +Illustration of a tufted titmouse with text, 'tfw - bevy template framework'
This is a template-based template for a bevy project. It is a simplification of the work done for [q_service.](https://github.com/ada-x64/q_service) diff --git a/crates/test_harness/README.md b/crates/test_harness/README.md index cad4a31..87ed36d 100644 --- a/crates/test_harness/README.md +++ b/crates/test_harness/README.md @@ -1,8 +1,8 @@
-Illustration of a common robin with worms in its mouth. Text, 'bevy test harness' +Illustration of a common robin with worms in its mouth. Text, 'bevy test harness'
-[ ![Coveralls](https://img.shields.io/coverallsCoverage/github/ada-x64/qproj?branch=q_test_harness) ]( https://coveralls.io/github/ada-x64/qproj?branch=main ) +[ ![Coveralls](https://img.shields.io/coverallsCoverage/github/ada-x64/qproj?branch=q_test_harness) ]( https://coveralls.io/github/ada-x64/qproj?branch=q_test_harness ) This is a simple test harness for bevy projects.