Skip to content

Commit 26bc024

Browse files
committed
Improve serialization format of EffectAsset
This change makes a few improvements to the serialized representation of an `EffectAsset`: - `LiteralExpr`, `ExprHandle`, and `Module` are now `#[serde(transparent)]`, which makes them less verbose. - `VectorValue` is serialized as its glam math type representation, making it a lot more readable in text format (_e.g._ RON). Before: ``` module: ( expressions: [ Literal(( value: Vector(( vector_type: ( elem_type: Float, count: 3, ), storage: (1067030938, 3227307213, 1118770935, 0), )), )), Literal(( value: Vector(( vector_type: ( elem_type: Bool, count: 2, ), storage: (0, 4294967295, 0, 0), )), )), Binary( op: Add, left: ( index: 2, ), right: ( index: 1, ), ), ], ), ``` After: ``` module: [ Literal(Vector(Vec3((1.2, -3.45, 87.54485)))), Literal(Vector(BVec2((false, true)))), Binary( op: Add, left: 2, right: 1, ), ] ```
1 parent 37e7927 commit 26bc024

File tree

4 files changed

+175
-5
lines changed

4 files changed

+175
-5
lines changed

CHANGELOG.md

+1
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
2626
- Merged the `InitModifier` and `UpdateModifier` traits into the `Modifier` subtrait; see other changelog entries for details. This helps manage modifiers in a unified way, and generally simplifies writing and maintain modifiers compatible with both the init and update contexts.
2727
- `EffectAsset::init()` and `EffectAsset::update()` now take a `Modifier`-bound type, and validate its `ModifierContext` is compatible (and panics if not).
2828
- `EffectAsset::render()` now panics if the modifier is not compatible with the `ModifierContext::Render`. Note that this indicates a malformed render modifier, because all objects implementing `RenderModifier` must include `ModifierContext::Render` in their `Modifier::context()`.
29+
- Improved the serialization format to reduce verbosity, by making the following types `#[serde(transparent)]`: `ExprHandle`, `LiteralExpr`, `Module`.
2930

3031
### Removed
3132

src/asset.rs

