262 lines
7.0 KiB
C#
262 lines
7.0 KiB
C#
using UnityEngine;
|
||
using UnityEngine.Playables;
|
||
using System;
|
||
using System.Threading.Tasks;
|
||
|
||
public enum EBuildingType
|
||
{
|
||
UpgradeBuilding = 0,
|
||
Pause = 1,
|
||
Continue = 2,
|
||
Next = 3,
|
||
OpenFix = 4,
|
||
}
|
||
|
||
public class OnUpgradeBuildingData
|
||
{
|
||
public OnUpgradeBuildingData(EBuildingType buildingType, bool CanContinue = true)
|
||
{
|
||
this.type = buildingType;
|
||
this.CanContinue = CanContinue;
|
||
}
|
||
public EBuildingType type;//0-UpgradeBuilding;1-暂停;2-继续;3-下一步 (-1-打开修复)
|
||
public bool CanContinue;//是否可以继续
|
||
public int TimelineId;
|
||
public float StartTime;
|
||
public float Duration;
|
||
public float Speed = 1;
|
||
public string NextPrefab;
|
||
public string CurrentPrefab;
|
||
}
|
||
|
||
public class OnUpgradeBuildingFix
|
||
{
|
||
public TaskCompletionSource<bool> ts = new TaskCompletionSource<bool>();
|
||
}
|
||
|
||
public class SwitchVirtualCameraEvent
|
||
{
|
||
public int type;
|
||
public bool isDrag = true;
|
||
}
|
||
|
||
public class Building : MonoBehaviour
|
||
{
|
||
public PlayableDirector[] directors;
|
||
public PlayableDirector fix;
|
||
public PlayableDirector fade;
|
||
public PlayableDirector enter;
|
||
double _targetTime;
|
||
PlayableDirector _currentDirector;
|
||
private OnUpgradeBuildingData _upgradeBuildingData;
|
||
|
||
private void Awake()
|
||
{
|
||
if (fix == null && transform.parent != null)
|
||
{
|
||
fix = transform.parent.Find("Fix")?.GetComponent<PlayableDirector>();
|
||
}
|
||
if (directors != null && directors.Length > 0)
|
||
{
|
||
for (int i = 0; i < directors.Length; i++)
|
||
{
|
||
var director = directors[i];
|
||
director.initialTime = 0;
|
||
director.Evaluate();
|
||
}
|
||
}
|
||
}
|
||
|
||
public void SetTimelineDone(int index)
|
||
{
|
||
if (index >= directors.Length)
|
||
{
|
||
Debug.LogError($"[Building::SetTimelineDone] index {index} is out of range, directors length is {directors.Length}");
|
||
index = directors.Length - 1;
|
||
}
|
||
var director = directors[index];
|
||
director.time = director.duration;
|
||
director.initialTime = director.time;
|
||
}
|
||
|
||
public void SetTimelineAllDone()
|
||
{
|
||
for (int i = 0; i < directors.Length; i++)
|
||
{
|
||
var director = directors[i];
|
||
director.time = director.duration;
|
||
director.initialTime = director.time;
|
||
director.Evaluate();
|
||
}
|
||
}
|
||
|
||
public void SetCurrentTimeLine(int index, float startTime, float duration, bool evaluate)
|
||
{
|
||
if (index >= directors.Length)
|
||
{
|
||
Debug.LogError($"[Building::SetCurrentTimeLine] index {index} is out of range, directors length is {directors.Length}");
|
||
index = directors.Length - 1;
|
||
}
|
||
|
||
var director = directors[index];
|
||
|
||
if (!evaluate)
|
||
{
|
||
director.time = 0;
|
||
director.initialTime = 0;
|
||
}
|
||
|
||
if (director.time >= startTime + duration)
|
||
{
|
||
return;
|
||
}
|
||
|
||
director.time = startTime;
|
||
|
||
director.initialTime = startTime;
|
||
|
||
_targetTime = startTime + duration;
|
||
|
||
if (_targetTime > director.duration + 0.01f)
|
||
{
|
||
Debug.LogError($"[Building::SetCurrentTimeLine] _targetTime {startTime + duration} is greater than director duration {director.duration}, clamping to duration.");
|
||
_targetTime = (float)director.duration;
|
||
}
|
||
|
||
if (evaluate)
|
||
{
|
||
director.Evaluate();
|
||
_currentDirector = director;
|
||
}
|
||
}
|
||
|
||
public void EvaluateAllDrictors()
|
||
{
|
||
for (int i = 0; i < directors.Length; i++)
|
||
{
|
||
var director = directors[i];
|
||
director.Evaluate();
|
||
}
|
||
}
|
||
|
||
public void Show(CampDataMM campData)
|
||
{
|
||
if (_currentDirector != null)
|
||
_currentDirector.Pause();
|
||
if (campData != null && campData.TimelineId >= 0 && campData.TimelineId < directors.Length)
|
||
{
|
||
_currentDirector = directors[campData.TimelineId];
|
||
}
|
||
else
|
||
{
|
||
_currentDirector = directors[^1];
|
||
Debug.LogError($"[Building::Show] campData is null or TimelineId {campData?.TimelineId} is out of range, directors length is {directors.Length}");
|
||
}
|
||
_currentDirector.gameObject.SetActive(true);
|
||
_currentDirector.Evaluate();
|
||
}
|
||
|
||
public void ShowFix()
|
||
{
|
||
if (fix != null)
|
||
{
|
||
fix.initialTime = 0;
|
||
fix.Evaluate();
|
||
fix.gameObject.SetActive(true);
|
||
}
|
||
else
|
||
{
|
||
Debug.LogError("fix is null");
|
||
}
|
||
}
|
||
|
||
public void OnUpgradeBuilding(OnUpgradeBuildingData data)
|
||
{
|
||
switch (data.type)
|
||
{
|
||
case EBuildingType.UpgradeBuilding:
|
||
|
||
//Debug.Log($"[Building::OnUpgradeBuilding update] director {_currentDirector.state} {_currentDirector.name} time {_currentDirector.time} {_targetTime}");
|
||
_currentDirector.Play();
|
||
_currentDirector.playableGraph.GetRootPlayable(0).SetSpeed(data.Speed);
|
||
_upgradeBuildingData = data;
|
||
break;
|
||
case EBuildingType.Pause:
|
||
_currentDirector.Pause();
|
||
break;
|
||
case EBuildingType.Continue:
|
||
_currentDirector.Resume();
|
||
break;
|
||
case EBuildingType.Next:
|
||
OnNext(data.TimelineId, data.StartTime, data.Duration);
|
||
break;
|
||
|
||
#if UNITY_EDITOR
|
||
case EBuildingType.OpenFix:
|
||
ShowFix();
|
||
break;
|
||
#endif
|
||
default:
|
||
break;
|
||
}
|
||
}
|
||
|
||
private void OnNext(int TimelineId, float startTime, float duration)
|
||
{
|
||
SetCurrentTimeLine(TimelineId, startTime, duration, true);
|
||
}
|
||
|
||
public async void OnFix(OnUpgradeBuildingFix onUpgradeBuildingFix, Action onFixed)
|
||
{
|
||
if (fix)
|
||
{
|
||
fix.Play();
|
||
await Awaiters.Seconds((float)fix.duration);
|
||
if (fix)
|
||
{
|
||
fix.Stop();
|
||
fix.gameObject.SetActive(false);
|
||
}
|
||
onFixed?.Invoke();
|
||
}
|
||
}
|
||
|
||
public double Fade()
|
||
{
|
||
if (fade == null)
|
||
return 0;
|
||
fade.time = 0;
|
||
fade.initialTime = 0;
|
||
_currentDirector = null;
|
||
fade.Play();
|
||
return fade.duration;
|
||
}
|
||
|
||
public double Enter()
|
||
{
|
||
if (enter == null)
|
||
return 0;
|
||
enter.time = 0;
|
||
enter.initialTime = 0;
|
||
enter.Play();
|
||
return enter.duration;
|
||
}
|
||
|
||
private void Update()
|
||
{
|
||
if (_currentDirector != null && _currentDirector.state == PlayState.Playing)
|
||
{
|
||
if (_targetTime - _currentDirector.time < 0.001f)
|
||
{
|
||
_currentDirector.Pause();
|
||
_currentDirector.time = _targetTime;
|
||
if (_upgradeBuildingData != null)
|
||
{
|
||
_upgradeBuildingData.CanContinue = true;
|
||
_upgradeBuildingData = null;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|