Skip to content

Commit

Permalink
feat: asset key macro
Browse files Browse the repository at this point in the history
  • Loading branch information
eerii committed Jul 25, 2024
1 parent 0d926c8 commit 60449a0
Show file tree
Hide file tree
Showing 6 changed files with 66 additions and 50 deletions.
55 changes: 54 additions & 1 deletion macros/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ use darling::{ast::NestedMeta, FromMeta};
use proc_macro as pm;
use proc_macro2::TokenStream;
use quote::quote;
use syn::{parse2, DeriveInput};
use syn::{parse2, Data, DeriveInput, Meta};

const DATA_PATH: &str = ".data";

Expand Down Expand Up @@ -33,6 +33,7 @@ pub fn persistent(args: pm::TokenStream, input: pm::TokenStream) -> pm::TokenStr
let path = format!("{}/{}.toml", DATA_PATH, args.name);
let name = ident.to_string();

// TODO: Propperly handle errors
let output = quote! {
#[derive(Resource, Serialize, Deserialize)]
#input
Expand Down Expand Up @@ -70,3 +71,55 @@ pub fn persistent(args: pm::TokenStream, input: pm::TokenStream) -> pm::TokenStr
};
output.into()
}

#[proc_macro_derive(AssetAttr, attributes(asset))]
pub fn derive_asset_attr(_item: pm::TokenStream) -> pm::TokenStream {
pm::TokenStream::new()
}

#[proc_macro_attribute]
pub fn asset_key(args: pm::TokenStream, input: pm::TokenStream) -> pm::TokenStream {
let input: TokenStream = input.into();
let DeriveInput { ident, data, .. } = parse2(input.clone()).unwrap();

let Data::Enum(data) = data else {
panic!("An asset key must be an Enum");
};

let names: Vec<_> = data
.variants
.iter()
.map(|v| {
// TODO: Check that the value path is "asset" and allow multiple attrs
let name = v.ident.clone();
let attr = v
.attrs
.get(0)
.expect("Each asset must provide a path attribute");
let Meta::NameValue(value) = attr.meta.clone() else {
panic!("The asset attribute must be in the form #[asset = \"path\"]");
};
let asset_path = value.value;
quote!((#ident::#name, asset_server.load(#asset_path)))
})
.collect();

let args: TokenStream = args.into();

let output = quote! {
#[derive(Copy, Clone, Eq, PartialEq, Hash, Reflect, macros::AssetAttr)]
#input

impl AssetKey for #ident {
type Asset = #args;
}

impl FromWorld for AssetMap<#ident> {
fn from_world(world: &mut World) -> Self {
let asset_server = world.resource::<AssetServer>();
[#(#names),*].into()
}
}
};
output.into()
}
15 changes: 3 additions & 12 deletions src/assets/fonts.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
use bevy::prelude::*;
use macros::asset_key;

use crate::prelude::*;

Expand All @@ -9,18 +10,8 @@ pub(super) fn plugin(app: &mut App) {

/// Defines all of the font assets
/// Easy to access on any system using `Res<AssetMap<FontAssetKey>>`
#[derive(Copy, Clone, Eq, PartialEq, Hash, Reflect)]
#[asset_key(Font)]
pub enum FontAssetKey {
#[asset = "fonts/sans.ttf"]
Main,
}

impl AssetKey for FontAssetKey {
type Asset = Font;
}

impl FromWorld for AssetMap<FontAssetKey> {
fn from_world(world: &mut World) -> Self {
let asset_server = world.resource::<AssetServer>();
[(FontAssetKey::Main, asset_server.load("fonts/sans.ttf"))].into()
}
}
15 changes: 3 additions & 12 deletions src/assets/meta.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
use bevy::prelude::*;
use macros::asset_key;

use crate::prelude::*;

Expand All @@ -9,18 +10,8 @@ pub(super) fn plugin(app: &mut App) {

/// Defines all of the meta assets
/// Easy to access on any system using `Res<AssetMap<MetaAssetKey>>`
#[derive(Copy, Clone, Eq, PartialEq, Hash, Reflect)]
#[asset_key(Image)]
pub enum MetaAssetKey {
#[asset = "meta/bevy.png"]
BevyLogo,
}

impl AssetKey for MetaAssetKey {
type Asset = Image;
}

impl FromWorld for AssetMap<MetaAssetKey> {
fn from_world(world: &mut World) -> Self {
let asset_server = world.resource::<AssetServer>();
[(MetaAssetKey::BevyLogo, asset_server.load("meta/bevy.png"))].into()
}
}
15 changes: 3 additions & 12 deletions src/assets/music.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
use bevy::prelude::*;
use macros::asset_key;

use crate::prelude::*;

Expand All @@ -9,18 +10,8 @@ pub(super) fn plugin(app: &mut App) {

/// Defines all of the musical assets
/// Easy to access on any system using `Res<AssetMap<MusicAssetKey>>`
#[derive(Copy, Clone, Eq, PartialEq, Hash, Reflect)]
#[asset_key(AudioSource)]
pub enum MusicAssetKey {
#[asset = "music/rain.ogg"]
Ambient,
}

impl AssetKey for MusicAssetKey {
type Asset = AudioSource;
}

impl FromWorld for AssetMap<MusicAssetKey> {
fn from_world(world: &mut World) -> Self {
let asset_server = world.resource::<AssetServer>();
[(MusicAssetKey::Ambient, asset_server.load("music/rain.ogg"))].into()
}
}
15 changes: 3 additions & 12 deletions src/assets/sound.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
use bevy::prelude::*;
use macros::asset_key;

use crate::prelude::*;

Expand All @@ -9,18 +10,8 @@ pub(super) fn plugin(app: &mut App) {

/// Defines all of the sound effects
/// Easy to access on any system using `Res<AssetMap<SoundAssetKey>>`
#[derive(Copy, Clone, Eq, PartialEq, Hash, Reflect)]
#[asset_key(AudioSource)]
pub enum SoundAssetKey {
#[asset = "sound/boing.ogg"]
Boing,
}

impl AssetKey for SoundAssetKey {
type Asset = AudioSource;
}

impl FromWorld for AssetMap<SoundAssetKey> {
fn from_world(world: &mut World) -> Self {
let asset_server = world.resource::<AssetServer>();
[(SoundAssetKey::Boing, asset_server.load("sound/boing.ogg"))].into()
}
}
1 change: 0 additions & 1 deletion src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@

// TODO: Documentation and code examples
// Readme
// TODO: Also use derive macros for assets
// TODO: UI Widgets
// Main menu
// UI Navigation with input (custom implementation)
Expand Down

0 comments on commit 60449a0

Please sign in to comment.