Skip to content

Instantly share code, notes, and snippets.

@CapitanLiteral
Created November 3, 2019 00:11
Show Gist options
  • Save CapitanLiteral/d8c58856e08faf5e107f123bf35d1192 to your computer and use it in GitHub Desktop.
Save CapitanLiteral/d8c58856e08faf5e107f123bf35d1192 to your computer and use it in GitHub Desktop.
Editor to display all editable prefabs
public static ScriptableObject DrawColoredList(ScriptableObject scriptableObject, int i, ScriptableObject selected)
{
if (scriptableObject == selected)
GUILayout.BeginHorizontal(EditorStyle.GetSelectedStyle());
else if (i % 2 == 0)
GUILayout.BeginHorizontal(EditorStyle.GetGreyedOutStyle());
else
GUILayout.BeginHorizontal();
if (GUILayout.Button(scriptableObject.name, EditorStyle.ListElementStyle))
{
selected = scriptableObject;
}
return selected;
}
using System.Collections;
using System.Collections.Generic;
using UnityEditor;
using UnityEngine;
public static class EditorWindowExtensions
{
public static void Save(this EditorWindow window)
{
var data = JsonUtility.ToJson(window, false);
EditorPrefs.SetString(window.GetType().ToString(), data);
}
public static void Load(this EditorWindow window)
{
var data = EditorPrefs.GetString(window.GetType().ToString(), JsonUtility.ToJson(window, false));
JsonUtility.FromJsonOverwrite(data, window);
}
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public static class EditorStyle
{
public static GUIStyle GreyedOutStyle { get; } = GetGreyedOutStyle();
public static GUIStyle SelectedStyle { get; } = GetSelectedStyle();
public static Texture2D GreyedOut { get; } = MakeTex(1, 1, new Color(1.0f, 1.0f, 1.0f, 0.1f));
public static Texture2D Selected { get; } = MakeTex(1, 1, new Color(1.0f, 0.0f, 0.0f, 0.5f));
public static GUIStyle ListElementStyle { get; } = GetListBtnStyle();
public static Texture2D MakeTex(int width, int height, Color col)
{
var pix = new Color[width * height];
for (int i = 0; i < pix.Length; i++)
{
pix[i] = col;
}
var result = new Texture2D(width, height);
result.SetPixels(pix);
result.Apply();
return result;
}
private static GUIStyle GetListBtnStyle()
{
var s = new GUIStyle();
s.normal.textColor = Color.white;
s.margin.bottom = 3;
s.margin.top = 2;
return s;
}
public static GUIStyle GetGreyedOutStyle()
{
GUIStyle style = new GUIStyle();
style.normal.background = EditorStyle.GreyedOut;
return style;
}
public static GUIStyle GetSelectedStyle()
{
GUIStyle style = new GUIStyle();
style.normal.background = EditorStyle.Selected;
return style;
}
}
using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using UnityEditor;
using UnityEditor.Compilation;
using UnityEngine;
using Object = UnityEngine.Object;
public class PrefabEditor : EditorWindow
{
private ScriptableObject selected;
private Dictionary<Type, List<ScriptableObject>> m_editables = new Dictionary<Type, List<ScriptableObject>>();
private Dictionary<string, Type> m_types = new Dictionary<string, Type>();
private List<string> m_options;
[SerializeField] private int leftColumnSize = 200;
//Left Right Top Down
[SerializeField] private Margins<int> margins = new Margins<int>(10, 40, 40, 40);
[SerializeField] private int popUpSelected = 0;
Vector2 leftMenuScrollPos;
Vector2 rightMenuScrollPos;
#region UnityRelated
[MenuItem("Window/ScriptableObjects/Editor", false, 5)]
public static void ShowWindow()
{
//Show existing window instance. If one doesn't exist, make one.
GetWindow(typeof(PrefabEditor));
}
private void OnEnable()
{
LoadEditableScriptableObject();
this.Load();
}
protected void OnDisable() { this.Save(); }
private void OnProjectChange() { LoadEditableScriptableObject(); }
private void OnGUI()
{
Rect left = LeftColumnRect();
Rect right = RightColumnRect();
LeftColumn(left);
RightColumn(right);
}
#endregion
#region LayoutRects
private Rect RightColumnRect()
{
Rect right = position;
right.position = new Vector2(margins.Left + leftColumnSize, margins.Top);
right.width = position.width - leftColumnSize;
return right;
}
private Rect LeftColumnRect()
{
Rect left = position;
left.position = new Vector2(margins.Left, margins.Top);
left.width = leftColumnSize;
return left;
}
private Rect LeftColumnTopRect()
{
Rect left = LeftColumnRect();
left.height = left.height * 0.8f;
return left;
}
private Rect LeftColumnBottomRect()
{
Rect left = LeftColumnRect();
left.position = new Vector2(left.position.x, left.height * 0.8f);
left.height = left.height * 0.2f;
return left;
}
#endregion
#region Layouts
private void RightColumn(Rect right)
{
GUILayout.BeginArea(right);
rightMenuScrollPos = EditorGUILayout.BeginScrollView(rightMenuScrollPos,
GUILayout.Width(position.width - leftColumnSize - margins.Left),
GUILayout.Height(position.height - margins.Top));
if (selected != null)
{
var editor = Editor.CreateEditor(selected);
editor.OnInspectorGUI();
}
EditorGUILayout.EndScrollView();
GUILayout.EndArea();
}
private void LeftColumn(Rect left)
{
LeftColumTop();
LeftColumnBottom();
}
private void LeftColumTop()
{
Type selectedType = GetSelectedScriptableObjectType();
GUILayout.BeginArea(LeftColumnTopRect());
popUpSelected = EditorGUILayout.Popup(popUpSelected, m_options.ToArray());
leftMenuScrollPos = EditorGUILayout.BeginScrollView(leftMenuScrollPos, GUILayout.Width(leftColumnSize),
GUILayout.Height(LeftColumnTopRect().height - margins.Down));
if (selectedType != null)
{
if (selected != null)
{
if (selectedType != selected.GetType())
{
selected = m_editables[selectedType][0];
}
}
List<ScriptableObject> editableScriptableObjects = m_editables[selectedType];
DrawScriptableObjects(editableScriptableObjects);
}
else
{
EditorGUILayout.LabelField("No editable assets found");
EditorGUILayout.LabelField("try this [EditableScriptableObject]");
}
EditorGUILayout.EndScrollView();
GUILayout.EndArea();
}
private void LeftColumnBottom()
{
GUILayout.BeginArea(LeftColumnBottomRect());
DrawCreateAsset();
GUILayout.EndArea();
}
#endregion
#region MainLogic
private void DrawCreateAsset()
{
if (GetSelectedScriptableObjectType() != null)
{
Type type = GetSelectedScriptableObjectType();
if (GUILayout.Button($"New {type}"))
{
CreateAsset(type);
}
}
}
private Type GetSelectedScriptableObjectType()
{
return popUpSelected > m_options.Count || !m_types.ContainsKey(m_options[popUpSelected])
? null
: m_types[m_options[popUpSelected]];
}
private void CreateAsset(Type type)
{
string path = EditorUtility.SaveFilePanel("Save textures to folder",
$"{Application.dataPath}/ScriptableObjects/",
"New " + type, "asset");
if (path.Length != 0)
{
Debug.Log(path);
}
Object newAsset = CreateInstance(type);
string newAssetPath = path;
Debug.Log(newAssetPath);
string relativePath = path.Substring(path.IndexOf("Assets/", StringComparison.Ordinal));
AssetDatabase.CreateAsset(newAsset, relativePath);
AssetDatabase.SaveAssets();
AssetDatabase.Refresh();
EditorUtility.FocusProjectWindow();
Selection.activeObject = newAsset;
selected = (ScriptableObject) newAsset;
}
private void DrawScriptableObjects(List<ScriptableObject> editableScriptableObjects)
{
int i = 0;
foreach (var scriptableObject in editableScriptableObjects)
{
if (selected == null)
{
selected = scriptableObject;
}
selected = EditorDrawers.DrawColoredList(scriptableObject, i, selected);
i++;
GUILayout.EndHorizontal();
}
}
private void LoadEditableScriptableObject()
{
var types = EditorUtils.GetTypesWith<EditableScriptableObject>(false);
m_editables = new Dictionary<Type, List<ScriptableObject>>();
m_types = new Dictionary<string, Type>();
m_options = new List<string>();
foreach (var type in types)
{
EditorUtils.FindAssetsByType(type);
m_editables.Add(type, new List<ScriptableObject>());
if (type.IsSubclassOf(typeof(ScriptableObject)))
{
var resources = Resources.FindObjectsOfTypeAll(type);
foreach (var resource in resources)
{
m_editables[type].Add((ScriptableObject) resource);
}
m_types.Add(type.ToString(), type);
m_options.Add(type.ToString());
}
}
}
#endregion
}
public static partial class EditorUtils
{
public static bool TryGetFolderToLoad(out string path)
{
path = "";
var activeObject = Selection.activeObject;
if (TryGetObjectPath(activeObject, out path))
{
return true;
}
return false;
}
public static void SaveAsset<T>(T model, string name) where T : Object
{
var activeObject = Selection.activeObject;
string path;
if (TryGetObjectPath(activeObject, out path))
{
ProjectWindowUtil.CreateAsset(model, path + "/"+name);
}
}
public static bool TryGetObjectPath(Object activeObject, out string path)
{
path = "";
if (activeObject == null)
{
path = "Assets";
}
else
{
path = AssetDatabase.GetAssetPath(activeObject);
}
if (path.Length > 0)
{
if (!Directory.Exists(path))
{
var lastSlash = path.LastIndexOf('/');
path = path.Substring(0, lastSlash + 1);
}
return true;
}
return false;
}
public static void DrawButton(Action OnButtonPressed)
{
DrawButton(ObjectNames.NicifyVariableName(OnButtonPressed.Method.Name), OnButtonPressed);
}
public static void DrawButton(string label, Action OnButtonPressed)
{
if (GUILayout.Button(label))
{
OnButtonPressed?.Invoke();
}
}
public static IEnumerable<Type> GetTypesWith<TAttribute>(bool inherit)
where TAttribute : Attribute
{
return AppDomain.CurrentDomain.GetAssemblies()
.SelectMany(a => a.GetTypes())
.Where(t => t.IsDefined(typeof(TAttribute), inherit));
}
public static List<T> FindAssetsByType<T>() where T : Object
{
List<T> assets = new List<T>();
string[] guids = AssetDatabase.FindAssets(string.Format("t:{0}", typeof(T)));
for( int i = 0; i < guids.Length; i++ )
{
string assetPath = AssetDatabase.GUIDToAssetPath( guids[i] );
T asset = AssetDatabase.LoadAssetAtPath<T>( assetPath );
if( asset != null )
{
assets.Add(asset);
}
}
return assets;
}
public static List<Object> FindAssetsByType(Type type)
{
List<Object> assets = new List<Object>();
string[] guids = AssetDatabase.FindAssets(string.Format("t:{0}", type));
for( int i = 0; i < guids.Length; i++ )
{
string assetPath = AssetDatabase.GUIDToAssetPath(guids[i]);
var asset = AssetDatabase.LoadAssetAtPath(assetPath, type);
if( asset != null )
{
assets.Add(asset);
}
}
return assets;
}
}
public class Margins<T>
{
public Margins(T top, T down, T left, T right)
{
Top = top;
Down = down;
Left = left;
Right = right;
}
public Margins() {
}
public T Top { get; set; }
public T Down { get; set; }
public T Left { get; set; }
public T Right { get; set; }
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment