﻿using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEditor;
using System.IO;
using Baidu.VR.LitJson;
using UnityEditor.SceneManagement;
using UnityEngine.SceneManagement;

namespace Baidu.VR.DepthpanoEditor
{
	public class DepthpanoEditor : EditorWindow
	{
		private static DepthpanoEditor builderWindow = null;

		[MenuItem("BaiduVR/景深漫游抽帧插件")]
		public static void OpenDepthpanoEditorWindow()
		{
			if (builderWindow == null)
			{
				builderWindow = GetWindow<DepthpanoEditor>();
				builderWindow.titleContent = new GUIContent("景深漫游抽帧插件");
			}
			builderWindow.Show();
		}

		private enum EditorPanel
		{
			NewOpen,
			Main,
            ExportPanoTip
		}
		private EditorPanel curEditorPanel = EditorPanel.NewOpen;

		private DepthpanoEditorConfig curEditorConfig = null;
		private string curEditorConfigSavePath = null;
		private List<DECameraPoint> curDECameraPoints = new List<DECameraPoint>();
		private bool curDECameraAllSelected = false;

		private int newDecCounter = 0;

        private int newPointCounter = 1;

        private GameObject highModel = null;
        private GameObject lowModel = null;
        private bool applied = false;

        private SerializedPropertyTable cameraTable;

		private static string[] imageResluations = new string[] { "4k", "8k" };
		private int selectedImageResluation = 1;

		private static string[] imageFormats = new string[] { "jpg", "png" };
		private int selectedImageFormat = 0;

        private const int defaultJpgQuality = 75;
        private const float defaultDepthNearPlane = 0.001f;
        private const float defaultDepthFarPlane = 1000.0f;

        private int jpgQuality = defaultJpgQuality;
		private float depthNearPlane = defaultDepthNearPlane;
		private float depthFarPlane = defaultDepthFarPlane;

        private bool exportNormalTexture = false;

        private bool exportMaterial = true;

		private string exportFilePath = "";

		private bool exportSuccess = true;

		public DECameraPoint lastPreviewPoint = null;
		public Vector3 lastScenePivot;
		public Quaternion lastSceneRot;


		private DECameraPoint[] FindCameraObjects()
		{
            DECameraPoint[] ret = curDECameraPoints.ToArray();
            for (int i = 0; i < ret.Length; i++)
            {
                ret[i].Number = i + 1;
            }
            return ret;
		}

