//----------------------------------------------------------------------------------------------------------------------

        /// Import images in the path to create StreamingImageSequence assets with those images
        /// <param name="path"> Can be a directory path or a file path</param>
        /// <param name="targetAsset"> The target asset where the images are assigned to</param>
        /// <param name="askToCopy"> Ask to copy if path is not under StreamingAssets. Default to true</param>
        internal static void ImportImages(string path,
                                          StreamingImageSequencePlayableAsset targetAsset, bool askToCopy = true)
        {
            Assert.IsFalse(string.IsNullOrEmpty(path));

            FindFolderAndImages(path, out string folder, out List <string> relFilePaths);
            if (relFilePaths.Count <= 0)
            {
                EditorUtility.DisplayDialog(StreamingImageSequenceConstants.DIALOG_HEADER, @"No files in folder:: " + folder, "OK");
                return;
            }

            //Estimate the asset name. Use the filename without numbers at the end
            string assetName = EstimateAssetName(relFilePaths[0]);

            // set dest folder
            string streamingAssetsPath = AssetEditorUtility.NormalizeAssetPath(Application.streamingAssetsPath);

            //Set importer param
            ImageFileImporterParam importerParam = new ImageFileImporterParam {
                strSrcFolder          = folder,
                RelativeFilePaths     = relFilePaths,
                CopyToStreamingAssets = true,
                TargetAsset           = targetAsset
            };


            //Import immediately if the assets are already under StreamingAssets
            if (folder.StartsWith(streamingAssetsPath) || !askToCopy)
            {
                importerParam.strDstFolder          = importerParam.strSrcFolder;
                importerParam.CopyToStreamingAssets = false;
                ImageSequenceImporter.Import(importerParam);
            }
            else
            {
                importerParam.strDstFolder = Path.Combine(streamingAssetsPath, assetName).Replace("\\", "/");
                ImageSequenceImportWindow.Show(importerParam);
            }
        }
//----------------------------------------------------------------------------------------------------------------------
        public override void OnInspectorGUI()
        {
            //View resolution
            Vector2 res = ViewEditorUtility.GetMainGameViewSize();

            EditorGUILayout.LabelField("Resolution (Modify GameView size to change)");
            ++EditorGUI.indentLevel;
            EditorGUILayout.LabelField("Width", res.x.ToString(CultureInfo.InvariantCulture));
            EditorGUILayout.LabelField("Height", res.y.ToString(CultureInfo.InvariantCulture));
            --EditorGUI.indentLevel;
            EditorGUILayout.Space(15f);

            //Check if the asset is actually inspected
            if (null != TimelineEditor.selectedClip && TimelineEditor.selectedClip.asset != m_asset)
            {
                return;
            }

            ValidateAssetFolder();

            string prevFolder = m_asset.GetFolder();

            string newFolder = InspectorUtility.ShowFolderSelectorGUI("Cache Output Folder", "Select Folder",
                                                                      prevFolder,
                                                                      AssetEditorUtility.NormalizeAssetPath
                                                                      );

            if (newFolder != prevFolder)
            {
                m_asset.SetFolder(AssetEditorUtility.NormalizeAssetPath(newFolder));
                GUIUtility.ExitGUI();
            }

            TimelineClipSISData timelineClipSISData = m_asset.GetBoundTimelineClipSISData();

            if (null == timelineClipSISData)
            {
                return;
            }

            GUILayout.Space(15);

            //Capture Selected Frames
            using (new EditorGUILayout.VerticalScope(GUI.skin.box)) {
                ShowCaptureSelectedFramesGUI(TimelineEditor.selectedClip, timelineClipSISData);
                ShowLockFramesGUI(TimelineEditor.selectedClip, timelineClipSISData);
            }

            ShortcutBinding updateRenderCacheShortcut
                = ShortcutManager.instance.GetShortcutBinding(SISEditorConstants.SHORTCUT_UPDATE_RENDER_CACHE);

            GUILayout.Space(15);
            if (GUILayout.Button($"Update Render Cache ({updateRenderCacheShortcut})"))
            {
                PlayableDirector director = TimelineEditor.inspectedDirector;
                if (null == director)
                {
                    EditorUtility.DisplayDialog("Streaming Image Sequence",
                                                "PlayableAsset is not loaded in scene. Please load the correct scene before doing this operation.",
                                                "Ok");
                    return;
                }

                //Loop time
                EditorCoroutineUtility.StartCoroutine(UpdateRenderCacheCoroutine(director, m_asset), this);
            }
        }
