Newer
Older
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
use proc_macro::TokenStream;
use syn::{parse_macro_input, DeriveInput};
pub(crate) mod fqpath;
pub(crate) mod utils;
pub(crate) mod asset_system;
pub(crate) mod json_loader;
#[cfg(feature = "kayak")]
pub(crate) mod kayak;
pub(crate) mod std_traits;
/// Generate loader and handler implementations for keyed JSON resources. The asset must implement `bevy::asset::Asset`, as well as
/// `serde::Deserialize` and `serde::Serialize`
///
/// Container Attributes:
///
/// - `loader(extension = "")`: *Required* - The file extension associated with this asset
/// - `loader(uuid = "")`: *Required* - The uuid to use for the generated index asset. This _must_ be different to the UUID provided for the asset itself
/// - `loader(storage = qualified::path::to::AssetStorage)`: The qualified path to an asset storage instance. Defaults to `AssetHandles`
/// - `loader(asset_name = my_asset)`: The property of the asset storage used to store the asset. Defaults to the snake case version of the struct name & must be a valid identifier
/// - `loader(index_name = my_asset_index)`: The property of the asset storage used to store an index of the asset types. Defaults to `asset_name`, suffixed with `_index` & must be a valid identifier
///
/// Property Attributes:
///
/// - `loader(asset_id)`: Label a property of the asset as the identifier, to be used as the key on which it will be matched. Must implement [std::fmt::Display].
/// If not present, will be assumed to be a property named "id". If no such property is present, and this attribute is not specified, that is considered an error
///
/// ## Examples
///
/// By default, it is assumed that each resource is keyed by a property named "id", that the
/// storage
///
/// ```rust
/// # use std::collections::HashMap;
/// # use bevy::asset::Handle;
/// # use bevy::prelude::Resource;
/// # use bevy::reflect::{TypePath, TypeUuid};
/// # use serde::{Deserialize, Serialize};
/// # use micro_games_macros::JsonLoader;
///
/// #[derive(Resource)]
/// pub struct AssetHandles {
/// simple_asset: HashMap<String, Handle<SimpleAsset>>,
/// simple_asset_index: HashMap<String, Handle<SimpleAssetIndex>>,
/// }
///
/// #[derive(JsonLoader, TypePath, TypeUuid, Serialize, Deserialize)]
/// #[loader(extension = "satt", uuid = "00000000-0000-0000-0000-000000000000")]
/// #[uuid = "00000000-0000-0000-0000-000000000001"]
/// pub struct SimpleAsset {
/// id: String,
/// widget: usize,
/// }
///
/// fn main() {
/// bevy::app::App::new()
/// .add_plugins(bevy::prelude::DefaultPlugins)
/// .add_plugins(SimpleAssetPlugin);
/// }
/// ```
///
/// Attributes can also be used to customise most of the default assumptions made by this derive:
///
/// ```rust
/// # use std::collections::HashMap;
/// # use bevy::asset::Handle;
/// # use bevy::prelude::Resource;
/// # use bevy::reflect::{TypePath, TypeUuid};
/// # use serde::{Deserialize, Serialize};
/// # use micro_games_macros::JsonLoader;
///
/// #[derive(JsonLoader, TypePath, TypeUuid, Serialize, Deserialize)]
/// #[loader(
/// extension = "asset.json", uuid = "00000000-0000-0000-0000-000000000000",
/// storage = inner_module::SimpleAssetLocator,
/// asset_name = some_asset_prop, index_name = set_of_assets
/// )]
/// #[uuid = "00000000-0000-0000-0000-000000000001"]
/// pub struct MyAsset {
/// /// The asset identifier needs to implement [std::fmt::Display]
/// #[asset_id]
/// uniq_ident: usize,
/// }
///
/// pub mod inner_module {
/// # use bevy::prelude::{Handle, Resource};
/// # use std::collections::HashMap;
///
/// #[derive(Resource)]
/// pub struct SimpleAssetLocator {
/// pub some_asset_prop: HashMap<String, Handle<super::MyAsset>>,
/// pub set_of_assets: HashMap<String, Handle<super::MyAssetIndex>>,
/// }
/// }
///
/// fn main() {
/// bevy::app::App::new()
/// .add_plugins(bevy::prelude::DefaultPlugins)
/// .add_plugins(MyAssetPlugin);
/// }
/// ```
#[proc_macro_derive(JsonLoader, attributes(loader, asset_id))]
pub fn json_loader(input: TokenStream) -> TokenStream {
let input = parse_macro_input!(input as DeriveInput);
json_loader::json_loader(input).into()
}
/// Convert a mapping of name -> Asset type into an asset loading system
///
/// ## Examples
///
/// Convert a struct that represents mappings between names and asset types
/// into an asset system to handle loading, and storing asset handles
///
/// ```rust
/// use bevy::prelude::{Image, Res, Resource};
/// use micro_games_macros::asset_system;
///
/// #[asset_system]
/// pub struct AssetHandles {
/// my_asset: Image,
/// }
///
/// pub fn loading_system(mut loader: AssetHandlesLoader) {
/// loader.load_my_asset("path/to/asset.png", "Asset");
/// }
/// pub fn use_asset_system(assets: Res<AssetHandles>) {
/// let handle = assets.my_asset("Asset");
/// }
/// ```
///
/// Annotate any property with a `skip` attribute to omit it from the resulting loader
///
/// ```rust
/// use bevy::prelude::{Image, TextureAtlas};
/// use micro_games_macros::asset_system;
///
/// #[asset_system]
/// pub struct AssetHandles {
/// image: Image,
/// #[skip]
/// spritesheet: TextureAtlas
/// }
///
/// impl <'w>AssetHandlesLoader<'w> {
/// pub fn load_spritesheet(&mut self, path: String, name: String) {
/// let image_handle = self.load_image(path, name.clone());
/// // let sheet_handle = .. more code ..
/// // self.spritesheet.insert(name, sheet_handle);
/// }
/// }
/// ```
///
/// Include extra properties in the generated loader with one or more `loader_property` attributes.
/// The included property must be a `SystemParam`, and has access to the `'w` lifetime
///
/// ```rust
/// use bevy::prelude::{EventWriter, Event, Image, TextureAtlas, Assets, ResMut, Vec2, Handle};
/// use micro_games_macros::{asset_system, loader_property};
///
/// #[derive(Event)]
/// pub struct LoadingEvent {
/// pub event_id: usize,
/// }
///
/// #[asset_system]
/// #[loader_property(pub load_events: EventWriter<'w, LoadingEvent>)]
/// #[loader_property(pub sheets: ResMut<'w, Assets<TextureAtlas>>)]
/// pub struct AssetHandles {
/// image: Image,
/// #[skip]
/// spritesheet: TextureAtlas
/// }
///
/// impl <'w>AssetHandlesLoader<'w> {
/// pub fn load_spritesheet(&mut self, path: String, name: String) -> Handle<TextureAtlas> {
/// let image_handle = self.load_image(path, name.clone());
/// let sheet = TextureAtlas::new_empty(image_handle, Vec2::ZERO);
/// let sheet_handle = self.sheets.add(sheet);
///
/// self.storage.spritesheet.insert(name.clone(), sheet_handle.clone());
/// self.load_events.send(LoadingEvent { event_id: 123 });
///
/// sheet_handle
/// }
/// }
/// ```
#[proc_macro_attribute]
pub fn asset_system(_: TokenStream, input: TokenStream) -> TokenStream {
let input = parse_macro_input!(input as DeriveInput);
asset_system::asset_system(input).into()
/// Marker attribute, used exclusively by other proc macros
#[proc_macro_attribute]
#[doc(hidden)]
pub fn skip(_: TokenStream, input: TokenStream) -> TokenStream {
input
}
/// Marker attribute, used exclusively by other proc macros
#[proc_macro_attribute]
#[doc(hidden)]
pub fn loader_property(_: TokenStream, input: TokenStream) -> TokenStream {
input
}
#[proc_macro_derive(Widget)]
#[cfg(feature = "kayak")]
pub fn derive_kayak_wigdet(input: TokenStream) -> TokenStream {
let input = parse_macro_input!(input as DeriveInput);
kayak::derive_widget(input).into()
}
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
/// Derive [std::convert::From] for single property tuple or named struct types
///
/// ## Examples
///
/// `FromInner` can derive `From` for single-property tuple structs
///
/// ```rust
/// use micro_games_macros::FromInner;
///
/// #[derive(PartialEq, Eq, Debug, FromInner)]
/// struct MyValue(i32);
///
/// let value = 123i32.into();
///
/// assert_eq!(MyValue(123), value);
/// assert_eq!(MyValue::from(123), value);
/// ```
///
/// As well as single-property named structs
///
///
/// ```rust
/// use micro_games_macros::FromInner;
///
/// #[derive(PartialEq, Eq, Debug, FromInner)]
/// struct MyValue {
/// foo_bar: usize,
/// }
///
/// let value = MyValue::from(2000);
///
/// assert_eq!(value.foo_bar, 2000);
/// assert_eq!(MyValue { foo_bar: 2000 }, value);
/// assert_eq!(MyValue::from(2000), value);
/// ```
#[proc_macro_derive(FromInner)]
pub fn derive_from_inner(input: TokenStream) -> TokenStream {
let input = parse_macro_input!(input as DeriveInput);
std_traits::from_inner::derive(input).into()