		private SerializedPropertyTreeView.Column[] CreateCameraColumn(out string[] propnames)
		{
			propnames = new string[10];
			var columns = new SerializedPropertyTreeView.Column[10];
			columns[0] = new SerializedPropertyTreeView.Column
			{
				headerContent = new GUIContent("选择"),
				headerTextAlignment = TextAlignment.Left,
				sortedAscending = true,
				sortingArrowAlignment = TextAlignment.Center,
				width = 30,
				autoResize = false,
				allowToggleVisibility = true,
				propertyName = "Check",
				dependencyIndices = null,
				compareDelegate = null,
				drawDelegate = SerializedPropertyTreeView.DefaultDelegates.s_DrawCheckbox
			};
			columns[1] = new SerializedPropertyTreeView.Column
			{
				headerContent = new GUIContent("序号"),
				headerTextAlignment = TextAlignment.Left,
				sortedAscending = true,
				sortingArrowAlignment = TextAlignment.Center,
				width = 30,
				autoResize = false,
				allowToggleVisibility = true,
				propertyName = "Number",
				dependencyIndices = null,
				compareDelegate = null,
				drawDelegate = (Rect r, SerializedProperty prop, SerializedProperty[] dep) =>
                {
                    if (prop != null && prop.serializedObject != null && prop.serializedObject.targetObject != null)
                    {
                        int no = ((DECameraPoint)prop.serializedObject.targetObject).Number;
                        EditorGUI.LabelField(r, no.ToString(), EditorStyles.label);
                    }
				},
			};
			columns[2] = new SerializedPropertyTreeView.Column
			{
				headerContent = new GUIContent("漫游点名称"),
				headerTextAlignment = TextAlignment.Left,
				sortedAscending = true,
				sortingArrowAlignment = TextAlignment.Center,
				width = 127,
				minWidth = 25f,
				maxWidth = 200,
				autoResize = false,
				allowToggleVisibility = true,
				propertyName = "Number",
				dependencyIndices = null,
				compareDelegate = null,
				drawDelegate = (Rect r, SerializedProperty prop, SerializedProperty[] dep) =>
				{
					if (prop != null && prop.serializedObject != null && prop.serializedObject.targetObject != null)
					{
						string name = ((DECameraPoint)prop.serializedObject.targetObject).name;
						string newName = EditorGUI.TextField(r, name, EditorStyles.label);
						if (newName.Length > 20) newName = newName.Substring(0, 20);
                        if (newName.Length <= 0) newName = name;
                        ((DECameraPoint)prop.serializedObject.targetObject).name = newName;
					}
				},
			};
			columns[3] = new SerializedPropertyTreeView.Column
			{
				headerContent = new GUIContent("摄像机坐标"),
				headerTextAlignment = TextAlignment.Left,
				sortedAscending = true,
				sortingArrowAlignment = TextAlignment.Center,
				width = 117,
				autoResize = false,
				allowToggleVisibility = true,
				propertyName = "Number",
				dependencyIndices = null,
				compareDelegate = null,
				drawDelegate = (Rect r, SerializedProperty prop, SerializedProperty[] dep) =>
				{
					if (prop != null && prop.serializedObject != null && prop.serializedObject.targetObject != null)
					{
						Vector3 pos = ((DECameraPoint)prop.serializedObject.targetObject).GetPosition();
						EditorGUI.LabelField(r, pos.ToString(), EditorStyles.label);
					}
				},
			};
			columns[4] = new SerializedPropertyTreeView.Column
			{
				headerContent = new GUIContent("漫游点坐标"),
				headerTextAlignment = TextAlignment.Left,
				sortedAscending = true,
				sortingArrowAlignment = TextAlignment.Center,
				width = 117,
				autoResize = false,
				allowToggleVisibility = true,
				propertyName = "Number",
				dependencyIndices = null,
				compareDelegate = null,
				drawDelegate = (Rect r, SerializedProperty prop, SerializedProperty[] dep) =>
				{
					if (prop != null && prop.serializedObject != null && prop.serializedObject.targetObject != null)
					{
						Vector3? pos = ((DECameraPoint)prop.serializedObject.targetObject).GetGroundPosition();
						if (pos == null)
						{
							EditorGUI.LabelField(r, "无漫游点", EditorStyles.label);
						}
						else
						{
							EditorGUI.LabelField(r, pos.ToString(), EditorStyles.label);
						}
					}
				},
			};
			columns[5] = new SerializedPropertyTreeView.Column
			{
				headerContent = new GUIContent("复制"),
				headerTextAlignment = TextAlignment.Left,
				sortedAscending = true,
				sortingArrowAlignment = TextAlignment.Center,
				width = 40,
				autoResize = false,
				allowToggleVisibility = true,
				propertyName = "Number",
				dependencyIndices = null,
				compareDelegate = null,
				drawDelegate = (Rect r, SerializedProperty prop, SerializedProperty[] dep) =>
				{
					Event evt = Event.current;
					GUIContent content = new GUIContent("复制");
					switch (evt.type)
					{
						case EventType.MouseDown:
							if (r.Contains(evt.mousePosition))
							{
								DECameraPoint p = (DECameraPoint)prop.serializedObject.targetObject;
								DECameraPoint newP = CopyDECameraPoint(p);
								Selection.activeGameObject = newP.gameObject;
							}
							break;
						default:
							break;
					}
					EditorGUI.DropdownButton(r, content, FocusType.Passive, EditorStyles.miniButton);
				},
			};
			columns[6] = new SerializedPropertyTreeView.Column
			{
				headerContent = new GUIContent("删除"),
				headerTextAlignment = TextAlignment.Left,
				sortedAscending = true,
				sortingArrowAlignment = TextAlignment.Center,
				width = 40,
				autoResize = false,
				allowToggleVisibility = true,
				propertyName = "Number",
				dependencyIndices = null,
				compareDelegate = null,
				drawDelegate = (Rect r, SerializedProperty prop, SerializedProperty[] dep) =>
				{
					Event evt = Event.current;
					GUIContent content = new GUIContent("删除");
					switch (evt.type)
					{
						case EventType.MouseDown:
							if (r.Contains(evt.mousePosition))
							{
								DeleteDECameraPoint((DECameraPoint)prop.serializedObject.targetObject);
							}
							break;
						default:
							break;
					}
					EditorGUI.DropdownButton(r, content, FocusType.Passive, EditorStyles.miniButton);
				},
			};
			columns[7] = new SerializedPropertyTreeView.Column
			{
				headerContent = new GUIContent("预览"),
				headerTextAlignment = TextAlignment.Left,
				sortedAscending = true,
				sortingArrowAlignment = TextAlignment.Center,
				width = 40,
				autoResize = false,
				allowToggleVisibility = true,
				propertyName = "Number",
				dependencyIndices = null,
				compareDelegate = null,
				drawDelegate = (Rect r, SerializedProperty prop, SerializedProperty[] dep) =>
				{
					Event evt = Event.current;
					GUIContent content = new GUIContent("预览");
					switch (evt.type)
					{
						case EventType.MouseDown:
							if (r.Contains(evt.mousePosition))
							{
								DECameraPoint point = (DECameraPoint)prop.serializedObject.targetObject;
								if (point != lastPreviewPoint)
								{
									lastScenePivot = SceneView.lastActiveSceneView.pivot;
									lastSceneRot = SceneView.lastActiveSceneView.rotation;
									lastPreviewPoint = point;
									Transform trans = point.transform;
									SceneView.lastActiveSceneView.pivot = trans.position + trans.forward * SceneView.lastActiveSceneView.cameraDistance;
									SceneView.lastActiveSceneView.rotation = trans.rotation;
								}
								else
								{
									SceneView.lastActiveSceneView.pivot = lastScenePivot;
									SceneView.lastActiveSceneView.rotation = lastSceneRot;
									lastPreviewPoint = null;
								}
							}
							break;
						default:
							break;
					}
					EditorGUI.DropdownButton(r, content, FocusType.Passive, EditorStyles.miniButton);
				},
			};
			columns[8] = new SerializedPropertyTreeView.Column
			{
				headerContent = new GUIContent("上移"),
				headerTextAlignment = TextAlignment.Left,
				sortedAscending = true,
				sortingArrowAlignment = TextAlignment.Center,
				width = 40,
				autoResize = false,
				allowToggleVisibility = true,
				propertyName = "Number",
				dependencyIndices = null,
				compareDelegate = null,
				drawDelegate = (Rect r, SerializedProperty prop, SerializedProperty[] dep) =>
				{
					Event evt = Event.current;
					GUIContent content = new GUIContent("↑");
					switch (evt.type)
					{
						case EventType.MouseDown:
							if (r.Contains(evt.mousePosition))
							{
								MoveUpDECameraPoint((DECameraPoint)prop.serializedObject.targetObject);
							}
							break;
						default:
							break;
					}
					EditorGUI.DropdownButton(r, content, FocusType.Passive, EditorStyles.miniButton);
				},
			};
			columns[9] = new SerializedPropertyTreeView.Column
			{
				headerContent = new GUIContent("下移"),
				headerTextAlignment = TextAlignment.Left,
				sortedAscending = true,
				sortingArrowAlignment = TextAlignment.Center,
				width = 40,
				autoResize = false,
				allowToggleVisibility = true,
				propertyName = "Number",
				dependencyIndices = null,
				compareDelegate = null,
				drawDelegate = (Rect r, SerializedProperty prop, SerializedProperty[] dep) =>
				{
					Event evt = Event.current;
					GUIContent content = new GUIContent("↓");
					switch (evt.type)
					{
						case EventType.MouseDown:
							if (r.Contains(evt.mousePosition))
							{
								MoveDownDECameraPoint((DECameraPoint)prop.serializedObject.targetObject);
							}
							break;
						default:
							break;
					}
					EditorGUI.DropdownButton(r, content, FocusType.Passive, EditorStyles.miniButton);
				},
			};
			for (var i = 0; i < columns.Length; i++)
			{
				var column = columns[i];
				propnames[i] = column.propertyName;
			}
			return columns;
		}

		private void Awake()
		{
			EditorSceneManager.sceneOpened += OnSceneOpened;
			SceneView.onSceneGUIDelegate += OnSceneGUI;

			cameraTable = new SerializedPropertyTable("Table", FindCameraObjects, CreateCameraColumn);
		}