//---------------------------------------------------------------------------------------------------------------------

        /// <summary>
        /// Import a timeline file exported from DCC tools into the scene in the Timeline object
        /// </summary>
        /// <param name="jsTimelinePath">The path of the file</param>
        /// <param name="destFolder">The dest folder of the imported files</param>
        public static void ImportTimeline(string jsTimelinePath, string destFolder = "")
        {
            // prepare asset name, paths, etc
            string assetName      = Path.GetFileNameWithoutExtension(jsTimelinePath);
            string timelineFolder = Path.GetDirectoryName(jsTimelinePath);

            if (string.IsNullOrEmpty(timelineFolder))
            {
                Debug.LogError("Can't get directory name for: " + jsTimelinePath);
                return;
            }
            timelineFolder = Path.Combine(timelineFolder, destFolder, assetName).Replace("\\", "/");

            //Check if we are exporting from external asset
            if (!timelineFolder.StartsWith("Assets/"))
            {
                timelineFolder = Path.Combine("Assets", destFolder, assetName);
            }

            Directory.CreateDirectory(timelineFolder);
            string        strJson     = File.ReadAllText(jsTimelinePath);
            TimelineParam container   = JsonUtility.FromJson <TimelineParam>(strJson);
            string        assetFolder = container.assetFolder;

            if (string.IsNullOrEmpty(assetFolder))
            {
                assetFolder = Path.GetDirectoryName(jsTimelinePath);
            }

            //delete existing objects in the scene that is pointing to the Director
            string           timelinePath = Path.Combine(timelineFolder, assetName + "_Timeline.playable").Replace("\\", "/");
            PlayableDirector director     = RemovePlayableFromDirectorsInScene(timelinePath);

            if (null == director)
            {
                GameObject directorGo = new GameObject(assetName);
                director = directorGo.AddComponent <PlayableDirector>();
            }

            //Create timeline asset
            TimelineAsset asset = ScriptableObject.CreateInstance <TimelineAsset>();

            AssetEditorUtility.OverwriteAsset(asset, timelinePath);

            director.playableAsset = asset;
            string strHome = System.Environment.GetFolderPath(System.Environment.SpecialFolder.Personal);

            int numTracks = container.Tracks.Length;

            for (int index = numTracks - 1; index >= 0; index--)
            {
                var    track          = container.Tracks[index];
                string strFootagePath = track.Footage;
                // remove '~' if necessary
                if (strFootagePath.StartsWith("~"))
                {
                    strFootagePath = strHome + strFootagePath.Substring(1);
                }
                if (!Path.IsPathRooted(strFootagePath))
                {
                    strFootagePath = Path.Combine(assetFolder, strFootagePath);
                }
                string strFootageName = Path.GetFileNameWithoutExtension(strFootagePath);
                string strJsonFootage = File.ReadAllText(strFootagePath);
                StreamingImageSequencePlayableAssetParam trackMovieContainer = JsonUtility.FromJson <StreamingImageSequencePlayableAssetParam>(strJsonFootage);

                int numImages = trackMovieContainer.Pictures.Count;
                if (numImages > 0)
                {
                    List <string> originalImagePaths = new List <string>(trackMovieContainer.Pictures);

                    for (int xx = 0; xx < numImages; ++xx)
                    {
                        string fileName = trackMovieContainer.Pictures[xx];
                        // replace '~' with the path to home (for Linux environment
                        if (fileName.StartsWith("~"))
                        {
                            fileName = strHome + fileName.Substring(1);
                        }
                        trackMovieContainer.Pictures[xx] = Path.GetFileName(fileName);
                    }

                    string destFootageFolder = Application.streamingAssetsPath;
                    destFootageFolder = Path.Combine(destFootageFolder, strFootageName).Replace("\\", "/");
                    Directory.CreateDirectory(destFootageFolder); //make sure the directory exists
                    trackMovieContainer.Folder = AssetEditorUtility.NormalizeAssetPath(destFootageFolder);

                    for (int i = 0; i < numImages; ++i)
                    {
                        string destFilePath = Path.Combine(destFootageFolder, trackMovieContainer.Pictures[i]);
                        if (File.Exists(destFilePath))
                        {
                            File.Delete(destFilePath);
                        }

                        string srcFilePath = Path.GetFullPath(Path.Combine(assetFolder, originalImagePaths[i])).Replace("\\", "/");
                        FileUtil.CopyFileOrDirectory(srcFilePath, destFilePath);
                    }
                }


                StreamingImageSequencePlayableAsset sisAsset = ScriptableObject.CreateInstance <StreamingImageSequencePlayableAsset>();
                sisAsset.InitFolder(trackMovieContainer);

                string playableAssetPath = Path.Combine(timelineFolder, strFootageName + "_StreamingImageSequence.playable");
                AssetEditorUtility.OverwriteAsset(sisAsset, playableAssetPath);

                StreamingImageSequenceTrack movieTrack = asset.CreateTrack <StreamingImageSequenceTrack>(null, strFootageName);
                TimelineClip clip = movieTrack.CreateDefaultClip();
                clip.asset    = sisAsset;
                clip.start    = track.Start;
                clip.duration = track.Duration;
                clip.CreateCurves("Curves: " + clip.displayName);

                TimelineClipSISData sisData = new TimelineClipSISData(clip);
                sisAsset.InitTimelineClipCurve(clip);
                sisAsset.BindTimelineClipSISData(sisData);


                if (Object.FindObjectOfType(typeof(UnityEngine.EventSystems.EventSystem)) == null)
                {
                    var es = new GameObject();
                    es.AddComponent <UnityEngine.EventSystems.EventSystem>();
                    es.AddComponent <UnityEngine.EventSystems.StandaloneInputModule>();
                    es.name = "EventSystem";
                }
                GameObject canvasObj = null;
                Canvas     canvas    = Object.FindObjectOfType(typeof(Canvas)) as Canvas;
                if (canvas != null)
                {
                    canvasObj = canvas.gameObject;
                }
                else
                {
                    canvasObj = UIUtility.CreateCanvas().gameObject;
                }

                Transform directorT = director.gameObject.transform;
                directorT.SetParent(canvasObj.transform);
                directorT.localPosition = new Vector3(0.0f, 0.0f, 0.0f);

                GameObject imageGo = null;
                Transform  imageT  = directorT.Find(strFootageName);
                if (null == imageT)
                {
                    imageGo = new GameObject(strFootageName);
                    imageT  = imageGo.transform;
                }
                else
                {
                    imageGo = imageT.gameObject;
                }

                Image image = imageGo.GetOrAddComponent <Image>();
                StreamingImageSequenceRenderer renderer = imageGo.GetOrAddComponent <StreamingImageSequenceRenderer>();

                RectTransform rectTransform = imageGo.GetComponent <RectTransform>();
                rectTransform.SetParent(directorT);
                rectTransform.localPosition = new Vector3(0.0f, 0.0f, 0.0f);
                rectTransform.sizeDelta     = new Vector2(trackMovieContainer.Resolution.Width,
                                                          trackMovieContainer.Resolution.Height);

                director.SetGenericBinding(movieTrack, renderer);
                EditorUtility.SetDirty(director);
            }

            //cause crash if this is called inside of OnImportAsset()
            UnityEditor.EditorApplication.delayCall += () => {
                AssetDatabase.Refresh();
                if (null != director)
                {
                    Selection.activeGameObject = director.gameObject;
                }
            };
        }
//----------------------------------------------------------------------------------------------------------------------

        internal static string ShowFolderSelectorGUI(string label,
                                                     string dialogTitle,
                                                     string fieldValue,
                                                     Func <string, string> onValidFolderSelected)
        {
            string newDirPath = null;

            using (new EditorGUILayout.HorizontalScope()) {
                if (!string.IsNullOrEmpty(label))
                {
                    EditorGUILayout.PrefixLabel(label);
                }

                EditorGUILayout.SelectableLabel(fieldValue,
                                                EditorStyles.textField, GUILayout.Height(EditorGUIUtility.singleLineHeight)
                                                );

                //Drag drop
                Rect folderRect = GUILayoutUtility.GetLastRect();

                Event evt = Event.current;
                switch (evt.type)
                {
                case EventType.DragUpdated:
                case EventType.DragPerform:
                    if (!folderRect.Contains(evt.mousePosition))
                    {
                        return(fieldValue);
                    }

                    DragAndDrop.visualMode = DragAndDropVisualMode.Copy;
                    if (evt.type == EventType.DragPerform)
                    {
                        DragAndDrop.AcceptDrag();

                        if (DragAndDrop.paths.Length <= 0)
                        {
                            break;
                        }
                        fieldValue = DragAndDrop.paths[0];
//                            onDragAndDrop(DragAndDrop.paths[0]);
                    }

                    break;

                default:
                    break;
                }


                newDirPath = InspectorUtility.ShowSelectFolderButton(dialogTitle, fieldValue, onValidFolderSelected);

                if (GUILayout.Button("Show", GUILayout.Width(50f), GUILayout.Height(EditorGUIUtility.singleLineHeight)))
                {
                    EditorUtility.RevealInFinder(newDirPath);
                }
            }

            using (new EditorGUILayout.HorizontalScope()) {
                GUILayout.FlexibleSpace();
                EditorGUI.BeginDisabledGroup(!AssetDatabase.IsValidFolder(newDirPath));
                if (GUILayout.Button("Highlight in Project Window", GUILayout.Width(180f)))
                {
                    AssetEditorUtility.PingAssetByPath(newDirPath);
                }
                EditorGUI.EndDisabledGroup();
            }

            return(newDirPath);
        }