Beispiel #1
0
        void PopulateRegen()
        {
            var files = AssetDatabase.FindAssets("t:Script");

            for (int i = 0; i < files.Length; ++i)
            {
                var f = files[i];
                EditorUtility.DisplayProgressBar("Detecting Smart Types", string.Format("Reading script {0} / {1}", i, files.Length), (float)i / (float)files.Length);
                string path = AssetDatabase.GUIDToAssetPath(f);
                using (var file = File.OpenText(SmartEditorUtils.ToAbsolutePath(path))){
                    var line = file.ReadLine();
                    if (line.StartsWith(SMARTTYPE_HEADER))
                    {
                        // Get data type from header
                        // SMARTTYPE {data type}
                        string type = line.Replace(SMARTTYPE_HEADER, "");
                        path = SmartEditorUtils.ToDirectory(path);

                        Dictionary <string, bool> types = null;
                        if (!_regenTypesByPath.TryGetValue(path, out types))
                        {
                            types = new Dictionary <string, bool>();
                            _regenTypesByPath.Add(path, types);
                        }
                        types[type] = true;
                    }
                }
            }
            EditorUtility.ClearProgressBar();
        }
Beispiel #2
0
        void Write(string outputFileName, string templateFileName, string t, string fullPath, ref string log)
        {
            try {
                string format = Resources.Load <TextAsset>(templateFileName).text;
                if (!Directory.Exists(fullPath))
                {
                    Directory.CreateDirectory(fullPath);
                }
                string absPathToScript = fullPath + outputFileName;
                string relPathToScript = SmartEditorUtils.ToRelativePath(absPathToScript);
                scriptAbsPathToGuid[absPathToScript] = AssetDatabase.AssetPathToGUID(relPathToScript);

                File.WriteAllText(absPathToScript, string.Format(format, t, PrettyTypeName(t), Capitalize(t)));
                log += "\n  " + outputFileName;
            } catch (System.FormatException e) {
                Debug.LogError("Bad formatting in template " + templateFileName);
                throw e;
            }
        }
        protected void DrawTypeHeader()
        {
            EditorGUILayout.Space();
            var gs = new GUIStyle(EditorStyles.largeLabel);

            gs.fontSize = 18;
            EditorGUILayout.LabelField("Smart " + _displayType, gs, GUILayout.MaxHeight(25));

            EditorGUILayout.BeginHorizontal();
            gs.fontSize = 16;
            Color gcc = GUI.contentColor;

            GUI.contentColor = SmartEditorUtils.GetSmartColor(_smartType);
            GUILayout.Label(_iconSmart, GUILayout.Width(24));
            GUI.contentColor = gcc;
            EditorGUILayout.LabelField(target.name, gs, GUILayout.MaxHeight(24));
            EditorGUILayout.EndHorizontal();

            EditorGUILayout.Space();
        }
        protected virtual void OnEnable()
        {
            _typeName    = target.GetType().Name;
            _displayType = (string)target.GetType().GetField("DISPLAYTYPE", BindingFlags.Static | BindingFlags.NonPublic).GetValue(null);
            _valueType   = (string)target.GetType().GetField("VALUETYPE", BindingFlags.Static | BindingFlags.NonPublic).GetValue(null);
            _dataType    = serializedObject.FindProperty("_dataType");
            _description = serializedObject.FindProperty("_description");

            _updateDecoratorsMulti = target.GetType().GetMethodPrivate("UpdateDecorators", BindingFlags.NonPublic | BindingFlags.Instance);
            _decorators            = serializedObject.FindProperty("_decorators");

            if (!_const)
            {
                _getRelay              = CacheGetRelay();
                _getListenerCount      = _getRelay.FieldType.GetProperty("listenerCount", BindingFlags.Instance | BindingFlags.Public | BindingFlags.FlattenHierarchy);
                _getListeners          = _getRelay.FieldType.GetField("_listeners", BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.FlattenHierarchy);
                _isOnRestoreOverridden = IsOnRestoreOverridden(target.GetType());
            }

            #region Cache available decorator types
            _decoratorTypes.Clear();

            System.Type tDecBase = null;
            _smartType = SmartEditorUtils.GetSmartObjectType(target as SmartBase, out _tData);
            switch (_smartType)
            {
            case SmartEditorUtils.SmartObjectType.EVENT:
            case SmartEditorUtils.SmartObjectType.EVENT_MULTI:
                // Event decorators
                tDecBase = typeof(SmartEventDecoratorBase);
                break;

            case SmartEditorUtils.SmartObjectType.VAR:
            case SmartEditorUtils.SmartObjectType.MULTI:
                tDecBase = typeof(SmartDataDecoratorBase <>).MakeGenericType(_tData);
                break;

            case SmartEditorUtils.SmartObjectType.SET:
                tDecBase = typeof(SmartSetDecoratorBase <>).MakeGenericType(_tData);
                break;
            }

            if (tDecBase != null)
            {
                foreach (var a in System.AppDomain.CurrentDomain.GetAssemblies())
                {
                    foreach (var t in a.GetTypes())
                    {
                        if (!t.IsAbstract && t.IsSubclassOf(tDecBase))
                        {
                            _decoratorTypes.Add(t);
                        }
                    }
                }
            }
            #endregion

            _decBtnStyle = new GUILayoutOption[] {
                GUILayout.MaxWidth(18), GUILayout.MaxHeight(18)
            };
            _iconChevronUp   = Resources.Load <Texture2D>("GUI/chevron_up");
            _iconChevronDown = Resources.Load <Texture2D>("GUI/chevron_down");
            _iconWarn        = EditorGUIUtility.Load("icons/_Help.png") as Texture2D;
            _iconGo          = EditorGUIUtility.IconContent("GameObject Icon").image as Texture2D;
            _iconAsset       = EditorGUIUtility.IconContent("Prefab Icon").image as Texture2D;
            _iconSmart       = SmartEditorUtils.LoadSmartIcon(_smartType);

            PopulateRefs();

            EditorApplication.update += Update;
        }
