using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEditor;
using UnityEngine.Timeline;
using System.IO;
using UnityEngine.Playables;
public class ExtractTimelineText
{
[MenuItem("Tools/提取剧情文字")]
static void Extract(){
Editor_LuaConfig.Instance().Init();
string fullPath = "Assets/Resources/Story"; //路径
string txtPath = Application.dataPath + "/dialog.txt";
int storyCount = 0;
//获取指定路径下面的所有资源文件
if (Directory.Exists(fullPath)){
DirectoryInfo direction = new DirectoryInfo(fullPath);
FileInfo[] files = direction.GetFiles("*",SearchOption.TopDirectoryOnly);
// Debug.Log(files.Length);
StreamWriter writer;
FileInfo file = new FileInfo(txtPath);
writer = file.CreateText();
for(int i=0;i<files.Length;i++){
if (files[i].Name.EndsWith(".meta")){
continue;
}
if(!files[i].Name.EndsWith(".prefab"))
continue;
// Debug.Log( "Name:" + files[i].Name ); //打印出来这个文件架下的所有文件
string prefabPath = fullPath + "/" + files[i].Name;
GameObject tempObj = AssetDatabase.LoadAssetAtPath(prefabPath, typeof(GameObject)) as GameObject;
if(tempObj == null){
Debug.LogWarning("not found prefab, name: " + prefabPath);
}else{
PlayableDirector playableDirector = tempObj.GetComponent<PlayableDirector>();
if(playableDirector == null)
continue;
writer.WriteLine("------story name " + files[i].Name + "------");
storyCount++;
PlayableAsset asset = playableDirector.playableAsset;
if(asset == null){
Debug.LogWarning("asset is null, story path: " + prefabPath);
writer.WriteLine("Error: asset is null, story path: " + prefabPath);
}else{
// Debug.Log("asset name: " + asset.name);
foreach (PlayableBinding pb in asset.outputs)
{
var track = pb.sourceObject as TrackAsset;
if (track != null && track is DialogueTrack)
{
foreach (TimelineClip clip in track.GetClips())
{
// Debug.Log("name:" + clip.displayName + "时间:" + clip.duration);
DialogueClip dialogueClip = clip.asset as DialogueClip;
// Debug.Log(dialogueClip.playerNameIndex + "---" + Editor_LuaConfig.Instance().GetDialogConfigText(dialogueClip.playerNameIndex.ToString()));
string txt1 = Editor_LuaConfig.Instance().GetDialogConfigText(dialogueClip.playerNameIndex.ToString());
if(string.IsNullOrEmpty(txt1)){
Debug.LogWarning("not found index " + dialogueClip.playerNameIndex + ", story name: " + files[i].Name);
}
string txt2 = Editor_LuaConfig.Instance().GetDialogConfigText(dialogueClip.contentIndex.ToString());
if(string.IsNullOrEmpty(txt1)){
Debug.LogWarning("not found index " + dialogueClip.contentIndex + ", story name: " + files[i].Name);
}
writer.WriteLine(txt1 + ":" + txt2);
}
break;
}
}
}
}
}
writer.Flush();
writer.Dispose();
writer.Close();
Debug.Log("story text write finish!!! total count = " + storyCount);
}
Editor_LuaMgr.Instance().DisposeLuaenv();
Editor_LuaConfig.Instance().Release();
}
}
public PlayableDirector InitStory(string name, Action<PlayableDirector> pdCallback, bool usePosition=false, Vector3 position=default(Vector3), Vector3 rotation=default(Vector3)){
string fullPath = "Story/" + name;
if(String.IsNullOrEmpty(name))
{
Debug.Log("没填要播放的story timeline名字");
return null;
}
if (playableDirector != null)
{
playableDirector.Stop();
}
Debug.Log("Timeline: start load story timeline: " + fullPath);
GameObject timeline = ObjectMgr.Instance().CreateObj(fullPath, null) as GameObject;
if(timeline == null){
Debug.LogWarning("timeline error name: " + name);
pdCallback(null);
return null;
}
UIMgr.Instance().DoSetUIShow(false);
timeline.SetAllChildLayer("Timeline");
if(usePosition){
timeline.transform.position = position;
timeline.transform.rotation = Quaternion.Euler(rotation);
}
List<Camera> cameras = new List<Camera>();
timeline.GetComponentsInChildren<Camera>(true, cameras);
for (int i = 0; i < cameras.Count; i++)
{
cameras[i].cullingMask = (1<<0) + (1<<1) + (1<<4) + (1<<14) + (1<<16);
cameras[i].depth = 5;
var al = cameras[i].GetComponent<AudioListener>();
if(al != null){
GameObject.Destroy(al);
}
}
playableDirector = timeline.GetComponentInChildren<PlayableDirector>();
playableDirector.stopped += pdCallback;
playableDirector.stopped += OnPlayableDirectorStoryStopped;
// timeline.transform.position = position;
// timeline.transform.rotation = Quaternion.Euler(rotation);
mBindings = new Dictionary<string, PlayableBinding>();
PlayableAsset asset = playableDirector.playableAsset;
if(asset == null){
Debug.LogWarning("asset is null, timeline name: " + name);
pdCallback(null);
return null;
}
Dictionary<UnityEngine.Object, ActiveActorPartInfo> partInfos = new Dictionary<UnityEngine.Object, ActiveActorPartInfo>();
// 角色运行时会被替换,角色的身体某一部分可能会设置隐藏/显示,这里记录需要设置的角色,以便替换角色后关联上隐藏部分
foreach(var output in asset.outputs){
UnityEngine.Object obj = playableDirector.GetGenericBinding(output.sourceObject);
if(obj != null && obj is GameObject && (obj as GameObject).GetComponent<SkinnedMeshRenderer>() != null){
Transform parent = (obj as GameObject).transform.parent;
if(parent != null && parent.GetComponent<Animator>() != null){
ActiveActorPartInfo info = new ActiveActorPartInfo();
info.partName = (obj as GameObject).name;
info.output = output;
info.objPart = obj as GameObject;
info.objParent = parent.gameObject;
if(!partInfos.ContainsKey(output.sourceObject))
partInfos.Add(output.sourceObject, info);
}
}
}
StoryActor[] storyActors = timeline.GetComponentsInChildren<StoryActor>();
for (int i = storyActors.Length-1; i >=0; i--)
{
if(storyActors[i].actor != null){
Vector3 scale = storyActors[i].transform.localScale;
GameObject objIns = GameObject.Instantiate(storyActors[i].actor.gameObject);
objIns.transform.SetParent(storyActors[i].transform.parent);
objIns.transform.localPosition = Vector3.zero;
objIns.transform.localRotation = Quaternion.identity;
objIns.transform.localScale = scale;
// objIns.transform.name = storyActors[i].transform.name; //保留clone方便查看
if(objIns.GetComponent<Animator>() != null)
objIns.GetComponent<Animator>().runtimeAnimatorController = storyActors[i].GetComponent<Animator>().runtimeAnimatorController;
foreach(var output in asset.outputs){
UnityEngine.Object obj = playableDirector.GetGenericBinding(output.sourceObject);
GameObject objBind = null;
if(obj != null && obj is Animator){
objBind = (obj as Animator).gameObject;
}
if(obj != null && obj is Transform){
objBind = (obj as Transform).gameObject;
}
if(obj != null && obj is GameObject){
objBind = obj as GameObject;
// 替换 角色的身体某一部分
if(partInfos.ContainsKey(output.sourceObject) && partInfos[output.sourceObject].objParent == storyActors[i].gameObject){
playableDirector.SetGenericBinding(output.sourceObject, objIns.transform.Find(objBind.name).gameObject);
}
}
if(objBind != null && storyActors[i].gameObject == objBind){
playableDirector.SetGenericBinding(output.sourceObject, objIns);
}
}
GameObject.Destroy(storyActors[i].gameObject);
}
}
foreach(var output in asset.outputs){
if(mBindings.ContainsKey(output.streamName)){
Debug.Log("the same key: " + output.streamName);
}else{
mBindings.Add(output.streamName, output);
}
}
Debug.Log("Timeline: load story timeline finish: " + fullPath);
return playableDirector;
}