Closed konceptosociala closed 1 year ago
There's no built in mechanism for that, since there's no graceful way to dynamically check for trait implementations on an arbitrary type in Rust. I recommend solving it at the application layer. You could e.g. use a declarative macro to reduce boilerplate if desired.
#[macro_export]
macro_rules! world_serializer {
($ctx:ident, $($comp:ty),*) => {
impl SerializeContext for $ctx {
fn component_count(&self, archetype: &Archetype) -> usize {
archetype.component_types()
.filter(|&t|
$(
t == std::any::TypeId::of::<$comp>() ||
)*
false
)
.count()
}
fn serialize_component_ids<S: serde::ser::SerializeTuple>(
&mut self,
archetype: &Archetype,
mut out: S,
) -> Result<S::Ok, S::Error> {
$(
try_serialize_id::<$comp, _, _>(archetype, stringify!($comp), &mut out)?;
)*
out.end()
}
fn serialize_components<S: serde::ser::SerializeTuple>(
&mut self,
archetype: &Archetype,
mut out: S,
) -> Result<S::Ok, S::Error> {
$(
try_serialize::<$comp, _>(archetype, &mut out)?;
)*
out.end()
}
}
impl DeserializeContext for $ctx {
fn deserialize_component_ids<'de, A: serde::de::SeqAccess<'de>>(
&mut self,
mut seq: A,
) -> Result<ColumnBatchType, A::Error> {
self.components.clear();
let mut batch = ColumnBatchType::new();
while let Some(id) = seq.next_element()? {
match id.as_str() {
$(
stringify!($comp) => {
batch.add::<$comp>();
}
)*
_ => {},
}
self.components.push(id);
}
Ok(batch)
}
fn deserialize_components<'de, A: serde::de::SeqAccess<'de>>(
&mut self,
entity_count: u32,
mut seq: A,
batch: &mut ColumnBatchBuilder,
) -> Result<(), A::Error> {
for component in &self.components {
match component.as_str() {
$(
stringify!($comp) => {
deserialize_column::<$comp, _>(entity_count, &mut seq, batch)?;
}
)*
_ => {},
}
}
Ok(())
}
}
}
}
It says
type must be known at this point
| cannot infer type of the type parameter `T` declared on the associated function `next_element`
while let Some(id) = seq.next_element::<T>()? {
+++++
String
s as ComponentId (e.g. stringify!($comp))?What should I specifiy as T?
The type of your component IDs. In your case, perhaps &str
or String
?
Am I able to use string literals/Strings as ComponentId (e.g. stringify!($comp))?
Yep, any serializable type should work fine. I like to use enums, but strings make it easier to maintain forwards-compatibility, so they're not a bad choice.
What should I specifiy as T?
The type of your component IDs. In your case, perhaps
&str
orString
?Am I able to use string literals/Strings as ComponentId (e.g. stringify!($comp))?
Yep, any serializable type should work fine. I like to use enums, but strings make it easier to maintain forwards-compatibility, so they're not a bad choice.
I also have thought so, and as saving world was successful, loading it made no error, but the world was just empty So I considered using String inappropriate
Using String
for component IDs is probably not the reason that happened.
I am sorry, I've just forgotten to serialize Camera, so nothing appears on the screen :) Everything is working, thx for your job!
If I want to make save-load implementation for
World
in my game/engine, I would like to save all components I may, which are a part of a scene being saved. But according to docs I can only serialize a limited range of components, which are hardcoded likeIs there any approach to make it universal for all serializable components in a
World
?