		private void OnDestroy()
		{
			EditorSceneManager.sceneOpened -= OnSceneOpened;
			SceneView.onSceneGUIDelegate -= OnSceneGUI;
		}

		private void OnGUI()
		{
			RenderTitle();
			EditorGUILayout.Space();

			switch (curEditorPanel)
			{
				case EditorPanel.NewOpen:
					RenderNewOpenPanel();
					break;
				case EditorPanel.Main:
					RenderMainPanel();
					break;
                case EditorPanel.ExportPanoTip:
                    RenderExportPanoTipPanel();
                    break;
            }
		}

		private void RenderTitle()
		{
			EditorGUILayout.BeginHorizontal();
            GUILayout.Space(builderWindow.position.width / 2.0f);
			if (GUILayout.Button(@"帮助"))
			{
				Application.OpenURL("https://vr.baidu.com/doc/vrcc/skrpqxhdx");
			}
			EditorGUILayout.EndHorizontal();
		}

		private void RenderNewOpenPanel()
		{
			EditorGUILayout.BeginHorizontal();
            if (GUILayout.Button(@"新建配置文件(.decu)"))
            {
                newDecCounter++;
                curEditorConfig = new DepthpanoEditorConfig();
                curEditorConfigSavePath = null;
                Clear();
                curEditorPanel = EditorPanel.Main;
            }
            if (GUILayout.Button(@"打开配置文件(.decu)"))
			{
				string configPath = EditorUtility.OpenFilePanel("打开配置文件", Application.dataPath.Replace("Assets", "DepthpanoEditorConfigs"), "decu,dec");
				if (!string.IsNullOrEmpty(configPath))
				{
					curEditorConfig = DepthpanoEditorConfig.GetConfigByFilePath(configPath);
					bool openSuccess = true;
					if (curEditorConfig == null)
					{
						openSuccess = false;
					}
					else
					{
						openSuccess = File.Exists(Application.dataPath.Replace("Assets", curEditorConfig.scenePath));
					}

					if (openSuccess)
					{
						curEditorConfigSavePath = configPath;
						Clear();
						EditorSceneManager.OpenScene(curEditorConfig.scenePath, OpenSceneMode.Single);
                        if (!string.IsNullOrEmpty(curEditorConfig.highModel))
                        {
                            highModel = PathToGameObject(curEditorConfig.highModel);
                        }
                        if (!string.IsNullOrEmpty(curEditorConfig.lowModel))
                        {
                            lowModel = PathToGameObject(curEditorConfig.lowModel);
                        }
                        if (highModel != null)
                        {
                            applied = true;
                        }
                        exportMaterial = lowModel != null;
                        curEditorPanel = EditorPanel.Main;
					}
					else
					{
						EditorUtility.DisplayDialog("打开配置文件错误", "所选配置错误，请选择正确的配置文件！", "确认");
					}
				}
			}
			EditorGUILayout.EndHorizontal();
		}

		private void Clear()
		{
			foreach (var point in curDECameraPoints)
			{
				if (point != null)
				{
					if (Application.isPlaying)
					{
						Destroy(point.gameObject);
					}
					else
					{
						DestroyImmediate(point.gameObject);
					}
				}
			}
            highModel = null;
            lowModel = null;
            applied = false;
            curDECameraPoints.Clear();
			curDECameraAllSelected = false;
            newPointCounter = 1;
            selectedImageResluation = 1;
			selectedImageFormat = 0;
			jpgQuality = defaultJpgQuality;
			depthNearPlane = defaultDepthNearPlane;
			depthFarPlane = defaultDepthFarPlane;
            exportNormalTexture = false;
            exportMaterial = true;
            string projectDir = Application.dataPath.Replace("/Assets", "");
			exportFilePath = Application.dataPath.Replace("Assets", "DepthpanoEditorConfigs/") +
				projectDir.Substring(projectDir.LastIndexOf('/') + 1) + "景深全景图组.zip";
		}

		private void RenderMainPanel()
        {
            GUILayout.Label("模型信息");

            GameObject newHighModel = EditorGUILayout.ObjectField("高精度模型(必选)", highModel, typeof(GameObject), true) as GameObject;
            if (applied)
            {
                if (newHighModel != highModel)
                {
                    if (EditorUtility.DisplayDialog("提示", "修改高精度模型可能会造成漫游点信息错误，是否要继续替换高精度模型？", "是", "否"))
                    {
                        highModel = newHighModel;
                    }
                }
            }
            else
            {
                highModel = newHighModel;
            }

            GameObject newLowModel = EditorGUILayout.ObjectField("低精度模型", lowModel, typeof(GameObject), true) as GameObject;
            if (applied)
            {
                if (lowModel == null && newLowModel != null)
                {
                    exportMaterial = EditorUtility.DisplayDialog("提示", "添加低精度模型后，素材包中可以导出包含支持沙盘功能的素材，是否需要生成沙盘素材？", "是", "否");
                }
                else if (lowModel != null && newLowModel == null)
                {
                    exportMaterial = !EditorUtility.DisplayDialog("提示", "删除低精度模型后，素材包中建议不导出包含支持沙盘功能的素材，是否去除生成沙盘素材？", "是", "否");
                }
                lowModel = newLowModel;
            }
            else
            {
                lowModel = newLowModel;
            }

            GUILayout.Label("*注：请确保高精度模型和低精度模型位置重合！");

            if (!applied)
            {
                if (GUILayout.Button("应用"))
                {
                    if (highModel == null)
                    {
                        EditorUtility.DisplayDialog("未选择高精度模型", "未选择高精度模型，请先选择高精度模型。", "是");
                    }
                    else
                    {
                        exportMaterial = lowModel != null;
                        applied = true;
                    }
                }
            }

            if (applied)
            {
                EditorGUILayout.Space();

                GUILayout.Label("设置漫游点");
                GUILayout.Label("*注：请先对地面物体模型添加mesh collider！");

                using (new EditorGUILayout.VerticalScope())
                {
                    if (cameraTable != null)
                    {
                        cameraTable.OnGUI();
                    }
                }

                EditorGUILayout.BeginHorizontal();

                curDECameraAllSelected = true;
                foreach (var p in curDECameraPoints)
                {
                    if (!p.Check)
                    {
                        curDECameraAllSelected = false;
                        break;
                    }
                }
                bool select = GUILayout.Toggle(curDECameraAllSelected, "全选", GUILayout.Width(40.0f));
                GUILayout.Space(100.0f);
                if (select != curDECameraAllSelected)
                {
                    foreach (var p in curDECameraPoints)
                    {
                        p.Check = select;
                    }
                }
                curDECameraAllSelected = select;

                if (GUILayout.Button(@"新增"))
                {
                    NewDECameraPoint();
                }
                if (GUILayout.Button(@"批量删除"))
                {
                    List<DECameraPoint> selectedPoints = new List<DECameraPoint>();
                    foreach (var p in curDECameraPoints)
                    {
                        if (p.Check)
                        {
                            selectedPoints.Add(p);
                        }
                    }
                    foreach (var p in selectedPoints)
                    {
                        DeleteDECameraPoint(p);
                    }
                    curDECameraAllSelected = false;
                }
                EditorGUILayout.EndHorizontal();

                EditorGUILayout.Space();
                RenderExportConfigArea();

                EditorGUILayout.BeginHorizontal();
                if (GUILayout.Button(@"关闭"))
                {
                    string tipstr = string.Format("关闭插件，是否保存当前场景的编辑信息？", curEditorConfig.scenePath);
                    int r = EditorUtility.DisplayDialogComplex("关闭", tipstr, "保存", "不保存", "取消");
                    if (r == 0)
                    {
                        if (SaveEditorConfig())
                        {
                            Clear();
                            if (builderWindow != null)
                            {
                                builderWindow.Close();
                            }
                            //curEditorPanel = EditorPanel.NewOpen;
                        }
                    }
                    else if (r == 1)
                    {
                        Clear();
                        if (builderWindow != null)
                        {
                            builderWindow.Close();
                        }
                        //curEditorPanel = EditorPanel.NewOpen;
                    }
                }
                if (GUILayout.Button(@"保存配置文件(.decu)"))
                {
                    SaveEditorConfig();
                }
                if (GUILayout.Button(@"导出景深素材(.zip)"))
                {
                    if (SaveEditorConfig())
                    {
                        if (curDECameraPoints.Count <= 0)
                        {
                            EditorUtility.DisplayDialog("错误", "请在场景中配置至少一个漫游点！", "确认");
                        }
                        else if (highModel == null)
                        {
                            EditorUtility.DisplayDialog("未选择高精度模型", "未选择高精度模型，请先选择高精度模型。", "是");
                        }
                        else
                        {
                            ExportDepthpanoRaw();
                        }
                    }
                }
                EditorGUILayout.EndHorizontal();
            }
		}

