Skip to content
Snippets Groups Projects
Verified Commit 50225742 authored by Louis's avatar Louis :fire:
Browse files

Add more thorough example to rustdoc

parent 4011b693
No related branches found
No related tags found
No related merge requests found
# Micro Game Macros # Micro Game Macros
![docs.rs](https://img.shields.io/docsrs/micro_game_macros?style=for-the-badge) [![docs.rs](https://img.shields.io/docsrs/micro_games_macros?style=for-the-badge)](https://docs.rs/micro_games_macros)
![Crates.io](https://img.shields.io/crates/v/micro_game_macros?style=for-the-badge) [![Crates.io](https://img.shields.io/crates/v/micro_games_macros?style=for-the-badge)](https://crates.io/crates/micro_games_macros)
A collection of utility macros for building games A collection of utility macros for building games
......
hard_tabs = true
use_field_init_shorthand = true
use_try_shorthand = true
//! A collection of complimentary utility macros for building games
//!
//! Use the [asset_system] macro to create a set of types that manage loading assets, and then
//! derive [JsonLoader] for any asset type to create a flexible resource loader that links in
//! to the generated asset system
//!
//! ```rust
//! use bevy::prelude::{App, DefaultPlugins, Image, Plugin, Res, ResMut, Resource, Assets, TextureAtlas};
//! use bevy::reflect::{TypePath, TypeUuid};
//! use micro_games_macros::{asset_system, JsonLoader};
//! use serde::{Deserialize, Serialize};
//!
//! // We can customise the properties on the "asset loader" type that the
//! // macro generates by adding "loader_property" annotations. The parameter
//! // to this macro is simple any property declaration that could be added to
//! // a regular type that derives SystemParam (including lifetimes)
//!
//! #[asset_system]
//! #[loader_property(pub sheets: ResMut<'w, Assets<TextureAtlas>>)]
//! pub struct AssetHandles {
//! // For non-JsonLoader assets, you just need to specify a name -> AssetType property.
//! // The generated asset handles type will contain a hashmap of name -> Handle<AssetType>
//! // under the property name specified. Loading functions such as load_asset_name will
//! // be created on the loading type, where the first parameter is the path and the second
//! // parameter is the asset name that will be used in the hashmap for later retrieval of
//! // the asset
//! images: Image,
//! // To use an asset_system with a JsonLoader, you will need to add entries for both the
//! // asset itself and its index type (generated by JsonLoader). Specific instances of
//! // an asset are stored under the Item type (no suffix), keyed in the handle map by their
//! // ID property. The index generated from each file (a map of ID -> Item) is stored under
//! // the Index type (type name: AssetName + Index), keyed by the name provided when loading
//! // the asset
//! some_resource: MyCoolResource,
//! // The property names generate load functions, but don't have to match the name of the
//! // resource being loaded. Index & Item types for a JsonLoader resource can have their
//! // names specified as part of the JsonLoader derive
//! some_index_of_resources: MyCoolResourceIndex,
//! }
//!
//! #[derive(JsonLoader, TypePath, TypeUuid, Serialize, Deserialize)]
//! #[loader(extension = "mcr", uuid = "00000000-0000-0000-0000-000000000000",
//! asset_name = some_resource, index_name = some_index_of_resources)]
//! #[uuid = "10000000-0000-0000-0000-000000000001"]
//! pub struct MyCoolResource {
//! // You must include exactly one of either a property named "id", or another property annotated
//! // with the "asset_id" attribute.
//! #[asset_id]
//! some_identifier: String,
//! foo: usize,
//! bar: bool,
//! }
//!
//! // The asset system generates a system param for scheduling the load of an asset. It uses bevy's
//! // asset server, which makes the system compatible with plugins such as bevy_embedded_assets
//! pub fn loading_system(mut loader: AssetHandlesLoader) {
//! // The loader contains a number of functions for loading either individual assets
//! // (two parameters, path and id), or a series of assets (a single parameter, a vector
//! // of tuples each denoting path and id)
//! loader.load_images("path/to/my_image.png", "my_image");
//!
//! // JsonLoader assets require the use of the Index type to correctly load them, even for
//! // files that only contain one object instance. The identifier (either id or asset_id)
//! // will be used to add each instance of an asset to the Item type map
//! loader.load_some_index_of_resources("path/to/my_asset.mcr", "my_asset");
//! }
//!
//! pub fn use_asset_system(assets: Res<AssetHandles>) {
//! // JsonLoader assets can be accessed through the item type functions. These functions
//! // provide a weak handle to the asset, meaning that the assets will usually unload
//! // if removed from the AssetHandles type unless another strong handle was created externally
//! let some_resource_handle = assets.some_resource("the_asset_id");
//!
//! // The handle functions exactly match the name of the asset property in the originally
//! // defined struct
//! let image_handle = assets.images("my_image");
//! }
//!
//! pub struct AssetSystemPlugin;
//! impl Plugin for AssetSystemPlugin {
//! fn build(&self, app: &mut App) {
//! app.init_resource::<AssetHandles>()
//! // JsonLoader will create a plugin that wraps all of the functionality for a single
//! // asset type, including loaders and hot reload support
//! .add_plugins(MyCoolResourcePlugin);
//! }
//! }
//!
//! fn main() {
//! let app = App::new()
//! .add_plugins((DefaultPlugins, AssetSystemPlugin));
//! }
//! ```
use proc_macro::TokenStream; use proc_macro::TokenStream;
use syn::{parse_macro_input, DeriveInput}; use syn::{parse_macro_input, DeriveInput};
...@@ -42,22 +136,22 @@ pub(crate) mod std_traits; ...@@ -42,22 +136,22 @@ pub(crate) mod std_traits;
/// ///
/// #[derive(Resource)] /// #[derive(Resource)]
/// pub struct AssetHandles { /// pub struct AssetHandles {
/// simple_asset: HashMap<String, Handle<SimpleAsset>>, /// simple_asset: HashMap<String, Handle<SimpleAsset>>,
/// simple_asset_index: HashMap<String, Handle<SimpleAssetIndex>>, /// simple_asset_index: HashMap<String, Handle<SimpleAssetIndex>>,
/// } /// }
/// ///
/// #[derive(JsonLoader, TypePath, TypeUuid, Serialize, Deserialize)] /// #[derive(JsonLoader, TypePath, TypeUuid, Serialize, Deserialize)]
/// #[loader(extension = "satt", uuid = "00000000-0000-0000-0000-000000000000")] /// #[loader(extension = "satt", uuid = "00000000-0000-0000-0000-000000000000")]
/// #[uuid = "00000000-0000-0000-0000-000000000001"] /// #[uuid = "00000000-0000-0000-0000-000000000001"]
/// pub struct SimpleAsset { /// pub struct SimpleAsset {
/// id: String, /// id: String,
/// widget: usize, /// widget: usize,
/// } /// }
/// ///
/// fn main() { /// fn main() {
/// bevy::app::App::new() /// bevy::app::App::new()
/// .add_plugins(bevy::prelude::DefaultPlugins) /// .add_plugins(bevy::prelude::DefaultPlugins)
/// .add_plugins(SimpleAssetPlugin); /// .add_plugins(SimpleAssetPlugin);
/// } /// }
/// ``` /// ```
/// ///
...@@ -79,26 +173,26 @@ pub(crate) mod std_traits; ...@@ -79,26 +173,26 @@ pub(crate) mod std_traits;
/// )] /// )]
/// #[uuid = "00000000-0000-0000-0000-000000000001"] /// #[uuid = "00000000-0000-0000-0000-000000000001"]
/// pub struct MyAsset { /// pub struct MyAsset {
/// /// The asset identifier needs to implement [std::fmt::Display] /// /// The asset identifier needs to implement [std::fmt::Display]
/// #[asset_id] /// #[asset_id]
/// uniq_ident: usize, /// uniq_ident: usize,
/// } /// }
/// ///
/// pub mod inner_module { /// pub mod inner_module {
/// # use bevy::prelude::{Handle, Resource}; /// # use bevy::prelude::{Handle, Resource};
/// # use std::collections::HashMap; /// # use std::collections::HashMap;
/// ///
/// #[derive(Resource)] /// #[derive(Resource)]
/// pub struct SimpleAssetLocator { /// pub struct SimpleAssetLocator {
/// pub some_asset_prop: HashMap<String, Handle<super::MyAsset>>, /// pub some_asset_prop: HashMap<String, Handle<super::MyAsset>>,
/// pub set_of_assets: HashMap<String, Handle<super::MyAssetIndex>>, /// pub set_of_assets: HashMap<String, Handle<super::MyAssetIndex>>,
/// } /// }
/// } /// }
/// ///
/// fn main() { /// fn main() {
/// bevy::app::App::new() /// bevy::app::App::new()
/// .add_plugins(bevy::prelude::DefaultPlugins) /// .add_plugins(bevy::prelude::DefaultPlugins)
/// .add_plugins(MyAssetPlugin); /// .add_plugins(MyAssetPlugin);
/// } /// }
/// ``` /// ```
#[proc_macro_derive(JsonLoader, attributes(loader, asset_id))] #[proc_macro_derive(JsonLoader, attributes(loader, asset_id))]
...@@ -120,14 +214,14 @@ pub fn json_loader(input: TokenStream) -> TokenStream { ...@@ -120,14 +214,14 @@ pub fn json_loader(input: TokenStream) -> TokenStream {
/// ///
/// #[asset_system] /// #[asset_system]
/// pub struct AssetHandles { /// pub struct AssetHandles {
/// my_asset: Image, /// my_asset: Image,
/// } /// }
/// ///
/// pub fn loading_system(mut loader: AssetHandlesLoader) { /// pub fn loading_system(mut loader: AssetHandlesLoader) {
/// loader.load_my_asset("path/to/asset.png", "Asset"); /// loader.load_my_asset("path/to/asset.png", "Asset");
/// } /// }
/// pub fn use_asset_system(assets: Res<AssetHandles>) { /// pub fn use_asset_system(assets: Res<AssetHandles>) {
/// let handle = assets.my_asset("Asset"); /// let handle = assets.my_asset("Asset");
/// } /// }
/// ``` /// ```
/// ///
...@@ -139,17 +233,17 @@ pub fn json_loader(input: TokenStream) -> TokenStream { ...@@ -139,17 +233,17 @@ pub fn json_loader(input: TokenStream) -> TokenStream {
/// ///
/// #[asset_system] /// #[asset_system]
/// pub struct AssetHandles { /// pub struct AssetHandles {
/// image: Image, /// image: Image,
/// #[skip] /// #[skip]
/// spritesheet: TextureAtlas /// spritesheet: TextureAtlas,
/// } /// }
/// ///
/// impl <'w>AssetHandlesLoader<'w> { /// impl<'w> AssetHandlesLoader<'w> {
/// pub fn load_spritesheet(&mut self, path: String, name: String) { /// pub fn load_spritesheet(&mut self, path: String, name: String) {
/// let image_handle = self.load_image(path, name.clone()); /// let image_handle = self.load_image(path, name.clone());
/// // let sheet_handle = .. more code .. /// // let sheet_handle = .. more code ..
/// // self.spritesheet.insert(name, sheet_handle); /// // self.spritesheet.insert(name, sheet_handle);
/// } /// }
/// } /// }
/// ``` /// ```
/// ///
...@@ -157,34 +251,36 @@ pub fn json_loader(input: TokenStream) -> TokenStream { ...@@ -157,34 +251,36 @@ pub fn json_loader(input: TokenStream) -> TokenStream {
/// The included property must be a `SystemParam`, and has access to the `'w` lifetime /// The included property must be a `SystemParam`, and has access to the `'w` lifetime
/// ///
/// ```rust /// ```rust
/// use bevy::prelude::{EventWriter, Event, Image, TextureAtlas, Assets, ResMut, Vec2, Handle}; /// use bevy::prelude::{Assets, Event, EventWriter, Handle, Image, ResMut, TextureAtlas, Vec2};
/// use micro_games_macros::{asset_system, loader_property}; /// use micro_games_macros::{asset_system, loader_property};
/// ///
/// #[derive(Event)] /// #[derive(Event)]
/// pub struct LoadingEvent { /// pub struct LoadingEvent {
/// pub event_id: usize, /// pub event_id: usize,
/// } /// }
/// ///
/// #[asset_system] /// #[asset_system]
/// #[loader_property(pub load_events: EventWriter<'w, LoadingEvent>)] /// #[loader_property(pub load_events: EventWriter<'w, LoadingEvent>)]
/// #[loader_property(pub sheets: ResMut<'w, Assets<TextureAtlas>>)] /// #[loader_property(pub sheets: ResMut<'w, Assets<TextureAtlas>>)]
/// pub struct AssetHandles { /// pub struct AssetHandles {
/// image: Image, /// image: Image,
/// #[skip] /// #[skip]
/// spritesheet: TextureAtlas /// spritesheet: TextureAtlas,
/// } /// }
/// ///
/// impl <'w>AssetHandlesLoader<'w> { /// impl<'w> AssetHandlesLoader<'w> {
/// pub fn load_spritesheet(&mut self, path: String, name: String) -> Handle<TextureAtlas> { /// pub fn load_spritesheet(&mut self, path: String, name: String) -> Handle<TextureAtlas> {
/// let image_handle = self.load_image(path, name.clone()); /// let image_handle = self.load_image(path, name.clone());
/// let sheet = TextureAtlas::new_empty(image_handle, Vec2::ZERO); /// let sheet = TextureAtlas::new_empty(image_handle, Vec2::ZERO);
/// let sheet_handle = self.sheets.add(sheet); /// let sheet_handle = self.sheets.add(sheet);
/// ///
/// self.storage.spritesheet.insert(name.clone(), sheet_handle.clone()); /// self.storage
/// self.load_events.send(LoadingEvent { event_id: 123 }); /// .spritesheet
/// /// .insert(name.clone(), sheet_handle.clone());
/// sheet_handle /// self.load_events.send(LoadingEvent { event_id: 123 });
/// } ///
/// sheet_handle
/// }
/// } /// }
/// ``` /// ```
#[proc_macro_attribute] #[proc_macro_attribute]
...@@ -240,7 +336,7 @@ pub fn derive_kayak_wigdet(input: TokenStream) -> TokenStream { ...@@ -240,7 +336,7 @@ pub fn derive_kayak_wigdet(input: TokenStream) -> TokenStream {
/// ///
/// #[derive(PartialEq, Eq, Debug, FromInner)] /// #[derive(PartialEq, Eq, Debug, FromInner)]
/// struct MyValue { /// struct MyValue {
/// foo_bar: usize, /// foo_bar: usize,
/// } /// }
/// ///
/// let value = MyValue::from(2000); /// let value = MyValue::from(2000);
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment