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(); }
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; }
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(); } }
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(); } }
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); }