public static void Serialize(this AnimationSet animationSet, AnimationSerializeContext context) { if (Asserts.enabled && !animationSet.ValidateAlphaMasks()) { throw new InvalidOperationException( "Attempting to save animation set with missing or invalid alpha masks"); } context.bw.WriteNullableString(animationSet.friendlyName); context.bw.Write(animationSet.importOrigin); context.bw.WriteNullableString(animationSet.behaviour); if (context.bw.WriteBoolean(animationSet.Heightmap != null)) { animationSet.Heightmap.Serialize(context); } // If you don't seem to have set any physics bounds, I will just generate them... if (animationSet.physicsStartX == 0 && animationSet.physicsEndX == 1 && animationSet.physicsStartZ == 0 && animationSet.physicsEndZ == 1 && animationSet.physicsHeight == 0 || animationSet.physicsEndX - animationSet.physicsStartX <= 0) { animationSet.AutoGeneratePhysicsAndDepthBounds(); } // NOTE: only writing out values that cannot be auto-generated if (animationSet.Heightmap != null) { Debug.Assert(!Asserts.enabled || animationSet.Heightmap.IsObjectHeightmap || animationSet.physicsHeight == 0); context.bw.Write(animationSet.physicsHeight); if (animationSet.physicsHeight > 0) { animationSet.depthBounds.Serialize(context); } context.bw.Write(animationSet.flatDirection); // <- for the sake of editing, keep this value around } else { context.bw.Write(animationSet.physicsStartX); context.bw.Write(animationSet.physicsEndX); context.bw.Write(animationSet.physicsStartZ); context.bw.Write(animationSet.physicsHeight); context.bw.Write(animationSet.flatDirection); if (animationSet.physicsHeight == 0) { context.bw.Write(animationSet.physicsEndZ); } } if (context.Version >= 38) { context.bw.Write(animationSet.coplanarPriority); } if (context.Version >= 36) { context.bw.Write(animationSet.doAboveCheck); } if (context.bw.WriteBoolean(animationSet.Ceiling != null)) { animationSet.Ceiling.Serialize(context); } animationSet.animations.SerializeTagLookup(context, a => a.Serialize(context)); // Unused Animations { if (animationSet.unusedAnimations == null) { context.bw.Write(0); // unused animations is lazy-initialized } else { context.bw.Write(animationSet.unusedAnimations.Count); foreach (var animation in animationSet.unusedAnimations) { animation.Serialize(context); } } } context.bw.WriteNullableString(animationSet.cue); // Shadow layers: { if (animationSet.shadowLayers == null) { context.bw.Write(0); } else { context.bw.Write(animationSet.shadowLayers.Count); foreach (var sl in animationSet.shadowLayers) { context.bw.Write(sl.startHeight); sl.shadowSpriteRef.Serialize(context); } animationSet.RecalculateCachedShadowBounds(); context.bw.Write(animationSet.cachedShadowBounds); } } // Properties: if (context.Version >= 40) { context.bw.Write(animationSet.properties.Count); foreach (var kvp in animationSet.properties) { context.bw.Write(kvp.Key); context.bw.Write(kvp.Value ?? string.Empty); // (null value should probably be blocked by editor, but being safe...) } } }