		private float expect4KTime = 0.4f;
		private float expect8KTime = 1.3f;
        private bool showAdvance = false;

		private void RenderExportConfigArea()
		{
			GUILayout.Label("导出设置");
			EditorGUILayout.Space();

            showAdvance = EditorGUILayout.Foldout(showAdvance, "高级设置");
            if (showAdvance)
            {
                EditorGUILayout.BeginHorizontal();
                GUILayout.Space(30.0f);
                GUILayout.Label("通常情况下无须修改默认参数配置");
                EditorGUILayout.EndHorizontal();

                EditorGUILayout.BeginHorizontal();
                GUILayout.Space(30.0f);
                float newDepthNearPlane = EditorGUILayout.FloatField("摄像机近平面（需>0）", depthNearPlane);
                if (newDepthNearPlane <= 0 || newDepthNearPlane > depthFarPlane)
                {
                    depthNearPlane = defaultDepthNearPlane;
                }
                else
                {
                    depthNearPlane = newDepthNearPlane;
                }
                EditorGUILayout.EndHorizontal();

                EditorGUILayout.BeginHorizontal();
                GUILayout.Space(30.0f);
                depthFarPlane = EditorGUILayout.FloatField("摄像机远平面（需>摄像机近平面）", depthFarPlane);
                if (depthFarPlane <= depthNearPlane)
                {
                    depthFarPlane = defaultDepthFarPlane;
                }
                EditorGUILayout.EndHorizontal();

                EditorGUILayout.BeginHorizontal();
                GUILayout.Space(30.0f);
                int newJpgQuality = EditorGUILayout.IntField("JPG质量参数（[1, 100]）", jpgQuality);
                if (newJpgQuality < 1 || newJpgQuality > 100)
                {
                    jpgQuality = defaultJpgQuality;
                }
                else
                {
                    jpgQuality = newJpgQuality;
                }
                EditorGUILayout.EndHorizontal();

                EditorGUILayout.BeginHorizontal();
                GUILayout.Space(30.0f);
                exportNormalTexture = GUILayout.Toggle(exportNormalTexture, "导出法线贴图");
                EditorGUILayout.EndHorizontal();
            }

            selectedImageResluation = EditorGUILayout.Popup("图片清晰度", selectedImageResluation, imageResluations);
            selectedImageFormat = EditorGUILayout.Popup("图片格式", selectedImageFormat, imageFormats);

            EditorGUILayout.BeginHorizontal();
			GUILayout.Label("导出位置");
			if (GUILayout.Button("选择文件夹"))
			{
				string dir = Application.dataPath.Replace("Assets", "DepthpanoEditorConfigs");
				string defaultName = exportFilePath.Substring(exportFilePath.LastIndexOf('/') + 1);
				string targetDir = EditorUtility.SaveFilePanel("导出位置", dir, defaultName, "zip");
				if (!string.IsNullOrEmpty(targetDir))
				{
					exportFilePath = targetDir;
				}
			}
			if (!string.IsNullOrEmpty(exportFilePath))
			{
				GUILayout.Label(exportFilePath);
			}
			EditorGUILayout.EndHorizontal();
            exportMaterial = GUILayout.Toggle(exportMaterial, "生成沙盘素材");
        }

        private void RenderExportPanoTipPanel()
        {
            string message = "预计用时" + Mathf.RoundToInt((selectedImageResluation == 1 ? expect8KTime : expect4KTime) * curDECameraPoints.Count) + "秒，正在导出，请稍等…";
            EditorGUILayout.LabelField(message);
        }

