340 lines
9.4 KiB
C#
340 lines
9.4 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using Unity.HLODSystem.Serializer;
|
|
using Unity.HLODSystem.SpaceManager;
|
|
using UnityEngine;
|
|
|
|
|
|
namespace Unity.HLODSystem.Streaming
|
|
{
|
|
public abstract class HLODControllerBase : MonoBehaviour, ISerializationCallbackReceiver
|
|
{
|
|
#region Interface
|
|
|
|
//This method is only used during creation.
|
|
//Because the GameObject may have been deleted in Runtime, it does not work.
|
|
//So, explicitly make it available only in the Editor.
|
|
#if UNITY_EDITOR
|
|
public abstract GameObject GetHighSceneObject(int id);
|
|
#endif
|
|
|
|
public abstract void Install();
|
|
|
|
|
|
public abstract void OnStart();
|
|
public abstract void OnStop();
|
|
|
|
public abstract int HighObjectCount { get; }
|
|
public abstract int LowObjectCount { get; }
|
|
|
|
public abstract void LoadHighObject(int id,Action<GameObject> loadDoneCallback);
|
|
public abstract void LoadLowObject(int id, Action<GameObject> loadDoneCallback);
|
|
|
|
public abstract void UnloadHighObject(int id);
|
|
public abstract void UnloadLowObject(int id);
|
|
|
|
#endregion
|
|
|
|
#region Unity Events
|
|
public void Awake()
|
|
{
|
|
m_spaceManager = new QuadTreeSpaceManager();
|
|
}
|
|
|
|
public void Start()
|
|
{
|
|
m_root.Initialize(this, m_spaceManager, null);
|
|
LoadManager.Instance.RegisterController(this);
|
|
OnStart();
|
|
}
|
|
|
|
public void OnEnable()
|
|
{
|
|
HLODManager.Instance.Register(this);
|
|
}
|
|
|
|
public void OnDisable()
|
|
{
|
|
HLODManager.Instance.Unregister(this);
|
|
}
|
|
|
|
public void OnDestroy()
|
|
{
|
|
OnStop();
|
|
LoadManager.Instance.UnregisterController(this);
|
|
HLODManager.Instance.Unregister(this);
|
|
m_spaceManager = null;
|
|
m_root = null;
|
|
}
|
|
#endregion
|
|
|
|
#region Method
|
|
class LoadInfo
|
|
{
|
|
public LoadManager.Handle Handle;
|
|
public List<Action<LoadManager.Handle>> Callbacks = new List<Action<LoadManager.Handle>>();
|
|
|
|
public void LoadDone(LoadManager.Handle handle)
|
|
{
|
|
foreach (var callback in Callbacks)
|
|
{
|
|
callback?.Invoke(handle);
|
|
}
|
|
Callbacks.Clear();
|
|
}
|
|
}
|
|
|
|
private Dictionary<int, LoadInfo> m_createdHighObjects = new Dictionary<int, LoadInfo>();
|
|
private Dictionary<int, LoadInfo> m_createdLowObjects = new Dictionary<int, LoadInfo>();
|
|
|
|
public LoadManager.Handle GetHighObject(int id, int level, float distance, Action<LoadManager.Handle> loadDoneCallback)
|
|
{
|
|
LoadInfo loadInfo = null;
|
|
//already processing object to load.
|
|
if (m_createdHighObjects.TryGetValue(id, out loadInfo) == true)
|
|
{
|
|
//already load done.
|
|
if (loadInfo.Handle.LoadedObject != null)
|
|
{
|
|
loadDoneCallback?.Invoke(loadInfo.Handle);
|
|
}
|
|
//not finished loading yet.
|
|
else
|
|
{
|
|
loadInfo.Callbacks.Add(loadDoneCallback);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
loadInfo = new LoadInfo();
|
|
m_createdHighObjects[id] = loadInfo;
|
|
loadInfo.Callbacks.Add(loadDoneCallback);
|
|
loadInfo.Handle = LoadManager.Instance.LoadHighObject(this, id, level, distance, loadInfo.LoadDone);
|
|
}
|
|
|
|
return loadInfo.Handle;
|
|
}
|
|
|
|
public LoadManager.Handle GetLowObject(int id, int level, float distance, Action<LoadManager.Handle> loadDoneCallback)
|
|
{
|
|
LoadInfo loadInfo = null;
|
|
//already processing object to load.
|
|
if (m_createdLowObjects.TryGetValue(id, out loadInfo) == true)
|
|
{
|
|
//already load done.
|
|
if (loadInfo.Handle.LoadedObject != null)
|
|
{
|
|
loadDoneCallback?.Invoke(loadInfo.Handle);
|
|
}
|
|
//not finished loading yet.
|
|
else
|
|
{
|
|
loadInfo.Callbacks.Add(loadDoneCallback);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
loadInfo = new LoadInfo();
|
|
m_createdLowObjects[id] = loadInfo;
|
|
loadInfo.Callbacks.Add(loadDoneCallback);
|
|
loadInfo.Handle = LoadManager.Instance.LoadLowObject(this, id, level, distance, loadInfo.LoadDone);
|
|
}
|
|
|
|
return loadInfo.Handle;
|
|
}
|
|
|
|
public void ReleaseHighObject(LoadManager.Handle handle)
|
|
{
|
|
if (m_createdHighObjects.ContainsKey(handle.Id) == false)
|
|
{
|
|
return;
|
|
}
|
|
|
|
m_createdHighObjects.Remove(handle.Id);
|
|
LoadManager.Instance.UnloadHighObject(handle);
|
|
}
|
|
|
|
public void ReleaseLowObject(LoadManager.Handle handle)
|
|
{
|
|
if (m_createdLowObjects.ContainsKey(handle.Id) == false)
|
|
{
|
|
return;
|
|
}
|
|
|
|
m_createdLowObjects.Remove(handle.Id);
|
|
LoadManager.Instance.UnloadLowObject(handle);
|
|
}
|
|
|
|
public void UpdateCull(Camera camera)
|
|
{
|
|
if (m_spaceManager == null)
|
|
return;
|
|
|
|
m_spaceManager.UpdateCamera(this.transform, camera);
|
|
|
|
if ( m_controlMode == Mode.AutoControl)
|
|
m_root.Cull(m_spaceManager.IsCull(m_cullDistance, m_root.Bounds));
|
|
else if (m_controlMode == Mode.ManualControl && m_manualLevel.value < 0 )
|
|
m_root.Cull(true);
|
|
else
|
|
m_root.Cull(false);
|
|
|
|
m_root.Update(m_controlMode, m_manualLevel.value, m_lodDistance);
|
|
}
|
|
|
|
public bool IsLoadDone()
|
|
{
|
|
return Root.IsLoadDone();
|
|
}
|
|
public int GetNodeCount()
|
|
{
|
|
return m_treeNodeContainer.Count;
|
|
}
|
|
public int GetReadyNodeCount()
|
|
{
|
|
int count = 0;
|
|
for ( int i = 0; i < m_treeNodeContainer.Count; ++i )
|
|
{
|
|
var node = m_treeNodeContainer.Get(i);
|
|
if (node.IsNodeReadySelf())
|
|
count += 1;
|
|
}
|
|
|
|
return count;
|
|
}
|
|
|
|
public void SetManualLevel(int level)
|
|
{
|
|
m_manualLevel.value = level;
|
|
}
|
|
|
|
public int GetManualLevel()
|
|
{
|
|
return m_manualLevel.value;
|
|
}
|
|
|
|
public int GetMaxManualLevel()
|
|
{
|
|
return m_manualLevel.maxValue;
|
|
}
|
|
|
|
public void SetControlMode(Mode mode)
|
|
{
|
|
m_controlMode = mode;
|
|
}
|
|
|
|
public void UpdateMaxManualLevel()
|
|
{
|
|
int maxLevel = 0;
|
|
for (int i = 0; i < m_treeNodeContainer.Count; ++i)
|
|
{
|
|
maxLevel = Mathf.Max(maxLevel, m_treeNodeContainer.Get(i).Level);
|
|
}
|
|
|
|
m_manualLevel.maxValue = maxLevel;
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region variables
|
|
private ISpaceManager m_spaceManager;
|
|
|
|
[SerializeField]
|
|
private HLODTreeNodeContainer m_treeNodeContainer;
|
|
[SerializeField]
|
|
private HLODTreeNode m_root;
|
|
|
|
[SerializeField] private float m_cullDistance;
|
|
[SerializeField] private float m_lodDistance;
|
|
|
|
[SerializeField]
|
|
private int m_controllerID;
|
|
|
|
[SerializeField]
|
|
private UserDataSerializerBase m_userDataSerializer;
|
|
|
|
[SerializeField]
|
|
private Mode m_controlMode = Mode.AutoControl;
|
|
[SerializeField]
|
|
|
|
private Utils.RangeInt m_manualLevel = new Utils.RangeInt(-1, 10, 0);
|
|
|
|
public enum Mode
|
|
{
|
|
DisableHLOD,
|
|
ManualControl,
|
|
AutoControl,
|
|
|
|
}
|
|
|
|
public HLODTreeNodeContainer Container
|
|
{
|
|
set
|
|
{
|
|
m_treeNodeContainer = value;
|
|
UpdateContainer();
|
|
}
|
|
get { return m_treeNodeContainer; }
|
|
}
|
|
|
|
public UserDataSerializerBase UserDataserializer
|
|
{
|
|
set
|
|
{
|
|
m_userDataSerializer = value;
|
|
}
|
|
get
|
|
{
|
|
return m_userDataSerializer;
|
|
}
|
|
}
|
|
|
|
public int ControllerID
|
|
{
|
|
set { m_controllerID = value;}
|
|
get { return m_controllerID; }
|
|
}
|
|
|
|
public HLODTreeNode Root
|
|
{
|
|
set
|
|
{
|
|
m_root = value;
|
|
UpdateContainer();
|
|
}
|
|
get { return m_root; }
|
|
}
|
|
|
|
public float CullDistance
|
|
{
|
|
set { m_cullDistance = value; }
|
|
get { return m_cullDistance; }
|
|
}
|
|
|
|
public float LODDistance
|
|
{
|
|
set { m_lodDistance = value; }
|
|
get { return m_lodDistance; }
|
|
}
|
|
#endregion
|
|
|
|
public void OnBeforeSerialize()
|
|
{
|
|
|
|
}
|
|
|
|
public void OnAfterDeserialize()
|
|
{
|
|
UpdateContainer();
|
|
}
|
|
|
|
private void UpdateContainer()
|
|
{
|
|
if (m_root == null)
|
|
return;
|
|
|
|
m_root.SetContainer(m_treeNodeContainer);
|
|
}
|
|
}
|
|
|
|
} |