UniversalViewer/Assets/Scripts/ModelViewerBase/Containers/ObjectContainer.cs

257 lines
7.0 KiB
C#
Raw Permalink Normal View History

2024-04-21 22:38:26 +08:00
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);
2024-04-21 22:38:26 +08:00
[JsonIgnore] public bool DoNotSave;
public int ModelId;
public string GUID = "";
public bool LoadInProgress = false;
public List<UIHandle> Handles = new List<UIHandle>();
public List<Renderer> Renderers = new List<Renderer>();
public Dictionary<SkinnedMeshRenderer, List<MorphHelper>> Morphs = new Dictionary<SkinnedMeshRenderer, List<MorphHelper>>();
public List<FrameContent> Frames = new List<FrameContent>();
public List<GameObject> InstantiatedObjects = new List<GameObject>();
public List<AssetBundleEntry> LoadedAssets = new List<AssetBundleEntry>();
2024-04-21 22:38:26 +08:00
protected bool _setKeyframe = true;
protected bool _applicationQuitting = false;
public void Awake()
{
if (GUID == "")
GUID = System.Guid.NewGuid().ToString();
}
public static T Create<T>(string name = "Container") where T : ObjectContainer
{
var container = new GameObject(name).AddComponent<T>();
return container;
}
protected virtual void Start()
{
if (ModelViewerMain.GetInstance() == null) return;
if (DoNotSave) return;
if(Frames.Count == 0)
2024-04-21 22:38:26 +08:00
{
SetDefaultFrame();
2024-04-21 22:38:26 +08:00
}
ModelViewerMain.RegisterObject(this);
2024-04-21 22:38:26 +08:00
}
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);
2024-04-21 22:38:26 +08:00
}
public virtual KeyframeData SerializeFrame()
{
return KeyframeData.Serialize(_keyframeType, this);
2024-04-21 22:38:26 +08:00
}
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);
2024-04-21 22:38:26 +08:00
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;
}
}
}
/// <summary> Returns true if frame existed or false if it was created </summary>
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;
2024-04-22 06:00:51 +08:00
//Debug.Log("Setting frame for " + name);
2024-04-21 22:38:26 +08:00
//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);
2024-04-21 22:38:26 +08:00
Frames = new List<FrameContent>()
{
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());
2024-04-21 22:38:26 +08:00
}
public virtual void Destroy()
2024-04-21 22:38:26 +08:00
{
Destroy(this.gameObject);
}
public void EnableKeyframeSet()
{
_setKeyframe = true;
}
public void DisableKeyframeSet()
{
_setKeyframe = false;
}
#endregion
private void OnApplicationQuit()
{
_applicationQuitting = true;
}
}