        private bool SaveEditorConfig()
		{
            // first save scene
            if (string.IsNullOrEmpty(SceneManager.GetActiveScene().path))
            {
                bool saved = EditorSceneManager.SaveScene(SceneManager.GetActiveScene());
                if (!saved)
                {
                    return saved;
                }
                Debug.LogError(SceneManager.GetActiveScene().path);
            }
            curEditorConfig.scenePath = SceneManager.GetActiveScene().path;
            bool isNew = curEditorConfigSavePath == null;
			bool ret = false;
			if (isNew || !File.Exists(curEditorConfigSavePath))
			{
				string dir = Application.dataPath.Replace("Assets", "DepthpanoEditorConfigs");
				if (!Directory.Exists(dir))
				{
					Directory.CreateDirectory(dir);
				}
				curEditorConfigSavePath = EditorUtility.SaveFilePanel("保存配置文件", dir, "百度VR景深配置" + newDecCounter, "decu");
				if (string.IsNullOrEmpty(curEditorConfigSavePath))
				{
					curEditorConfigSavePath = null;
				}
			}
			if (curEditorConfigSavePath != null)
			{
                curEditorConfig.highModel = highModel == null ? null : GameObjectToPath(highModel);
                curEditorConfig.lowModel = lowModel == null ? null : GameObjectToPath(lowModel);
                curEditorConfig.groups = new DepthpanoEditorGroupInfo[1];
                curEditorConfig.groups[0] = new DepthpanoEditorGroupInfo();
                curEditorConfig.groups[0].name = "group1";
                curEditorConfig.groups[0].cameras = new DepthpanoCameraInfo[curDECameraPoints.Count];
				for (int i = 0; i < curDECameraPoints.Count; i++)
				{
                    curEditorConfig.groups[0].cameras[i] = new DepthpanoCameraInfo();
                    curEditorConfig.groups[0].cameras[i].cameraName = curDECameraPoints[i].name;
                    curEditorConfig.groups[0].cameras[i].cameraPos = Vector3Info.FromVector3(curDECameraPoints[i].transform.position);
				}
				ret = DepthpanoEditorConfig.SaveConfigToPath(curEditorConfig, curEditorConfigSavePath);
				if (!ret)
				{
					EditorUtility.DisplayDialog("保存配置文件失败", "保存配置文件失败", "确认");
					if (isNew)
					{
						curEditorConfigSavePath = null;
					}
				}
			}
			return ret;
		}

