| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511 | using System;using System.Collections.Generic;using System.Linq;using UnityEngine;using UnityEngine.Rendering;namespace COM3D2.MeidoPhotoStudio.Plugin{    using static MenuFileUtility;    internal class PropManager : IManager    {        public const string header = "PROP";        private MeidoManager meidoManager;        private static bool cubeActive = true;        public static bool CubeActive        {            get => cubeActive;            set            {                if (value != cubeActive)                {                    cubeActive = value;                    CubeActiveChange?.Invoke(null, EventArgs.Empty);                }            }        }        private static bool cubeSmall;        public static bool CubeSmall        {            get => cubeSmall;            set            {                if (value != cubeSmall)                {                    cubeSmall = value;                    CubeSmallChange?.Invoke(null, EventArgs.Empty);                }            }        }        private static event EventHandler CubeActiveChange;        private static event EventHandler CubeSmallChange;        private List<DragPointDogu> doguList = new List<DragPointDogu>();        public int DoguCount => doguList.Count;        public event EventHandler DoguListChange;        public string[] PropNameList        {            get            {                return doguList.Count == 0                    ? new[] { Translation.Get("systemMessage", "noProps") }                    : doguList.Select(dogu => dogu.Name).ToArray();            }        }        public PropManager(MeidoManager meidoManager)        {            this.meidoManager = meidoManager;            this.meidoManager.BeginCallMeidos += DetachProps;            this.meidoManager.EndCallMeidos += OnEndCall;        }        public void Serialize(System.IO.BinaryWriter binaryWriter)        {            binaryWriter.Write(header);            binaryWriter.Write(doguList.Count);            foreach (DragPointDogu dogu in doguList)            {                binaryWriter.Write(dogu.assetName);                AttachPointInfo info = dogu.attachPointInfo;                info.Serialize(binaryWriter);                binaryWriter.WriteVector3(dogu.MyObject.position);                binaryWriter.WriteQuaternion(dogu.MyObject.rotation);                binaryWriter.WriteVector3(dogu.MyObject.localScale);            }        }        public void Deserialize(System.IO.BinaryReader binaryReader)        {            Dictionary<string, string> modToModPath = null;            ClearDogu();            int numberOfProps = binaryReader.ReadInt32();            for (int i = 0; i < numberOfProps; i++)            {                string assetName = binaryReader.ReadString();                bool result = false;                if (assetName.EndsWith(".menu"))                {                    if (assetName.Contains('#'))                    {                        if (modToModPath == null)                        {                            modToModPath = new Dictionary<string, string>(StringComparer.InvariantCultureIgnoreCase);                            foreach (string mod in Menu.GetModFiles())                            {                                modToModPath.Add(System.IO.Path.GetFileName(mod), mod);                            }                        }                        string[] assetParts = assetName.Split('#');                        ModItem item = new ModItem()                        {                            MenuFile = modToModPath[assetParts[0]],                            BaseMenuFile = assetParts[1],                            IsMod = true,                            IsOfficialMod = true                        };                        result = SpawnModItemProp(item);                    }                    else                    {                        if (assetName.StartsWith("handitem")) result = SpawnObject(assetName);                        else result = SpawnModItemProp(new ModItem() { MenuFile = assetName });                    }                }                else if (assetName.StartsWith("MYR_"))                {                    string[] assetParts = assetName.Split('#');                    int id = int.Parse(assetParts[0].Substring(4));                    string prefabName;                    if (assetParts.Length == 2 && !string.IsNullOrEmpty(assetParts[1])) prefabName = assetParts[1];                    else                    {                        // deserialize modifiedMM and maybe MM 23.0+.                        MyRoomCustom.PlacementData.Data data = MyRoomCustom.PlacementData.GetData(id);                        prefabName = !string.IsNullOrEmpty(data.resourceName) ? data.resourceName : data.assetName;                    }                    result = SpawnMyRoomProp(new MyRoomItem() { ID = id, PrefabName = prefabName });                }                else if (assetName.StartsWith("BG_")) result = SpawnBG(assetName);                else result = SpawnObject(assetName);                AttachPointInfo info = AttachPointInfo.Deserialize(binaryReader);                Vector3 position = binaryReader.ReadVector3();                Quaternion rotation = binaryReader.ReadQuaternion();                Vector3 scale = binaryReader.ReadVector3();                if (result)                {                    DragPointDogu dogu = doguList[i];                    Transform obj = dogu.MyObject;                    obj.position = position;                    obj.rotation = rotation;                    obj.localScale = scale;                    dogu.attachPointInfo = info;                }            }            GameMain.Instance.StartCoroutine(DeserializeAttach());        }        private System.Collections.IEnumerator DeserializeAttach()        {            yield return new WaitForEndOfFrame();            foreach (DragPointDogu dogu in doguList)            {                AttachPointInfo info = dogu.attachPointInfo;                if (info.AttachPoint != AttachPoint.None)                {                    Meido parent = meidoManager.GetMeido(info.MaidIndex);                    if (parent != null)                    {                        Transform obj = dogu.MyObject;                        Vector3 position = obj.position;                        Vector3 scale = obj.localScale;                        Quaternion rotation = obj.rotation;                        Transform point = parent.IKManager.GetAttachPointTransform(info.AttachPoint);                        dogu.MyObject.SetParent(point, true);                        info = new AttachPointInfo(                            info.AttachPoint,                            parent.Maid.status.guid,                            parent.Slot                        );                        obj.position = position;                        obj.localScale = scale;                        obj.rotation = rotation;                    }                }            }        }        public void Activate()        {            CubeSmallChange += OnCubeSmall;        }        public void Deactivate()        {            ClearDogu();            CubeSmallChange -= OnCubeSmall;        }        public void Update() { }        private void ClearDogu()        {            foreach (DragPointDogu dogu in doguList)            {                if (dogu != null)                {                    dogu.Delete -= DeleteDogu;                    GameObject.Destroy(dogu.gameObject);                }            }            doguList.Clear();        }        private GameObject GetDeploymentObject()        {            return GameObject.Find("Deployment Object Parent")                ?? new GameObject("Deployment Object Parent");        }        public bool SpawnModItemProp(ModItem modItem)        {            GameObject dogu = MenuFileUtility.LoadModel(modItem);            string name = modItem.MenuFile;            if (dogu != null) AttachDragPoint(dogu, modItem.ToString(), name, new Vector3(0f, 0f, 0.5f));            return dogu != null;        }        public bool SpawnMyRoomProp(MyRoomItem item)        {            MyRoomCustom.PlacementData.Data data = MyRoomCustom.PlacementData.GetData(item.ID);            GameObject dogu = GameObject.Instantiate(data.GetPrefab());            string name = Translation.Get("myRoomPropNames", item.PrefabName);            if (dogu != null) AttachDragPoint(dogu, item.ToString(), name, new Vector3(0f, 0f, 0.5f));            else Utility.LogInfo($"Could not load MyRoomCreative prop '{item.PrefabName}'");            return dogu != null;        }        public bool SpawnBG(string assetName)        {            if (assetName.StartsWith("BG_")) assetName = assetName.Substring(3);            GameObject obj = GameMain.Instance.BgMgr.CreateAssetBundle(assetName)                ?? Resources.Load<GameObject>("BG/" + assetName)                ?? Resources.Load<GameObject>("BG/2_0/" + assetName);            if (obj != null)            {                GameObject dogu = GameObject.Instantiate(obj);                string name = Translation.Get("bgNames", assetName);                dogu.transform.localScale = Vector3.one * 0.1f;                AttachDragPoint(dogu, $"BG_{assetName}", name, Vector3.zero);            }            return obj != null;        }        public bool SpawnObject(string assetName)        {            // TODO: Add a couple more things to ignore list            GameObject dogu = null;            string doguName = Translation.Get("propNames", assetName, false);            Vector3 doguPosition = new Vector3(0f, 0f, 0.5f);            if (assetName.EndsWith(".menu"))            {                dogu = MenuFileUtility.LoadModel(assetName);                string handItem = Utility.HandItemToOdogu(assetName);                if (Translation.Has("propNames", handItem)) doguName = Translation.Get("propNames", handItem);            }            else if (assetName.StartsWith("mirror"))            {                Material mirrorMaterial = new Material(Shader.Find("Mirror"));                dogu = GameObject.CreatePrimitive(PrimitiveType.Plane);                Renderer mirrorRenderer = dogu.GetComponent<Renderer>();                mirrorRenderer.material = mirrorMaterial;                mirrorRenderer.enabled = true;                MirrorReflection2 mirrorReflection = dogu.AddComponent<MirrorReflection2>();                mirrorReflection.m_TextureSize = 2048;                Vector3 localPosition = new Vector3(0f, 0.96f, 0f);                dogu.transform.Rotate(dogu.transform.right, 90f);                switch (assetName)                {                    case "mirror1":                        dogu.transform.localScale = new Vector3(0.2f, 0.4f, 0.2f);                        break;                    case "mirror2":                        dogu.transform.localScale = new Vector3(0.1f, 0.4f, 0.2f);                        break;                    case "mirror3":                        localPosition.y = 0.85f;                        dogu.transform.localScale = new Vector3(0.03f, 0.18f, 0.124f);                        break;                }                dogu.transform.localPosition = localPosition;            }            else if (assetName.IndexOf(':') >= 0)            {                string[] assetParts = assetName.Split(':');                GameObject obj = GameMain.Instance.BgMgr.CreateAssetBundle(assetParts[0])                    ?? Resources.Load<GameObject>("BG/" + assetParts[0]);                try                {                    GameObject bg = GameObject.Instantiate(obj);                    int num = int.Parse(assetParts[1]);                    dogu = bg.transform.GetChild(num).gameObject;                    dogu.transform.SetParent(null);                    GameObject.Destroy(bg);                }                catch { }            }            else            {                GameObject obj = GameMain.Instance.BgMgr.CreateAssetBundle(assetName)                    ?? Resources.Load<GameObject>("Prefab/" + assetName);                try                {                    dogu = GameObject.Instantiate<GameObject>(obj);                    dogu.transform.localPosition = Vector3.zero;                    MeshRenderer[] meshRenderers = dogu.GetComponentsInChildren<MeshRenderer>();                    for (int i = 0; i < meshRenderers.Length; i++)                    {                        if (meshRenderers[i] != null                            && meshRenderers[i].gameObject.name.ToLower().IndexOf("castshadow") < 0                        ) meshRenderers[i].shadowCastingMode = ShadowCastingMode.Off;                    }                    Collider collider = dogu.transform.GetComponent<Collider>();                    if (collider != null) collider.enabled = false;                    foreach (Transform transform in dogu.transform)                    {                        collider = transform.GetComponent<Collider>();                        if (collider != null)                        {                            collider.enabled = false;                        }                    }                }                catch { }                #region particle system experiment                // if (asset.StartsWith("Particle/"))                // {                //     ParticleSystem particleSystem = go.GetComponent<ParticleSystem>();                //     if (particleSystem != null)                //     {                //         ParticleSystem.MainModule main;                //         main = particleSystem.main;                //         main.loop = true;                //         main.duration = Mathf.Infinity;                //         ParticleSystem[] particleSystems = particleSystem.GetComponents<ParticleSystem>();                //         foreach (ParticleSystem part in particleSystems)                //         {                //             ParticleSystem.EmissionModule emissionModule = part.emission;                //             ParticleSystem.Burst[] bursts = new ParticleSystem.Burst[emissionModule.burstCount];                //             emissionModule.GetBursts(bursts);                //             for (int i = 0; i < bursts.Length; i++)                //             {                //                 bursts[i].cycleCount = Int32.MaxValue;                //             }                //             emissionModule.SetBursts(bursts);                //             main = part.main;                //             main.loop = true;                //             main.duration = Mathf.Infinity;                //         }                //     }                // }                #endregion            }            if (dogu != null)            {                AttachDragPoint(dogu, assetName, doguName, doguPosition);                return true;            }            else            {                Utility.LogInfo($"Could not spawn object '{assetName}'");            }            return false;        }        private void AttachDragPoint(GameObject dogu, string assetName, string name, Vector3 position)        {            // TODO: Figure out why some props aren't centred properly            // Doesn't happen in MM but even after copy pasting the code, it doesn't work :/            GameObject deploymentObject = GetDeploymentObject();            GameObject finalDogu = new GameObject(name);            dogu.transform.SetParent(finalDogu.transform, true);            finalDogu.transform.SetParent(deploymentObject.transform, false);            finalDogu.transform.position = position;            DragPointDogu dragDogu = DragPoint.Make<DragPointDogu>(                PrimitiveType.Cube, Vector3.one * 0.12f, DragPoint.LightBlue            );            dragDogu.Initialize(() => finalDogu.transform.position, () => Vector3.zero);            dragDogu.Set(finalDogu.transform);            dragDogu.AddGizmo(scale: 0.45f, mode: CustomGizmo.GizmoMode.World);            dragDogu.ConstantScale = true;            dragDogu.Delete += DeleteDogu;            dragDogu.DragPointScale = CubeSmall ? DragPointGeneral.smallCube : 1f;            dragDogu.assetName = assetName;            doguList.Add(dragDogu);            OnDoguListChange();        }        public DragPointDogu GetDogu(int doguIndex)        {            if (doguList.Count == 0 || doguIndex >= doguList.Count || doguIndex < 0) return null;            return doguList[doguIndex];        }        public void AttachProp(            int doguIndex, AttachPoint attachPoint, Meido meido, bool worldPositionStays = true        )        {            if (doguList.Count == 0 || doguIndex >= doguList.Count || doguIndex < 0) return;            AttachProp(doguList[doguIndex], attachPoint, meido, worldPositionStays);        }        private void AttachProp(            DragPointDogu dragDogu, AttachPoint attachPoint, Meido meido, bool worldPositionStays = true        )        {            GameObject dogu = dragDogu.MyGameObject;            Transform attachPointTransform = meido?.IKManager.GetAttachPointTransform(attachPoint)                ?? GetDeploymentObject().transform;            dragDogu.attachPointInfo = new AttachPointInfo(                attachPoint: meido == null ? AttachPoint.None : attachPoint,                maidGuid: meido == null ? String.Empty : meido.Maid.status.guid,                maidIndex: meido == null ? -1 : meido.Slot            );            Vector3 position = dogu.transform.position;            Quaternion rotation = dogu.transform.rotation;            Vector3 scale = dogu.transform.localScale;            dogu.transform.SetParent(attachPointTransform, worldPositionStays);            if (worldPositionStays)            {                dogu.transform.position = position;                dogu.transform.rotation = rotation;            }            else            {                dogu.transform.localPosition = Vector3.zero;                dogu.transform.rotation = Quaternion.identity;            }            dogu.transform.localScale = scale;            if (meido == null) Utility.FixGameObjectScale(dogu);        }        private void DetachProps(object sender, EventArgs args)        {            foreach (DragPointDogu dogu in doguList)            {                if (dogu.attachPointInfo.AttachPoint != AttachPoint.None)                {                    dogu.MyObject.SetParent(GetDeploymentObject().transform, true);                }            }        }        private void OnEndCall(object sender, EventArgs args) => ReattachProps(useGuid: true);        private void ReattachProps(bool useGuid, bool forceStay = false)        {            foreach (DragPointDogu dragDogu in doguList)            {                AttachPointInfo info = dragDogu.attachPointInfo;                Meido meido = useGuid                    ? this.meidoManager.GetMeido(info.MaidGuid)                    : this.meidoManager.GetMeido(info.MaidIndex);                bool worldPositionStays = forceStay || meido == null;                AttachProp(dragDogu, dragDogu.attachPointInfo.AttachPoint, meido, worldPositionStays);            }        }        private void DeleteDogu(object sender, EventArgs args)        {            DragPointDogu dogu = (DragPointDogu)sender;            doguList.RemoveAll(dragDogu =>                {                    if (dragDogu == dogu)                    {                        GameObject.Destroy(dragDogu.gameObject);                        return true;                    }                    return false;                }            );            OnDoguListChange();        }        private void OnCubeSmall(object sender, EventArgs args)        {            foreach (DragPointDogu dogu in doguList)            {                dogu.DragPointScale = CubeSmall ? DragPointGeneral.smallCube : 1f;            }        }        private void OnDoguListChange()        {            this.DoguListChange?.Invoke(this, EventArgs.Empty);        }    }}
 |