Beispiel #5
0
        void PostProcessMeta()
        {
            #region Repair GUIDS
            bool refresh = false;
            foreach (var a in scriptAbsPathToGuid)
            {
                // Get latest guid of script from assetdatabase and compare to cached to see if changed
                string newGuid = AssetDatabase.AssetPathToGUID(SmartEditorUtils.ToRelativePath(a.Key));
                if (newGuid != a.Value)
                {
                    Debug.LogWarningFormat("Repairing changed GUID for script {0}", a.Key);
                    string metaPath = a.Key + ".meta";

                    #region Repair meta file
                    if (File.Exists(metaPath))
                    {
                        // Find line with latest guid and replace with cached guid
                        var lines = File.ReadAllLines(a.Key);
                        for (int i = 0; i < lines.Length; ++i)
                        {
                            string l = lines[i];
                            if (l.Contains(newGuid))
                            {
                                Debug.LogFormat("\n\tRestoring {0} to {1}", newGuid, a.Value);
                                lines[i] = l.Replace(newGuid, a.Value);

                                // Save and flag for asset database refresh
                                File.WriteAllLines(a.Key, lines);
                                refresh = true;
                                break;
                            }
                        }
                    }
                    #endregion
                }
            }
            if (refresh)
            {
                AssetDatabase.Refresh();
            }
            #endregion

            #region Set icons
            refresh = false;
            foreach (var a in scriptAbsPathToGuid)
            {
                string metaPath = a.Key + ".meta";
                if (File.Exists(metaPath))
                {
                    var lines = File.ReadAllLines(metaPath);

                    // Read meta file, look for line with "icon:"
                    for (int i = 0; i < lines.Length; ++i)
                    {
                        string l = lines[i];

                        // Line must have "icon: " and default icon stuff
                        if (l.Contains(ICON_MATCH))
                        {
                            // Get type of script, then get associated icon from utilities
                            string      pathToScript = AssetDatabase.GUIDToAssetPath(a.Value);
                            MonoScript  script       = AssetDatabase.LoadAssetAtPath <MonoScript>(pathToScript);
                            System.Type tData;
                            var         sot = SmartEditorUtils.GetSmartObjectType(script.GetClass(), out tData);

                            //TODO Implement icons for component types
                            if (sot == SmartEditorUtils.SmartObjectType.NONE)
                            {
                                break;
                            }
                            Texture2D icon = SmartEditorUtils.LoadSmartIcon(sot, false, true);

                            // Get guid of icon and jam it in there
                            string pathToIcon = AssetDatabase.GetAssetPath(icon);
                            string iconGuid   = AssetDatabase.AssetPathToGUID(pathToIcon);

                            bool modified = false;
                            if (l.Contains(ICON_DEFAULT))
                            {
                                // Replace entire default icon
                                l        = l.Replace(ICON_DEFAULT, string.Format("{{fileID: 2800000, guid: {0}, type: 3}}", iconGuid));
                                modified = true;
                            }
                            else if (l.Contains(ICON_CUSTOM_HEAD))
                            {
                                // Isolate guid to check if changed
                                string check = l.Trim().Replace(ICON_MATCH, "").Replace(ICON_CUSTOM_HEAD, "").Replace(ICON_CUSTOM_TAIL, "");
                                if (check != iconGuid)
                                {
                                    var sb = new System.Text.StringBuilder();

                                    // Whitespace
                                    for (int j = 0; j < l.Length; ++j)
                                    {
                                        if (l[j] != ' ')
                                        {
                                            break;
                                        }
                                        sb.Append(' ');
                                    }

                                    // Build with new guid
                                    sb.Append(ICON_MATCH);
                                    sb.Append(ICON_CUSTOM_HEAD);
                                    sb.Append(iconGuid);
                                    sb.Append(ICON_CUSTOM_TAIL);
                                    l = sb.ToString();

                                    modified = true;
                                }
                            }

                            if (modified)
                            {
                                Debug.Log("Setting icon for script " + a.Key);
                                // Save and flag for asset database refresh
                                lines[i] = l;
                                File.WriteAllLines(metaPath, lines);
                                refresh = true;
                            }
                            break;
                        }
                    }
                }
                else
                {
                    Debug.LogError("Meta file not found: " + metaPath);
                }
            }
            #endregion

            if (refresh)
            {
                AssetDatabase.Refresh();
            }
        }