		private void ExportMeshDepthObjAndMtl(string targetDir)
        {
            GameObject baseModel = null;
            if (lowModel != null)
            {
                lowModel.SetActive(true);
                baseModel = lowModel;
            }
            else
            {
                baseModel = highModel;
            }

            MeshFilter[] mfs = baseModel.GetComponentsInChildren<MeshFilter>();
            int meshCounter = 0;
            int mtlCounter = 0;

            string newTargetObjDir = string.Format(@"{0}/depth.obj", targetDir);
            if (File.Exists(newTargetObjDir)) File.Delete(newTargetObjDir);
            StreamWriter objSW = new StreamWriter(newTargetObjDir);

            StreamWriter mtlSW = null;
            if (exportMaterial)
            {
                string newTargetMtlDir = string.Format(@"{0}/depth.mtl", targetDir);
                if (File.Exists(newTargetMtlDir)) File.Delete(newTargetMtlDir);
                mtlSW = new StreamWriter(newTargetMtlDir);
            }

            objSW.WriteLine("mtllib depth.mtl");

            if (exportMaterial)
            {
                mtlSW.WriteLine("newmtl DefaultMtl");
                mtlSW.WriteLine("d 0.000000");
                mtlSW.WriteLine("illum 1");
            }

            int tOffset = 1;
            int texcounter = 0;

            Dictionary<Material, string> savedMaterial = new Dictionary<Material, string>();
            Dictionary<Texture2D, string> savedTexture = new Dictionary<Texture2D, string>();

            foreach (var mf in mfs)
            {
                if (mf.GetComponentInParent<DECameraPoint>() != null) continue;
                if (mf.sharedMesh == null) continue;
                string name = string.Format("mesh_{0}", meshCounter);
                meshCounter++;
                objSW.WriteLine(string.Format("o {0}", name));

                Transform trans = mf.transform;
                MeshRenderer renderer = mf.GetComponent<MeshRenderer>();

                foreach (Vector3 v in mf.sharedMesh.vertices)
                {
                    Vector3 pos = trans.TransformPoint(v);
                    // to right hand system
                    objSW.WriteLine(string.Format("v {0} {1} {2}", pos.x, pos.y, -pos.z));
                }
                foreach (Vector2 v in mf.sharedMesh.uv)
                {
                    objSW.WriteLine(string.Format("vt {0} {1}", v.x, v.y));
                }
                foreach (Vector3 v in mf.sharedMesh.normals)
                {
                    Vector3 normal = trans.TransformDirection(v);
                    // to right hand system
                    objSW.WriteLine(string.Format("vn {0} {1} {2}", normal.x, normal.y, -normal.z));
                }

                int fcounter = 0;
                int f0 = 0, f1 = 0;

                for (int i = 0; i < mf.sharedMesh.subMeshCount; i++)
                {
                    if (exportMaterial)
                    {
                        bool mtlUsed = false;
                        if (renderer != null && renderer.enabled && i < renderer.sharedMaterials.Length)
                        {
                            Material mat = renderer.sharedMaterials[i];
                            if (mat != null)
                            {
                                HashSet<string> mtlKeywords = new HashSet<string>(mat.shaderKeywords);

                                string mtlName;
                                if (!savedMaterial.TryGetValue(mat, out mtlName))
                                {
                                    mtlName = string.Format("mtl_{0}", mtlCounter);
                                    mtlCounter++;
                                    savedMaterial.Add(mat, mtlName);

                                    // export mtl and texture
                                    mtlSW.WriteLine(string.Format("newmtl {0}", mtlName));

                                    if (mat.HasProperty("_Metallic"))
                                    {
                                        float f = mat.GetFloat("_Metallic");
                                        mtlSW.WriteLine(string.Format("Ns {0}", f));
                                    }

                                    mtlSW.WriteLine("Ka 1.000000 1.000000 1.000000");

                                    if (mat.HasProperty("_Color"))
                                    {
                                        Color c = mat.GetColor("_Color");
                                        mtlSW.WriteLine(string.Format("Kd {0} {1} {2}", c.r, c.g, c.b));
                                        mtlSW.WriteLine(string.Format("Ks {0} {1} {2}", c.r, c.g, c.b));
                                    }
                                    else
                                    {
                                        mtlSW.WriteLine("Kd 1.000000 1.000000 1.000000");
                                        mtlSW.WriteLine("Ks 1.000000 1.000000 1.000000");
                                    }

                                    if (mtlKeywords.Contains("_EMISSION") && mat.HasProperty("_EmissionColor"))
                                    {
                                        Color c = mat.GetColor("_EmissionColor");
                                        mtlSW.WriteLine(string.Format("Ke {0} {1} {2}", c.r, c.g, c.b));
                                    }

                                    mtlSW.WriteLine("Ni 1.000000");

                                    float d = 1.0f;

                                    if (mat.HasProperty("_Color"))
                                    {
                                        if (mat.HasProperty("_Mode")) // check transparent by _Mode in Standard Shader
                                        {
                                            float f = mat.GetFloat("_Mode");
                                            if (f != 1.0)
                                            {
                                                d = mat.color.a;
                                            }
                                        }
                                        else if (mat.renderQueue >= 3000) // check transparent by render Queue
                                        {
                                            d = mat.color.a;
                                        }
                                    }

                                    mtlSW.WriteLine(string.Format("d {0}", d));

                                    mtlSW.WriteLine("illum 1");

                                    System.Func<Texture2D, string> exportTex = (tex) =>
                                    {
                                        string assetPath = AssetDatabase.GetAssetPath(tex);
                                    /*assetPath = Application.dataPath.Substring(0, Application.dataPath.Length - 6) + assetPath;
                                    FileInfo fi = new FileInfo(assetPath);
                                    string ret = string.Format(@"texture_{0}{1}", texcounter, fi.Extension);*/
                                        TextureImporter ti = AssetImporter.GetAtPath(assetPath) as TextureImporter;
                                        TextureImporterType baseImportType = TextureImporterType.Default;
                                        if (ti != null && ti.textureType != TextureImporterType.Default)
                                        {
                                            baseImportType = ti.textureType;

                                            ti.textureType = TextureImporterType.Default;
                                            ti.SaveAndReimport();
                                        }

                                        string ret = string.Format(@"texture_{0}.jpg", texcounter);
                                        string texExportPath = string.Format(@"{0}/{1}", targetDir, ret);
                                        texcounter++;
                                    //File.Copy(assetPath, texExportPath);
                                    RenderTexture renderTex = RenderTexture.GetTemporary(
                                                    tex.width,
                                                    tex.height,
                                                    0,
                                                    RenderTextureFormat.Default,
                                                    RenderTextureReadWrite.Linear);

                                        Graphics.Blit(tex, renderTex);
                                        RenderTexture previous = RenderTexture.active;
                                        RenderTexture.active = renderTex;
                                        Texture2D readableText = new Texture2D(tex.width, tex.height);
                                        readableText.ReadPixels(new Rect(0, 0, renderTex.width, renderTex.height), 0, 0);
                                        readableText.Apply();
                                        RenderTexture.active = previous;
                                        RenderTexture.ReleaseTemporary(renderTex);

                                        byte[] bytes = readableText.EncodeToJPG(75);
                                        File.WriteAllBytes(texExportPath, bytes);
                                        DestroyImmediate(readableText);

                                        if (ti != null && baseImportType != TextureImporterType.Default)
                                        {
                                            ti.textureType = baseImportType;
                                            ti.SaveAndReimport();
                                        }
                                        return ret;
                                    };

                                    if (mat.mainTexture != null)
                                    {
                                        Texture2D tex2D = mat.mainTexture as Texture2D;
                                        if (tex2D != null)
                                        {
                                            string texName;
                                            if (!savedTexture.TryGetValue(tex2D, out texName))
                                            {
                                                texName = exportTex(tex2D);
                                                savedTexture.Add(tex2D, texName);
                                            }
                                            mtlSW.WriteLine(string.Format("map_Kd {0}", texName));
                                        }
                                    }

                                    if (exportNormalTexture && mat.HasProperty("_BumpMap"))
                                    {
                                        Texture2D tex2D = mat.GetTexture("_BumpMap") as Texture2D;
                                        if (tex2D != null)
                                        {
                                            string texName;
                                            if (!savedTexture.TryGetValue(tex2D, out texName))
                                            {
                                                texName = exportTex(tex2D);
                                                savedTexture.Add(tex2D, texName);
                                            }
                                            mtlSW.WriteLine(string.Format("map_Bump {0}", texName));
                                        }
                                    }

                                    if (mat.HasProperty("_MetallicGlossMap"))
                                    {
                                        Texture2D tex2D = mat.GetTexture("_MetallicGlossMap") as Texture2D;
                                        if (tex2D != null)
                                        {
                                            string texName;
                                            if (!savedTexture.TryGetValue(tex2D, out texName))
                                            {
                                                texName = exportTex(tex2D);
                                                savedTexture.Add(tex2D, texName);
                                            }
                                            mtlSW.WriteLine(string.Format("map_Ns {0}", texName));
                                        }
                                    }

                                    if (mtlKeywords.Contains("_EMISSION") && mat.HasProperty("_EmissionMap"))
                                    {
                                        Texture2D tex2D = mat.GetTexture("_EmissionMap") as Texture2D;
                                        if (tex2D != null)
                                        {
                                            string texName;
                                            if (!savedTexture.TryGetValue(tex2D, out texName))
                                            {
                                                texName = exportTex(tex2D);
                                                savedTexture.Add(tex2D, texName);
                                            }
                                            mtlSW.WriteLine(string.Format("map_Ke {0}", texName));
                                        }
                                    }
                                    // end export mtl and texture
                                }
                                objSW.WriteLine(string.Format("usemtl {0}", mtlName));
                                mtlUsed = true;
                            }
                        }

                        if (!mtlUsed)
                        {
                            objSW.WriteLine("usemtl DefaultMtl");
                        }
                    }

                    int[] triangles = mf.sharedMesh.GetTriangles(i);
                    foreach (int t in triangles)
                    {
                        int tt = t + tOffset;
                        // to right hand system
                        if (fcounter == 0)
                        {
                            f0 = tt;
                            fcounter++;
                        }
                        else if (fcounter == 1)
                        {
                            f1 = tt;
                            fcounter++;
                        }
                        else if (fcounter == 2)
                        {
                            objSW.WriteLine(string.Format("f {0}/{0}/{0} {1}/{1}/{1} {2}/{2}/{2}", f0, tt, f1));
                            fcounter = 0;
                        }
                    }
                }
                tOffset += mf.sharedMesh.vertices.Length;
            }
			objSW.Close();

            if (exportMaterial)
            {
                mtlSW.Close();
            }

            if (lowModel != null)
            {
                lowModel.SetActive(false);
            }
        }

