717 lines
29 KiB
C#
717 lines
29 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.Linq;
|
|
using Framework;
|
|
using Gameplay.Story.Cmp.Data;
|
|
using Gameplay.Story.Cmp.Timeline.AudioAction;
|
|
using Gameplay.Story.Cmp.Timeline.BlockChoiceAction;
|
|
using Gameplay.Story.Cmp.Timeline.CameraPosAction;
|
|
using Gameplay.Story.Cmp.Timeline.CameraPropAction;
|
|
using Gameplay.Story.Cmp.Timeline.CameraRotAction;
|
|
using Gameplay.Story.Cmp.Timeline.CommonAction;
|
|
using Gameplay.Story.Cmp.Timeline.MsgAction;
|
|
using Gameplay.Story.Cmp.Timeline.PlayerAction;
|
|
using Gameplay.Story.Cmp.Timeline.PlayerEmojiAction;
|
|
using Gameplay.Story.Cmp.Timeline.PlayerPosAction;
|
|
using Gameplay.Story.Cmp.Timeline.PlayerRotAction;
|
|
using Gameplay.Story.Cmp.Timeline.PlayerTalkAction;
|
|
using Gameplay.Story.Cmp.Timeline.SceneSwitchAction;
|
|
using Gameplay.Story.Cmp.Timeline.SetNameAction;
|
|
using Gameplay.Story.Cmp.Timeline.UIImageSetAction;
|
|
using Gameplay.Story.Cmp.Timeline.UIModChangeAction;
|
|
using Gameplay.Story.Cmp.Timeline.WeaponHideAction;
|
|
using Sirenix.Utilities.Editor;
|
|
using UnityEditor;
|
|
using UnityEngine;
|
|
using UnityEngine.Playables;
|
|
using UnityEngine.Timeline;
|
|
namespace Gameplay.Story.Cmp.Utils
|
|
{
|
|
public static class TimelineUtils
|
|
{
|
|
|
|
private static readonly Dictionary<int, AnimationTrack> PlayerActionTrackDic = new Dictionary<int, AnimationTrack>();
|
|
private static readonly Dictionary<int, PlayerEmojiActionTrack> PlayerEmojiActionTrackDic = new Dictionary<int, PlayerEmojiActionTrack>();
|
|
private static readonly Dictionary<int, PlayerPosActionTrack> PlayerPosTrackDic = new Dictionary<int, PlayerPosActionTrack>();
|
|
private static readonly Dictionary<int, PlayerTalkActionTrack> PlayerTalkTrackDic = new Dictionary<int, PlayerTalkActionTrack>();
|
|
private static readonly Dictionary<int, PlayerRotActionTrack> PlayerRotTrackDic = new Dictionary<int, PlayerRotActionTrack>();
|
|
private static readonly Dictionary<int, CachePlayerAnimClips> PlayerClipDic = new Dictionary<int, CachePlayerAnimClips>();
|
|
private static readonly Dictionary<int, WeaponHideActionTrack> WeaponHideActionTrackDic = new Dictionary<int, WeaponHideActionTrack>();
|
|
private static readonly Dictionary<int, SetNameActionTrack> SetNameActionTrackDic = new Dictionary<int, SetNameActionTrack>();
|
|
private static readonly Dictionary<int, AudioActionTrack> AudioActionTrackDic = new Dictionary<int, AudioActionTrack>();
|
|
private static readonly List<StoryExcelPlayerData> PlayerDataList = new List<StoryExcelPlayerData>();
|
|
private static MsgActionTrack _msgActionTrack;
|
|
private static BlockChoiceActionTrack _blockChoiceTrack;
|
|
private static SceneSwitchActionTrack _sceneSwitchTrack;
|
|
private static CameraPosActionTrack _cameraPosActionTrack;
|
|
private static CameraRotActionTrack _cameraRotActionTrack;
|
|
private static CameraPropActionTrack _cameraPropActionTrack;
|
|
private static UIModChangeActionTrack _uiModChangeTrack;
|
|
private const float SampleTime = 1f;
|
|
|
|
public static TimelineAsset CreateTimelineAsset(string savePath,
|
|
StoryExcelData storyExcelData)
|
|
{
|
|
// 判断文件是否存在,如果存在则先删除
|
|
var fullPath = Application.dataPath.Replace("Assets", "") + savePath;
|
|
if (System.IO.File.Exists(fullPath))
|
|
{
|
|
// 先进行checkout
|
|
// VersionControlSystem.Checkout(savePath);
|
|
AssetDatabase.DeleteAsset(savePath);
|
|
AssetDatabase.Refresh();
|
|
|
|
}
|
|
var timelineAsset = ScriptableObject.CreateInstance<TimelineAsset>();
|
|
AssetDatabase.CreateAsset(timelineAsset, savePath);
|
|
|
|
PlayerActionTrackDic.Clear();
|
|
PlayerEmojiActionTrackDic.Clear();
|
|
PlayerPosTrackDic.Clear();
|
|
PlayerTalkTrackDic.Clear();
|
|
PlayerRotTrackDic.Clear();
|
|
SetNameActionTrackDic.Clear();
|
|
PlayerClipDic.Clear();
|
|
WeaponHideActionTrackDic.Clear();
|
|
AudioActionTrackDic.Clear();
|
|
|
|
PlayerDataList.Clear();
|
|
PlayerDataList.AddRange(storyExcelData.playerList);
|
|
|
|
_CreateGroupTracks(timelineAsset);
|
|
|
|
var currentTime = 0f;
|
|
var onlyOnce = true;
|
|
for (var i = 0; i < storyExcelData.blockList.Count; i++)
|
|
{
|
|
var block = storyExcelData.blockList[i];
|
|
var totalTime = _CreatePlayers(block, currentTime);
|
|
if (onlyOnce)
|
|
{
|
|
_CreateCameraPosTrack(block, currentTime, totalTime);
|
|
_CreateCameraRotTrack(block, currentTime, totalTime);
|
|
_CreateSceneSwitch(currentTime, totalTime);
|
|
onlyOnce = false;
|
|
}
|
|
|
|
_CreateMsgAction(_msgActionTrack, block, currentTime, totalTime);
|
|
_CreateBlockChoice(currentTime, totalTime);
|
|
currentTime += totalTime;
|
|
}
|
|
|
|
// 角色相关的只创建第一次
|
|
var playerList = PlayerDataList;
|
|
for (var i = 0; i < playerList.Count; i++)
|
|
{
|
|
var playerData = playerList[i];
|
|
_CreatePlayerPos(PlayerPosTrackDic[playerData.playerId], playerData, 0, SampleTime);
|
|
_CreatePlayerRot(PlayerRotTrackDic[playerData.playerId], playerData, 0, SampleTime);
|
|
_CreateWeaponHides(WeaponHideActionTrackDic[playerData.playerId], playerData, 0, SampleTime);
|
|
}
|
|
|
|
// 保存到指定路径
|
|
|
|
// 保存时间轴资源为.asset文件
|
|
EditorUtility.SetDirty(timelineAsset);
|
|
AssetDatabase.SaveAssets();
|
|
AssetDatabase.Refresh();
|
|
return timelineAsset;
|
|
}
|
|
|
|
private static void _CreateCameraRotTrack(StoryExcelBlockData block,
|
|
float startTime,
|
|
float during)
|
|
{
|
|
var clip = _cameraRotActionTrack.CreateClip<CameraRotActionClip>();
|
|
clip.start = startTime;
|
|
clip.duration = during;
|
|
}
|
|
|
|
private static void _CreateCameraPosTrack(StoryExcelBlockData block,
|
|
float startTime,
|
|
float during)
|
|
{
|
|
var clip = _cameraPosActionTrack.CreateClip<CameraPosActionClip>();
|
|
clip.start = startTime;
|
|
clip.duration = during;
|
|
}
|
|
|
|
private static void _CreateGroupTracks(TimelineAsset timelineAsset)
|
|
{
|
|
// 创建剧情轨道
|
|
var groupBlockTrack = timelineAsset.CreateTrack<GroupTrack>(null, "剧情") as GroupTrack;
|
|
_msgActionTrack = timelineAsset.CreateTrack<MsgActionTrack>(groupBlockTrack, "剧情文字");
|
|
_blockChoiceTrack = timelineAsset.CreateTrack<BlockChoiceActionTrack>(groupBlockTrack, "剧情选项");
|
|
_sceneSwitchTrack = timelineAsset.CreateTrack<SceneSwitchActionTrack>(groupBlockTrack, "场景切换");
|
|
// StoryManager.instance.msgManager.msgTrack = _blockLine;
|
|
// 创建角色轨道
|
|
var playerGroupTrack = timelineAsset.CreateTrack<GroupTrack>(null, "角色") as GroupTrack;
|
|
foreach (var playerData in PlayerDataList)
|
|
{
|
|
var combieName = playerData.playerName + playerData.playerId;
|
|
var groupTrackSplit = timelineAsset.CreateTrack<GroupTrack>(playerGroupTrack, combieName);
|
|
// 创建角色说话轨道
|
|
var playerTalkActionTrack = timelineAsset.CreateTrack<PlayerTalkActionTrack>(groupTrackSplit, "说话") as PlayerTalkActionTrack;
|
|
playerTalkActionTrack.playerId = playerData.playerId;
|
|
PlayerTalkTrackDic.Add(playerData.playerId, playerTalkActionTrack);
|
|
// 创建角色动作轨道
|
|
// var playerActionTrack = timelineAsset.CreateTrack<PlayerActionTrack>(groupTrackSplit, "动作") as PlayerActionTrack;
|
|
// playerActionTrack.playerId = playerData.playerId;
|
|
var playerActionTrack = timelineAsset.CreateTrack<AnimationTrack>(groupTrackSplit, "动作") as AnimationTrack;
|
|
playerActionTrack.applyAvatarMask = false;
|
|
PlayerActionTrackDic.Add(playerData.playerId, playerActionTrack);
|
|
PlayerClipDic.Add(playerData.playerId, new CachePlayerAnimClips()
|
|
{
|
|
playerId = playerData.playerId
|
|
});
|
|
// 创建角色表情轨道
|
|
var playerEmojiActionTrack = timelineAsset.CreateTrack<PlayerEmojiActionTrack>(groupTrackSplit, "表情") as PlayerEmojiActionTrack;
|
|
playerEmojiActionTrack.playerId = playerData.playerId;
|
|
PlayerEmojiActionTrackDic.Add(playerData.playerId, playerEmojiActionTrack);
|
|
// 创建角色位置轨道
|
|
var playerPosActionTrack = timelineAsset.CreateTrack<PlayerPosActionTrack>(groupTrackSplit, "位置");
|
|
PlayerPosTrackDic.Add(playerData.playerId, playerPosActionTrack);
|
|
playerPosActionTrack.playerId = playerData.playerId;
|
|
// 创建角色朝向轨道
|
|
var playerRotActionTrack = timelineAsset.CreateTrack<PlayerRotActionTrack>(groupTrackSplit, "朝向");
|
|
PlayerRotTrackDic.Add(playerData.playerId, playerRotActionTrack);
|
|
// 创建角色武器隐藏轨道
|
|
var weaponHideActionTrack = timelineAsset.CreateTrack<WeaponHideActionTrack>(groupTrackSplit, "武器隐藏");
|
|
weaponHideActionTrack.playerId = playerData.playerId;
|
|
WeaponHideActionTrackDic.Add(playerData.playerId, weaponHideActionTrack);
|
|
var setNameActionTrack = timelineAsset.CreateTrack<SetNameActionTrack>(groupTrackSplit, "名字");
|
|
setNameActionTrack.playerId = playerData.playerId;
|
|
SetNameActionTrackDic.Add(playerData.playerId, setNameActionTrack);
|
|
//创建角色音效轨道
|
|
var audioActionTrack = timelineAsset.CreateTrack<AudioActionTrack>(groupTrackSplit, "音频");
|
|
audioActionTrack.playerId = playerData.playerId;
|
|
AudioActionTrackDic.Add(playerData.playerId, audioActionTrack);
|
|
}
|
|
// 创建相机轨道
|
|
var cameraGroupTrack = timelineAsset.CreateTrack<GroupTrack>(null, "相机");
|
|
{
|
|
// 创建相机位置轨道
|
|
var cameraPosActionTrack = timelineAsset.CreateTrack<CameraPosActionTrack>(cameraGroupTrack, "位置");
|
|
_cameraPosActionTrack = cameraPosActionTrack;
|
|
// 创建相机朝向轨道
|
|
var cameraRotActionTrack = timelineAsset.CreateTrack<CameraRotActionTrack>(cameraGroupTrack, "朝向");
|
|
_cameraRotActionTrack = cameraRotActionTrack;
|
|
// 创建相机size轨道
|
|
var cameraSizeActionTrack = timelineAsset.CreateTrack<CameraPropActionTrack>(cameraGroupTrack, "属性");
|
|
_cameraPropActionTrack = cameraSizeActionTrack;
|
|
// 创建一个空的clip
|
|
var clip = cameraSizeActionTrack.CreateClip<CameraPropActionClip>();
|
|
clip.start = 0f;
|
|
clip.duration = 1f;
|
|
}
|
|
|
|
// 创建UI轨道
|
|
var UIGroupTrack = timelineAsset.CreateTrack<GroupTrack>(null, "UI");
|
|
{
|
|
// 创建UI模式切换
|
|
var uimodChangeTrack = timelineAsset.CreateTrack<UIModChangeActionTrack>(UIGroupTrack, "模式切换");
|
|
_uiModChangeTrack = uimodChangeTrack;
|
|
// 默认显示3D相机内容
|
|
var clip = uimodChangeTrack.CreateClip<UIModChangeActionClip>();
|
|
clip.start = 0f;
|
|
clip.duration = 5f;
|
|
// 创建前景切换
|
|
var uiFrontChangeTrack = timelineAsset.CreateTrack<UIImageSetActionTrack>(UIGroupTrack, "前景切换");
|
|
uiFrontChangeTrack.imgPosType = 1;
|
|
// 创建背景切换
|
|
var uiBackChangeTrack = timelineAsset.CreateTrack<UIImageSetActionTrack>(UIGroupTrack, "背景切换");
|
|
uiBackChangeTrack.imgPosType = 0;
|
|
}
|
|
|
|
// 创建通用轨道
|
|
var commonGroupTrack = timelineAsset.CreateTrack<GroupTrack>(null, "通用");
|
|
{
|
|
// 创建通用轨道
|
|
var commonActionTrack = timelineAsset.CreateTrack<CommonActionTrack>(commonGroupTrack, "通用1");
|
|
}
|
|
}
|
|
|
|
private static float _ReadStartMotionLength(string motionName)
|
|
{
|
|
var motionConfig = EditorTableManager.instance.tables.MotionMapperConfig.Get(motionName);
|
|
if (motionConfig == null)
|
|
{
|
|
Debug.LogError("无效的动作名字:" + motionName);
|
|
return 1f;
|
|
}
|
|
var motionPath = motionConfig.MotionFullPath;
|
|
var loadDatas = AssetDatabase.LoadAllAssetsAtPath(motionPath);
|
|
AnimationClip clipStart = null;
|
|
for (int i = 0; i < loadDatas.Length; i++)
|
|
{
|
|
var loadData = loadDatas[i];
|
|
if (loadData is AnimationClip loadClip)
|
|
{
|
|
if (loadClip.name.EndsWith("_start"))
|
|
{
|
|
clipStart = loadClip;
|
|
}
|
|
}
|
|
}
|
|
if (clipStart == null)
|
|
{
|
|
return 1f;
|
|
}
|
|
return clipStart.length;
|
|
}
|
|
|
|
private static float _CreatePlayers(StoryExcelBlockData block,
|
|
float currentTime)
|
|
{
|
|
var totalTime = SampleTime;
|
|
var blockMsg = block.blockMsg;
|
|
var msgTime = blockMsg == null ? 0f : blockMsg.Length / 8f;
|
|
var playerDatas = block.playerDatas;
|
|
for (var i = 0; i < playerDatas.Count; i++)
|
|
{
|
|
var playerData = playerDatas[i];
|
|
// 读取startAnim
|
|
playerData = _SearchPlayerData(playerDatas, playerData.playerId);
|
|
var motionName = playerData.motionName;
|
|
var startMotionLength = _ReadStartMotionLength(motionName);
|
|
totalTime = Mathf.Max(totalTime, startMotionLength, msgTime);
|
|
if (playerData.isTalk)
|
|
{
|
|
_CreatePlayerTalks(PlayerTalkTrackDic[playerData.playerId], playerData, currentTime);
|
|
}
|
|
_CreatePlayerEmojis(PlayerEmojiActionTrackDic[playerData.playerId], playerData, currentTime,
|
|
totalTime);
|
|
}
|
|
|
|
// 所有角色都会创建位置轨道
|
|
var playerList = PlayerDataList;
|
|
for (var i = 0; i < playerList.Count; i++)
|
|
{
|
|
var playerData = playerList[i];
|
|
// _CreatePlayerPos(PlayerPosTrackDic[playerData.playerId], playerData, currentTime, totalTime);
|
|
// _CreatePlayerRot(PlayerRotTrackDic[playerData.playerId], playerData, currentTime, totalTime);
|
|
// _CreateWeaponHides(WeaponHideActionTrackDic[playerData.playerId], playerData, currentTime, totalTime);
|
|
|
|
playerData = _SearchPlayerData(playerDatas, playerData.playerId);
|
|
_CreatePlayerActions(PlayerActionTrackDic[playerData.playerId], playerData, currentTime, totalTime);
|
|
_CreateSetNameClips(playerData, currentTime);
|
|
|
|
}
|
|
|
|
|
|
|
|
return totalTime;
|
|
}
|
|
|
|
private static void _CreateSetNameClips(StoryExcelPlayerData playerData,
|
|
float currentTime)
|
|
{
|
|
var cacheData = PlayerClipDic[playerData.playerId];
|
|
var track = SetNameActionTrackDic[playerData.playerId];
|
|
var needCreate = false;
|
|
if (string.IsNullOrEmpty(cacheData.name))
|
|
{
|
|
// 创建新的
|
|
cacheData.name = playerData.playerName;
|
|
needCreate = true;
|
|
|
|
}
|
|
else
|
|
{
|
|
if (cacheData.name != playerData.playerName)
|
|
{
|
|
cacheData.name = playerData.playerName;
|
|
needCreate = true;
|
|
}
|
|
}
|
|
|
|
if (needCreate)
|
|
{
|
|
var clip = track.CreateClip<SetNameActionClip>();
|
|
clip.start = currentTime;
|
|
clip.duration = 1f;
|
|
var setNameActionClip = clip.asset as SetNameActionClip;
|
|
if (setNameActionClip == null)
|
|
{
|
|
return;
|
|
}
|
|
setNameActionClip.setName = playerData.playerName;
|
|
}
|
|
}
|
|
|
|
private static StoryExcelPlayerData _SearchPlayerData(List<StoryExcelPlayerData> searchList,
|
|
int playerId)
|
|
{
|
|
for (int i = 0; i < searchList.Count; i++)
|
|
{
|
|
var searchData = searchList[i];
|
|
if (searchData.playerId == playerId)
|
|
{
|
|
return searchData;
|
|
}
|
|
}
|
|
return new StoryExcelPlayerData()
|
|
{
|
|
playerId = playerId
|
|
};
|
|
}
|
|
|
|
private static void _CreateWeaponHides(WeaponHideActionTrack track,
|
|
StoryExcelPlayerData playerData,
|
|
float currentTime,
|
|
float during)
|
|
{
|
|
var clip = track.CreateClip<WeaponHideActionClip>();
|
|
clip.start = currentTime;
|
|
clip.duration = during;
|
|
|
|
var weaponHideActionClip = clip.asset as WeaponHideActionClip;
|
|
if (weaponHideActionClip == null)
|
|
{
|
|
return;
|
|
}
|
|
weaponHideActionClip.playerId = playerData.playerId;
|
|
}
|
|
|
|
private static void _CreatePlayerTalks(PlayerTalkActionTrack track,
|
|
StoryExcelPlayerData playerData,
|
|
float currentTime)
|
|
{
|
|
var clip = track.CreateClip<PlayerTalkActionClip>();
|
|
clip.start = currentTime;
|
|
}
|
|
|
|
private static void _CreatePlayerEmojis(PlayerEmojiActionTrack track,
|
|
StoryExcelPlayerData playerData,
|
|
float currentTime,
|
|
float during)
|
|
{
|
|
var emojiNames = playerData.faceNames;
|
|
var splitDuring = during / emojiNames.Count;
|
|
for (int i = 0; i < emojiNames.Count; i++)
|
|
{
|
|
var emojiName = emojiNames[i];
|
|
_CreatePlayerEmoji(track, playerData, currentTime, emojiName, splitDuring);
|
|
currentTime += splitDuring;
|
|
}
|
|
}
|
|
|
|
private static void _CreatePlayerEmoji(PlayerEmojiActionTrack track,
|
|
StoryExcelPlayerData playerData,
|
|
float currentTime,
|
|
string emojiName,
|
|
float during)
|
|
{
|
|
var clip = track.CreateClip<PlayerEmojiActionClip>();
|
|
clip.start = currentTime;
|
|
clip.duration = during;
|
|
|
|
var playerEmojiActionClip = clip.asset as PlayerEmojiActionClip;
|
|
if (playerEmojiActionClip == null)
|
|
{
|
|
return;
|
|
}
|
|
playerEmojiActionClip.playerId = playerData.playerId;
|
|
playerEmojiActionClip.emojiName = emojiName;
|
|
|
|
|
|
var emojiConfig = EditorTableManager.instance.tables.EmojiMapperConfig.Get(emojiName);
|
|
if (emojiConfig == null)
|
|
{
|
|
Debug.LogError("无效的表情名字:" + emojiName);
|
|
return;
|
|
}
|
|
playerEmojiActionClip.emojiId = emojiConfig.EmojiId;
|
|
|
|
}
|
|
|
|
private static void _CreatePlayerPos(PlayerPosActionTrack track,
|
|
StoryExcelPlayerData playerData,
|
|
float currentTime,
|
|
float during)
|
|
{
|
|
var clip = track.CreateClip<PlayerPosActionClip>();
|
|
var playerPosActionClip = clip.asset as PlayerPosActionClip;
|
|
if (playerPosActionClip == null)
|
|
{
|
|
return;
|
|
}
|
|
|
|
clip.start = currentTime;
|
|
clip.duration = during;
|
|
}
|
|
|
|
private static void _CreatePlayerRot(PlayerRotActionTrack track,
|
|
StoryExcelPlayerData playerData,
|
|
float currentTime,
|
|
float during)
|
|
{
|
|
var clip = track.CreateClip<PlayerRotActionClip>();
|
|
var playerRotActionClip = clip.asset as PlayerRotActionClip;
|
|
if (playerRotActionClip == null)
|
|
{
|
|
return;
|
|
}
|
|
playerRotActionClip.playerId = playerData.playerId;
|
|
|
|
clip.start = currentTime;
|
|
clip.duration = during;
|
|
}
|
|
|
|
private static void _CreatePlayerActions(AnimationTrack track,
|
|
StoryExcelPlayerData playerData,
|
|
double currentTime,
|
|
double during)
|
|
{
|
|
var cacheData = PlayerClipDic[playerData.playerId];
|
|
var motionName = playerData.motionName;
|
|
if (string.IsNullOrEmpty(motionName))
|
|
{
|
|
// 如果之前有,则把之前的loop拉长,end后移
|
|
if (cacheData.clipLoop != null
|
|
&& cacheData.clipEnd != null)
|
|
{
|
|
cacheData.clipLoop.duration += during;
|
|
cacheData.clipEnd.start = currentTime + during;
|
|
}
|
|
return;
|
|
}
|
|
var motionConfig = EditorTableManager.instance.tables.MotionMapperConfig.Get(motionName);
|
|
if (motionConfig == null)
|
|
{
|
|
Debug.LogError("无效的动作名字:" + motionName);
|
|
return;
|
|
}
|
|
var motionPath = motionConfig.MotionFullPath;
|
|
var loadDatas = AssetDatabase.LoadAllAssetsAtPath(motionPath);
|
|
AnimationClip clipStart = null, clipLoop = null, clipEnd = null;
|
|
for (int i = 0; i < loadDatas.Length; i++)
|
|
{
|
|
var loadData = loadDatas[i];
|
|
if (loadData is AnimationClip loadClip)
|
|
{
|
|
if (loadClip.name.EndsWith("_start"))
|
|
{
|
|
clipStart = loadClip;
|
|
}
|
|
if (loadClip.name.EndsWith("_loop"))
|
|
{
|
|
clipLoop = loadClip;
|
|
}
|
|
if (loadClip.name.EndsWith("_end"))
|
|
{
|
|
clipEnd = loadClip;
|
|
}
|
|
}
|
|
}
|
|
var workTime = currentTime;
|
|
var passTime = 0f;
|
|
if (clipStart != null)
|
|
{
|
|
var createClip = track.CreateClip(clipStart);
|
|
createClip.start = workTime;
|
|
if (cacheData.clipEnd != null)
|
|
{
|
|
createClip.start = cacheData.clipEnd.start;
|
|
}
|
|
createClip.duration = clipStart.length;
|
|
workTime += clipStart.length;
|
|
passTime += clipStart.length;
|
|
|
|
cacheData.clipStart = createClip;
|
|
}
|
|
else
|
|
{
|
|
Debug.Log("未找到start动作:" + motionName);
|
|
cacheData.clipStart = null;
|
|
}
|
|
if (clipLoop != null)
|
|
{
|
|
var createClip = track.CreateClip(clipLoop);
|
|
createClip.start = workTime;
|
|
createClip.duration = during - passTime;
|
|
|
|
cacheData.clipLoop = createClip;
|
|
}
|
|
else
|
|
{
|
|
Debug.Log("未找到loop动作:" + motionName);
|
|
cacheData.clipLoop = null;
|
|
}
|
|
if (clipEnd != null)
|
|
{
|
|
var createClip = track.CreateClip(clipEnd);
|
|
createClip.start = currentTime + during;
|
|
createClip.duration = clipEnd.length;
|
|
|
|
cacheData.clipEnd = createClip;
|
|
}
|
|
else
|
|
{
|
|
Debug.Log("未找到end动作:" + motionName);
|
|
|
|
cacheData.clipEnd = null;
|
|
}
|
|
}
|
|
|
|
private static float _CreatePlayerAction(AnimationTrack track,
|
|
StoryExcelPlayerData playerData,
|
|
float currentTime,
|
|
string motionName)
|
|
{
|
|
var clip = track.CreateClip<PlayerActionClip>();
|
|
var playerActionClip = clip.asset as PlayerActionClip;
|
|
if (playerActionClip == null)
|
|
{
|
|
return 0f;
|
|
}
|
|
playerActionClip.playerId = playerData.playerId;
|
|
playerActionClip.playerName = playerData.playerName;
|
|
playerActionClip.motionName = motionName;
|
|
clip.start = currentTime;
|
|
var motionConfig = EditorTableManager.instance.tables.MotionMapperConfig.Get(motionName);
|
|
if (motionConfig == null)
|
|
{
|
|
Debug.LogError("无效的动作名字:" + motionName);
|
|
return 0f;
|
|
}
|
|
var motionPath = motionConfig.MotionFullPath;
|
|
|
|
var motion = AssetDatabase.LoadAssetAtPath<AnimationClip>(motionPath);
|
|
if (motion == null)
|
|
{
|
|
Debug.LogError("无效的动作路径:" + motionPath);
|
|
return 0f;
|
|
}
|
|
playerActionClip.motionClip = motion;
|
|
|
|
clip.duration = motion.length;
|
|
return motion.length;
|
|
}
|
|
|
|
private static void _CreateSceneSwitch(float currentTime,
|
|
float during)
|
|
{
|
|
var clip = _sceneSwitchTrack.CreateClip<SceneSwitchActionClip>();
|
|
clip.start = currentTime;
|
|
clip.duration = during;
|
|
|
|
var sceneSwitchActionClip = clip.asset as SceneSwitchActionClip;
|
|
if (sceneSwitchActionClip == null)
|
|
{
|
|
return;
|
|
}
|
|
sceneSwitchActionClip.showIndex = 0;
|
|
}
|
|
|
|
private static void _CreateBlockChoice(float currentTime,
|
|
float during)
|
|
{
|
|
var clip = _blockChoiceTrack.CreateClip<BlockChoiceActionClip>();
|
|
clip.start = currentTime;
|
|
clip.duration = during;
|
|
|
|
var blockChoiceActionClip = clip.asset as BlockChoiceActionClip;
|
|
if (blockChoiceActionClip == null)
|
|
{
|
|
return;
|
|
}
|
|
blockChoiceActionClip.choiceMsgs = Array.Empty<string>();
|
|
blockChoiceActionClip.choiceBlockIds = Array.Empty<int>();
|
|
}
|
|
|
|
private static void _CreateMsgAction(MsgActionTrack blockLine,
|
|
StoryExcelBlockData block,
|
|
float currentTime,
|
|
float during)
|
|
{
|
|
var clip = blockLine.CreateClip<MsgActionClip>();
|
|
var msgActionClip = clip.asset as MsgActionClip;
|
|
if (msgActionClip == null)
|
|
{
|
|
return;
|
|
}
|
|
msgActionClip.blockId = block.blockId;
|
|
msgActionClip.msg = block.blockMsg;
|
|
clip.start = currentTime;
|
|
clip.duration = during;
|
|
}
|
|
|
|
public static TrackAsset SearchTrack(TimelineAsset timeline,
|
|
PlayableAsset clip)
|
|
{
|
|
var allTracks = timeline.GetOutputTracks();
|
|
foreach (var track in allTracks)
|
|
{
|
|
var clips = track.GetClips();
|
|
foreach (var trackClip in clips)
|
|
{
|
|
if (trackClip.asset == clip)
|
|
{
|
|
return track;
|
|
}
|
|
}
|
|
}
|
|
return null;
|
|
}
|
|
|
|
public static TimelineClip SearchBeforeClip(TrackAsset track,
|
|
PlayableAsset clip)
|
|
{
|
|
var clips = track.GetClips().ToArray();
|
|
for (int i = 0; i < clips.Length; i++)
|
|
{
|
|
var trackClip = clips[i];
|
|
if (trackClip.asset == clip)
|
|
{
|
|
if (i == 0)
|
|
{
|
|
return null;
|
|
}
|
|
return clips[i - 1];
|
|
}
|
|
}
|
|
return null;
|
|
}
|
|
|
|
public static TimelineClip SeachBehindClip(TrackAsset track,
|
|
PlayableAsset clip)
|
|
{
|
|
var clips = track.GetClips().ToArray();
|
|
for (int i = 0; i < clips.Length; i++)
|
|
{
|
|
var trackClip = clips[i];
|
|
if (trackClip.asset == clip)
|
|
{
|
|
if (i == clips.Length - 1)
|
|
{
|
|
return null;
|
|
}
|
|
var nextIndex = i + 1;
|
|
if (nextIndex >= clips.Length)
|
|
{
|
|
return null;
|
|
}
|
|
return clips[nextIndex];
|
|
}
|
|
}
|
|
return null;
|
|
}
|
|
|
|
|
|
private static void _CreatePlayerAudioTrack()
|
|
{
|
|
|
|
}
|
|
private static void _CreateAudioTrack(TimelineAsset timelineAsset)
|
|
{
|
|
var audioActionTrack = timelineAsset.CreateTrack<AudioActionTrack>();
|
|
//AudioActionTrackDic.Add(audioActionTrack);
|
|
}
|
|
private static void _CreateAudioClip()
|
|
{
|
|
|
|
}
|
|
}
|
|
}
|