implement new() for componentcontainer
This commit is contained in:
parent
e32b76857b
commit
a86e196c42
|
@ -1,5 +1,5 @@
|
|||
[build]
|
||||
target = "wasm32-unknown-unknown"
|
||||
#target = "wasm32-unknown-unknown"
|
||||
|
||||
[target.wasm32-unknown-unknown]
|
||||
rustflags = [
|
||||
|
|
|
@ -275,6 +275,13 @@ dependencies = [
|
|||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ecs"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"thiserror",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ecs_derive"
|
||||
version = "0.1.0"
|
||||
|
@ -292,6 +299,7 @@ dependencies = [
|
|||
name = "ecs_derive_test"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"ecs",
|
||||
"ecs_derive",
|
||||
]
|
||||
|
||||
|
|
|
@ -3,4 +3,5 @@ members = [
|
|||
"ecs",
|
||||
"ecs_derive",
|
||||
"ecs_derive_test",
|
||||
"ecs_wasm4_app",
|
||||
]
|
||||
|
|
|
@ -1,22 +1,12 @@
|
|||
[package]
|
||||
name = "cart"
|
||||
name = "ecs"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[lib]
|
||||
crate-type = ["cdylib"]
|
||||
path = "src/lib.rs"
|
||||
|
||||
[dependencies]
|
||||
buddy-alloc = { version = "0.4.1", optional = true }
|
||||
strum = { version = "0.24", features = ["derive"], default-features = false }
|
||||
enum_dispatch = "0.3.11"
|
||||
ecs_derive = { path = "../ecs_derive" }
|
||||
|
||||
[profile.release]
|
||||
opt-level = "z"
|
||||
lto = true
|
||||
|
||||
[features]
|
||||
# use `--no-default-features` or comment out next line to disable allocator
|
||||
default = ["buddy-alloc"]
|
||||
thiserror = "*"
|
|
@ -1,47 +1,8 @@
|
|||
#![cfg_attr(not(test), no_std)]
|
||||
#[cfg(feature = "buddy-alloc")]
|
||||
mod my_alloc;
|
||||
mod wasm4;
|
||||
use core::panic::PanicInfo;
|
||||
use thiserror::Error;
|
||||
|
||||
#[macro_use]
|
||||
extern crate alloc;
|
||||
#[derive(Debug, Error)]
|
||||
pub enum EcsError {
|
||||
#[error("ecs instantiation error {0}")]
|
||||
InstantiationError(String)
|
||||
|
||||
use wasm4::*;
|
||||
|
||||
mod ecs;
|
||||
|
||||
#[rustfmt::skip]
|
||||
const SMILEY: [u8; 8] = [
|
||||
0b11000011,
|
||||
0b10000001,
|
||||
0b00100100,
|
||||
0b00100100,
|
||||
0b00000000,
|
||||
0b00100100,
|
||||
0b10011001,
|
||||
0b11000011,
|
||||
];
|
||||
|
||||
|
||||
/*
|
||||
todo strum seems to have pulled in std??
|
||||
#[cfg_attr(not(test), panic_handler)]
|
||||
fn panic(info: &PanicInfo) -> ! {
|
||||
trace(format!("{}", info));
|
||||
loop {}
|
||||
} */
|
||||
|
||||
#[no_mangle]
|
||||
fn update() {
|
||||
unsafe { *DRAW_COLORS = 2 }
|
||||
text("Hello from Rust!", 10, 10);
|
||||
|
||||
let gamepad = unsafe { *GAMEPAD1 };
|
||||
if gamepad & BUTTON_1 != 0 {
|
||||
unsafe { *DRAW_COLORS = 4 }
|
||||
}
|
||||
|
||||
blit(&SMILEY, 76, 76, 8, 8, BLIT_1BPP);
|
||||
text("Press X to blink", 16, 90);
|
||||
}
|
||||
}
|
|
@ -1,12 +1,12 @@
|
|||
use std::ops::Range;
|
||||
|
||||
use proc_macro2::Ident;
|
||||
use proc_macro2::{Ident, TokenStream};
|
||||
use quote::{quote_spanned, quote, format_ident};
|
||||
use syn::{ExprRange, Type};
|
||||
|
||||
use crate::parsing::literals::get_bounds_range;
|
||||
|
||||
use super::{ComponentStrategy, ComponentImpl};
|
||||
use super::{ComponentStrategy, ComponentImpl, ComponentImplField};
|
||||
|
||||
use syn::{parse::Parse, Token};
|
||||
|
||||
|
@ -21,6 +21,7 @@ pub struct ContiguousComponent {
|
|||
fn_get_by_id: Ident,
|
||||
field_entity_has_map: Ident,
|
||||
fn_next_free_id: Ident,
|
||||
fn_claim: Ident,
|
||||
|
||||
}
|
||||
|
||||
|
@ -35,9 +36,12 @@ impl Parse for ContiguousComponent {
|
|||
input.parse::<Token![:]>()?;
|
||||
let ty: Type = input.parse()?;
|
||||
|
||||
let fn_get_by_id = format_ident!("get_{}", name);
|
||||
let field_entity_has_map = format_ident!("entity_has_{}", name);
|
||||
let fn_next_free_id = format_ident!("next_free_id_{}", name);
|
||||
let prefix = format!("component_{}_", name);
|
||||
|
||||
let fn_get_by_id = format_ident!("{}get_range", prefix);
|
||||
let field_entity_has_map = format_ident!("{}entity_has", prefix);
|
||||
let fn_next_free_id = format_ident!("{}next_free_id", prefix);
|
||||
let fn_create = format_ident!("{}claim_id", prefix);
|
||||
|
||||
Ok(Self{
|
||||
name,
|
||||
|
@ -49,6 +53,7 @@ impl Parse for ContiguousComponent {
|
|||
fn_get_by_id,
|
||||
field_entity_has_map,
|
||||
fn_next_free_id,
|
||||
fn_claim: fn_create,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
@ -64,6 +69,7 @@ impl ComponentStrategy for ContiguousComponent {
|
|||
field_entity_has_map,
|
||||
fn_get_by_id,
|
||||
fn_next_free_id,
|
||||
fn_claim,
|
||||
|
||||
..} = self;
|
||||
|
||||
|
@ -72,17 +78,32 @@ impl ComponentStrategy for ContiguousComponent {
|
|||
// test hi > lo
|
||||
|
||||
|
||||
imp.struct_items.push(quote! {
|
||||
#name: [#ty; #capacity]
|
||||
imp.struct_fields.push(ComponentImplField {
|
||||
field_name: quote! {
|
||||
#name
|
||||
},
|
||||
field_type: quote! {
|
||||
[#ty; #capacity]
|
||||
},
|
||||
initializer: initialize_fixed_length_array("e!{ #ty::default() }, *capacity),
|
||||
additional_args: vec![]
|
||||
});
|
||||
|
||||
imp.struct_items.push(quote! {
|
||||
#field_entity_has_map: [bool; #capacity]
|
||||
imp.struct_fields.push(ComponentImplField {
|
||||
field_name: quote! {
|
||||
#field_entity_has_map
|
||||
},
|
||||
field_type: quote! {
|
||||
[bool; #capacity]
|
||||
},
|
||||
initializer: initialize_fixed_length_array("e!{ false }, *capacity),
|
||||
additional_args: vec![]
|
||||
});
|
||||
|
||||
imp.struct_impl.push(quote_spanned! {self.kw_span.span=>
|
||||
pub fn #fn_get_by_id(&self, ids: std::ops::Range<usize>) -> Option<&[#ty]> {
|
||||
let count = ids.end - ids.start;
|
||||
// need to test if the requested span is within the range
|
||||
if count > #capacity {
|
||||
return Option::None; // A result instead?
|
||||
}
|
||||
|
@ -99,9 +120,33 @@ impl ComponentStrategy for ContiguousComponent {
|
|||
return Some(#lo + i)
|
||||
}
|
||||
}
|
||||
None
|
||||
}
|
||||
});
|
||||
|
||||
imp.struct_impl.push(quote_spanned! {self.kw_span.span=>
|
||||
fn #fn_claim(&mut self) -> Option<usize> {
|
||||
match self.#fn_next_free_id() {
|
||||
Some(free_id) => {
|
||||
self.#field_entity_has_map[free_id] = true;
|
||||
Some(free_id)
|
||||
},
|
||||
None => None
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
Ok(imp)
|
||||
}
|
||||
}
|
||||
|
||||
fn initialize_fixed_length_array(value: &TokenStream, count: usize) -> TokenStream {
|
||||
let mut values = vec![];
|
||||
for _ in 0..count {
|
||||
values.push(value.clone());
|
||||
}
|
||||
|
||||
quote! {
|
||||
[#(#values),*]
|
||||
}
|
||||
}
|
|
@ -15,10 +15,21 @@ pub trait ComponentStrategy {
|
|||
|
||||
#[derive(Default)]
|
||||
pub struct ComponentImpl{
|
||||
pub struct_items: Vec<TokenStream>,
|
||||
pub struct_fields: Vec<ComponentImplField>,
|
||||
pub struct_impl: Vec<TokenStream>,
|
||||
}
|
||||
|
||||
pub struct ComponentImplField {
|
||||
/// Name of the field.
|
||||
pub field_name: TokenStream,
|
||||
/// Name of the field.
|
||||
pub field_type: TokenStream,
|
||||
/// How to initialize the field. May use `?` to fail initialization and return a Err(EcsError)
|
||||
pub initializer: TokenStream,
|
||||
/// Arguments to add to new()
|
||||
pub additional_args: Vec<TokenStream>,
|
||||
}
|
||||
|
||||
pub mod kw {
|
||||
syn::custom_keyword!(sparse);
|
||||
syn::custom_keyword!(contiguous);
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
use proc_macro2::Ident;
|
||||
use quote::quote_spanned;
|
||||
use quote::{quote_spanned, quote};
|
||||
use syn::{Type, parse::Parse, Token};
|
||||
|
||||
use super::{ComponentStrategy, ComponentImpl};
|
||||
use super::{ComponentStrategy, ComponentImpl, ComponentImplField};
|
||||
|
||||
|
||||
pub struct SparseComponent {
|
||||
|
@ -34,8 +34,17 @@ impl ComponentStrategy for SparseComponent {
|
|||
ty,
|
||||
..
|
||||
} = self;
|
||||
imp.struct_items.push(quote_spanned! {self.kw_span.span=>
|
||||
#name: Vec<#ty>
|
||||
imp.struct_fields.push(ComponentImplField {
|
||||
field_name: quote_spanned! {self.kw_span.span=>
|
||||
#name
|
||||
},
|
||||
field_type: quote_spanned! {self.kw_span.span=>
|
||||
Vec<#ty>
|
||||
},
|
||||
initializer: quote! {
|
||||
vec![]
|
||||
},
|
||||
additional_args: vec![]
|
||||
});
|
||||
Ok(imp)
|
||||
}
|
||||
|
|
|
@ -5,7 +5,7 @@ use syn::{parse::Parse, Token};
|
|||
|
||||
use crate::ComponentImplGenError;
|
||||
|
||||
use self::components::{ComponentStrategy, ComponentImpl, parse_component};
|
||||
use self::components::{ComponentStrategy, ComponentImpl, parse_component, ComponentImplField};
|
||||
use quote::quote;
|
||||
|
||||
pub mod components;
|
||||
|
@ -16,18 +16,52 @@ pub struct ComponentContainer {
|
|||
|
||||
impl ComponentContainer {
|
||||
pub fn codegen(&mut self) -> Result<TokenStream, ComponentImplGenError> {
|
||||
let mut container_struct_items: Vec<TokenStream> = vec![];
|
||||
let mut container_struct_impl: Vec<TokenStream> = vec![];
|
||||
let mut container_struct_field_defs: Vec<TokenStream> = vec![];
|
||||
let mut container_struct_field: Vec<ComponentImplField> = vec![];
|
||||
|
||||
for component in &mut self.components {
|
||||
let ComponentImpl { mut struct_items, mut struct_impl } = component.core()?;
|
||||
container_struct_items.append(&mut struct_items);
|
||||
let ComponentImpl { struct_fields: struct_items, mut struct_impl } = component.core()?;
|
||||
for mut field in struct_items.into_iter() {
|
||||
container_struct_field_defs.push({
|
||||
let name = field.field_name.clone();
|
||||
let ty = field.field_type.clone();
|
||||
quote! {#name: #ty}
|
||||
});
|
||||
container_struct_field.push(field);
|
||||
}
|
||||
container_struct_impl.append(&mut struct_impl);
|
||||
}
|
||||
|
||||
// Build up the impl for new().
|
||||
container_struct_impl.push({
|
||||
let mut container_struct_initialize_args: Vec<TokenStream> = vec![];
|
||||
let let_statements: Vec<TokenStream> = container_struct_field.iter().map(
|
||||
|ComponentImplField {field_name, field_type, initializer, ..}| quote! {
|
||||
let #field_name: #field_type = #initializer;
|
||||
}
|
||||
).collect();
|
||||
|
||||
let field_names: Vec<TokenStream> = container_struct_field.iter().map(
|
||||
|ComponentImplField {field_name, ..}| quote! {
|
||||
#field_name
|
||||
}
|
||||
).collect();
|
||||
|
||||
quote!{
|
||||
pub fn new(#(#container_struct_initialize_args),*) -> Result<ComponentContainer, ecs::EcsError> {
|
||||
#(#let_statements) *
|
||||
|
||||
Ok(ComponentContainer {
|
||||
#(#field_names),*
|
||||
})
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
Ok(quote!{
|
||||
struct ComponentContainer {
|
||||
#(#container_struct_items),*
|
||||
#(#container_struct_field_defs),*
|
||||
}
|
||||
|
||||
impl ComponentContainer {
|
||||
|
|
|
@ -6,4 +6,5 @@ edition = "2021"
|
|||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
||||
ecs = { path = "../ecs" }
|
||||
ecs_derive = { path = "../ecs_derive" }
|
|
@ -1,21 +1,36 @@
|
|||
use ecs_derive::{component_container};
|
||||
|
||||
#[derive(Default)]
|
||||
struct Name(&'static str);
|
||||
|
||||
#[derive(Default)]
|
||||
struct Position {
|
||||
x: u32,
|
||||
y: u32
|
||||
}
|
||||
|
||||
#[derive(Default)]
|
||||
struct Physics {
|
||||
ageia: u32,
|
||||
}
|
||||
|
||||
component_container!{
|
||||
sparse name: Name,
|
||||
sparse title: String,
|
||||
contiguous 0..69 pos: Position,
|
||||
contiguous 8..32 physx: Physics,
|
||||
}
|
||||
|
||||
fn main() {
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use crate::ComponentContainer;
|
||||
|
||||
#[test]
|
||||
fn instantiate() {
|
||||
let mut cc: ComponentContainer = ComponentContainer::new().unwrap();
|
||||
|
||||
}
|
||||
}
|
|
@ -0,0 +1,22 @@
|
|||
[package]
|
||||
name = "cart"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
[lib]
|
||||
crate-type = ["cdylib"]
|
||||
|
||||
[dependencies]
|
||||
buddy-alloc = { version = "0.4.1", optional = true }
|
||||
strum = { version = "0.24", features = ["derive"], default-features = false }
|
||||
enum_dispatch = "0.3.11"
|
||||
ecs_derive = { path = "../ecs_derive" }
|
||||
|
||||
[profile.release]
|
||||
opt-level = "z"
|
||||
lto = true
|
||||
|
||||
[features]
|
||||
# use `--no-default-features` or comment out next line to disable allocator
|
||||
default = ["buddy-alloc"]
|
|
@ -0,0 +1,47 @@
|
|||
#![cfg_attr(not(test), no_std)]
|
||||
#[cfg(feature = "buddy-alloc")]
|
||||
mod my_alloc;
|
||||
mod wasm4;
|
||||
use core::panic::PanicInfo;
|
||||
|
||||
#[macro_use]
|
||||
extern crate alloc;
|
||||
|
||||
use wasm4::*;
|
||||
|
||||
mod ecs;
|
||||
|
||||
#[rustfmt::skip]
|
||||
const SMILEY: [u8; 8] = [
|
||||
0b11000011,
|
||||
0b10000001,
|
||||
0b00100100,
|
||||
0b00100100,
|
||||
0b00000000,
|
||||
0b00100100,
|
||||
0b10011001,
|
||||
0b11000011,
|
||||
];
|
||||
|
||||
|
||||
/*
|
||||
todo strum seems to have pulled in std??
|
||||
#[cfg_attr(not(test), panic_handler)]
|
||||
fn panic(info: &PanicInfo) -> ! {
|
||||
trace(format!("{}", info));
|
||||
loop {}
|
||||
} */
|
||||
|
||||
#[no_mangle]
|
||||
fn update() {
|
||||
unsafe { *DRAW_COLORS = 2 }
|
||||
text("Hello from Rust!", 10, 10);
|
||||
|
||||
let gamepad = unsafe { *GAMEPAD1 };
|
||||
if gamepad & BUTTON_1 != 0 {
|
||||
unsafe { *DRAW_COLORS = 4 }
|
||||
}
|
||||
|
||||
blit(&SMILEY, 76, 76, 8, 8, BLIT_1BPP);
|
||||
text("Press X to blink", 16, 90);
|
||||
}
|
Loading…
Reference in New Issue