		private int exportMainProcessBarIdx = 0;
		private int exportMainProcessBarTotal = 100;
		private void StartExportMainProcessBar(string title, string message)
		{
			exportMainProcessBarIdx = 0;
			EditorApplication.update = () =>
			{
                EditorUtility.DisplayProgressBar(title, message, (float)exportMainProcessBarIdx / exportMainProcessBarTotal);
				if (exportMainProcessBarIdx >= exportMainProcessBarTotal)
				{
					EditorUtility.ClearProgressBar();
					EditorApplication.update = null;
				}
			};
		}

		private void ExportDepthpanoRaw()
		{
			if (string.IsNullOrEmpty(exportFilePath)) return;
			if (File.Exists(exportFilePath))
			{
				bool or = EditorUtility.DisplayDialog("目标已存在",
					string.Format("{0}已存在。是否覆盖？", exportFilePath), "是", "否");
				if (!or) return;
			}
            string message = "预计用时" + (selectedImageResluation == 1 ? expect8KTime : expect4KTime) * curDECameraPoints.Count + "秒，正在导出，请稍等…";
            //StartExportMainProcessBar("正在导出", message);
            curEditorPanel = EditorPanel.ExportPanoTip;
            EditorApplication.delayCall = DelayStartExportDepthpanoRaw;
        }
		
        private void DelayStartExportDepthpanoRaw()
        {
            EditorApplication.delayCall = StartExportDepthpanoRaw;
        }

        private void StartExportDepthpanoRaw()
        {
            try
            {
                string dirPath = exportFilePath.Substring(0, exportFilePath.LastIndexOf('/') + 1);
                string tempPath = dirPath + Random.Range(int.MinValue, int.MaxValue).ToString();
                while (Directory.Exists(tempPath))
                {
                    tempPath = dirPath + Random.Range(int.MinValue, int.MaxValue).ToString();
                }

                Directory.CreateDirectory(tempPath);
                string groupPath = tempPath + "/group1";
                Directory.CreateDirectory(string.Format("{0}/{1}", tempPath, "panos"));

                ExportPanos(curDECameraPoints, groupPath);
                exportMainProcessBarIdx = 50;
                ExportMeshDepthObjAndMtl(groupPath);
                exportMainProcessBarIdx = 75;
                ExportConfig(curDECameraPoints, tempPath);
                exportMainProcessBarIdx = 80;

                string[] needZipFiles = Directory.GetFiles(tempPath, "*", SearchOption.AllDirectories);

                if (File.Exists(exportFilePath))
                {
                    File.Delete(exportFilePath);
                }
                DepthpanoEditorZipHelper.ZipFiles(exportFilePath, tempPath, needZipFiles);

                foreach (string file in needZipFiles)
                {
                    File.Delete(file);
                }
                Directory.Delete(tempPath, true);

                exportMainProcessBarIdx = 99;
                exportSuccess = true;
            }
            catch (System.Exception e)
            {
                Debug.LogError(e.Message);
                exportMainProcessBarIdx = 100;
                exportSuccess = false;
            }

            EditorApplication.delayCall = ShowExportResult;
        }

        private void ShowExportResult()
        {
            curEditorPanel = EditorPanel.Main;
            exportMainProcessBarIdx = 100;
            if (exportSuccess)
            {
                bool openFile = EditorUtility.DisplayDialog("导出成功",
                    string.Format("保存地址为：{0}。\n请前往https://vr.baidu.com/vrcc上传该素材，并编辑创作你的作品吧！", exportFilePath), "打开文件", "完成");
                if (openFile)
                {
                    EditorUtility.RevealInFinder(exportFilePath);
                }
            }
            else
            {
                EditorUtility.DisplayDialog("导出失败", "导出失败", "确认");
            }

            EditorApplication.delayCall = null;
        }

		private void ExportConfig(List<DECameraPoint> cameraPoints, string targetDir)
		{
			DepthpanoConfig root = new DepthpanoConfig();
			root.version = "2.0.0";
			root.type = "depthpano";
            root.objects = new DepthpanoGroupInfo[1];
            root.objects[0] = new DepthpanoGroupInfo();

            root.objects[0].id = "group1";
            root.objects[0].name = "默认分组1";

            if (exportMaterial)
            {
                ModelInfoWithMat modelInfo = new ModelInfoWithMat();
                modelInfo.source = "./group1/depth.obj";
                modelInfo.material = "./group1/depth.mtl";
                root.objects[0].model = modelInfo;
            }
            else
            {
                ModelInfo modelInfo = new ModelInfo();
                modelInfo.source = "./group1/depth.obj";
                root.objects[0].model = modelInfo;
            }

            root.objects[0].children = new DepthpanoInfo[cameraPoints.Count];
			for (int i = 0; i < cameraPoints.Count; i++)
			{
				DepthpanoInfo depthpanoInfo = new DepthpanoInfo();
				depthpanoInfo.transform = new TransformInfo();
				depthpanoInfo.image = new ImageInfo();
				depthpanoInfo.name = cameraPoints[i].name;
				depthpanoInfo.transform.position = Vector3Info.FromVector3(cameraPoints[i].transform.position);
				// to right hand system
				depthpanoInfo.transform.position.z = -depthpanoInfo.transform.position.z;
				depthpanoInfo.image.type = "cube";
				depthpanoInfo.image.cube_file = string.Format("./group1/panos/{0}/{0}_%s.jpg", i, i);

                root.objects[0].children[i] = depthpanoInfo;
			}
			string json = JsonMapper.ToJson(root);
			File.WriteAllText(string.Format("{0}/config.json", targetDir), json);
		}

		private void ExportPanos(List<DECameraPoint> points, string targetDir)
		{
            if (lowModel != null)
            {
                lowModel.SetActive(false);
            }
			for (int i = 0; i < points.Count; i++)
			{
				points[i].gameObject.SetActive(false);
			}
			int idxPerPano = 50 / points.Count;
			for (int i = 0; i < points.Count; i++)
			{
				VRCubeCapture dc = points[i].gameObject.AddComponent<VRCubeCapture>();

				string subDir = string.Format("{0}/{1}/", targetDir, "panos");
				dc.customPath = true;
				dc.customPathFolder = subDir;
				dc.Folder = i.ToString();
				dc._fileName = i.ToString();
				int res = 1024;
				if (selectedImageResluation == 1) res = 2048;
				dc.resolution = res;
				dc.resolutionH = res;
				dc.farPlane = depthFarPlane;
				dc.nearPlane = depthNearPlane;
				dc.ImageFormatType = (VRCubeCapture.VRFormatList)selectedImageFormat;
				dc.jpgQuality = jpgQuality;
				dc.StartCaptureImage();
				Camera c = dc.GetComponent<Camera>();
				DestroyImmediate(dc);
				DestroyImmediate(c);
				exportMainProcessBarIdx = idxPerPano * (i + 1);
			}
			for (int i = 0; i < points.Count; i++)
			{
				points[i].gameObject.SetActive(true);
			}
		}

