using System.Linq; using UnityEngine; using Newtonsoft.Json; using System.Collections.Generic; public class ObjectContainer : MonoBehaviour, IKeyframeSetter { protected virtual System.Type _serializeType => typeof(ObjectContainerSerializable); protected virtual System.Type _keyframeType => typeof(KeyframeData); [JsonIgnore] public bool DoNotSave; public int ModelId; public string GUID = ""; public bool LoadInProgress = false; public List Handles = new List(); public List Renderers = new List(); public Dictionary> Morphs = new Dictionary>(); public List Frames = new List(); public List InstantiatedObjects = new List(); public List LoadedAssets = new List(); protected bool _setKeyframe = true; protected bool _applicationQuitting = false; public void Awake() { if (GUID == "") GUID = System.Guid.NewGuid().ToString(); } public static T Create(string name = "Container") where T : ObjectContainer { var container = new GameObject(name).AddComponent(); return container; } protected virtual void Start() { if (ModelViewerMain.GetInstance() == null) return; if (DoNotSave) return; if(Frames.Count == 0) { SetDefaultFrame(); } ModelViewerMain.RegisterObject(this); } public virtual void PasteContainer(ObjectContainerSerializable bones, PoseLoadOptions pasteParams) { GUID = bones.GUID; } public virtual Vector3 GetCenter() { return transform.position; } public void ToggleVisible(GameObject go, bool value) { go.SetActive(value); } public void ToggleRendererVisible(Renderer r, bool value) { r.enabled = value; } public virtual ObjectContainerSerializable Serialize() { return ObjectContainerSerializable.Serialize(_serializeType, this); } public virtual KeyframeData SerializeFrame() { return KeyframeData.Serialize(_keyframeType, this); } protected virtual void OnDestroy() { if (_applicationQuitting) return; foreach (var rend in Renderers) { for (int i = rend.sharedMaterials.Length - 1; i >= 0; i--) { Destroy(rend.sharedMaterials[i]); } } foreach (var obj in InstantiatedObjects) { Destroy(obj); } ModelViewerMain.UnregisterObject(this); if (gameObject != null) Destroy(gameObject); ModelViewerMain.OnObjectDeleteEvent.Invoke(this); Resources.UnloadUnusedAssets(); System.GC.Collect(); } #region Timeline public virtual DataType GetDataType() { switch (this) { case CameraContainer _: return DataType.Camera; default: return DataType.Character; } } public FrameContent TryGetFrame(int frameNum) { return Frames.FirstOrDefault(f => f.FrameNum == frameNum); } public void GetClosestFrames(int frame, out FrameContent previousFrame, out FrameContent nextFrame) { previousFrame = null; nextFrame = null; var frames = Frames.OrderBy(f => f.FrameNum).ToArray(); for (int i = 0; i < Frames.Count; i++) { if (Frames[i].FrameNum < frame) { previousFrame = nextFrame = frames[i]; } else if (Frames[i].FrameNum == frame) { previousFrame = nextFrame = frames[i]; break; } else if (Frames[i].FrameNum > frame) { if (previousFrame == null) previousFrame = frames[i]; nextFrame = frames[i]; break; } } } /// Returns true if frame existed or false if it was created public bool GetCurrentFrame(int frame, out FrameContent currentFrame) { GetClosestFrames(frame, out var previousFrame, out var nextFrame); if (previousFrame.FrameNum == frame) { currentFrame = previousFrame; return true; } else if (nextFrame.FrameNum == frame) { currentFrame = nextFrame; return true; } else { currentFrame = new FrameContent(frame); Frames.Add(currentFrame); Frames = Frames.OrderBy(f => f.FrameNum).ToList(); return false; } } public virtual void SetKeyframe(int frameNum = -1) { if (DoNotSave || !_setKeyframe) return; //Debug.Log("Setting frame for " + name); //if (Frames.Count == 0) SetDefaultFrame(); if (frameNum == -1) frameNum = TimelineController.Instance.CurrentFrame; GetClosestFrames(frameNum, out var previousFrame, out var nextFrame); FrameContent currentFrame = null; if (previousFrame == null || previousFrame.FrameNum != frameNum) { currentFrame = new FrameContent(frameNum); Frames.Add(currentFrame); Frames = Frames.OrderBy(f => f.FrameNum).ToList(); } else if (previousFrame.FrameNum == frameNum) currentFrame = previousFrame; else if (nextFrame.FrameNum == frameNum) currentFrame = nextFrame; currentFrame.SetObjectData(SerializeFrame()); TimelineController.UpdateTimeline(); } public void SetDefaultFrame() { Debug.Log("Setting default frames for " + name); Frames = new List() { new FrameContent(0).SetObjectData(SerializeFrame()) }; } public virtual void DeserializeFrames(ObjectContainerSerializable serialized) { Frames = serialized.Frames.Select(f => new FrameContent(f)).ToList(); } public virtual void Lerp(KeyframeData frame1, KeyframeData frame2, float amount) { if (frame1 == frame2) { PastePose(frame1, new PoseLoadOptions(true)); } else { PastePose(frame1.Lerp(frame2, amount), new PoseLoadOptions(true)); } } public virtual void PastePose(KeyframeData frame, PoseLoadOptions pasteParams) { if (pasteParams.Root) { transform.SetTransform(frame.Root); } } public virtual void Deselect() { } public virtual void Select() { AssetLibrary.GetInstance().SetAssetList(LoadedAssets.Select(a=> new string[] {a.Name, a.FilePath}).ToList()); } public virtual void Destroy() { Destroy(this.gameObject); } public void EnableKeyframeSet() { _setKeyframe = true; } public void DisableKeyframeSet() { _setKeyframe = false; } #endregion private void OnApplicationQuit() { _applicationQuitting = true; } }