using System.Collections.Generic; using System.Linq; using System.Xml; using System.Xml.Serialization; using UnityEngine; namespace RimWorldAnimationStudio { public class Actor { // Data to/from animationDef [XmlArray("defNames"), XmlArrayItem("li")] public List defNames; [XmlArray("bodyDefTypes"), XmlArrayItem("li")] public List bodyDefTypes; [XmlArray("requiredGenitals"), XmlArrayItem("li")] public List requiredGenitals; [XmlArray("raceOffsets"), XmlArrayItem("li")] public List raceOffsets; [XmlArray("tags"), XmlArrayItem("li")] public List tags; public BodyTypeOffset bodyTypeOffset; public bool? initiator = false; public bool? controlGenitalAngle; public bool? isFucking; public bool? isFucked; // Data serialization control public bool ShouldSerializedefNames() { return defNames.NotNullOrEmpty(); } public bool ShouldSerializebodyDefTypes() { return bodyDefTypes.NotNullOrEmpty(); } public bool ShouldSerializerequiredGenitals() { return requiredGenitals.NotNullOrEmpty(); } public bool ShouldSerializeraceOffsets() { return raceOffsets.NotNullOrEmpty(); } public bool ShouldSerializetags() { return tags.NotNullOrEmpty(); } public bool ShouldSerializebodyTypeOffset() { return bodyTypeOffset?.AllOffsetsEmpty() == false; } public bool ShouldSerializeinitiator() { return initiator == true; } public bool ShouldSerializecontrolGenitalAngle() { return controlGenitalAngle == true; } public bool ShouldSerializeisFucking() { return isFucking == true; } public bool ShouldSerializeisFucked() { return isFucked == true; } // Data helper functions [XmlIgnore] public List DefNames { get { return defNames.NullOrEmpty() ? defNames = new List() : defNames; } set { defNames = value.NotNullOrEmpty() ? value : null; EventsManager.OnActorChanged(this); } } [XmlIgnore] public List BodyDefTypes { get { return bodyDefTypes.NullOrEmpty() ? bodyDefTypes = new List() : bodyDefTypes; } set { bodyDefTypes = value.NotNullOrEmpty() ? value : null; EventsManager.OnActorChanged(this); } } [XmlIgnore] public List RequiredGenitals { get { return requiredGenitals.NullOrEmpty() ? requiredGenitals = new List() : requiredGenitals; } set { requiredGenitals = value.NotNullOrEmpty() ? value : null; EventsManager.OnActorChanged(this); } } [XmlIgnore] public List RaceOffsets { get { return raceOffsets.NullOrEmpty() ? raceOffsets = new List() : raceOffsets; } set { raceOffsets = value.NotNullOrEmpty() ? value : null; EventsManager.OnActorChanged(this); } } [XmlIgnore] public List Tags { get { return tags.NullOrEmpty() ? tags = new List() : tags; } set { tags = value.NotNullOrEmpty() ? value : null; EventsManager.OnActorChanged(this); } } [XmlIgnore] public BodyTypeOffset BodyTypeOffset { get { return bodyTypeOffset == null ? bodyTypeOffset = new BodyTypeOffset() : bodyTypeOffset; } set { bodyTypeOffset = value; EventsManager.OnActorChanged(this); } } [XmlIgnore] public bool Initiator { get { return initiator == true; } set { if (value) { initiator = true; } else initiator = null; EventsManager.OnActorChanged(this); } } [XmlIgnore] public bool ControlGenitalAngle { get { return controlGenitalAngle == true; } set { if (value) { controlGenitalAngle = true; } else controlGenitalAngle = null; EventsManager.OnActorChanged(this); } } [XmlIgnore] public bool IsFucking { get { return isFucking == true; } set { if (value) { isFucking = true; } else isFucking = null; EventsManager.OnActorChanged(this); } } [XmlIgnore] public bool IsFucked { get { return isFucked == true; } set { if (value) { isFucked = true; } else isFucked = null; EventsManager.OnActorChanged(this); } } // Local data [XmlIgnore] public string bodyType = "Male"; [XmlIgnore] private PawnRaceDef pawnRaceDef; // Methods public PawnRaceDef GetPawnRaceDef() { if (pawnRaceDef == null) { pawnRaceDef = PawnRaceDefs.GetNamed("Human"); } return pawnRaceDef; } public void SetPawnRaceDef(string pawnRaceDefName) { PawnRaceDef pawnRaceDef = PawnRaceDefs.GetNamed(pawnRaceDefName); if (pawnRaceDef != null) { this.pawnRaceDef = pawnRaceDef; EventsManager.OnActorChanged(this); } } public Vector3 GetPawnRaceOffset() { if (pawnRaceDef == null) { pawnRaceDef = PawnRaceDefs.GetNamed("Human"); } PawnRaceOffset raceOffset = RaceOffsets.FirstOrDefault(x => x.defName == pawnRaceDef.defName); if (raceOffset == null) { raceOffset = new PawnRaceOffset(pawnRaceDef.defName); RaceOffsets.Add(raceOffset); } return raceOffset.GetOffset(); } public void SetPawnRaceOffset(Vector2 offset) { if (pawnRaceDef == null) { return; } PawnRaceOffset raceOffset = RaceOffsets.FirstOrDefault(x => x.defName == pawnRaceDef.defName); if (raceOffset == null) { raceOffset = new PawnRaceOffset(pawnRaceDef.defName); RaceOffsets.Add(raceOffset); EventsManager.OnActorChanged(this); } raceOffset.SetOffset(offset); } public Vector3 GetFinalTransformOffset() { Vector3 offset = GetPawnRaceOffset() + (GetPawnRaceDef().isHumanoid ? BodyTypeOffset.GetOffset(bodyType) : new Vector3()); return new Vector3(offset.x, offset.z, offset.y); } public int GetActorID() { if (Workspace.animationDef == null) return -1; return Workspace.animationDef.Actors.IndexOf(this); } // Pre-save / post-load public void OnPreSave() { BodyDefTypes = BodyDefTypes.Intersect(DefaultTags.bodyDefTypes.Concat(CustomTags.bodyDefTypes))?.ToList(); RequiredGenitals = RequiredGenitals.Intersect(DefaultTags.bodyParts.Concat(CustomTags.bodyParts))?.ToList(); RaceOffsets = RaceOffsets.Except(RaceOffsets.Where(x => x.OffsetIsZero()))?.ToList(); } public void OnPostLoad() { } } }