		private void NewDECameraPoint()
		{
			string name = string.Format("漫游点{0:D3}",newPointCounter);
            newPointCounter++;
            Vector3 pos;
            if (highModel != null)
            {
                pos = GetCenter(highModel);
            }
            else
            {
                pos = SceneView.lastActiveSceneView.pivot;
            }
			DECameraPoint newP = AddDECameraPoint(name, pos);

            int checkCount = 0;
            while (checkCount < 10)
            {
                newP.CheckGround();
                Vector3? groundPos = newP.GetGroundPosition();
                if (groundPos.HasValue)
                {
                    if (Mathf.Abs(newP.transform.position.y - groundPos.Value.y - 1.7f) <= 0.00001f)
                    {
                        break;
                    }
                    else
                    {
                        newP.transform.position = groundPos.Value + new Vector3(0.0f, 1.7f, 0.0f);
                    }
                }
                else
                {
                    break;
                }
                checkCount++;
            }
            Selection.activeGameObject = newP.gameObject;
		}

        private static Vector3 GetCenter(GameObject obj)
        {
            Vector3 center = Vector3.zero;
            Renderer[] renders = obj.GetComponentsInChildren<Renderer>();
            foreach (Renderer r in renders)
            {
                center += r.bounds.center;
            }
            if (renders.Length > 0)
            {
                center /= renders.Length;
            }
            Bounds bounds = new Bounds(center, Vector3.zero);
            foreach (Renderer r in renders)
            {
                bounds.Encapsulate(r.bounds);
            }
            return bounds.center;
        }

        private DECameraPoint AddDECameraPoint(string name, Vector3 pos)
		{
			GameObject obj = Instantiate(Resources.Load<GameObject>("PanoPoint"));
			obj.name = name;
			obj.transform.position = pos;
			DECameraPoint p = obj.GetComponent<DECameraPoint>();
			curDECameraPoints.Add(p);
			return p;
		}

		private static float COPY_OFFSET_RADIUS = 0.2f;
		private DECameraPoint CopyDECameraPoint(DECameraPoint basePoint)
		{
			GameObject obj = Instantiate(basePoint.gameObject);
			obj.name = basePoint.name + "副本";
			obj.transform.position +=  Quaternion.Euler(0.0f, Random.Range(0.0f, 360.0f), 0.0f) * (Vector3.forward * COPY_OFFSET_RADIUS);
			DECameraPoint p = obj.GetComponent<DECameraPoint>();
			curDECameraPoints.Add(p);
			return p;
		}

		private void DeleteDECameraPoint(DECameraPoint point)
		{
			curDECameraPoints.Remove(point);
			if (Application.isPlaying)
			{
				Destroy(point.gameObject);
			}
			else
			{
				DestroyImmediate(point.gameObject);
			}
		}

		private void MoveUpDECameraPoint(DECameraPoint point)
		{
			int idx = curDECameraPoints.IndexOf(point);
			if (idx > 0 && idx <= curDECameraPoints.Count - 1)
			{
				curDECameraPoints[idx] = curDECameraPoints[idx - 1];
				curDECameraPoints[idx - 1] = point;
			}
		}

		private void MoveDownDECameraPoint(DECameraPoint point)
		{
			int idx = curDECameraPoints.IndexOf(point);
			if (idx < curDECameraPoints.Count - 1 && idx >= 0)
			{
				curDECameraPoints[idx] = curDECameraPoints[idx + 1];
				curDECameraPoints[idx + 1] = point;
			}
		}

		private void OnSceneOpened(Scene path, OpenSceneMode mode)
		{
            if (curEditorConfig != null)
            {
                if (curEditorConfig.groups[0].cameras != null)
                {
                    for (int i = 0; i < curEditorConfig.groups[0].cameras.Length; i++)
                    {
                        AddDECameraPoint(curEditorConfig.groups[0].cameras[i].cameraName, curEditorConfig.groups[0].cameras[i].cameraPos.GetVector3());
                    }
                }
            }
		}

		private void OnInspectorUpdate()
		{
			cameraTable.OnInspectorUpdate();
		}
		private void OnHierarchyChange()
		{
			cameraTable.OnHierarchyChange();
		}

		private void OnSelectionChange()
		{
			cameraTable.OnSelectionChange();
		}

		private void OnDisable()
		{
			Clear();
		}

		private static void OnSceneGUI(SceneView sceneView)
		{
			DECameraPoint[] points = FindObjectsOfType<DECameraPoint>();
			foreach (var p in points)
			{
				if (p == null)
					return;

				Vector3 center = p.transform.position;

				Handles.Label(center, p.name);
			}
		}

        private static string GameObjectToPath(GameObject obj)
        {
            string path = obj.name;
            Transform parent = obj.transform.parent;
            while (parent != null)
            {
                path = parent.name + "/" + path;
                parent = parent.parent;
            }
            return path;
        }

        private static GameObject PathToGameObject(string path)
        {
            string[] names = path.Split(new char[] { '/' });
            GameObject[] rootObjects = SceneManager.GetActiveScene().GetRootGameObjects();

            for (int i = 0; i < rootObjects.Length; i++)
            {
                if (rootObjects[i].name == names[0])
                {
                    if (names.Length == 1)
                    {
                        return rootObjects[i];
                    }
                    else
                    {
                        Transform trans = PathToTransfrom(rootObjects[i].transform, names, 1);
                        if (trans != null)
                        {
                            return trans.gameObject;
                        }
                    }
                }
            }

            return null;
        }

        private static Transform PathToTransfrom(Transform baseTrans, string[] names, int index)
        {
            foreach (Transform child in baseTrans)
            {
                if (child.name == names[index])
                {
                    if (names.Length == index + 1)
                    {
                        return child;
                    }
                    else
                    {
                        Transform ret = PathToTransfrom(child, names, index + 1);
                        if (ret != null)
                        {
                            return ret;
                        }
                    }
                }
            }
            return null;
        }
    }
}