|
@@ -19,327 +19,327 @@ public class MeidoSerializer : Serializer<Meido>
|
|
private static SimpleSerializer<TransformDTO> TransformDtoSerializer =>
|
|
private static SimpleSerializer<TransformDTO> TransformDtoSerializer =>
|
|
Serialization.GetSimple<TransformDTO>();
|
|
Serialization.GetSimple<TransformDTO>();
|
|
|
|
|
|
- private static void SerializeHead(Meido meido, BinaryWriter writer)
|
|
|
|
|
|
+ public override void Serialize(Meido meido, BinaryWriter writer)
|
|
{
|
|
{
|
|
- var body = meido.Body;
|
|
|
|
-
|
|
|
|
- writer.WriteVersion(headVersion);
|
|
|
|
-
|
|
|
|
- // eye direction
|
|
|
|
- writer.WriteQuaternion(body.quaDefEyeL * Quaternion.Inverse(meido.DefaultEyeRotL));
|
|
|
|
- writer.WriteQuaternion(body.quaDefEyeR * Quaternion.Inverse(meido.DefaultEyeRotR));
|
|
|
|
-
|
|
|
|
- // free look
|
|
|
|
- writer.Write(meido.FreeLook);
|
|
|
|
- writer.WriteVector3(body.offsetLookTarget);
|
|
|
|
- writer.WriteVector3(Utility.GetFieldValue<TBody, Vector3>(body, "HeadEulerAngle"));
|
|
|
|
|
|
+ var maid = meido.Maid;
|
|
|
|
|
|
- // Head/eye to camera
|
|
|
|
- writer.Write(meido.HeadToCam);
|
|
|
|
- writer.Write(meido.EyeToCam);
|
|
|
|
|
|
+ using var memoryStream = new MemoryStream();
|
|
|
|
+ using var tempWriter = new BinaryWriter(memoryStream, Encoding.UTF8);
|
|
|
|
|
|
- // face
|
|
|
|
- var faceDict = meido.SerializeFace();
|
|
|
|
|
|
+ tempWriter.WriteVersion(version);
|
|
|
|
|
|
- writer.Write(faceDict.Count);
|
|
|
|
|
|
+ TransformDtoSerializer.Serialize(new TransformDTO(maid.transform), tempWriter);
|
|
|
|
|
|
- foreach (var (hash, value) in faceDict)
|
|
|
|
- {
|
|
|
|
- writer.Write(hash);
|
|
|
|
- writer.Write(value);
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
|
|
+ SerializeHead(meido, tempWriter);
|
|
|
|
|
|
- private static void SerializeBody(Meido meido, BinaryWriter writer)
|
|
|
|
- {
|
|
|
|
- writer.WriteVersion(bodyVersion);
|
|
|
|
|
|
+ SerializeBody(meido, tempWriter);
|
|
|
|
|
|
- // pose
|
|
|
|
- var poseBuffer = meido.SerializePose(true);
|
|
|
|
|
|
+ SerializeClothing(meido, tempWriter);
|
|
|
|
|
|
- writer.Write(poseBuffer.Length);
|
|
|
|
- writer.Write(poseBuffer);
|
|
|
|
|
|
+ writer.Write(memoryStream.Length);
|
|
|
|
+ writer.Write(memoryStream.ToArray());
|
|
|
|
|
|
- PoseInfoSerializer.Serialize(meido.CachedPose, writer);
|
|
|
|
|
|
+ static void SerializeHead(Meido meido, BinaryWriter writer)
|
|
|
|
+ {
|
|
|
|
+ var body = meido.Body;
|
|
|
|
|
|
- // TODO: Think about how to indicate code for new versions of serialization.
|
|
|
|
- #region v2
|
|
|
|
- // sub mune rotation
|
|
|
|
- var body = meido.Body;
|
|
|
|
|
|
+ writer.WriteVersion(headVersion);
|
|
|
|
|
|
- writer.WriteQuaternion(body.GetBone("Mune_L_sub").localRotation);
|
|
|
|
- writer.WriteQuaternion(body.GetBone("Mune_R_sub").localRotation);
|
|
|
|
- #endregion
|
|
|
|
- }
|
|
|
|
|
|
+ // eye direction
|
|
|
|
+ writer.WriteQuaternion(body.quaDefEyeL * Quaternion.Inverse(meido.DefaultEyeRotL));
|
|
|
|
+ writer.WriteQuaternion(body.quaDefEyeR * Quaternion.Inverse(meido.DefaultEyeRotR));
|
|
|
|
|
|
- private static void SerializeClothing(Meido meido, BinaryWriter writer)
|
|
|
|
- {
|
|
|
|
- var maid = meido.Maid;
|
|
|
|
- var body = meido.Body;
|
|
|
|
|
|
+ // free look
|
|
|
|
+ writer.Write(meido.FreeLook);
|
|
|
|
+ writer.WriteVector3(body.offsetLookTarget);
|
|
|
|
+ writer.WriteVector3(Utility.GetFieldValue<TBody, Vector3>(body, "HeadEulerAngle"));
|
|
|
|
|
|
- writer.WriteVersion(clothingVersion);
|
|
|
|
|
|
+ // Head/eye to camera
|
|
|
|
+ writer.Write(meido.HeadToCam);
|
|
|
|
+ writer.Write(meido.EyeToCam);
|
|
|
|
|
|
- // body visible
|
|
|
|
- writer.Write(body.GetMask(TBody.SlotID.body));
|
|
|
|
|
|
+ // face
|
|
|
|
+ var faceDict = meido.SerializeFace();
|
|
|
|
|
|
- // clothing
|
|
|
|
- foreach (var clothingSlot in MaidDressingPane.ClothingSlots)
|
|
|
|
- {
|
|
|
|
- var value = true;
|
|
|
|
|
|
+ writer.Write(faceDict.Count);
|
|
|
|
|
|
- if (clothingSlot is TBody.SlotID.wear)
|
|
|
|
|
|
+ foreach (var (hash, value) in faceDict)
|
|
{
|
|
{
|
|
- if (MaidDressingPane.WearSlots.Any(slot => body.GetSlotLoaded(slot)))
|
|
|
|
- value = MaidDressingPane.WearSlots.Any(slot => body.GetMask(slot));
|
|
|
|
|
|
+ writer.Write(hash);
|
|
|
|
+ writer.Write(value);
|
|
}
|
|
}
|
|
- else if (clothingSlot is TBody.SlotID.megane)
|
|
|
|
- {
|
|
|
|
- var slots = new[] { TBody.SlotID.megane, TBody.SlotID.accHead };
|
|
|
|
-
|
|
|
|
- if (slots.Any(slot => body.GetSlotLoaded(slot)))
|
|
|
|
- value = slots.Any(slot => body.GetMask(slot));
|
|
|
|
- }
|
|
|
|
- else if (body.GetSlotLoaded(clothingSlot))
|
|
|
|
- value = body.GetMask(clothingSlot);
|
|
|
|
-
|
|
|
|
- writer.Write(value);
|
|
|
|
}
|
|
}
|
|
|
|
|
|
- // zurashi and mekure
|
|
|
|
- writer.Write(meido.CurlingFront);
|
|
|
|
- writer.Write(meido.CurlingBack);
|
|
|
|
- writer.Write(meido.PantsuShift);
|
|
|
|
-
|
|
|
|
- // mpn attach props
|
|
|
|
- var hasKousokuUpper = body.GetSlotLoaded(TBody.SlotID.kousoku_upper);
|
|
|
|
-
|
|
|
|
- writer.Write(hasKousokuUpper);
|
|
|
|
- writer.Write(maid.GetProp(MPN.kousoku_upper).strTempFileName);
|
|
|
|
-
|
|
|
|
- var hasKousokuLower = body.GetSlotLoaded(TBody.SlotID.kousoku_lower);
|
|
|
|
|
|
+ static void SerializeBody(Meido meido, BinaryWriter writer)
|
|
|
|
+ {
|
|
|
|
+ writer.WriteVersion(bodyVersion);
|
|
|
|
|
|
- writer.Write(hasKousokuLower);
|
|
|
|
- writer.Write(maid.GetProp(MPN.kousoku_lower).strTempFileName);
|
|
|
|
|
|
+ // pose
|
|
|
|
+ var poseBuffer = meido.SerializePose(true);
|
|
|
|
|
|
- // hair/skirt gravity
|
|
|
|
- writer.Write(meido.HairGravityActive);
|
|
|
|
- writer.Write(meido.HairGravityControl.Control.transform.localPosition);
|
|
|
|
|
|
+ writer.Write(poseBuffer.Length);
|
|
|
|
+ writer.Write(poseBuffer);
|
|
|
|
|
|
- writer.Write(meido.SkirtGravityActive);
|
|
|
|
- writer.Write(meido.SkirtGravityControl.Control.transform.localPosition);
|
|
|
|
- }
|
|
|
|
|
|
+ PoseInfoSerializer.Serialize(meido.CachedPose, writer);
|
|
|
|
|
|
- private static void DeserializeHead(Meido meido, BinaryReader reader, SceneMetadata metadata)
|
|
|
|
- {
|
|
|
|
- var body = meido.Body;
|
|
|
|
|
|
+ // TODO: Think about how to indicate code for new versions of serialization.
|
|
|
|
+ #region v2
|
|
|
|
+ // sub mune rotation
|
|
|
|
+ var body = meido.Body;
|
|
|
|
|
|
- _ = reader.ReadVersion();
|
|
|
|
|
|
+ writer.WriteQuaternion(body.GetBone("Mune_L_sub").localRotation);
|
|
|
|
+ writer.WriteQuaternion(body.GetBone("Mune_R_sub").localRotation);
|
|
|
|
+ #endregion
|
|
|
|
+ }
|
|
|
|
|
|
- var mmConverted = metadata.MMConverted;
|
|
|
|
|
|
+ static void SerializeClothing(Meido meido, BinaryWriter writer)
|
|
|
|
+ {
|
|
|
|
+ var maid = meido.Maid;
|
|
|
|
+ var body = meido.Body;
|
|
|
|
|
|
- var eyeRotationL = reader.ReadQuaternion();
|
|
|
|
- var eyeRotationR = reader.ReadQuaternion();
|
|
|
|
|
|
+ writer.WriteVersion(clothingVersion);
|
|
|
|
|
|
- if (!mmConverted)
|
|
|
|
- {
|
|
|
|
- eyeRotationL *= meido.DefaultEyeRotL;
|
|
|
|
- eyeRotationR *= meido.DefaultEyeRotR;
|
|
|
|
- }
|
|
|
|
|
|
+ // body visible
|
|
|
|
+ writer.Write(body.GetMask(TBody.SlotID.body));
|
|
|
|
|
|
- body.quaDefEyeL = eyeRotationL;
|
|
|
|
- body.quaDefEyeR = eyeRotationR;
|
|
|
|
|
|
+ // clothing
|
|
|
|
+ foreach (var clothingSlot in MaidDressingPane.ClothingSlots)
|
|
|
|
+ {
|
|
|
|
+ var value = true;
|
|
|
|
+
|
|
|
|
+ if (clothingSlot is TBody.SlotID.wear)
|
|
|
|
+ {
|
|
|
|
+ if (MaidDressingPane.WearSlots.Any(slot => body.GetSlotLoaded(slot)))
|
|
|
|
+ value = MaidDressingPane.WearSlots.Any(slot => body.GetMask(slot));
|
|
|
|
+ }
|
|
|
|
+ else if (clothingSlot is TBody.SlotID.megane)
|
|
|
|
+ {
|
|
|
|
+ var slots = new[] { TBody.SlotID.megane, TBody.SlotID.accHead };
|
|
|
|
+
|
|
|
|
+ if (slots.Any(slot => body.GetSlotLoaded(slot)))
|
|
|
|
+ value = slots.Any(slot => body.GetMask(slot));
|
|
|
|
+ }
|
|
|
|
+ else if (body.GetSlotLoaded(clothingSlot))
|
|
|
|
+ value = body.GetMask(clothingSlot);
|
|
|
|
+
|
|
|
|
+ writer.Write(value);
|
|
|
|
+ }
|
|
|
|
|
|
- var freeLook = meido.FreeLook = reader.ReadBoolean();
|
|
|
|
- var offsetLookTarget = reader.ReadVector3();
|
|
|
|
- var headEulerAngle = reader.ReadVector3();
|
|
|
|
|
|
+ // zurashi and mekure
|
|
|
|
+ writer.Write(meido.CurlingFront);
|
|
|
|
+ writer.Write(meido.CurlingBack);
|
|
|
|
+ writer.Write(meido.PantsuShift);
|
|
|
|
|
|
- if (freeLook)
|
|
|
|
- body.offsetLookTarget = offsetLookTarget;
|
|
|
|
|
|
+ // mpn attach props
|
|
|
|
+ var hasKousokuUpper = body.GetSlotLoaded(TBody.SlotID.kousoku_upper);
|
|
|
|
|
|
- if (!metadata.MMConverted)
|
|
|
|
- {
|
|
|
|
- Utility.SetFieldValue(body, "HeadEulerAngleG", Vector3.zero);
|
|
|
|
- Utility.SetFieldValue(body, "HeadEulerAngle", headEulerAngle);
|
|
|
|
- }
|
|
|
|
|
|
+ writer.Write(hasKousokuUpper);
|
|
|
|
+ writer.Write(maid.GetProp(MPN.kousoku_upper).strTempFileName);
|
|
|
|
|
|
- meido.HeadToCam = reader.ReadBoolean();
|
|
|
|
- meido.EyeToCam = reader.ReadBoolean();
|
|
|
|
|
|
+ var hasKousokuLower = body.GetSlotLoaded(TBody.SlotID.kousoku_lower);
|
|
|
|
|
|
- var faceBlendCount = reader.ReadInt32();
|
|
|
|
|
|
+ writer.Write(hasKousokuLower);
|
|
|
|
+ writer.Write(maid.GetProp(MPN.kousoku_lower).strTempFileName);
|
|
|
|
|
|
- for (var i = 0; i < faceBlendCount; i++)
|
|
|
|
- {
|
|
|
|
- var hash = reader.ReadString();
|
|
|
|
- var value = reader.ReadSingle();
|
|
|
|
|
|
+ // hair/skirt gravity
|
|
|
|
+ writer.Write(meido.HairGravityActive);
|
|
|
|
+ writer.Write(meido.HairGravityControl.Control.transform.localPosition);
|
|
|
|
|
|
- meido.SetFaceBlendValue(hash, value);
|
|
|
|
|
|
+ writer.Write(meido.SkirtGravityActive);
|
|
|
|
+ writer.Write(meido.SkirtGravityControl.Control.transform.localPosition);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
- private static void DeserializeBody(Meido meido, BinaryReader reader, SceneMetadata metadata)
|
|
|
|
|
|
+ public override void Deserialize(Meido meido, BinaryReader reader, SceneMetadata metadata)
|
|
{
|
|
{
|
|
- var version = reader.ReadVersion();
|
|
|
|
|
|
+ var maid = meido.Maid;
|
|
|
|
|
|
- var muneSetting = new KeyValuePair<bool, bool>(true, true);
|
|
|
|
|
|
+ maid.GetAnimation().Stop();
|
|
|
|
+ meido.DetachAllMpnAttach();
|
|
|
|
+ meido.StopBlink();
|
|
|
|
|
|
- if (metadata.MMConverted)
|
|
|
|
- meido.IKManager.Deserialize(reader);
|
|
|
|
- else
|
|
|
|
- {
|
|
|
|
- var poseBufferLength = reader.ReadInt32();
|
|
|
|
- var poseBuffer = reader.ReadBytes(poseBufferLength);
|
|
|
|
|
|
+ reader.ReadInt64(); // data length
|
|
|
|
|
|
- muneSetting = meido.SetFrameBinary(poseBuffer);
|
|
|
|
- }
|
|
|
|
|
|
+ _ = reader.ReadVersion();
|
|
|
|
|
|
- var poseInfo = PoseInfoSerializer.Deserialize(reader, metadata);
|
|
|
|
|
|
+ var transformDto = TransformDtoSerializer.Deserialize(reader, metadata);
|
|
|
|
+ var maidTransform = maid.transform;
|
|
|
|
|
|
- Utility.SetPropertyValue(meido, nameof(Meido.CachedPose), poseInfo);
|
|
|
|
|
|
+ // TODO: use transform.SetRotationAndPosition
|
|
|
|
+ maidTransform.position = transformDto.Position;
|
|
|
|
+ maidTransform.rotation = transformDto.Rotation;
|
|
|
|
+ maidTransform.localScale = transformDto.LocalScale;
|
|
|
|
+
|
|
|
|
+ meido.IKManager.SetDragPointScale(maidTransform.localScale.x);
|
|
|
|
|
|
- meido.SetMune(!muneSetting.Key, true);
|
|
|
|
- meido.SetMune(!muneSetting.Value);
|
|
|
|
|
|
+ DeserializeHead(meido, reader, metadata);
|
|
|
|
|
|
- if (version < 2)
|
|
|
|
- return;
|
|
|
|
|
|
+ DeserializeBody(meido, reader, metadata);
|
|
|
|
|
|
- var muneLSubRotation = reader.ReadQuaternion();
|
|
|
|
- var muneSubRRotation = reader.ReadQuaternion();
|
|
|
|
|
|
+ DeserializeClothing(meido, reader, metadata);
|
|
|
|
|
|
- var body = meido.Body;
|
|
|
|
|
|
+ static void DeserializeHead(Meido meido, BinaryReader reader, SceneMetadata metadata)
|
|
|
|
+ {
|
|
|
|
+ var body = meido.Body;
|
|
|
|
|
|
- if (muneSetting.Key)
|
|
|
|
- body.GetBone("Mune_L_sub").localRotation = muneLSubRotation;
|
|
|
|
|
|
+ _ = reader.ReadVersion();
|
|
|
|
|
|
- if (muneSetting.Value)
|
|
|
|
- body.GetBone("Mune_R_sub").localRotation = muneSubRRotation;
|
|
|
|
- }
|
|
|
|
|
|
+ var mmConverted = metadata.MMConverted;
|
|
|
|
|
|
- private static void DeserializeClothing(Meido meido, BinaryReader reader, SceneMetadata metadata)
|
|
|
|
- {
|
|
|
|
- var body = meido.Body;
|
|
|
|
|
|
+ var eyeRotationL = reader.ReadQuaternion();
|
|
|
|
+ var eyeRotationR = reader.ReadQuaternion();
|
|
|
|
|
|
- _ = reader.ReadVersion();
|
|
|
|
|
|
+ if (!mmConverted)
|
|
|
|
+ {
|
|
|
|
+ eyeRotationL *= meido.DefaultEyeRotL;
|
|
|
|
+ eyeRotationR *= meido.DefaultEyeRotR;
|
|
|
|
+ }
|
|
|
|
|
|
- meido.SetBodyMask(reader.ReadBoolean());
|
|
|
|
|
|
+ body.quaDefEyeL = eyeRotationL;
|
|
|
|
+ body.quaDefEyeR = eyeRotationR;
|
|
|
|
|
|
- foreach (var clothingSlot in MaidDressingPane.ClothingSlots)
|
|
|
|
- {
|
|
|
|
- var value = reader.ReadBoolean();
|
|
|
|
|
|
+ var freeLook = meido.FreeLook = reader.ReadBoolean();
|
|
|
|
+ var offsetLookTarget = reader.ReadVector3();
|
|
|
|
+ var headEulerAngle = reader.ReadVector3();
|
|
|
|
|
|
- if (metadata.MMConverted)
|
|
|
|
- continue;
|
|
|
|
|
|
+ if (freeLook)
|
|
|
|
+ body.offsetLookTarget = offsetLookTarget;
|
|
|
|
|
|
- if (clothingSlot is TBody.SlotID.wear)
|
|
|
|
|
|
+ if (!metadata.MMConverted)
|
|
{
|
|
{
|
|
- body.SetMask(TBody.SlotID.wear, value);
|
|
|
|
- body.SetMask(TBody.SlotID.mizugi, value);
|
|
|
|
- body.SetMask(TBody.SlotID.onepiece, value);
|
|
|
|
|
|
+ Utility.SetFieldValue(body, "HeadEulerAngleG", Vector3.zero);
|
|
|
|
+ Utility.SetFieldValue(body, "HeadEulerAngle", headEulerAngle);
|
|
}
|
|
}
|
|
- else if (clothingSlot is TBody.SlotID.megane)
|
|
|
|
|
|
+
|
|
|
|
+ meido.HeadToCam = reader.ReadBoolean();
|
|
|
|
+ meido.EyeToCam = reader.ReadBoolean();
|
|
|
|
+
|
|
|
|
+ var faceBlendCount = reader.ReadInt32();
|
|
|
|
+
|
|
|
|
+ for (var i = 0; i < faceBlendCount; i++)
|
|
{
|
|
{
|
|
- body.SetMask(TBody.SlotID.megane, value);
|
|
|
|
- body.SetMask(TBody.SlotID.accHead, value);
|
|
|
|
|
|
+ var hash = reader.ReadString();
|
|
|
|
+ var value = reader.ReadSingle();
|
|
|
|
+
|
|
|
|
+ meido.SetFaceBlendValue(hash, value);
|
|
}
|
|
}
|
|
- else if (body.GetSlotLoaded(clothingSlot))
|
|
|
|
- body.SetMask(clothingSlot, value);
|
|
|
|
}
|
|
}
|
|
|
|
|
|
- // zurashi and mekure
|
|
|
|
- var curlingFront = reader.ReadBoolean();
|
|
|
|
- var curlingBack = reader.ReadBoolean();
|
|
|
|
- var curlingPantsu = reader.ReadBoolean();
|
|
|
|
-
|
|
|
|
- if (!metadata.MMConverted)
|
|
|
|
|
|
+ static void DeserializeBody(Meido meido, BinaryReader reader, SceneMetadata metadata)
|
|
{
|
|
{
|
|
- if (meido.CurlingFront != curlingFront)
|
|
|
|
- meido.SetCurling(Meido.Curl.Front, curlingFront);
|
|
|
|
-
|
|
|
|
- if (meido.CurlingBack != curlingBack)
|
|
|
|
- meido.SetCurling(Meido.Curl.Back, curlingBack);
|
|
|
|
|
|
+ var version = reader.ReadVersion();
|
|
|
|
|
|
- meido.SetCurling(Meido.Curl.Shift, curlingPantsu);
|
|
|
|
- }
|
|
|
|
|
|
+ var muneSetting = new KeyValuePair<bool, bool>(true, true);
|
|
|
|
|
|
- // MPN attach upper prop
|
|
|
|
- var hasKousokuUpper = reader.ReadBoolean();
|
|
|
|
- var upperMenuFile = reader.ReadString();
|
|
|
|
|
|
+ if (metadata.MMConverted)
|
|
|
|
+ meido.IKManager.Deserialize(reader);
|
|
|
|
+ else
|
|
|
|
+ {
|
|
|
|
+ var poseBufferLength = reader.ReadInt32();
|
|
|
|
+ var poseBuffer = reader.ReadBytes(poseBufferLength);
|
|
|
|
|
|
- if (hasKousokuUpper)
|
|
|
|
- meido.SetMpnProp(new MpnAttachProp(MPN.kousoku_upper, upperMenuFile), false);
|
|
|
|
|
|
+ muneSetting = meido.SetFrameBinary(poseBuffer);
|
|
|
|
+ }
|
|
|
|
|
|
- // MPN attach lower prop
|
|
|
|
- var hasKousokuLower = reader.ReadBoolean();
|
|
|
|
- var lowerMenuFile = reader.ReadString();
|
|
|
|
|
|
+ var poseInfo = PoseInfoSerializer.Deserialize(reader, metadata);
|
|
|
|
|
|
- if (hasKousokuLower)
|
|
|
|
- meido.SetMpnProp(new MpnAttachProp(MPN.kousoku_lower, lowerMenuFile), false);
|
|
|
|
|
|
+ Utility.SetPropertyValue(meido, nameof(Meido.CachedPose), poseInfo);
|
|
|
|
|
|
- // hair gravity
|
|
|
|
- var hairGravityActive = reader.ReadBoolean();
|
|
|
|
- var hairPosition = reader.ReadVector3();
|
|
|
|
|
|
+ meido.SetMune(!muneSetting.Key, true);
|
|
|
|
+ meido.SetMune(!muneSetting.Value);
|
|
|
|
|
|
- meido.HairGravityActive = hairGravityActive;
|
|
|
|
|
|
+ if (version < 2)
|
|
|
|
+ return;
|
|
|
|
|
|
- if (meido.HairGravityActive)
|
|
|
|
- meido.ApplyGravity(hairPosition);
|
|
|
|
|
|
+ var muneLSubRotation = reader.ReadQuaternion();
|
|
|
|
+ var muneSubRRotation = reader.ReadQuaternion();
|
|
|
|
|
|
- // skirt gravity
|
|
|
|
- var skirtGravityActive = reader.ReadBoolean();
|
|
|
|
- var skirtPosition = reader.ReadVector3();
|
|
|
|
|
|
+ var body = meido.Body;
|
|
|
|
|
|
- meido.SkirtGravityActive = skirtGravityActive;
|
|
|
|
|
|
+ if (muneSetting.Key)
|
|
|
|
+ body.GetBone("Mune_L_sub").localRotation = muneLSubRotation;
|
|
|
|
|
|
- if (meido.SkirtGravityActive)
|
|
|
|
- meido.ApplyGravity(skirtPosition, true);
|
|
|
|
- }
|
|
|
|
|
|
+ if (muneSetting.Value)
|
|
|
|
+ body.GetBone("Mune_R_sub").localRotation = muneSubRRotation;
|
|
|
|
+ }
|
|
|
|
|
|
- public override void Serialize(Meido meido, BinaryWriter writer)
|
|
|
|
- {
|
|
|
|
- var maid = meido.Maid;
|
|
|
|
|
|
+ static void DeserializeClothing(Meido meido, BinaryReader reader, SceneMetadata metadata)
|
|
|
|
+ {
|
|
|
|
+ var body = meido.Body;
|
|
|
|
|
|
- using var memoryStream = new MemoryStream();
|
|
|
|
- using var tempWriter = new BinaryWriter(memoryStream, Encoding.UTF8);
|
|
|
|
|
|
+ _ = reader.ReadVersion();
|
|
|
|
|
|
- tempWriter.WriteVersion(version);
|
|
|
|
|
|
+ meido.SetBodyMask(reader.ReadBoolean());
|
|
|
|
|
|
- TransformDtoSerializer.Serialize(new TransformDTO(maid.transform), tempWriter);
|
|
|
|
|
|
+ foreach (var clothingSlot in MaidDressingPane.ClothingSlots)
|
|
|
|
+ {
|
|
|
|
+ var value = reader.ReadBoolean();
|
|
|
|
+
|
|
|
|
+ if (metadata.MMConverted)
|
|
|
|
+ continue;
|
|
|
|
+
|
|
|
|
+ if (clothingSlot is TBody.SlotID.wear)
|
|
|
|
+ {
|
|
|
|
+ body.SetMask(TBody.SlotID.wear, value);
|
|
|
|
+ body.SetMask(TBody.SlotID.mizugi, value);
|
|
|
|
+ body.SetMask(TBody.SlotID.onepiece, value);
|
|
|
|
+ }
|
|
|
|
+ else if (clothingSlot is TBody.SlotID.megane)
|
|
|
|
+ {
|
|
|
|
+ body.SetMask(TBody.SlotID.megane, value);
|
|
|
|
+ body.SetMask(TBody.SlotID.accHead, value);
|
|
|
|
+ }
|
|
|
|
+ else if (body.GetSlotLoaded(clothingSlot))
|
|
|
|
+ body.SetMask(clothingSlot, value);
|
|
|
|
+ }
|
|
|
|
|
|
- SerializeHead(meido, tempWriter);
|
|
|
|
|
|
+ // zurashi and mekure
|
|
|
|
+ var curlingFront = reader.ReadBoolean();
|
|
|
|
+ var curlingBack = reader.ReadBoolean();
|
|
|
|
+ var curlingPantsu = reader.ReadBoolean();
|
|
|
|
|
|
- SerializeBody(meido, tempWriter);
|
|
|
|
|
|
+ if (!metadata.MMConverted)
|
|
|
|
+ {
|
|
|
|
+ if (meido.CurlingFront != curlingFront)
|
|
|
|
+ meido.SetCurling(Meido.Curl.Front, curlingFront);
|
|
|
|
|
|
- SerializeClothing(meido, tempWriter);
|
|
|
|
|
|
+ if (meido.CurlingBack != curlingBack)
|
|
|
|
+ meido.SetCurling(Meido.Curl.Back, curlingBack);
|
|
|
|
|
|
- writer.Write(memoryStream.Length);
|
|
|
|
- writer.Write(memoryStream.ToArray());
|
|
|
|
- }
|
|
|
|
|
|
+ meido.SetCurling(Meido.Curl.Shift, curlingPantsu);
|
|
|
|
+ }
|
|
|
|
|
|
- public override void Deserialize(Meido meido, BinaryReader reader, SceneMetadata metadata)
|
|
|
|
- {
|
|
|
|
- var maid = meido.Maid;
|
|
|
|
|
|
+ // MPN attach upper prop
|
|
|
|
+ var hasKousokuUpper = reader.ReadBoolean();
|
|
|
|
+ var upperMenuFile = reader.ReadString();
|
|
|
|
|
|
- maid.GetAnimation().Stop();
|
|
|
|
- meido.DetachAllMpnAttach();
|
|
|
|
- meido.StopBlink();
|
|
|
|
|
|
+ if (hasKousokuUpper)
|
|
|
|
+ meido.SetMpnProp(new MpnAttachProp(MPN.kousoku_upper, upperMenuFile), false);
|
|
|
|
|
|
- reader.ReadInt64(); // data length
|
|
|
|
|
|
+ // MPN attach lower prop
|
|
|
|
+ var hasKousokuLower = reader.ReadBoolean();
|
|
|
|
+ var lowerMenuFile = reader.ReadString();
|
|
|
|
|
|
- _ = reader.ReadVersion();
|
|
|
|
|
|
+ if (hasKousokuLower)
|
|
|
|
+ meido.SetMpnProp(new MpnAttachProp(MPN.kousoku_lower, lowerMenuFile), false);
|
|
|
|
|
|
- var transformDto = TransformDtoSerializer.Deserialize(reader, metadata);
|
|
|
|
- var maidTransform = maid.transform;
|
|
|
|
|
|
+ // hair gravity
|
|
|
|
+ var hairGravityActive = reader.ReadBoolean();
|
|
|
|
+ var hairPosition = reader.ReadVector3();
|
|
|
|
|
|
- // TODO: use transform.SetRotationAndPosition
|
|
|
|
- maidTransform.position = transformDto.Position;
|
|
|
|
- maidTransform.rotation = transformDto.Rotation;
|
|
|
|
- maidTransform.localScale = transformDto.LocalScale;
|
|
|
|
|
|
+ meido.HairGravityActive = hairGravityActive;
|
|
|
|
|
|
- meido.IKManager.SetDragPointScale(maidTransform.localScale.x);
|
|
|
|
|
|
+ if (meido.HairGravityActive)
|
|
|
|
+ meido.ApplyGravity(hairPosition);
|
|
|
|
|
|
- DeserializeHead(meido, reader, metadata);
|
|
|
|
|
|
+ // skirt gravity
|
|
|
|
+ var skirtGravityActive = reader.ReadBoolean();
|
|
|
|
+ var skirtPosition = reader.ReadVector3();
|
|
|
|
|
|
- DeserializeBody(meido, reader, metadata);
|
|
|
|
|
|
+ meido.SkirtGravityActive = skirtGravityActive;
|
|
|
|
|
|
- DeserializeClothing(meido, reader, metadata);
|
|
|
|
|
|
+ if (meido.SkirtGravityActive)
|
|
|
|
+ meido.ApplyGravity(skirtPosition, true);
|
|
|
|
+ }
|
|
}
|
|
}
|
|
}
|
|
}
|