+86-5
Original file line numberDiff line numberDiff line change
@@ -592,6 +592,8 @@ impl AssetLoader for EffectAssetLoader {
592592

593593
#[cfg(test)]
594594
mod tests {
595+
use ron::ser::PrettyConfig;
596+
595597
use crate::*;
596598

597599
use super::*;
@@ -734,15 +736,94 @@ mod tests {
734736

735737
#[test]
736738
fn test_serde_ron() {
739+
let w = ExprWriter::new();
740+
741+
let pos = w.lit(Vec3::new(1.2, -3.45, 87.54485));
742+
let x = w.lit(BVec2::new(false, true));
743+
let _ = x + pos.clone();
744+
let mod_pos = SetAttributeModifier::new(Attribute::POSITION, pos.expr());
745+
737746
let effect = EffectAsset {
738747
name: "Effect".into(),
739748
capacity: 4096,
740749
spawner: Spawner::rate(30.0.into()),
750+
module: w.finish(),
741751
..Default::default()
742-
};
743-
744-
let s = ron::to_string(&effect).unwrap();
745-
let _effect_serde: EffectAsset = ron::from_str(&s).unwrap();
746-
// assert_eq!(effect, effect_serde);
752+
}
753+
.with_property("my_prop", Vec3::new(1.2, -2.3, 55.32).into())
754+
.init(mod_pos);
755+
756+
let s = ron::ser::to_string_pretty(&effect, PrettyConfig::new().new_line("\n".to_string()))
757+
.unwrap();
758+
assert_eq!(
759+
s,
760+
r#"(
761+
name: "Effect",
762+
capacity: 4096,
763+
spawner: (
764+
num_particles: Single(30.0),
765+
spawn_time: Single(1.0),
766+
period: Single(1.0),
767+
starts_active: true,
768+
starts_immediately: true,
769+
),
770+
z_layer_2d: 0.0,
771+
simulation_space: Global,
772+
simulation_condition: WhenVisible,
773+
init_modifiers: [
774+
{
775+
"SetAttributeModifier": (
776+
attribute: "position",
777+
value: 1,
778+
),
779+
},
780+
],
781+
update_modifiers: [],
782+
render_modifiers: [],
783+
properties: [
784+
(
785+
name: "my_prop",
786+
default_value: Vector(Vec3((1.2, -2.3, 55.32))),
787+
),
788+
],
789+
motion_integration: PostUpdate,
790+
module: [
791+
Literal(Vector(Vec3((1.2, -3.45, 87.54485)))),
792+
Literal(Vector(BVec2((false, true)))),
793+
Binary(
794+
op: Add,
795+
left: 2,
796+
right: 1,
797+
),
798+
],
799+
alpha_mode: Blend,
800+
)"#
801+
);
802+
let effect_serde: EffectAsset = ron::from_str(&s).unwrap();
803+
assert_eq!(effect.name, effect_serde.name);
804+
assert_eq!(effect.capacity, effect_serde.capacity);
805+
assert_eq!(effect.spawner, effect_serde.spawner);
806+
assert_eq!(effect.z_layer_2d, effect_serde.z_layer_2d);
807+
assert_eq!(effect.simulation_space, effect_serde.simulation_space);
808+
assert_eq!(
809+
effect.simulation_condition,
810+
effect_serde.simulation_condition
811+
);
812+
assert_eq!(effect.properties, effect_serde.properties);
813+
assert_eq!(effect.motion_integration, effect_serde.motion_integration);
814+
assert_eq!(effect.module, effect_serde.module);
815+
assert_eq!(effect.alpha_mode, effect_serde.alpha_mode);
816+
assert_eq!(
817+
effect.init_modifiers().count(),
818+
effect_serde.init_modifiers().count()
819+
);
820+
assert_eq!(
821+
effect.update_modifiers().count(),
822+
effect_serde.update_modifiers().count()
823+
);
824+
assert_eq!(
825+
effect.render_modifiers().count(),
826+
effect_serde.render_modifiers().count()
827+
);
747828
}
748829
}

src/graph/expr.rs