Beispiel #6
0
        void OnGUI()
        {
            bool repaint = false;

            if (_t.Count == 0)
            {
                _t.Add("");
            }

            Color gbc = GUI.backgroundColor;

            EditorGUILayout.BeginVertical(); {                  // Used to GetLastRect to control total height of window
                EditorGUILayout.Space();

                if (!_isRegenerating)
                {
                    EditorGUILayout.LabelField("Data Types", GUILayout.MaxWidth(70));
                    if (InlineHelpButton())
                    {
                        _showTypeTooltip = !_showTypeTooltip;
                    }

                    if (_isParsingAssemblies)
                    {
                        EditorGUI.ProgressBar(GUILayoutUtility.GetLastRect(), _parseProgress, "Parsing Types");
                    }

                    ++EditorGUI.indentLevel;
                    if (_showTypeTooltip)
                    {
                        EditorGUILayout.HelpBox("Case-sensitive. Include any namespaces/nesting.\nBasic types (e.g. int, float) and Unity types (e.g. Vector3) don't need namespaces.", MessageType.Info);
                    }
                    _toRemove.Clear();

                    int  focusedField       = -1;
                    var  btnOptions         = new GUILayoutOption[] { GUILayout.Width(20), GUILayout.Height(13) };
                    bool missingGenericArgs = false;
                    for (int i = 0; i < _t.Count; ++i)
                    {
                        bool   typeIsOpenGeneric = false;
                        string focusName         = string.Format(TYPE_FIELD_NAME, i);
                        EditorGUILayout.BeginHorizontal(); {
                            GUI.SetNextControlName(focusName);
                            if (_t[i].Contains("#") || _t[i].Contains("<,") || _t[i].Contains(",,") || _t[i].Contains("<>") || _t[i].Contains(",>"))
                            {
                                GUI.backgroundColor = Color.red;
                                missingGenericArgs  = true;
                                typeIsOpenGeneric   = true;
                            }
                            _t[i] = WithoutSelectAll(() => EditorGUILayout.TextField(_t[i]));
                            GUI.backgroundColor = gbc;

                            GUI.backgroundColor = Color.red;
                            GUI.enabled         = _t.Count > 1;
                            if (GUILayout.Button("-", btnOptions))
                            {
                                _toRemove.Add(_t[i]);
                            }
                            GUI.enabled         = true;
                            GUI.backgroundColor = gbc;
                        } EditorGUILayout.EndHorizontal();

                        if (typeIsOpenGeneric)
                        {
                            EditorGUILayout.HelpBox("Replace all # with type arguments", MessageType.Error);
                        }

                        // Get focused field for autocomplete
                        string focus = GUI.GetNameOfFocusedControl();
                        if (focus == focusName)
                        {
                            if (settingsDirty)
                            {
                                OnFocus();
                            }
                            if (!string.IsNullOrEmpty(_t[i]))
                            {
                                focusedField = i;
                            }
                            else
                            {
                                _lastTypeName = null;
                            }
                        }
                    }

                    // Autocomplete
                    if (!_isParsingAssemblies && focusedField >= 0)
                    {
                        // Check if changed
                        string t = _t[focusedField];
                        if (t != _lastTypeName)
                        {
                            _typeAutocompleteScroll = Vector2.zero;
                            _lastTypeName           = t;
                            // Start match
                            _typeMatchIndex = 0;
                            _typesAutocompleted.Clear();
                            _matching = true;
                        }

                        // Match
                        if (_matching)
                        {
                            _acSw.Start();
                            bool skip = false;
                            while (_typeMatchIndex < _typeNames.Count)
                            {
                                if (_typeNames[_typeMatchIndex].Contains(t))
                                {
                                    _typesAutocompleted.Add(_typeNames[_typeMatchIndex]);
                                }
                                ++_typeMatchIndex;
                                if (_acSw.Elapsed.TotalSeconds > SmartTypeCreatorSettings.DEFAULT.asyncTypeLoadFrameTime)
                                {
                                    skip    = true;
                                    repaint = true;
                                    break;
                                }
                            }
                            if (!skip)
                            {
                                // Finished
                                _matching = false;
                            }
                            _acSw.Stop();
                            _acSw.Reset();
                        }

                        // Autocomplete box
                        if (_typesAutocompleted.Count > 0)
                        {
                            _typeAutocompleteScroll = EditorGUILayout.BeginScrollView(
                                _typeAutocompleteScroll,
                                GUILayout.Height(GetTypeAutocompleteHeight()),
                                GUILayout.ExpandWidth(true)
                                ); {
                                EditorGUILayout.BeginHorizontal(); {
                                    GUILayout.Space(30);
                                    GUI.backgroundColor = _matching ? Color.yellow : Color.green;
                                    EditorGUILayout.BeginVertical(EditorStyles.helpBox, GUILayout.Height(_typesAutocompleted.Count * 20)); {
                                        // Fake header space
                                        // Don't render occluded elements, according to scroll
                                        int offset = Mathf.Max(0, Mathf.FloorToInt(_typeAutocompleteScroll.y / 20) - 1);
                                        GUILayout.Space(offset * 20);
                                        GUI.backgroundColor = gbc;
                                        for (int i = offset; i < _typesAutocompleted.Count; ++i)
                                        {
                                            EditorGUILayout.BeginHorizontal(); {
                                                if (GUILayout.Button("Select", GUILayout.MaxWidth(75)))
                                                {
                                                    _t[focusedField] = _typesAutocompleted[i];
                                                    GUI.FocusControl(null);
                                                    repaint = true;
                                                }
                                                EditorGUILayout.LabelField(_typesAutocompleted[i]);
                                            } EditorGUILayout.EndHorizontal();
                                            if (i > offset + MAX_AUTOCOMPLETE_LINES + 1)
                                            {
                                                break;
                                            }
                                        }
                                    } EditorGUILayout.EndVertical();
                                } EditorGUILayout.EndHorizontal();
                            } EditorGUILayout.EndScrollView();
                        }
                    }
                    else
                    {
                        _matching     = false;
                        _lastTypeName = null;
                        _typesAutocompleted.Clear();
                    }

                    if (_toRemove.Count > 0)
                    {
                        foreach (string s in _toRemove)
                        {
                            _t.Remove(s);
                        }
                        _toRemove.Clear();
                    }

                    EditorGUILayout.BeginHorizontal(); {
                        GUI.enabled = false;
                        EditorGUILayout.TextField("");
                        GUI.enabled         = true;
                        GUI.backgroundColor = Color.green;
                        if (GUILayout.Button("+", GUILayout.Width(20), GUILayout.Height(14)))
                        {
                            _t.Add("");
                        }
                        GUI.backgroundColor = gbc;
                    } EditorGUILayout.EndHorizontal();
                    --EditorGUI.indentLevel;

                    EditorGUILayout.BeginHorizontal(); {
                        _path = EditorGUILayout.TextField(
                            new GUIContent("Path", "Folder for generated scripts. If Individual Subfolders ticked, subfolders will be created here."),
                            _path
                            );
                        if (GUILayout.Button("Select...", GUILayout.Width(75)))
                        {
                            string p = EditorUtility.OpenFolderPanel("Select folder for generated Smart Types", _path, "");
                            if (!string.IsNullOrEmpty(p))
                            {
                                _path = SmartEditorUtils.ToRelativePath(p);
                            }
                        }
                    } EditorGUILayout.EndHorizontal();

                    _overwrite  = EditorGUILayout.Toggle(new GUIContent("Overwrite", "If false, will ignore types that already exist in the target path."), _overwrite);
                    _subfolders = EditorGUILayout.Toggle(new GUIContent("Individual Subfolders", "Create subfolders for each type within the target path."), _subfolders);

                    EditorGUILayout.Space();
                    EditorGUILayout.BeginHorizontal(EditorStyles.helpBox); {
                        EditorGUILayout.BeginVertical(GUILayout.Width(150)); {
                            GUI.backgroundColor = Color.green;
                            GUI.enabled         = !missingGenericArgs && _settingsValid;
                            if (GUILayout.Button("Create"))
                            {
                                PopulateTemplates();
                                int successes = 0;
                                scriptAbsPathToGuid.Clear();
                                for (int i = 0; i < _t.Count; ++i)
                                {
                                    if (CreateType(_t[i], _overwrite))
                                    {
                                        ++successes;
                                        _toRemove.Add(_t[i]);
                                    }
                                }
                                if (successes > 0)
                                {
                                    if (successes == _t.Count)
                                    {
                                        ClosePopup();
                                    }
                                    else
                                    {
                                        // Remove successful types
                                        foreach (string s in _toRemove)
                                        {
                                            _t.Remove(s);
                                        }
                                    }
                                    AssetDatabase.Refresh();
                                    PostProcessMeta();
                                }
                            }

                            GUI.enabled         = _settingsValid;
                            GUI.backgroundColor = Color.cyan;
                            if (GUILayout.Button("Regenerate..."))
                            {
                                PopulateRegen();
                            }
                            GUI.backgroundColor = Color.magenta;
                            if (GUILayout.Button("Regenerate All"))
                            {
                                PopulateRegen();
                                RegenNow();
                            }
                            GUI.backgroundColor = gbc;
                            GUI.enabled         = true;
                        } EditorGUILayout.EndVertical();

                        DrawSettings();
                    } EditorGUILayout.EndHorizontal();
                }
                else
                {
                    // Regen mode
                    EditorGUILayout.LabelField("Regenerate types:");
                    EditorGUILayout.Space();
                    ++EditorGUI.indentLevel;

                    foreach (var a in _regenTypesByPath)
                    {
                        EditorGUILayout.LabelField(a.Key);
                        ++EditorGUI.indentLevel;
                        _regenTypes.Clear();
                        foreach (string type in a.Value.Keys)
                        {
                            _regenTypes.Add(type);
                        }
                        foreach (string type in _regenTypes)
                        {
                            a.Value[type] = EditorGUILayout.ToggleLeft(type, a.Value[type]);
                        }
                        --EditorGUI.indentLevel;
                    }
                    --EditorGUI.indentLevel;

                    EditorGUILayout.Space();
                    EditorGUILayout.Space();

                    EditorGUILayout.BeginHorizontal(EditorStyles.helpBox); {
                        EditorGUILayout.BeginVertical(GUILayout.Width(150)); {
                            GUI.backgroundColor = Color.green;
                            if (GUILayout.Button("Regenerate!"))
                            {
                                RegenNow();
                            }

                            GUI.backgroundColor = Color.red;
                            if (GUILayout.Button("Cancel"))
                            {
                                _regenTypesByPath.Clear();
                            }
                            GUI.backgroundColor = gbc;
                        } EditorGUILayout.EndVertical();

                        DrawSettings();
                    } EditorGUILayout.EndHorizontal();
                }
            } EditorGUILayout.EndVertical();

            // GetLastRect for entire vertical group to control total height of window
            SetHeight(GUILayoutUtility.GetLastRect().height);

            if (repaint)
            {
                Repaint();
            }
        }
Beispiel #7
0
        bool CreateType(string typeName, bool overwrite, string path = "")
        {
            if (string.IsNullOrEmpty(typeName))
            {
                return(false);
            }
            foreach (var c in typeName)
            {
                if (!LEGALCHARS.Contains(c.ToString()))
                {
                    Debug.LogError("Type name " + typeName + " contains illegal characters.");
                    return(false);
                }
            }
            string prettyName = PrettyTypeName(typeName);

            if (string.IsNullOrEmpty(prettyName))
            {
                return(false);
            }

            bool globPath = string.IsNullOrEmpty(path);

            string fullPath = SmartEditorUtils.ToAbsolutePath(globPath ? _path : path) + "/";

            if (globPath && _subfolders)
            {
                if (!fullPath.EndsWith(prettyName + "/"))
                {
                    fullPath += prettyName + "/";
                }
            }

            Debug.LogFormat("Creating classes in {0}", fullPath);

            List <string> filenames = new List <string>();

            foreach (var a in _templateToOutput)
            {
                filenames.Add(string.Format(a.Value, prettyName) + ".cs");
            }

            bool   filesExist = false;
            string log        = overwrite ? "Overwriting file(s):" : "File(s) already exist:";

            foreach (string f in filenames)
            {
                filesExist |= CheckFile(f, fullPath, ref log);
            }

            bool makeFiles = true;

            if (filesExist)
            {
                if (overwrite)
                {
                    Debug.LogWarning(log);
                }
                else
                {
                    EditorUtility.DisplayDialog("Error: Files exist", log + "\n\nOperation cancelled, no files written.\n\nTick Overwrite to force.", "OK");
                    makeFiles = false;
                }
            }
            if (makeFiles)
            {
                string writeLog = "Created files:";
                int    i        = 0;
                foreach (var a in _templateToOutput)
                {
                    try {
                        Write(filenames[i], a.Key, typeName, fullPath, ref writeLog);
                    } catch (System.Exception e) {
                        Debug.LogErrorFormat("Skipping file due to error: {0}\nCheck custom template settings - template filename '{1}' may be incorrect.\nError:\n{2}\n{3}", fullPath + filenames[i], a.Key, e.Message, e.StackTrace);
                    }
                    ++i;
                }

                Debug.Log(writeLog);
            }

            return(makeFiles);
        }