Commit 67cef272 authored by Simon Goller's avatar Simon Goller Committed by Rahix

Use custom proc macro for angel system

parent 1aa9b988
......@@ -110,6 +110,7 @@ dependencies = [
"console_error_panic_hook",
"js-sys",
"legion",
"macro-impl",
"nalgebra",
"ncollide2d",
"rand",
......@@ -255,6 +256,15 @@ dependencies = [
"cfg-if 0.1.10",
]
[[package]]
name = "macro-impl"
version = "0.1.0"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "matrixmultiply"
version = "0.2.3"
......
......@@ -20,6 +20,7 @@ ncollide2d = "0.26.1"
console_error_panic_hook = "0.1.6"
anyhow = "1.0"
rand = "0.7.3"
macro-impl = {path = "macro-impl"}
[dependencies.legion]
version = "0.3.1"
......
[package]
name = "macro-impl"
version = "0.1.0"
authors = ["Simon Goller <neosam+github@posteo.de>"]
edition = "2018"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[lib]
proc-macro = true
[dependencies]
syn = {version="1.0", features = ["full"] }
quote = "1.0"
proc-macro2 = "1.0"
\ No newline at end of file
extern crate proc_macro;
use std::str::FromStr;
use proc_macro::TokenStream;
use quote::{ToTokens};
use syn::{ReturnType, parse_macro_input};
fn wrap_function(token_stream: TokenStream, attr: TokenStream) -> TokenStream {
let mut function = parse_macro_input!(token_stream as syn::ItemFn);
let output = function.sig.output;
function.sig.output = ReturnType::Default;
//let prepend = format!("match || {} {{ ", output.to_token_stream().to_string());
//let append = "}() { Ok(_) => {}, Err(err) => println!(\"{}\", err), }";
let prepend = format!("crate::error::handle_system_result(|| {} {{ ", output.to_token_stream().to_string());
let append = "})";
let mut function_block_str = function.block.to_token_stream().to_string();
function_block_str.insert_str(1, &prepend);
function_block_str.insert_str(function_block_str.len() - 2, append);
println!("{}", function_block_str);
let function_block_token_stream = TokenStream::from_str(&function_block_str).unwrap();
let function_block = parse_macro_input!(function_block_token_stream as syn::Block);
function.block = Box::new(function_block);
let attr_str: String = attr.to_string();
let legion_system_str = if attr_str.is_empty() {
"#[legion::system]".to_string()
} else {
format!("#[legion::system({})]", attr_str)
};
let new_function_string = format!("{} {}", legion_system_str, function.to_token_stream().to_string());
println!("{}", new_function_string);
TokenStream::from_str(&new_function_string).unwrap()
}
#[proc_macro_attribute]
pub fn angel_system(attr: TokenStream, item: TokenStream) -> TokenStream {
println!("attr: \"{}\"", attr.to_string());
println!("item: \"{}\"", item.to_string());
wrap_function(item, attr)
}
......@@ -92,7 +92,7 @@ impl BottleAngelState {
}
}
#[legion::system]
#[macro_impl::angel_system]
#[read_component(colliders::Collider)]
#[read_component(components::Matebottledrop)]
#[write_component(components::Sprite)]
......@@ -135,7 +135,7 @@ pub fn collect_bottledrops(
Ok(())
}
#[legion::system]
#[macro_impl::angel_system]
#[write_component(components::Player)]
pub fn update_bottle_shift(
#[state] hours_to_award: &mut usize,
......
......@@ -90,7 +90,7 @@ impl super::AngelShiftImpl for NetworkSwitchShift {
}
}
#[legion::system]
#[macro_impl::angel_system]
#[read_component(colliders::Collider)]
#[read_component(components::NetworkSwitch)]
#[write_component(components::Sprite)]
......@@ -136,7 +136,7 @@ pub fn reconnect_switches(
Ok(())
}
#[legion::system]
#[macro_impl::angel_system]
#[write_component(components::Player)]
pub fn update_network_switch_shift(
#[state] hours_to_award: &mut usize,
......
......@@ -14,7 +14,7 @@ impl Edge {
}
}
#[legion::system]
#[macro_impl::angel_system]
#[read_component(Edge)]
#[read_component(components::Position)]
pub fn draw_edges(
......
......@@ -46,13 +46,14 @@ pub fn update_nodes(node: &mut Node, #[resource] clock: &resources::Clock) {
}
}
#[legion::system(for_each)]
//#[legion::system(for_each)]
#[macro_impl::angel_system(for_each)]
pub fn draw_nodes(
node: &Node,
pos: &components::Position,
#[resource] rendering: &mut resources::Rendering,
#[resource] clock: &resources::Clock,
) {
) -> anyhow::Result<()> {
// TODO: Replace by proper API
rendering.begin_path();
rendering.set_fill_style(&colors::BACKGROUND);
......@@ -62,7 +63,7 @@ pub fn draw_nodes(
10.0,
0.0,
std::f64::consts::TAU,
);
)?;
rendering.fill();
rendering.begin_path();
......@@ -74,7 +75,7 @@ pub fn draw_nodes(
10.0,
0.0,
std::f64::consts::TAU,
);
)?;
rendering.stroke();
let time = clock.wall_time();
......@@ -88,7 +89,7 @@ pub fn draw_nodes(
18.0,
0.0,
std::f64::consts::TAU * amount_completed,
);
)?;
rendering.stroke();
}
......@@ -106,7 +107,8 @@ pub fn draw_nodes(
radius,
0.0,
std::f64::consts::TAU,
);
)?;
rendering.stroke();
}
Ok(())
}
......@@ -4,13 +4,13 @@ use crate::resources;
pub struct TheSun;
#[legion::system(for_each)]
#[macro_impl::angel_system(for_each)]
pub fn draw_thesun(
_: &TheSun,
pos: &components::Position,
#[resource] rendering: &mut resources::Rendering,
#[resource] clock: &resources::Clock,
) {
) -> anyhow::Result<()> {
// TODO: Replace by proper API
rendering.begin_path();
rendering.set_fill_style(&colors::PRIMARY1_SHADE1);
......@@ -20,7 +20,7 @@ pub fn draw_thesun(
30.0,
0.0,
std::f64::consts::TAU,
);
)?;
rendering.fill();
let now = clock.wall_time();
......@@ -34,7 +34,7 @@ pub fn draw_thesun(
40.0,
0.0 + now,
0.4 * std::f64::consts::TAU + now,
);
)?;
rendering.stroke();
rendering.begin_path();
......@@ -45,6 +45,7 @@ pub fn draw_thesun(
55.0,
4.0 - now,
4.0 + 0.66 * std::f64::consts::TAU - now,
);
)?;
rendering.stroke();
Ok(())
}
......@@ -29,3 +29,10 @@ impl<T> AnyhowWebExt<T> for Result<T, web_sys::Element> {
})
}
}
pub fn handle_system_result<F>(mut f: F)
where F: FnMut() -> anyhow::Result<()> {
if let Err(_) = f() {
panic!();
}
}
......@@ -20,8 +20,8 @@ impl gamestate::State for GameOverState {
&mut self,
mut init: gamestate::StateInitializer,
) -> anyhow::Result<gamestate::Transition> {
init.register_onclick("game-over-replay");
init.register_onclick("game-over-quit");
init.register_onclick("game-over-replay")?;
init.register_onclick("game-over-quit")?;
self.gui_svg
.style()
.set_property("display", "block")
......
......@@ -73,7 +73,7 @@ impl gamestate::State for HeavenState {
&mut self,
mut init: gamestate::StateInitializer,
) -> anyhow::Result<gamestate::Transition> {
init.register_onclick("heaven-start-shift");
init.register_onclick("heaven-start-shift")?;
self.gui_svg
.style()
.set_property("display", "block")
......
......@@ -58,7 +58,7 @@ impl InGameState {
.add_thread_local(systems::move_movable_system())
.flush();
assigned_shift.init_gameworld(&mut world, &mut resources, &mut schedule_builder, &level);
assigned_shift.init_gameworld(&mut world, &mut resources, &mut schedule_builder, &level)?;
schedule_builder
.flush()
......@@ -110,7 +110,7 @@ impl gamestate::State for InGameState {
rendering.deregister_image(image);
}
rendering.set_transform(1.0, 0.0, 0.0, 1.0, 0.0, 0.0);
rendering.set_transform(1.0, 0.0, 0.0, 1.0, 0.0, 0.0)?;
self.gui_svg
.style()
.set_property("display", "none")
......@@ -184,7 +184,7 @@ impl gamestate::State for InGameState {
.resources
.get::<resources::Rendering>()
.context("Resource 'Rendering' could not be found")?;
rendering.set_transform(1.0, 0.0, 0.0, 1.0, 0.0, 0.0);
rendering.set_transform(1.0, 0.0, 0.0, 1.0, 0.0, 0.0)?;
rendering.set_fill_style(&colors::BACKGROUND);
rendering.fill_rect(0.0, 0.0, 1920.0, 1080.0);
}
......
......@@ -70,7 +70,7 @@ impl gamestate::State for LevelLoadingState {
handle.do_transition(gamestate::Transition::replace(
states::InGameState::new(level, rendering, player.clone(), assigned_shift).unwrap(),
)); // ignore-unwrap - Inside a closure
)).unwrap(); // ignore-unwrap - Inside a closure
});
Ok(gamestate::Transition::Loop)
}
......
......@@ -20,7 +20,7 @@ impl gamestate::State for MainMenuState {
&mut self,
mut init: gamestate::StateInitializer,
) -> anyhow::Result<gamestate::Transition> {
init.register_onclick("main-menu-play");
init.register_onclick("main-menu-play")?;
self.gui_svg
.style()
.set_property("display", "block")
......
use crate::resources;
#[legion::system]
#[macro_impl::angel_system]
pub fn camera(
#[resource] rendering: &resources::Rendering,
#[resource] camera: &resources::Camera,
......
......@@ -11,7 +11,7 @@ const DEBUG_COLLIDER_COLOR: resources::Color = resources::Color {
alpha: 0.5,
};
#[legion::system(for_each)]
#[macro_impl::angel_system(for_each)]
pub fn draw_debug_colliders(
position: &components::Position,
collider: &colliders::Collider,
......
......@@ -3,7 +3,7 @@ use crate::utils;
use crate::error::AnyhowWebExt;
#[legion::system]
#[macro_impl::angel_system]
pub fn update_game_manager(
#[resource] clock: &resources::Clock,
#[resource] game_manager: &mut resources::GameManager,
......
......@@ -5,7 +5,7 @@ use legion::IntoQuery;
use anyhow::Context;
#[legion::system]
#[macro_impl::angel_system]
#[read_component(components::Position)]
pub fn move_camera_to_player(
world: &legion::world::SubWorld,
......@@ -21,7 +21,7 @@ pub fn move_camera_to_player(
Ok(())
}
#[legion::system(for_each)]
#[macro_impl::angel_system(for_each)]
pub fn move_movable(
position: &mut components::Position,
movable: &mut components::Movable,
......
......@@ -14,7 +14,7 @@ pub fn sanity_goes_up_and_down(
player.sanity = (clock.wall_time() as f32).sin() * 0.5 + 0.5;
}
#[legion::system]
#[macro_impl::angel_system]
#[read_component(components::Player)]
pub fn update_sanity_bar(
world: &legion::world::SubWorld,
......@@ -30,7 +30,7 @@ pub fn update_sanity_bar(
Ok(())
}
#[legion::system]
#[macro_impl::angel_system]
#[write_component(components::Player)]
pub fn player_sanity_check(
world: &mut legion::world::SubWorld,
......
......@@ -2,7 +2,7 @@ use crate::components;
use crate::resources;
use anyhow::Context;
#[legion::system(for_each)]
#[macro_impl::angel_system(for_each)]
#[read_component(components::Position)]
#[read_component(components::Sprite)]
pub fn draw_sprites(
......
......@@ -19,7 +19,7 @@ pub fn draw_tmp_stationary_obstacles_barrier(
rendering.fill();
}
#[legion::system]
#[macro_impl::angel_system]
#[read_component(colliders::Collider)]
#[read_component(components::ObstacleInsanity)]
#[write_component(components::Player)]
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment