public void DrawWithCache(string guid, Rect rect)
            {
                Item item;

                if (this.cache.TryGetValue(guid, out item) == false)
                {
                    item = new Item();

                    item.path = AssetDatabase.GUIDToAssetPath(guid);
                    var obj = AssetDatabase.LoadAssetAtPath <UnityEngine.Object>(item.path);

                    if (obj != null)
                    {
                        var dirty = false;
                        var go    = obj as GameObject;
                        if (go != null)
                        {
                            dirty = this.IsDirty(go.GetInstanceID());
                            if (dirty == false)
                            {
                                var comps = go.GetComponents <MonoBehaviour>();
                                foreach (var comp in comps)
                                {
                                    dirty = this.IsDirty(comp.GetInstanceID());
                                    if (dirty == true)
                                    {
                                        break;
                                    }
                                }
                            }
                        }
                        else
                        {
                            dirty = this.IsDirty(obj.GetInstanceID());
                        }

                        item.instanceId = obj.GetInstanceID();
                        item.isDirty    = dirty;
                    }

                    if (FlowProjectWindowObject.IsValidPackage(item.path) == true)
                    {
                        item.isValidPackage = true;
                        item.isPackage      = true;
                    }

                    var packageDir = item.path;

                    if (System.IO.File.Exists(packageDir) == true)
                    {
                        var splitted = item.path.Split('/');
                        packageDir = string.Join("/", splitted, 0, splitted.Length - 1);
                    }

                    if (FlowProjectWindowObject.IsValidPackage(packageDir) == true || FlowProjectWindowObject.IsValidPackage(System.IO.Path.Combine(packageDir, "..")) == true)
                    {
                        var last = item.path.Split('/');
                        if (last.Length > 0)
                        {
                            item.isValidPackage = true;

                            var folder = last[last.Length - 1];
                            if (folder == "Screens")
                            {
                                item.isScreensFolder = true;
                            }
                            else if (folder == "Transitions")
                            {
                                item.isTransitionsFolder = true;
                            }
                            else if (folder == "Components")
                            {
                                item.isComponentsFolder = true;
                            }
                            else if (folder == "Layouts")
                            {
                                item.isLayoutsFolder = true;
                            }
                            else if (item.path.EndsWith("Base.cs") == true)
                            {
                                item.withSystemLabel = true;
                                item.isBaseClass     = true;
                            }
                        }
                    }

                    this.cache.Add(guid, item);
                }

                this.OnGUIItem(item.path, rect, item);
            }
        public static void CreateTransition(FlowWindow flowWindow, FlowWindow toWindow, string localPath, System.Action <TransitionInputTemplateParameters> callback = null)
        {
            if (flowWindow.GetScreen() == null)
            {
                return;
            }

            var screenPath = AssetDatabase.GetAssetPath(flowWindow.GetScreen());

            screenPath = System.IO.Path.GetDirectoryName(screenPath);
            var splitted    = screenPath.Split(new string[] { "/" }, System.StringSplitOptions.RemoveEmptyEntries);
            var packagePath = string.Join("/", splitted, 0, splitted.Length - 1);
            var path        = packagePath + localPath;

            FlowChooserFilterWindow.Show <TransitionInputTemplateParameters>(
                root: null,
                onSelect: (element) => {
                // Clean up previous transitions if exists
                var attachItem = flowWindow.GetAttachItem(toWindow);
                if (attachItem != null)
                {
                    if (attachItem.transition != null && attachItem.transitionParameters != null)
                    {
                        AssetDatabase.DeleteAsset(AssetDatabase.GetAssetPath(attachItem.transitionParameters.gameObject));

                        attachItem.transition           = null;
                        attachItem.transitionParameters = null;
                    }
                }

                if (System.IO.Directory.Exists(path) == false)
                {
                    System.IO.Directory.CreateDirectory(path);
                }

                if (element == null)
                {
                    return;
                }

                var elementPath = AssetDatabase.GetAssetPath(element.gameObject);
                var targetName  = "Transition-" + element.gameObject.name + "-" + (toWindow.IsFunction() == true ? FlowSystem.GetWindow(toWindow.functionId).directory : toWindow.directory);
                var targetPath  = path + "/" + targetName + ".prefab";

                if (AssetDatabase.CopyAsset(elementPath, targetPath) == true)
                {
                    AssetDatabase.ImportAsset(targetPath);

                    var newInstance        = AssetDatabase.LoadAssetAtPath <GameObject>(targetPath);
                    var instance           = newInstance.GetComponent <TransitionInputTemplateParameters>();
                    instance.useAsTemplate = false;
                    EditorUtility.SetDirty(instance);

                    attachItem.transition           = instance.transition;
                    attachItem.transitionParameters = instance;

                    if (callback != null)
                    {
                        callback(instance);
                    }
                }
            },
                onEveryGUI: (element) => {
                // on gui

                var style      = new GUIStyle(GUI.skin.label);
                style.wordWrap = true;

                if (element != null)
                {
                    GUILayout.Label(element.name, style);
                }
                else
                {
                    GUILayout.Label("None", style);
                }
            },
                predicate: (element) => {
                var elementPath = AssetDatabase.GetAssetPath(element.gameObject);
                var isInPackage = FlowProjectWindowObject.IsValidPackage(elementPath + "/../");

                if (element.transition != null && (isInPackage == true || element.useAsTemplate == true))
                {
                    var name     = element.GetType().FullName;
                    var baseName = name.Substring(0, name.IndexOf("Parameters"));

                    var type = System.Type.GetType(baseName + ", " + element.GetType().Assembly.FullName, throwOnError: true, ignoreCase: true);
                    if (type != null)
                    {
                        var attribute = type.GetCustomAttributes(inherit: true).OfType <TransitionCameraAttribute>().FirstOrDefault();
                        if (attribute != null)
                        {
                            return(true);
                        }
                        else
                        {
                            Debug.Log("No Attribute: " + baseName, element);
                        }
                    }
                    else
                    {
                        Debug.Log("No type: " + baseName);
                    }
                }

                return(false);
            },
                strongType: false,
                directory: null,
                useCache: false,
                drawNoneOption: true,
                updateRedraw: true);
        }