+3
Original file line numberDiff line numberDiff line change
@@ -125,6 +125,7 @@ type Index = NonZeroU32;
125125
Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Reflect, Serialize, Deserialize,
126126
)]
127127
#[repr(transparent)]
128+
#[serde(transparent)]
128129
pub struct ExprHandle {
129130
index: Index,
130131
}
@@ -161,6 +162,7 @@ impl ExprHandle {
161162
/// [`lit()`]: Module::lit
162163
/// [`attr()`]: Module::attr
163164
#[derive(Debug, Default, Clone, PartialEq, Hash, Reflect, Serialize, Deserialize)]
165+
#[serde(transparent)]
164166
pub struct Module {
165167
expressions: Vec<Expr>,
166168
}
@@ -870,6 +872,7 @@ impl Expr {
870872
///
871873
/// [`is_const()`]: LiteralExpr::is_const
872874
#[derive(Debug, Clone, Copy, PartialEq, Hash, Reflect, Serialize, Deserialize)]
875+
#[serde(transparent)]
873876
pub struct LiteralExpr {
874877
value: Value,
875878
}

src/graph/mod.rs

+85
Original file line numberDiff line numberDiff line change
@@ -437,6 +437,7 @@ impl ElemType for u32 {
437437

438438
/// Variant storage for a vector value.
439439
#[derive(Debug, Clone, Copy, Reflect, Serialize, Deserialize)]
440+
#[serde(from = "VectorValueEnum", into = "VectorValueEnum")]
440441
pub struct VectorValue {
441442
vector_type: VectorType,
442443
storage: [u32; 4],
@@ -1203,6 +1204,90 @@ impl From<Vec4> for VectorValue {
12031204
}
12041205
}
12051206

1207+
/// Helper used as placeholder instead of [`VectorValue`] for serialization.
1208+
///
1209+
/// This enables serializing [`VectorValue`] as a glam type enum, instead of the
1210+
/// compressed binary runtime representation actually stored inside
1211+
/// [`VectorValue`].
1212+
#[derive(Serialize, Deserialize)]
1213+
enum VectorValueEnum {
1214+
BVec2(BVec2),
1215+
BVec3(BVec3),
1216+
BVec4(BVec4),
1217+
IVec2(IVec2),
1218+
IVec3(IVec3),
1219+
IVec4(IVec4),
1220+
UVec2(UVec2),
1221+
UVec3(UVec3),
1222+
UVec4(UVec4),
1223+
Vec2(Vec2),
1224+
Vec3(Vec3),
1225+
Vec4(Vec4),
1226+
}
1227+
1228+
impl From<VectorValueEnum> for VectorValue {
1229+
fn from(value: VectorValueEnum) -> Self {
1230+
match value {
1231+
VectorValueEnum::BVec2(v) => VectorValue::new_bvec2(v),
1232+
VectorValueEnum::BVec3(v) => VectorValue::new_bvec3(v),
1233+
VectorValueEnum::BVec4(v) => VectorValue::new_bvec4(v),
1234+
VectorValueEnum::IVec2(v) => VectorValue::new_ivec2(v),
1235+
VectorValueEnum::IVec3(v) => VectorValue::new_ivec3(v),
1236+
VectorValueEnum::IVec4(v) => VectorValue::new_ivec4(v),
1237+
VectorValueEnum::UVec2(v) => VectorValue::new_uvec2(v),
1238+
VectorValueEnum::UVec3(v) => VectorValue::new_uvec3(v),
1239+
VectorValueEnum::UVec4(v) => VectorValue::new_uvec4(v),
1240+
VectorValueEnum::Vec2(v) => VectorValue::new_vec2(v),
1241+
VectorValueEnum::Vec3(v) => VectorValue::new_vec3(v),
1242+
VectorValueEnum::Vec4(v) => VectorValue::new_vec4(v),
1243+
}
1244+
}
1245+
}
1246+
1247+
impl From<VectorValue> for VectorValueEnum {
1248+
fn from(value: VectorValue) -> Self {
1249+
let count = value.vector_type.count();
1250+
match value.elem_type() {
1251+
ScalarType::Bool => {
1252+
if count == 2 {
1253+
VectorValueEnum::BVec2(value.as_bvec2())
1254+
} else if count == 3 {
1255+
VectorValueEnum::BVec3(value.as_bvec3())
1256+
} else {
1257+
VectorValueEnum::BVec4(value.as_bvec4())
1258+
}
1259+
}
1260+
ScalarType::Int => {
1261+
if count == 2 {
1262+
VectorValueEnum::IVec2(value.as_ivec2())
1263+
} else if count == 3 {
1264+
VectorValueEnum::IVec3(value.as_ivec3())
1265+
} else {
1266+
VectorValueEnum::IVec4(value.as_ivec4())
1267+
}
1268+
}
1269+
ScalarType::Uint => {
1270+
if count == 2 {
1271+
VectorValueEnum::UVec2(value.as_uvec2())
1272+
} else if count == 3 {
1273+
VectorValueEnum::UVec3(value.as_uvec3())
1274+
} else {
1275+
VectorValueEnum::UVec4(value.as_uvec4())
1276+
}
1277+
}
1278+
ScalarType::Float => {
1279+
if count == 2 {
1280+
VectorValueEnum::Vec2(value.as_vec2())
1281+
} else if count == 3 {
1282+
VectorValueEnum::Vec3(value.as_vec3())
1283+
} else {
1284+
VectorValueEnum::Vec4(value.as_vec4())
1285+
}
1286+
}
1287+
}
1288+
}
1289+
}
1290+
12061291
/// Floating-point matrix value.
12071292
#[derive(Debug, Clone, Copy, Reflect, Serialize, Deserialize)]
12081293
pub struct MatrixValue {

0 commit comments

Comments
 (0)